mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
typing
This commit is contained in:
@@ -21,6 +21,7 @@ import json
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.guid
|
import ifcopenshell.guid
|
||||||
|
import ifcopenshell.util.element
|
||||||
import blenderbim.bim.helper
|
import blenderbim.bim.helper
|
||||||
import blenderbim.bim.handler
|
import blenderbim.bim.handler
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
@@ -36,7 +37,7 @@ class EnableEditingAttributes(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
obj = bpy.data.objects.get(self.obj)
|
obj = bpy.data.objects[self.obj]
|
||||||
props = obj.BIMAttributeProperties
|
props = obj.BIMAttributeProperties
|
||||||
props.attributes.clear()
|
props.attributes.clear()
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.element
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
import blenderbim.core.covering as core
|
import blenderbim.core.covering as core
|
||||||
|
|
||||||
|
|||||||
@@ -18,25 +18,28 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import bmesh
|
import bmesh
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
def calculate_height(obj):
|
def calculate_height(obj: bpy.types.Object) -> float:
|
||||||
return obj.dimensions[2]
|
return obj.dimensions[2]
|
||||||
|
|
||||||
|
|
||||||
def calculate_edges_lengths(objs, context):
|
def calculate_edges_lengths(objs: list[bpy.types.Object], context: bpy.types.Context):
|
||||||
return calculate_mesh_quantity(objs, context, lambda bm: sum((e.calc_length() for e in bm.edges if e.select)))
|
return calculate_mesh_quantity(objs, context, lambda bm: sum((e.calc_length() for e in bm.edges if e.select)))
|
||||||
|
|
||||||
|
|
||||||
def calculate_faces_areas(objs, context):
|
def calculate_faces_areas(objs: list[bpy.types.Object], context: bpy.types.Context) -> float:
|
||||||
return calculate_mesh_quantity(objs, context, lambda bm: sum((f.calc_area() for f in bm.faces if f.select)))
|
return calculate_mesh_quantity(objs, context, lambda bm: sum((f.calc_area() for f in bm.faces if f.select)))
|
||||||
|
|
||||||
|
|
||||||
def calculate_volumes(objs, context):
|
def calculate_volumes(objs: list[bpy.types.Object], context: bpy.types.Context) -> float:
|
||||||
return calculate_mesh_quantity(objs, context, lambda bm: bm.calc_volume())
|
return calculate_mesh_quantity(objs, context, lambda bm: bm.calc_volume())
|
||||||
|
|
||||||
|
|
||||||
def calculate_mesh_quantity(objs: bpy.types.Object, context, operation):
|
def calculate_mesh_quantity(
|
||||||
|
objs: list[bpy.types.Object], context: bpy.types.Context, operation: Callable[[bmesh.types.BMesh], float]
|
||||||
|
) -> float:
|
||||||
"""Get the sum of the target quantity on all passed mesh objects
|
"""Get the sum of the target quantity on all passed mesh objects
|
||||||
|
|
||||||
:param objs: iterable of mesh object
|
:param objs: iterable of mesh object
|
||||||
@@ -58,7 +61,7 @@ def calculate_mesh_quantity(objs: bpy.types.Object, context, operation):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def calculate_formwork_area(objs, context):
|
def calculate_formwork_area(objs: list[bpy.types.Object], context: bpy.types.Context) -> float:
|
||||||
"""
|
"""
|
||||||
Formwork is defined as the surface area required to cover all exposed
|
Formwork is defined as the surface area required to cover all exposed
|
||||||
surfaces of one or more objects, excluding top surfaces (i.e. that have a
|
surfaces of one or more objects, excluding top surfaces (i.e. that have a
|
||||||
@@ -85,6 +88,7 @@ def calculate_formwork_area(objs, context):
|
|||||||
copied_obj.name = "Formwork"
|
copied_obj.name = "Formwork"
|
||||||
copied_obj.BIMObjectProperties.ifc_definition_id = 0
|
copied_obj.BIMObjectProperties.ifc_definition_id = 0
|
||||||
modifier = copied_obj.modifiers.new("Formwork", "REMESH")
|
modifier = copied_obj.modifiers.new("Formwork", "REMESH")
|
||||||
|
assert isinstance(modifier, bpy.types.RemeshModifier)
|
||||||
modifier.mode = "SHARP"
|
modifier.mode = "SHARP"
|
||||||
# This hardcoded value may be optimised through a better understanding of the octree division.
|
# This hardcoded value may be optimised through a better understanding of the octree division.
|
||||||
# These values are based off some trial and error heuristics I've learned through experience.
|
# These values are based off some trial and error heuristics I've learned through experience.
|
||||||
@@ -108,7 +112,7 @@ def calculate_formwork_area(objs, context):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def calculate_side_formwork_area(objs, context):
|
def calculate_side_formwork_area(objs: list[bpy.types.Object], context: bpy.types.Context) -> float:
|
||||||
"""
|
"""
|
||||||
Side formwork is defined as the surface area required to cover all exposed
|
Side formwork is defined as the surface area required to cover all exposed
|
||||||
surfaces of one or more objects, excluding top and bottom surfaces (i.e.
|
surfaces of one or more objects, excluding top and bottom surfaces (i.e.
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ from bpy.props import (
|
|||||||
)
|
)
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
def get_subelement_class(self, context):
|
def get_subelement_class(self, context):
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import json
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.api.pset
|
import ifcopenshell.api.pset
|
||||||
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
import ifcopenshell.util.selector
|
import ifcopenshell.util.selector
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
Function = namedtuple("Function", ["measure", "name", "description"])
|
Function = namedtuple("Function", ["measure", "name", "description"])
|
||||||
@@ -47,7 +49,7 @@ def quantify(ifc_file: ifcopenshell.file, elements: set[ifcopenshell.entity_inst
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def edit_qtos(ifc_file, results) -> None:
|
def edit_qtos(ifc_file: ifcopenshell.file, results: dict[ifcopenshell.entity_instance, Any]) -> None:
|
||||||
for element, qtos in results.items():
|
for element, qtos in results.items():
|
||||||
for name, quantities in qtos.items():
|
for name, quantities in qtos.items():
|
||||||
qto = ifcopenshell.util.element.get_pset(element, name, should_inherit=False)
|
qto = ifcopenshell.util.element.get_pset(element, name, should_inherit=False)
|
||||||
@@ -59,7 +61,7 @@ def edit_qtos(ifc_file, results) -> None:
|
|||||||
|
|
||||||
|
|
||||||
class SI2ProjectUnitConverter:
|
class SI2ProjectUnitConverter:
|
||||||
def __init__(self, ifc_file):
|
def __init__(self, ifc_file: ifcopenshell.file):
|
||||||
self.project_units = {
|
self.project_units = {
|
||||||
"IfcAreaMeasure": ifcopenshell.util.unit.get_project_unit(ifc_file, "AREAUNIT"),
|
"IfcAreaMeasure": ifcopenshell.util.unit.get_project_unit(ifc_file, "AREAUNIT"),
|
||||||
"IfcLengthMeasure": ifcopenshell.util.unit.get_project_unit(ifc_file, "LENGTHUNIT"),
|
"IfcLengthMeasure": ifcopenshell.util.unit.get_project_unit(ifc_file, "LENGTHUNIT"),
|
||||||
|
|||||||
@@ -17,12 +17,15 @@
|
|||||||
# along with IfcPatch. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcPatch. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api
|
||||||
import ifcopenshell.util.pset
|
import ifcopenshell.util.pset
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
from logging import Logger
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class Patcher:
|
class Patcher:
|
||||||
def __init__(self, src, file, logger, property_name=None, quantity_name=None):
|
def __init__(self, src: str, file: ifcopenshell.file, logger: Logger, property_name: str, quantity_name: str):
|
||||||
"""Converts a property to a standardised quantity
|
"""Converts a property to a standardised quantity
|
||||||
|
|
||||||
IFC can store arbitrary key value metadata associated with a elements
|
IFC can store arbitrary key value metadata associated with a elements
|
||||||
@@ -40,14 +43,12 @@ class Patcher:
|
|||||||
|
|
||||||
:param property_name: The name of the property to convert into a
|
:param property_name: The name of the property to convert into a
|
||||||
quantity. The name of the property set is not considered.
|
quantity. The name of the property set is not considered.
|
||||||
:type property_name: str
|
|
||||||
:param quantity_name: The name of the quantity that this property should
|
:param quantity_name: The name of the quantity that this property should
|
||||||
be stored in. This should be a standard name that is one of the
|
be stored in. This should be a standard name that is one of the
|
||||||
quantity names of a buildingSMART quantity template. For example, it
|
quantity names of a buildingSMART quantity template. For example, it
|
||||||
may be "NetSideArea" for walls, which exists in
|
may be "NetSideArea" for walls, which exists in
|
||||||
Qto_WallBaseQuantities. The quantity set name will be based on the
|
Qto_WallBaseQuantities. The quantity set name will be based on the
|
||||||
standard buildingSMART quantity template.
|
standard buildingSMART quantity template.
|
||||||
:type quantity_name: str
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ class Patcher:
|
|||||||
self.source_property_name = property_name
|
self.source_property_name = property_name
|
||||||
self.destination_quantity_name = quantity_name
|
self.destination_quantity_name = quantity_name
|
||||||
|
|
||||||
def patch(self):
|
def patch(self) -> None:
|
||||||
self.qto_template_cache = {}
|
self.qto_template_cache = {}
|
||||||
self.psetqto = ifcopenshell.util.pset.get_template("IFC4")
|
self.psetqto = ifcopenshell.util.pset.get_template("IFC4")
|
||||||
|
|
||||||
@@ -76,7 +77,9 @@ class Patcher:
|
|||||||
[r.RelatingPropertyDefinition for r in product.IsDefinedBy if r.is_a("IfcRelDefinesByProperties")],
|
[r.RelatingPropertyDefinition for r in product.IsDefinedBy if r.is_a("IfcRelDefinesByProperties")],
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_product(self, product, definitions):
|
def process_product(
|
||||||
|
self, product: ifcopenshell.entity_instance, definitions: list[ifcopenshell.entity_instance]
|
||||||
|
) -> None:
|
||||||
value = None
|
value = None
|
||||||
has_quantity = False
|
has_quantity = False
|
||||||
qtos = {}
|
qtos = {}
|
||||||
@@ -98,12 +101,12 @@ class Patcher:
|
|||||||
"pset.edit_qto", self.file, qto=qto, Properties={self.destination_quantity_name: value}
|
"pset.edit_qto", self.file, qto=qto, Properties={self.destination_quantity_name: value}
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_qto_name(self, ifc_class):
|
def get_qto_name(self, ifc_class: str) -> Union[str, None]:
|
||||||
for template in self.get_qto_templates(ifc_class):
|
for template in self.get_qto_templates(ifc_class):
|
||||||
if self.destination_quantity_name in [t.Name for t in template.HasPropertyTemplates]:
|
if self.destination_quantity_name in [t.Name for t in template.HasPropertyTemplates]:
|
||||||
return template.Name
|
return template.Name
|
||||||
|
|
||||||
def get_qto_templates(self, ifc_class):
|
def get_qto_templates(self, ifc_class: str) -> list[ifcopenshell.entity_instance]:
|
||||||
if ifc_class not in self.qto_template_cache:
|
if ifc_class not in self.qto_template_cache:
|
||||||
self.qto_template_cache[ifc_class] = self.psetqto.get_applicable(ifc_class, qto_only=True)
|
self.qto_template_cache[ifc_class] = self.psetqto.get_applicable(ifc_class, qto_only=True)
|
||||||
return self.qto_template_cache[ifc_class]
|
return self.qto_template_cache[ifc_class]
|
||||||
|
|||||||
Reference in New Issue
Block a user