mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 10:33:20 +00:00
Fix bug where aggregates break with filtered elements during import.
This commit is contained in:
@@ -18,8 +18,11 @@
|
||||
|
||||
import bpy
|
||||
import uuid
|
||||
import zipfile
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.handler
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class IfcStore:
|
||||
|
||||
@@ -211,10 +211,6 @@ class IfcImporter:
|
||||
self.profile_code("Process element filter")
|
||||
self.create_collections()
|
||||
self.profile_code("Create collections")
|
||||
self.create_aggregates()
|
||||
self.profile_code("Create aggregates")
|
||||
self.create_aggregate_tree()
|
||||
self.profile_code("Create aggregate tree")
|
||||
self.create_openings_collection()
|
||||
self.profile_code("Create opening collection")
|
||||
self.create_materials()
|
||||
@@ -978,15 +974,16 @@ class IfcImporter:
|
||||
self.project["blender"].objects.link(obj)
|
||||
|
||||
def create_collections(self):
|
||||
if self.ifc_import_settings.collection_mode == "DECOMPOSITION" and len(self.file.by_type("IfcRelAggregates")) > 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"
|
||||
|
||||
if self.ifc_import_settings.collection_mode == "DECOMPOSITION":
|
||||
self.create_decomposition_collections()
|
||||
elif self.ifc_import_settings.collection_mode == "SPATIAL_DECOMPOSITION":
|
||||
self.create_spatial_decomposition_collections()
|
||||
|
||||
def create_decomposition_collections(self):
|
||||
self.create_spatial_decomposition_collections()
|
||||
self.create_aggregate_collections()
|
||||
|
||||
def create_spatial_decomposition_collections(self):
|
||||
containers = set([ifcopenshell.util.element.get_container(e) for e in self.elements])
|
||||
self.decomposition_containers = set()
|
||||
for container in containers:
|
||||
@@ -1014,18 +1011,23 @@ class IfcImporter:
|
||||
for rel_aggregate in element.IsDecomposedBy:
|
||||
self.add_related_objects(collection, rel_aggregate.RelatedObjects)
|
||||
|
||||
def create_aggregate_collections(self):
|
||||
self.create_aggregates()
|
||||
self.create_aggregate_tree()
|
||||
|
||||
def create_aggregates(self):
|
||||
if self.ifc_import_settings.has_filter:
|
||||
rel_aggregates = [e.IsDecomposedBy[0].RelatingObject for e in self.elements if e.IsDecomposedBy]
|
||||
rel_aggregates = [e.IsDecomposedBy[0] 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)
|
||||
print("Skipping aggregate collections for performance.")
|
||||
return
|
||||
|
||||
for rel_aggregate in rel_aggregates:
|
||||
self.create_aggregate(rel_aggregate)
|
||||
|
||||
def create_aggregate_tree(self):
|
||||
for aggregate in self.aggregates.values():
|
||||
|
||||
@@ -514,8 +514,9 @@ class LoadProject(bpy.types.Operator):
|
||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||
|
||||
def execute(self, context):
|
||||
if os.path.exists(self.filepath) and "ifc" in os.path.splitext(self.filepath)[1]:
|
||||
context.scene.BIMProperties.ifc_file = self.filepath
|
||||
if not os.path.exists(self.filepath) or "ifc" not in os.path.splitext(self.filepath)[1].lower():
|
||||
return {"FINISHED"}
|
||||
context.scene.BIMProperties.ifc_file = self.filepath
|
||||
context.scene.BIMProjectProperties.is_loading = True
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -583,8 +584,19 @@ class LoadProjectElements(bpy.types.Operator):
|
||||
for container in containers:
|
||||
for rel in container.ContainsElements:
|
||||
elements.update(rel.RelatedElements)
|
||||
self.append_decomposed_elements(elements)
|
||||
return elements
|
||||
|
||||
def append_decomposed_elements(self, elements):
|
||||
decomposed_elements = set()
|
||||
for element in elements:
|
||||
if element.IsDecomposedBy:
|
||||
for subelement in element.IsDecomposedBy[0].RelatedObjects:
|
||||
decomposed_elements.add(subelement)
|
||||
if decomposed_elements:
|
||||
self.append_decomposed_elements(decomposed_elements)
|
||||
elements.update(decomposed_elements)
|
||||
|
||||
def get_ifc_class_elements(self):
|
||||
elements = set()
|
||||
for filter_category in self.props.filter_categories:
|
||||
|
||||
@@ -64,7 +64,7 @@ def updateDataDir(self, context):
|
||||
blenderbim.bim.schema.ifc.data_dir = context.scene.BIMProperties.data_dir
|
||||
|
||||
|
||||
def updateIfcFile(self, context):
|
||||
def update_ifc_file(self, context):
|
||||
if context.scene.BIMProperties.ifc_file:
|
||||
blenderbim.bim.handler.loadIfcStore(context.scene)
|
||||
|
||||
@@ -221,7 +221,7 @@ class BIMProperties(PropertyGroup):
|
||||
data_dir: StringProperty(
|
||||
default=os.path.join(cwd, "data") + os.path.sep, name="Data Directory", update=updateDataDir
|
||||
)
|
||||
ifc_file: StringProperty(name="IFC File", update=updateIfcFile)
|
||||
ifc_file: StringProperty(name="IFC File", update=update_ifc_file)
|
||||
export_schema: EnumProperty(items=[("IFC4", "IFC4", ""), ("IFC2X3", "IFC2X3", "")], name="IFC Schema")
|
||||
last_transaction: StringProperty(name="Last Transaction")
|
||||
contexts: EnumProperty(items=getContexts, name="Contexts")
|
||||
|
||||
@@ -61,10 +61,14 @@ class TestLoadProjectElements(test.bim.bootstrap.NewFile):
|
||||
And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey"
|
||||
And the object "IfcSlab/Slab" is an "IfcSlab"
|
||||
And the object "IfcWall/Wall" is an "IfcWall"
|
||||
And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly"
|
||||
And the object "IfcBeam/Beam" is an "IfcBeam"
|
||||
And the object "IfcSite/My Site" is in the collection "IfcSite/My Site"
|
||||
And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building"
|
||||
And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor"
|
||||
And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1"
|
||||
And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty"
|
||||
And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty"
|
||||
And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor"
|
||||
And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1"
|
||||
And "scene.BIMProjectProperties.is_loading" is "False"
|
||||
@@ -79,20 +83,24 @@ class TestLoadProjectElements(test.bim.bootstrap.NewFile):
|
||||
Then "scene.BIMProjectProperties.filter_categories['IfcSite/My Site'].total_elements" is "0"
|
||||
Then "scene.BIMProjectProperties.filter_categories['IfcBuilding/My Building'].total_elements" is "0"
|
||||
Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Ground Floor'].total_elements" is "1"
|
||||
Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].total_elements" is "1"
|
||||
When I set "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Ground Floor'].is_selected" to "True"
|
||||
Then "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].total_elements" is "2"
|
||||
When I set "scene.BIMProjectProperties.filter_categories['IfcBuildingStorey/Level 1'].is_selected" to "True"
|
||||
And I press "bim.load_project_elements"
|
||||
Then the object "IfcProject/My Project" is an "IfcProject"
|
||||
And the object "IfcSite/My Site" is an "IfcSite"
|
||||
And the object "IfcBuilding/My Building" is an "IfcBuilding"
|
||||
And the object "IfcBuildingStorey/Ground Floor" is an "IfcBuildingStorey"
|
||||
And the object "IfcSlab/Slab" is an "IfcSlab"
|
||||
And the object "IfcBuildingStorey/Level 1" is an "IfcBuildingStorey"
|
||||
And the object "IfcWall/Wall" is an "IfcWall"
|
||||
And the object "IfcElementAssembly/Empty" is an "IfcElementAssembly"
|
||||
And the object "IfcBeam/Beam" is an "IfcBeam"
|
||||
And the object "IfcSite/My Site" is in the collection "IfcSite/My Site"
|
||||
And the object "IfcBuilding/My Building" is in the collection "IfcBuilding/My Building"
|
||||
And the object "IfcBuildingStorey/Ground Floor" is in the collection "IfcBuildingStorey/Ground Floor"
|
||||
And the object "IfcSlab/Slab" is in the collection "IfcBuildingStorey/Ground Floor"
|
||||
And the object "IfcBuildingStorey/Level 1" does not exist
|
||||
And the object "IfcWall/Wall" does not exist
|
||||
And the object "IfcBuildingStorey/Level 1" is in the collection "IfcBuildingStorey/Level 1"
|
||||
And the object "IfcWall/Wall" is in the collection "IfcBuildingStorey/Level 1"
|
||||
And the object "IfcElementAssembly/Empty" is in the collection "IfcElementAssembly/Empty"
|
||||
And the object "IfcBeam/Beam" is in the collection "IfcElementAssembly/Empty"
|
||||
And the object "IfcBuildingStorey/Ground Floor" does not exist
|
||||
And the object "IfcSlab/Slab" does not exist
|
||||
"""
|
||||
|
||||
@test.bim.bootstrap.scenario
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
|
||||
FILE_NAME('basic.ifc','2021-09-11T19:44:13+10:00',(),(),'IfcOpenShell 0.6.0b0','BlenderBIM 0.0.999999','Nobody');
|
||||
FILE_NAME('basic.ifc','2021-09-12T16:48:33+10:00',(),(),'IfcOpenShell 0.6.0b0','BlenderBIM 0.0.999999','Nobody');
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
@@ -110,8 +110,8 @@ DATA;
|
||||
#133=IFCSHAPEREPRESENTATION(#22,'Box','BoundingBox',(#132));
|
||||
#134=IFCPRODUCTDEFINITIONSHAPE($,$,(#133,#130));
|
||||
#135=IFCSTYLEDITEM(#129,(#101),'Material');
|
||||
#136=IFCOWNERHISTORY(#9,#8,.READWRITE.,.ADDED.,1631353443,#9,#8,1631353443);
|
||||
#137=IFCRELCONTAINEDINSPATIALSTRUCTURE('1CgivZt6z1l8IgKaTkZMcT',#136,$,$,(#116),#71);
|
||||
#136=IFCOWNERHISTORY(#9,#8,.READWRITE.,.MODIFIED.,1631429228,#9,#8,1631353443);
|
||||
#137=IFCRELCONTAINEDINSPATIALSTRUCTURE('1CgivZt6z1l8IgKaTkZMcT',#136,$,$,(#116,#159),#71);
|
||||
#148=IFCCARTESIANPOINT((0.,0.,3.));
|
||||
#149=IFCDIRECTION((0.,0.,1.));
|
||||
#150=IFCDIRECTION((1.,0.,0.));
|
||||
@@ -122,5 +122,34 @@ DATA;
|
||||
#155=IFCDIRECTION((1.,0.,0.));
|
||||
#156=IFCAXIS2PLACEMENT3D(#153,#154,#155);
|
||||
#157=IFCLOCALPLACEMENT(#152,#156);
|
||||
#158=IFCOWNERHISTORY(#9,#8,.READWRITE.,.MODIFIED.,1631429175,#9,#8,1631429175);
|
||||
#159=IFCELEMENTASSEMBLY('122brjtWrFAPe7NkNdFNlG',#158,'Empty',$,$,#174,$,$,$,.ACCESSORY_ASSEMBLY.);
|
||||
#170=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#171=IFCDIRECTION((0.,0.,1.));
|
||||
#172=IFCDIRECTION((1.,0.,0.));
|
||||
#173=IFCAXIS2PLACEMENT3D(#170,#171,#172);
|
||||
#174=IFCLOCALPLACEMENT(#152,#173);
|
||||
#175=IFCOWNERHISTORY(#9,#8,.READWRITE.,.MODIFIED.,1631429290,#9,#8,1631429215);
|
||||
#176=IFCBEAM('2f_ancUNT1$Btb3bI4H7gM',#175,'Beam',$,$,#216,#194,$,.BEAM.);
|
||||
#182=IFCINDEXEDPOLYGONALFACE((1,2,4,3));
|
||||
#183=IFCINDEXEDPOLYGONALFACE((3,4,8,7));
|
||||
#184=IFCINDEXEDPOLYGONALFACE((7,8,6,5));
|
||||
#185=IFCINDEXEDPOLYGONALFACE((5,6,2,1));
|
||||
#186=IFCINDEXEDPOLYGONALFACE((3,7,5,1));
|
||||
#187=IFCINDEXEDPOLYGONALFACE((8,4,2,6));
|
||||
#188=IFCCARTESIANPOINTLIST3D(((-1.,-1.,-1.),(-1.,-1.,1.),(-1.,1.,-1.),(-1.,1.,1.),(1.,-1.,-1.),(1.,-1.,1.),(1.,1.,-1.),(1.,1.,1.)));
|
||||
#189=IFCPOLYGONALFACESET(#188,$,(#182,#183,#184,#185,#186,#187),$);
|
||||
#190=IFCSHAPEREPRESENTATION(#21,'Body','Tessellation',(#189));
|
||||
#191=IFCCARTESIANPOINT((-1.,-1.,-1.));
|
||||
#192=IFCBOUNDINGBOX(#191,2.,2.,2.);
|
||||
#193=IFCSHAPEREPRESENTATION(#22,'Box','BoundingBox',(#192));
|
||||
#194=IFCPRODUCTDEFINITIONSHAPE($,$,(#193,#190));
|
||||
#205=IFCOWNERHISTORY(#9,#8,.READWRITE.,.ADDED.,1631429238,#9,#8,1631429238);
|
||||
#206=IFCRELAGGREGATES('1SGr7ReC13EhuetdWMr2G9',#205,$,$,#159,(#176));
|
||||
#212=IFCCARTESIANPOINT((0.,0.,-3.));
|
||||
#213=IFCDIRECTION((0.,0.,1.));
|
||||
#214=IFCDIRECTION((1.,0.,0.));
|
||||
#215=IFCAXIS2PLACEMENT3D(#212,#213,#214);
|
||||
#216=IFCLOCALPLACEMENT(#174,#215);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
|
||||
Reference in New Issue
Block a user