Creating walls are more stable and now directly goes to the IFC representation instead of reverse engineering Blender meshes

This commit is contained in:
Dion Moult
2022-09-15 10:46:52 +10:00
parent 81e46b533b
commit 280ce56431
@@ -650,23 +650,18 @@ class DumbWallGenerator:
def generate(self): def generate(self):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(IfcStore.get_file()) self.layers = get_material_layer_parameters(self.relating_type)
thicknesses = [] if not self.layers["thickness"]:
for rel in self.relating_type.HasAssociations:
if rel.is_a("IfcRelAssociatesMaterial"):
material = rel.RelatingMaterial
if material.is_a("IfcMaterialLayerSet"):
thicknesses = [l.LayerThickness for l in material.MaterialLayers]
break
if not sum(thicknesses):
return return
self.body = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
self.collection = bpy.context.view_layer.active_layer_collection.collection self.collection = bpy.context.view_layer.active_layer_collection.collection
self.collection_obj = bpy.data.objects.get(self.collection.name) self.collection_obj = bpy.data.objects.get(self.collection.name)
self.width = sum(thicknesses) * unit_scale self.width = self.layers["thickness"]
self.height = 3 self.height = 3.
self.length = 1 self.length = 1.
self.rotation = 0 self.rotation = 0.
self.location = Vector((0, 0, 0)) self.location = Vector((0, 0, 0))
if self.has_sketch(): if self.has_sketch():
@@ -774,31 +769,17 @@ class DumbWallGenerator:
return self.create_wall() return self.create_wall()
def create_wall(self): def create_wall(self):
verts = [ representation = ifcopenshell.api.run(
Vector((0, self.width, 0)), "geometry.add_wall_representation",
Vector((0, 0, 0)), tool.Ifc.get(),
Vector((0, self.width, self.height)), context=self.body,
Vector((0, 0, self.height)), thickness=self.layers["thickness"],
Vector((self.length, self.width, 0)), offset=self.layers["offset"],
Vector((self.length, 0, 0)), length=self.length,
Vector((self.length, self.width, self.height)), height=self.height,
Vector((self.length, 0, self.height)), )
] ifc_class = self.get_relating_type_class(self.relating_type)
faces = [ mesh = bpy.data.meshes.new("Dummy")
[1, 3, 2, 0],
[4, 6, 7, 5],
[1, 0, 4, 5],
[3, 7, 6, 2],
[0, 2, 6, 4],
[1, 5, 7, 3],
]
mesh = bpy.data.meshes.new(name="Wall")
mesh.from_pydata(verts, [], faces)
ifc_classes = ifcopenshell.util.type.get_applicable_entities(self.relating_type.is_a(), self.file.schema)
# Standard cases are deprecated, so let's cull them
ifc_class = [c for c in ifc_classes if "StandardCase" not in c][0]
obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh) obj = bpy.data.objects.new(tool.Model.generate_occurrence_name(self.relating_type, ifc_class), mesh)
obj.location = self.location obj.location = self.location
obj.rotation_euler[2] = self.rotation obj.rotation_euler[2] = self.rotation
@@ -806,29 +787,39 @@ class DumbWallGenerator:
obj.location[2] = self.collection_obj.location[2] obj.location[2] = self.collection_obj.location[2]
self.collection.objects.link(obj) self.collection.objects.link(obj)
bpy.ops.bim.assign_class( element = blenderbim.core.root.assign_class(
obj=obj.name, tool.Ifc,
tool.Collector,
tool.Root,
obj=obj,
ifc_class=ifc_class, ifc_class=ifc_class,
ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef", should_add_representation=False,
context=self.body,
) )
ifcopenshell.api.run(
blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type) "geometry.assign_representation", tool.Ifc.get(), product=element, representation=representation
)
blenderbim.core.geometry.switch_representation(
tool.Geometry,
obj=obj,
representation=representation,
should_reload=True,
enable_dynamic_voids=False,
is_global=True,
should_sync_changes_first=False,
)
blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=self.relating_type)
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric") pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric")
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbLayer2"}) ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbLayer2"})
MaterialData.load(self.file) MaterialData.load(self.file)
try: obj.select_set(True)
obj.select_set(True)
except RuntimeError:
def msg(self, context):
txt = "The created object could not be assigned to a collection. "
txt += "Has any IfcSpatialElement been deleted?"
self.layout.label(text=txt)
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
return obj return obj
def get_relating_type_class(self, relating_type):
classes = ifcopenshell.util.type.get_applicable_entities(relating_type.is_a(), tool.Ifc.get().schema)
return [c for c in classes if "StandardCase" not in c][0]
def generate_axis(usecase_path, ifc_file, settings): def generate_axis(usecase_path, ifc_file, settings):
axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Plan", "Axis", "GRAPH_VIEW") axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Plan", "Axis", "GRAPH_VIEW")
@@ -860,7 +851,7 @@ def generate_axis(usecase_path, ifc_file, settings):
"geometry.assign_representation", "geometry.assign_representation",
ifc_file, ifc_file,
should_run_listeners=False, should_run_listeners=False,
**{"product": product, "representation": new_axis} **{"product": product, "representation": new_axis},
) )
bpy.data.meshes.remove(mesh) bpy.data.meshes.remove(mesh)
@@ -1039,3 +1030,17 @@ class DumbWallPlaner:
if min_face and max_face: if min_face and max_face:
break break
return min_face, max_face return min_face, max_face
def get_material_layer_parameters(element):
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
offset = 0.
thickness = 0.
material = ifcopenshell.util.element.get_material(element)
if material:
if material.is_a("IfcMaterialLayerSetUsage"):
offset = material.OffsetFromReferenceLine / unit_scale
material = material.ForLayerSet
if material.is_a("IfcMaterialLayerSet"):
thickness = sum([l.LayerThickness for l in material.MaterialLayers]) / unit_scale
return {"thickness": thickness, "offset": offset}