Filtered imports is now much faster and works with omitted aggregates

This commit is contained in:
Dion Moult
2021-08-21 21:09:48 +10:00
parent fd603f7035
commit 5e6343885c
2 changed files with 33 additions and 19 deletions
+30 -18
View File
@@ -224,6 +224,8 @@ class IfcImporter:
self.profile_code("Create project")
self.create_spatial_hierarchy()
self.profile_code("Create spatial hierarchy")
self.process_element_filter()
self.profile_code("Process element filter")
self.create_aggregates()
self.profile_code("Create aggregates")
self.create_aggregate_tree()
@@ -234,8 +236,6 @@ class IfcImporter:
self.profile_code("Create materials")
self.create_styles()
self.profile_code("Create styles")
self.process_element_filter()
self.profile_code("Process element filter")
self.parse_native_elements()
self.profile_code("Parsing native elements")
self.create_grids()
@@ -290,16 +290,20 @@ class IfcImporter:
return abs(coords[0]) > limit or abs(coords[1]) > limit or abs(coords[2]) > limit
def process_element_filter(self):
if not self.ifc_import_settings.ifc_selector:
if self.ifc_import_settings.ifc_import_filter == "NONE" or not self.ifc_import_settings.ifc_selector:
self.elements = self.file.by_type("IfcElement")
return
selector = ifcopenshell.util.selector.Selector()
elements = selector.parse(self.file, self.ifc_import_settings.ifc_selector)
if self.ifc_import_settings.ifc_import_filter == "WHITELIST":
self.filter_mode = "WHITELIST"
self.include_elements = set(elements)
self.elements = self.include_elements
elif self.ifc_import_settings.ifc_import_filter == "BLACKLIST":
self.exclude_elements = set(elements)
self.filter_mode = "BLACKLIST"
self.exclude_elements = set(elements)
self.elements = [e for e in self.file.by_type("IfcElement") if e not in self.exclude_elements]
def parse_native_elements(self):
if self.filter_mode == "WHITELIST":
@@ -637,16 +641,8 @@ class IfcImporter:
def create_empty_and_2d_elements(self):
curve_products = []
if self.filter_mode == "WHITELIST":
self.elements = self.include_elements
elif self.filter_mode == "BLACKLIST":
self.elements = [e for e in self.file.by_type("IfcElement") if e not in self.exclude_elements]
else:
self.elements = self.file.by_type("IfcElement")
for element in self.elements:
if element.id() in self.added_data:
continue
unadded_data = set([e.id() for e in self.elements]) - set(self.added_data)
for element in unadded_data:
if element.is_a("IfcPort"):
continue
if not element.Representation:
@@ -1038,9 +1034,17 @@ class IfcImporter:
self.add_related_objects(collection, rel_aggregate.RelatedObjects)
def create_aggregates(self):
rel_aggregates = [a for a in self.file.by_type("IfcRelAggregates") if a.RelatingObject.is_a("IfcElement")]
for rel_aggregate in rel_aggregates:
self.create_aggregate(rel_aggregate)
if self.filter_mode in ["WHITELIST", "BLACKLIST"]:
rel_aggregates = [e.IsDecomposedBy[0].RelatingObject for e in self.elements if e.IsDecomposedBy]
else:
rel_aggregates = [a for a in self.file.by_type("IfcRelAggregates") if a.RelatingObject.is_a("IfcElement")]
if len(rel_aggregates) > 10000:
# More than 10,000 collections makes Blender unhappy
print("Falling back to SPATIAL_DECOMPOSITION collection mode")
self.ifc_import_settings.collection_mode = "SPATIAL_DECOMPOSITION"
else:
for rel_aggregate in rel_aggregates:
self.create_aggregate(rel_aggregate)
def create_aggregate_tree(self):
for aggregate in self.aggregates.values():
@@ -1191,8 +1195,15 @@ class IfcImporter:
):
bpy.data.objects.remove(self.spatial_structure_elements[global_id]["blender_obj"])
collection = self.spatial_structure_elements[global_id]["blender"]
elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION":
# TODO: refactor this to a more holistic collection mode feature
return self.place_object_in_spatial_tree(element.Decomposes[0].RelatingObject, obj)
else:
collection = self.aggregates[element.Decomposes[0].RelatingObject.GlobalId]["blender"]
aggregate = element.Decomposes[0].RelatingObject
aggregate_data = self.aggregates.get(aggregate.GlobalId)
if not aggregate_data:
return self.place_object_in_spatial_tree(aggregate, obj)
collection = aggregate_data["blender"]
if collection:
collection.objects.link(obj)
else:
@@ -1472,6 +1483,7 @@ class IfcImportSettings:
self.model_offset_coordinates = (0, 0, 0)
self.ifc_import_filter = "NONE"
self.ifc_selector = ""
self.collection_mode = "DECOMPOSITION"
@staticmethod
def factory(context, input_file, logger):
@@ -3,7 +3,9 @@ def get_primitive_type(attribute_or_data_type):
data_type = str(attribute_or_data_type.type_of_attribute())
else:
data_type = str(attribute_or_data_type)
if data_type.find("<list") == 0:
if data_type.find("<type") == 0:
return get_primitive_type(data_type[data_type[1:].find("<")+1:])
elif data_type.find("<list") == 0:
return ("list", get_primitive_type(data_type[data_type[1:].find("<")+1:]))
elif data_type.find("<set") == 0:
return ("set", get_primitive_type(data_type[data_type[1:].find("<")+1:]))