This commit is contained in:
Andrej730
2024-03-18 17:25:09 +05:00
parent a755ec99f9
commit ec7af4e719
3 changed files with 47 additions and 28 deletions
+45 -26
View File
@@ -32,12 +32,13 @@ import ifcopenshell.geom
import ifcopenshell.util.unit import ifcopenshell.util.unit
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import ifcopenshell.util.placement
import blenderbim.tool as tool 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 from blenderbim.bim.ifc import IfcStore, IFC_CONNECTED_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 from typing import Dict, Union, Optional
class MaterialCreator: class MaterialCreator:
@@ -200,20 +201,26 @@ class IfcImporter:
self.ifc_import_settings = ifc_import_settings self.ifc_import_settings = ifc_import_settings
self.diff = None self.diff = None
self.file: ifcopenshell.file = None self.file: ifcopenshell.file = None
self.context_settings = [] self.context_settings: list[ifcopenshell.geom.main.settings] = []
self.gross_context_settings = [] self.gross_context_settings: list[ifcopenshell.geom.main.settings] = []
self.contexts = [] self.contexts = []
self.project = None self.project = None
self.has_existing_project = False self.has_existing_project = False
self.collections = {} # element guids to blender collections mapping
self.elements = set() self.collections: dict[str, bpy.types.Collection] = {}
self.type_collection = None self.elements: set[ifcopenshell.entity_instance] = set()
self.annotations: set[ifcopenshell.entity_instance] = set()
self.gross_elements: set[ifcopenshell.entity_instance] = set()
self.element_types: set[ifcopenshell.entity_instance] = set()
self.spatial_elements: set[ifcopenshell.entity_instance] = set()
self.type_collection: bpy.types.Collection = None
self.type_products = {} self.type_products = {}
self.meshes = {} self.meshes = {}
self.mesh_shapes = {} self.mesh_shapes = {}
self.time = 0 self.time = 0
self.unit_scale = 1 self.unit_scale = 1
self.added_data = {} # ifc definition ids to blender elements mapping
self.added_data: dict[int, IFC_CONNECTED_TYPE] = {}
self.native_elements = set() self.native_elements = set()
self.native_data = {} self.native_data = {}
self.progress = 0 self.progress = 0
@@ -452,7 +459,9 @@ class IfcImporter:
for element in self.gross_elements: for element in self.gross_elements:
print(element) print(element)
def get_spatial_elements_filtered_by_elements(self, elements): def get_spatial_elements_filtered_by_elements(
self, elements: set[ifcopenshell.entity_instance]
) -> set[ifcopenshell.entity_instance]:
leaf_spatial_elements = set([ifcopenshell.util.element.get_container(e) for e in elements]) leaf_spatial_elements = set([ifcopenshell.util.element.get_container(e) for e in elements])
results = set() results = set()
for spatial_element in leaf_spatial_elements: for spatial_element in leaf_spatial_elements:
@@ -864,7 +873,7 @@ class IfcImporter:
except: except:
pass pass
def create_generic_elements(self, elements): def create_generic_elements(self, elements: set[ifcopenshell.entity_instance]) -> 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)
@@ -883,7 +892,7 @@ class IfcImporter:
print("{} / {} elements processed ...".format(i, total)) print("{} / {} elements processed ...".format(i, total))
self.create_product(element) self.create_product(element)
def create_generic_sqlite_elements(self, elements): def create_generic_sqlite_elements(self, elements: set[ifcopenshell.entity_instance]) -> None:
self.geometry_cache = self.file.get_geometry([e.id() for e in elements]) self.geometry_cache = self.file.get_geometry([e.id() for e in elements])
for geometry_id, geometry in self.geometry_cache["geometry"].items(): for geometry_id, geometry in self.geometry_cache["geometry"].items():
mesh_name = tool.Loader.get_mesh_name(type("Geometry", (), {"id": geometry_id})) mesh_name = tool.Loader.get_mesh_name(type("Geometry", (), {"id": geometry_id}))
@@ -930,7 +939,9 @@ class IfcImporter:
mesh = self.meshes.get(mesh_name) mesh = self.meshes.get(mesh_name)
self.create_product(element, mesh=mesh) self.create_product(element, mesh=mesh)
def create_products(self, products, settings=None): def create_products(
self, products, settings: Optional[ifcopenshell.geom.main.settings] = None
) -> set[ifcopenshell.entity_instance]:
results = set() results = set()
if not products: if not products:
return results return results
@@ -1053,7 +1064,7 @@ class IfcImporter:
return mapped_representation return mapped_representation
return None return None
def create_pointclouds(self, products): def create_pointclouds(self, products: set[ifcopenshell.entity_instance]) -> set[ifcopenshell.entity_instance]:
result = set() result = set()
for product in products: for product in products:
representation = self.get_pointcloud_representation(product) representation = self.get_pointcloud_representation(product)
@@ -1064,7 +1075,9 @@ class IfcImporter:
return result return result
def create_pointcloud(self, product, representation): def create_pointcloud(
self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, None]:
placement_matrix = self.get_element_matrix(product) placement_matrix = self.get_element_matrix(product)
vertex_list = [] vertex_list = []
for item in representation.Items: for item in representation.Items:
@@ -1547,14 +1560,14 @@ class IfcImporter:
self.project["blender"].BIMCollectionProperties.obj = obj self.project["blender"].BIMCollectionProperties.obj = obj
obj.BIMObjectProperties.collection = self.collections[project.GlobalId] = self.project["blender"] obj.BIMObjectProperties.collection = self.collections[project.GlobalId] = self.project["blender"]
def create_collections(self): def create_collections(self) -> None:
self.create_spatial_decomposition_collections() self.create_spatial_decomposition_collections()
if self.ifc_import_settings.collection_mode == "DECOMPOSITION": if self.ifc_import_settings.collection_mode == "DECOMPOSITION":
self.create_aggregate_and_nest_collections() self.create_aggregate_and_nest_collections()
elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION": elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION":
pass pass
def create_spatial_decomposition_collections(self): def create_spatial_decomposition_collections(self) -> None:
for rel_aggregate in self.project["ifc"].IsDecomposedBy or []: for rel_aggregate in self.project["ifc"].IsDecomposedBy or []:
self.create_spatial_decomposition_collection(self.project["blender"], rel_aggregate.RelatedObjects) self.create_spatial_decomposition_collection(self.project["blender"], rel_aggregate.RelatedObjects)
@@ -1567,7 +1580,9 @@ class IfcImporter:
tool.Loader.create_project_collection("Views") tool.Loader.create_project_collection("Views")
self.type_collection = tool.Loader.create_project_collection("Types") self.type_collection = tool.Loader.create_project_collection("Types")
def create_spatial_decomposition_collection(self, parent, related_objects): def create_spatial_decomposition_collection(
self, parent: Union[bpy.types.Collection, bpy.types.Object], related_objects: list[ifcopenshell.entity_instance]
) -> None:
for element in related_objects: for element in related_objects:
if element not in self.spatial_elements: if element not in self.spatial_elements:
continue continue
@@ -1617,9 +1632,9 @@ class IfcImporter:
self.ifc_import_settings.collection_mode = "SPATIAL_DECOMPOSITION" self.ifc_import_settings.collection_mode = "SPATIAL_DECOMPOSITION"
return return
aggregates = {} aggregates: dict[str, dict] = {}
for rel_aggregate in rel_aggregates: for rel_aggregate in rel_aggregates:
element = rel_aggregate.RelatingObject element: ifcopenshell.entity_instance = rel_aggregate.RelatingObject
collection = bpy.data.collections.new(tool.Loader.get_name(element)) collection = bpy.data.collections.new(tool.Loader.get_name(element))
aggregates[element.GlobalId] = {"element": element, "collection": collection} aggregates[element.GlobalId] = {"element": element, "collection": collection}
self.collections[element.GlobalId] = collection self.collections[element.GlobalId] = collection
@@ -1688,18 +1703,20 @@ class IfcImporter:
else: else:
blender_material.BIMStyleProperties.active_style_type = "Shading" blender_material.BIMStyleProperties.active_style_type = "Shading"
def place_objects_in_collections(self): def place_objects_in_collections(self) -> None:
for ifc_definition_id, obj in self.added_data.items(): for ifc_definition_id, obj in self.added_data.items():
if isinstance(obj, bpy.types.Object): if isinstance(obj, bpy.types.Object):
self.place_object_in_collection(self.file.by_id(ifc_definition_id), obj) self.place_object_in_collection(self.file.by_id(ifc_definition_id), obj)
def place_object_in_collection(self, element, obj): def place_object_in_collection(self, element: ifcopenshell.entity_instance, obj: bpy.types.Object) -> None:
if self.ifc_import_settings.collection_mode == "DECOMPOSITION": if self.ifc_import_settings.collection_mode == "DECOMPOSITION":
self.place_object_in_decomposition_collection(element, obj) self.place_object_in_decomposition_collection(element, obj)
elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION": elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION":
self.place_object_in_spatial_decomposition_collection(element, obj) self.place_object_in_spatial_decomposition_collection(element, obj)
def place_object_in_decomposition_collection(self, element, obj): def place_object_in_decomposition_collection(
self, element: ifcopenshell.entity_instance, obj: bpy.types.Object
) -> None:
if element.is_a("IfcProject"): if element.is_a("IfcProject"):
return return
elif element.is_a("IfcGridAxis"): elif element.is_a("IfcGridAxis"):
@@ -1719,7 +1736,9 @@ class IfcImporter:
else: else:
return self.place_object_in_spatial_decomposition_collection(element, obj) return self.place_object_in_spatial_decomposition_collection(element, obj)
def place_object_in_spatial_decomposition_collection(self, element, obj): def place_object_in_spatial_decomposition_collection(
self, element: ifcopenshell.entity_instance, obj: bpy.types.Object
) -> None:
if element.is_a("IfcProject"): if element.is_a("IfcProject"):
return return
elif element.is_a("IfcGridAxis"): elif element.is_a("IfcGridAxis"):
@@ -1763,7 +1782,7 @@ class IfcImporter:
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.ObjectType == "DRAWING": if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup.ObjectType == "DRAWING":
return rel.RelatingGroup return rel.RelatingGroup
def get_element_matrix(self, element): def get_element_matrix(self, element: ifcopenshell.entity_instance) -> np.array:
if isinstance(element, ifcopenshell.sqlite_entity): if isinstance(element, ifcopenshell.sqlite_entity):
result = self.geometry_cache["shapes"][element.id()]["matrix"] result = self.geometry_cache["shapes"][element.id()]["matrix"]
else: else:
@@ -1773,7 +1792,7 @@ class IfcImporter:
result[2][3] *= self.unit_scale result[2][3] *= self.unit_scale
return result return result
def scale_matrix(self, matrix): def scale_matrix(self, matrix: np.array) -> np.array:
matrix[0][3] *= self.unit_scale matrix[0][3] *= self.unit_scale
matrix[1][3] *= self.unit_scale matrix[1][3] *= self.unit_scale
matrix[2][3] *= self.unit_scale matrix[2][3] *= self.unit_scale
@@ -2002,7 +2021,7 @@ class IfcImportSettings:
self.has_filter = None self.has_filter = None
self.should_filter_spatial_elements = True self.should_filter_spatial_elements = True
self.should_setup_viewport_camera = True self.should_setup_viewport_camera = True
self.elements = set() self.elements: set[ifcopenshell.entity_instance] = set()
self.collection_mode = "DECOMPOSITION" self.collection_mode = "DECOMPOSITION"
@staticmethod @staticmethod
+1 -1
View File
@@ -36,7 +36,7 @@ from pathlib import Path
class Loader(blenderbim.core.tool.Loader): class Loader(blenderbim.core.tool.Loader):
@classmethod @classmethod
def create_project_collection(self, name): def create_project_collection(cls, name: str) -> bpy.types.Collection:
project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0]) project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0])
project_collection = project_obj.BIMObjectProperties.collection project_collection = project_obj.BIMObjectProperties.collection
for collection in project_collection.children: for collection in project_collection.children:
+1 -1
View File
@@ -183,7 +183,7 @@ class sqlite(file):
return True return True
return False return False
def get_geometry(self, ids): def get_geometry(self, ids: list[int]) -> dict[str, dict]:
import numpy as np import numpy as np
ids_csv = ",".join(map(str, ids)) ids_csv = ",".join(map(str, ids))