Dumb slabs now roundtrip the Blender solidify modifier

This commit is contained in:
Dion Moult
2021-05-31 17:43:42 +10:00
parent 6ff4c95ac7
commit d64d7cf27a
4 changed files with 66 additions and 9 deletions
+7
View File
@@ -14,6 +14,7 @@ class IfcStore:
pset_template_file = None
library_path = ""
library_file = None
element_listeners = set()
@staticmethod
def purge():
@@ -60,6 +61,10 @@ class IfcStore:
return
return obj
@staticmethod
def add_element_listener(callback):
IfcStore.element_listeners.add(callback)
@staticmethod
def link_element(element, obj):
IfcStore.id_map[element.id()] = obj
@@ -68,6 +73,8 @@ class IfcStore:
obj.BIMObjectProperties.ifc_definition_id = element.id()
blenderbim.bim.handler.subscribe_to(obj, "mode", blenderbim.bim.handler.mode_callback)
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
for listener in IfcStore.element_listeners:
listener(element, obj)
@staticmethod
def unlink_element(element=None, obj=None):
@@ -2,15 +2,19 @@ import bpy
import ifcopenshell
import ifcopenshell.api
from blenderbim.bim.module.model import product, wall, slab
from blenderbim.bim.ifc import IfcStore
from bpy.app.handlers import persistent
@persistent
def load_post(*args):
ifcopenshell.api.add_post_listener("geometry.add_representation", None, product.generate_box)
ifcopenshell.api.add_post_listener("geometry.add_representation", None, wall.generate_axis)
ifcopenshell.api.add_post_listener("geometry.add_representation", None, wall.calculate_quantities)
ifcopenshell.api.add_pre_listener("material.edit_layer", None, wall.DumbWallPlaner().regenerate_from_layer)
ifcopenshell.api.add_pre_listener("type.assign_type", None, wall.DumbWallPlaner().regenerate_from_type)
IfcStore.add_element_listener(slab.element_listener)
ifcopenshell.api.add_pre_listener("material.edit_layer", None, slab.DumbSlabPlaner().regenerate_from_layer)
ifcopenshell.api.add_pre_listener("type.assign_type", None, slab.DumbSlabPlaner().regenerate_from_type)
@@ -5,12 +5,53 @@ import ifcopenshell
import ifcopenshell.util.type
import ifcopenshell.util.unit
import mathutils.geometry
import blenderbim.bim.handler
from blenderbim.bim.ifc import IfcStore
from math import pi, degrees
from mathutils import Vector, Matrix
from ifcopenshell.api.material.data import Data as MaterialData
def element_listener(element, obj):
blenderbim.bim.handler.subscribe_to(obj, "mode", mode_callback)
def mode_callback(obj, data):
for obj in bpy.context.selected_objects + [bpy.context.active_object]:
if (
obj.mode != "EDIT"
or not obj.data
or not isinstance(obj.data, (bpy.types.Mesh, bpy.types.Curve, bpy.types.TextCurve))
or not obj.BIMObjectProperties.ifc_definition_id
or not bpy.context.scene.BIMProjectProperties.is_authoring
):
return
product = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
parametric = ifcopenshell.util.element.get_psets(product).get("EPset_Parametric")
if parametric and parametric["Engine"] != "BlenderBIM.DumbSlab":
return
modifier = [m for m in obj.modifiers if m.type == "SOLIDIFY"]
if modifier:
return
depth = obj.dimensions.z
bm = bmesh.from_edit_mesh(obj.data)
bmesh.ops.dissolve_limit(bm, angle_limit=pi / 180 * 1, verts=bm.verts, edges=bm.edges)
bm.faces.ensure_lookup_table()
non_bottom_faces = []
for face in bm.faces:
if face.normal.z > -0.9:
non_bottom_faces.append(face)
else:
face.normal_flip()
bmesh.ops.delete(bm, geom=non_bottom_faces, context="FACES")
bmesh.update_edit_mesh(obj.data)
bm.free()
modifier = obj.modifiers.new("Slab Depth", "SOLIDIFY")
modifier.use_even_offset = True
modifier.offset = 1
modifier.thickness = depth
class DumbSlabGenerator:
def __init__(self, relating_type):
self.relating_type = relating_type
@@ -686,7 +686,6 @@ class DumbWallGenerator:
return obj
def generate_axis(usecase_path, ifc_file, **settings):
axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Axis", "GRAPH_VIEW")
if not axis_context:
@@ -747,13 +746,19 @@ def calculate_quantities(usecase_path, ifc_file, **settings):
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)
})
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)
@@ -835,7 +840,7 @@ class DumbWallPlaner:
break
if not slide_vector:
continue
slide_vector *= (slide_magnitude / abs(slide_vector.y))
slide_vector *= slide_magnitude / abs(slide_vector.y)
vert.co += slide_vector
# An end face is a quad that is on one end of the wall or the other. It must