Dumb walls now auto calculate length, width, height, and simple volume quantities when being updated

This commit is contained in:
Dion Moult
2021-05-24 19:28:47 +10:00
parent 1abf854f01
commit bfe9213f67
3 changed files with 52 additions and 7 deletions
@@ -402,6 +402,7 @@ class DumbWallGenerator:
self.relating_type = relating_type self.relating_type = relating_type
def generate(self): def generate(self):
self.file = IfcStore.get_file()
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(IfcStore.get_file()) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(IfcStore.get_file())
thicknesses = [] thicknesses = []
for rel in self.relating_type.HasAssociations: for rel in self.relating_type.HasAssociations:
@@ -550,4 +551,7 @@ class DumbWallGenerator:
self.collection.objects.link(obj) self.collection.objects.link(obj)
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcWall") bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcWall")
bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name) bpy.ops.bim.assign_type(relating_type=self.relating_type.id(), related_object=obj.name)
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
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.DumbWall"})
return obj return obj
@@ -1,8 +1,12 @@
import bpy import bpy
import bmesh
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.util.unit
import ifcopenshell.util.element
import ifcopenshell.util.representation import ifcopenshell.util.representation
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.pset.data import Data as PsetData
def generate_box(usecase_path, ifc_file, **settings): def generate_box(usecase_path, ifc_file, **settings):
@@ -29,10 +33,48 @@ def generate_box(usecase_path, ifc_file, **settings):
) )
def calculate_dumb_quantities(usecase_path, ifc_file, **settings):
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
obj = settings["blender_object"]
product = ifc_file.by_id(obj.BIMObjectProperties.ifc_definition_id)
parametric = ifcopenshell.util.element.get_psets(product).get("EPset_Parametric")
if not parametric or parametric["Engine"] != "BlenderBIM.DumbWall":
return
qto = ifcopenshell.api.run(
"pset.add_qto", ifc_file, should_run_listeners=False, product=product, Name="Qto_WallBaseQuantities"
)
length = obj.dimensions[0] / unit_scale
width = obj.dimensions[1] / unit_scale
height = obj.dimensions[2] / unit_scale
if product.HasOpenings:
# TODO: calculate gross / net
gross_volume = 0
net_volume = 0
else:
bm = bmesh.new()
bm.from_mesh(obj.data)
gross_volume = bm.calc_volume()
net_volume = gross_volume
bm.free()
ifcopenshell.api.run("pset.edit_qto", ifc_file, should_run_listeners=False, qto=qto, Properties={
"Length": round(length, 2),
"Width": round(width, 2),
"Height": round(height, 2),
"GrossVolume": round(gross_volume, 2),
"NetVolume": round(net_volume, 2)
})
PsetData.load(ifc_file, obj.BIMObjectProperties.ifc_definition_id)
class ActivateParametricEngine(bpy.types.Operator): class ActivateParametricEngine(bpy.types.Operator):
bl_idname = "bim.activate_parametric_engine" bl_idname = "bim.activate_parametric_engine"
bl_label = "Activate Parametric Engine" bl_label = "Activate Parametric Engine"
def execute(self, context): def execute(self, context):
ifcopenshell.api.add_post_listener("geometry.add_representation", IfcStore.get_file(), generate_box) ifcopenshell.api.add_post_listener("geometry.add_representation", IfcStore.get_file(), generate_box)
ifcopenshell.api.add_post_listener(
"geometry.add_representation", IfcStore.get_file(), calculate_dumb_quantities
)
return {"FINISHED"} return {"FINISHED"}
@@ -44,11 +44,11 @@ class Usecase:
return self.create_variable_representation() return self.create_variable_representation()
def evaluate_geometry(self): def evaluate_geometry(self):
for modifier in self.settings["blender_object"].modifiers: for modifier in self.settings["blender_object"].modifiers:
if modifier.type == "BOOLEAN": if modifier.type == "BOOLEAN":
modifier.show_viewport = False modifier.show_viewport = False
mesh = self.settings["blender_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh() mesh = self.settings["blender_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
bm = bmesh.new() bm = bmesh.new()
bm.from_mesh(mesh) bm.from_mesh(mesh)
@@ -57,23 +57,22 @@ class Usecase:
if not self.settings["should_force_triangulation"]: if not self.settings["should_force_triangulation"]:
bmesh.ops.dissolve_limit( bmesh.ops.dissolve_limit(
bm, bm,
angle_limit=0.00174533, angle_limit=0.00174533, # 1 degree
use_dissolve_boundaries=False, use_dissolve_boundaries=False,
verts=bm.verts[:], verts=bm.verts[:],
edges=bm.edges[:], edges=bm.edges[:],
delimit={'MATERIAL'} delimit={"MATERIAL"},
) )
bm.to_mesh(mesh) bm.to_mesh(mesh)
bm.free() bm.free()
del bm del bm
self.settings["geometry"] = mesh self.settings["geometry"] = mesh
for modifier in self.settings["blender_object"].modifiers: for modifier in self.settings["blender_object"].modifiers:
if modifier.type == "BOOLEAN": if modifier.type == "BOOLEAN":
modifier.show_viewport = True modifier.show_viewport = True
def create_model_representation(self): def create_model_representation(self):
if self.settings["context"].is_a() == "IfcGeometricRepresentationContext": if self.settings["context"].is_a() == "IfcGeometricRepresentationContext":
return self.create_variable_representation() return self.create_variable_representation()
@@ -200,7 +199,7 @@ class Usecase:
"XLength": self.convert_si_to_unit(width), "XLength": self.convert_si_to_unit(width),
"YLength": self.convert_si_to_unit(height), "YLength": self.convert_si_to_unit(height),
"ZLength": self.convert_si_to_unit(self.settings["geometry"].clip_end), "ZLength": self.convert_si_to_unit(self.settings["geometry"].clip_end),
} },
) )
return self.file.createIfcShapeRepresentation( return self.file.createIfcShapeRepresentation(