mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 21:42:19 +00:00
typing
This commit is contained in:
@@ -38,8 +38,9 @@ import blenderbim.tool as tool
|
|||||||
import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper
|
import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper
|
||||||
from itertools import chain, accumulate
|
from itertools import chain, accumulate
|
||||||
from blenderbim.bim.ifc import IfcStore, IFC_CONNECTED_TYPE
|
from blenderbim.bim.ifc import IfcStore, IFC_CONNECTED_TYPE
|
||||||
|
from blenderbim.tool.loader import OBJECT_DATA_TYPE
|
||||||
from blenderbim.bim.module.drawing.prop import ANNOTATION_TYPES_DATA
|
from blenderbim.bim.module.drawing.prop import ANNOTATION_TYPES_DATA
|
||||||
from typing import Dict, Union, Optional
|
from typing import Dict, Union, Optional, Any
|
||||||
|
|
||||||
|
|
||||||
class MaterialCreator:
|
class MaterialCreator:
|
||||||
@@ -855,10 +856,10 @@ class IfcImporter:
|
|||||||
self.create_product(element, mesh=mesh)
|
self.create_product(element, mesh=mesh)
|
||||||
print("Done creating geometry")
|
print("Done creating geometry")
|
||||||
|
|
||||||
def create_spatial_elements(self):
|
def create_spatial_elements(self) -> None:
|
||||||
self.create_generic_elements(self.spatial_elements)
|
self.create_generic_elements(self.spatial_elements, unselectable=True)
|
||||||
|
|
||||||
def create_elements(self):
|
def create_elements(self) -> None:
|
||||||
self.create_generic_elements(self.elements)
|
self.create_generic_elements(self.elements)
|
||||||
tmp = self.context_settings
|
tmp = self.context_settings
|
||||||
self.context_settings = self.gross_context_settings
|
self.context_settings = self.gross_context_settings
|
||||||
@@ -876,7 +877,7 @@ class IfcImporter:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def create_generic_elements(self, elements: set[ifcopenshell.entity_instance]) -> None:
|
def create_generic_elements(self, elements: set[ifcopenshell.entity_instance], unselectable=False) -> None:
|
||||||
if isinstance(self.file, ifcopenshell.sqlite):
|
if isinstance(self.file, ifcopenshell.sqlite):
|
||||||
return self.create_generic_sqlite_elements(elements)
|
return self.create_generic_sqlite_elements(elements)
|
||||||
|
|
||||||
@@ -1108,7 +1109,12 @@ class IfcImporter:
|
|||||||
self.link_element(product, obj)
|
self.link_element(product, obj)
|
||||||
return product
|
return product
|
||||||
|
|
||||||
def create_product(self, element, shape=None, mesh=None):
|
def create_product(
|
||||||
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
shape: Optional[Any] = None,
|
||||||
|
mesh: Optional[OBJECT_DATA_TYPE] = None,
|
||||||
|
) -> Union[bpy.types.Object, None]:
|
||||||
if element is None:
|
if element is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1833,7 +1839,7 @@ class IfcImporter:
|
|||||||
):
|
):
|
||||||
return representation.Items[0].MappingTarget
|
return representation.Items[0].MappingTarget
|
||||||
|
|
||||||
def create_curve(self, element, shape):
|
def create_curve(self, element: ifcopenshell.entity_instance, shape) -> bpy.types.Curve:
|
||||||
if hasattr(shape, "geometry"):
|
if hasattr(shape, "geometry"):
|
||||||
geometry = shape.geometry
|
geometry = shape.geometry
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import os
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
# Progressively we'll refactor loading elements into Blender objects into this
|
# Progressively we'll refactor loading elements into Blender objects into this
|
||||||
@@ -34,6 +35,9 @@ from pathlib import Path
|
|||||||
# supplementary objects (e.g. drawings, structural analysis models, etc).
|
# supplementary objects (e.g. drawings, structural analysis models, etc).
|
||||||
|
|
||||||
|
|
||||||
|
OBJECT_DATA_TYPE = Union[bpy.types.Mesh, bpy.types.Curve]
|
||||||
|
|
||||||
|
|
||||||
class Loader(blenderbim.core.tool.Loader):
|
class Loader(blenderbim.core.tool.Loader):
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_project_collection(cls, name: str) -> bpy.types.Collection:
|
def create_project_collection(cls, name: str) -> bpy.types.Collection:
|
||||||
@@ -51,7 +55,7 @@ class Loader(blenderbim.core.tool.Loader):
|
|||||||
return collection
|
return collection
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_mesh_name(cls, geometry):
|
def get_mesh_name(cls, geometry) -> str:
|
||||||
representation_id = geometry.id
|
representation_id = geometry.id
|
||||||
if "-" in representation_id:
|
if "-" in representation_id:
|
||||||
representation_id = int(re.sub(r"\D", "", representation_id.split("-")[0]))
|
representation_id = int(re.sub(r"\D", "", representation_id.split("-")[0]))
|
||||||
@@ -62,11 +66,11 @@ class Loader(blenderbim.core.tool.Loader):
|
|||||||
return "{}/{}".format(context_id, representation_id)
|
return "{}/{}".format(context_id, representation_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_name(cls, element):
|
def get_name(cls, element: ifcopenshell.entity_instance) -> str:
|
||||||
return "{}/{}".format(element.is_a(), getattr(element, "Name", "None"))
|
return "{}/{}".format(element.is_a(), getattr(element, "Name", "None"))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def link_mesh(cls, shape, mesh):
|
def link_mesh(cls, shape, mesh: OBJECT_DATA_TYPE) -> None:
|
||||||
geometry = shape.geometry if hasattr(shape, "geometry") else shape
|
geometry = shape.geometry if hasattr(shape, "geometry") else shape
|
||||||
if "-" in geometry.id:
|
if "-" in geometry.id:
|
||||||
mesh.BIMMeshProperties.ifc_definition_id = int(geometry.id.split("-")[0])
|
mesh.BIMMeshProperties.ifc_definition_id = int(geometry.id.split("-")[0])
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from math import pi
|
from math import pi
|
||||||
from typing import Tuple, Iterable, Any
|
from typing import Tuple, Iterable, Any, Union, Literal
|
||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
@@ -599,14 +599,14 @@ def calculate_unit_scale(ifc_file, unit_type="LENGTHUNIT"):
|
|||||||
|
|
||||||
|
|
||||||
def format_length(
|
def format_length(
|
||||||
value,
|
value: float,
|
||||||
precision,
|
precision: float,
|
||||||
decimal_places=2,
|
decimal_places: int = 2,
|
||||||
suppress_zero_inches=True,
|
suppress_zero_inches=True,
|
||||||
unit_system="imperial",
|
unit_system: Union[Literal["metric"], Literal["imperial"]] = "imperial",
|
||||||
input_unit="foot",
|
input_unit="foot",
|
||||||
output_unit="foot",
|
output_unit="foot",
|
||||||
):
|
) -> str:
|
||||||
"""Formats a length for readability and imperial formatting
|
"""Formats a length for readability and imperial formatting
|
||||||
|
|
||||||
:param value: The value in meters if metric, or either decimal feet or
|
:param value: The value in meters if metric, or either decimal feet or
|
||||||
@@ -670,7 +670,7 @@ def format_length(
|
|||||||
def is_attr_type(
|
def is_attr_type(
|
||||||
content_type: ifcopenshell.ifcopenshell_wrapper.named_type | ifcopenshell.ifcopenshell_wrapper.type_declaration,
|
content_type: ifcopenshell.ifcopenshell_wrapper.named_type | ifcopenshell.ifcopenshell_wrapper.type_declaration,
|
||||||
ifc_unit_type_name: str,
|
ifc_unit_type_name: str,
|
||||||
) -> ifcopenshell.ifcopenshell_wrapper.type_declaration | None:
|
) -> Union[ifcopenshell.ifcopenshell_wrapper.type_declaration, None]:
|
||||||
cur_decl = content_type
|
cur_decl = content_type
|
||||||
while hasattr(cur_decl, "declared_type") is True:
|
while hasattr(cur_decl, "declared_type") is True:
|
||||||
cur_decl = cur_decl.declared_type()
|
cur_decl = cur_decl.declared_type()
|
||||||
|
|||||||
@@ -22,16 +22,17 @@ import ifcopenshell.api.owner.settings
|
|||||||
import ifcopenshell.util.pset
|
import ifcopenshell.util.pset
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
|
from logging import Logger
|
||||||
|
|
||||||
|
|
||||||
class Patcher:
|
class Patcher:
|
||||||
def __init__(self, src, file, logger, unit="METERS"):
|
def __init__(self, src: str, file: ifcopenshell.file, logger: Logger, unit: str = "METERS"):
|
||||||
"""Converts the length unit of a model to the specified unit
|
"""Converts the length unit of a model to the specified unit
|
||||||
|
|
||||||
Allowed metric units include METERS, MILLIMETERS, CENTIMETERS, etc.
|
Allowed metric units include METERS, MILLIMETERS, CENTIMETERS, etc.
|
||||||
Allowed imperial units include INCHES, FEET, MILES.
|
Allowed imperial units include INCHES, FEET, MILES.
|
||||||
|
|
||||||
:param unit: The name of the desired unit.
|
:param unit: The name of the desired unit, defaults to "METERS"
|
||||||
:type unit: str
|
:type unit: str
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -48,7 +49,7 @@ class Patcher:
|
|||||||
self.file = file
|
self.file = file
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.unit = unit
|
self.unit = unit
|
||||||
self.file_patched: ifcopenshell.file = None
|
self.file_patched: ifcopenshell.file
|
||||||
|
|
||||||
def patch(self):
|
def patch(self):
|
||||||
self.file_patched = ifcopenshell.util.unit.convert_file_length_units(self.file, self.unit)
|
self.file_patched = ifcopenshell.util.unit.convert_file_length_units(self.file, self.unit)
|
||||||
|
|||||||
@@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
from typing import Union
|
||||||
|
from logging import Logger
|
||||||
|
|
||||||
|
|
||||||
class Patcher:
|
class Patcher:
|
||||||
def __init__(self, src, file, logger, filepath=None):
|
def __init__(self, src: str, file: ifcopenshell.file, logger: Logger, filepath: str):
|
||||||
"""Merge two IFC models into one
|
"""Merge two IFC models into one
|
||||||
|
|
||||||
Note that other than combining the two IfcProject elements into one, no
|
Note that other than combining the two IfcProject elements into one, no
|
||||||
@@ -46,18 +48,25 @@ class Patcher:
|
|||||||
|
|
||||||
def patch(self):
|
def patch(self):
|
||||||
source = ifcopenshell.open(self.filepath)
|
source = ifcopenshell.open(self.filepath)
|
||||||
self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext")
|
self.existing_contexts: list[ifcopenshell.entity_instance] = self.file.by_type(
|
||||||
self.added_contexts = set()
|
"IfcGeometricRepresentationContext"
|
||||||
|
)
|
||||||
|
self.added_contexts: set[ifcopenshell.entity_instance] = set()
|
||||||
|
|
||||||
original_project = self.file.by_type("IfcProject")[0]
|
original_project = self.file.by_type("IfcProject")[0]
|
||||||
merged_project = self.file.add(source.by_type("IfcProject")[0])
|
merged_project = self.file.add(source.by_type("IfcProject")[0])
|
||||||
|
|
||||||
for element in source.by_type("IfcGeometricRepresentationContext"):
|
for element in source.by_type("IfcGeometricRepresentationContext"):
|
||||||
new = self.file.add(element)
|
new = self.file.add(element)
|
||||||
self.added_contexts.add(new)
|
self.added_contexts.add(new)
|
||||||
|
|
||||||
for element in source:
|
for element in source:
|
||||||
self.file.add(element)
|
self.file.add(element)
|
||||||
|
|
||||||
for inverse in self.file.get_inverse(merged_project):
|
for inverse in self.file.get_inverse(merged_project):
|
||||||
ifcopenshell.util.element.replace_attribute(inverse, merged_project, original_project)
|
ifcopenshell.util.element.replace_attribute(inverse, merged_project, original_project)
|
||||||
self.file.remove(merged_project)
|
self.file.remove(merged_project)
|
||||||
|
|
||||||
self.reuse_existing_contexts()
|
self.reuse_existing_contexts()
|
||||||
|
|
||||||
def reuse_existing_contexts(self):
|
def reuse_existing_contexts(self):
|
||||||
@@ -73,7 +82,9 @@ class Patcher:
|
|||||||
for added_context in to_delete:
|
for added_context in to_delete:
|
||||||
ifcopenshell.util.element.remove_deep2(self.file, added_context)
|
ifcopenshell.util.element.remove_deep2(self.file, added_context)
|
||||||
|
|
||||||
def get_equivalent_existing_context(self, added_context):
|
def get_equivalent_existing_context(
|
||||||
|
self, added_context: ifcopenshell.entity_instance
|
||||||
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
for context in self.existing_contexts:
|
for context in self.existing_contexts:
|
||||||
if context.is_a() != added_context.is_a():
|
if context.is_a() != added_context.is_a():
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.util.schema
|
import ifcopenshell.util.schema
|
||||||
|
from logging import Logger
|
||||||
|
|
||||||
|
|
||||||
class Patcher:
|
class Patcher:
|
||||||
def __init__(self, src, file, logger, schema="IFC4"):
|
def __init__(self, src: str, file: ifcopenshell.file, logger: Logger, schema: str = "IFC4"):
|
||||||
"""Migrate from one IFC version to another
|
"""Migrate from one IFC version to another
|
||||||
|
|
||||||
Note that this is experimental and will try to preserve as much data as
|
Note that this is experimental and will try to preserve as much data as
|
||||||
|
|||||||
@@ -17,10 +17,12 @@
|
|||||||
# along with IfcPatch. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcPatch. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import ifcopenshell
|
||||||
|
from logging import Logger
|
||||||
|
|
||||||
|
|
||||||
class Patcher:
|
class Patcher:
|
||||||
def __init__(self, src, file, logger):
|
def __init__(self, src: str, file: ifcopenshell.file, logger: Logger):
|
||||||
"""Purge IFC properties, relationships, and other data
|
"""Purge IFC properties, relationships, and other data
|
||||||
|
|
||||||
In some rare cases (i.e. "resetting" a model or for security purposes)
|
In some rare cases (i.e. "resetting" a model or for security purposes)
|
||||||
|
|||||||
Reference in New Issue
Block a user