mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-30 00:23:14 +00:00
Dumb slabs now roundtrip the Blender solidify modifier
This commit is contained in:
@@ -14,6 +14,7 @@ class IfcStore:
|
|||||||
pset_template_file = None
|
pset_template_file = None
|
||||||
library_path = ""
|
library_path = ""
|
||||||
library_file = None
|
library_file = None
|
||||||
|
element_listeners = set()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def purge():
|
def purge():
|
||||||
@@ -60,6 +61,10 @@ class IfcStore:
|
|||||||
return
|
return
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_element_listener(callback):
|
||||||
|
IfcStore.element_listeners.add(callback)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def link_element(element, obj):
|
def link_element(element, obj):
|
||||||
IfcStore.id_map[element.id()] = obj
|
IfcStore.id_map[element.id()] = obj
|
||||||
@@ -68,6 +73,8 @@ class IfcStore:
|
|||||||
obj.BIMObjectProperties.ifc_definition_id = element.id()
|
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, "mode", blenderbim.bim.handler.mode_callback)
|
||||||
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
|
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
|
||||||
|
for listener in IfcStore.element_listeners:
|
||||||
|
listener(element, obj)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def unlink_element(element=None, obj=None):
|
def unlink_element(element=None, obj=None):
|
||||||
|
|||||||
@@ -2,15 +2,19 @@ import bpy
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
from blenderbim.bim.module.model import product, wall, slab
|
from blenderbim.bim.module.model import product, wall, slab
|
||||||
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def load_post(*args):
|
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, 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.generate_axis)
|
||||||
ifcopenshell.api.add_post_listener("geometry.add_representation", None, wall.calculate_quantities)
|
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("material.edit_layer", None, wall.DumbWallPlaner().regenerate_from_layer)
|
||||||
ifcopenshell.api.add_pre_listener("type.assign_type", None, wall.DumbWallPlaner().regenerate_from_type)
|
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("material.edit_layer", None, slab.DumbSlabPlaner().regenerate_from_layer)
|
||||||
ifcopenshell.api.add_pre_listener("type.assign_type", None, slab.DumbSlabPlaner().regenerate_from_type)
|
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.type
|
||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
import mathutils.geometry
|
import mathutils.geometry
|
||||||
|
import blenderbim.bim.handler
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from math import pi, degrees
|
from math import pi, degrees
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
from ifcopenshell.api.material.data import Data as MaterialData
|
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:
|
class DumbSlabGenerator:
|
||||||
def __init__(self, relating_type):
|
def __init__(self, relating_type):
|
||||||
self.relating_type = relating_type
|
self.relating_type = relating_type
|
||||||
|
|||||||
@@ -686,7 +686,6 @@ class DumbWallGenerator:
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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, "Model", "Axis", "GRAPH_VIEW")
|
axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Axis", "GRAPH_VIEW")
|
||||||
if not axis_context:
|
if not axis_context:
|
||||||
@@ -747,13 +746,19 @@ def calculate_quantities(usecase_path, ifc_file, **settings):
|
|||||||
net_volume = gross_volume
|
net_volume = gross_volume
|
||||||
bm.free()
|
bm.free()
|
||||||
|
|
||||||
ifcopenshell.api.run("pset.edit_qto", ifc_file, should_run_listeners=False, qto=qto, properties={
|
ifcopenshell.api.run(
|
||||||
"Length": round(length, 2),
|
"pset.edit_qto",
|
||||||
"Width": round(width, 2),
|
ifc_file,
|
||||||
"Height": round(height, 2),
|
should_run_listeners=False,
|
||||||
"GrossVolume": round(gross_volume, 2),
|
qto=qto,
|
||||||
"NetVolume": round(net_volume, 2)
|
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)
|
PsetData.load(ifc_file, obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
|
||||||
|
|
||||||
@@ -835,7 +840,7 @@ class DumbWallPlaner:
|
|||||||
break
|
break
|
||||||
if not slide_vector:
|
if not slide_vector:
|
||||||
continue
|
continue
|
||||||
slide_vector *= (slide_magnitude / abs(slide_vector.y))
|
slide_vector *= slide_magnitude / abs(slide_vector.y)
|
||||||
vert.co += slide_vector
|
vert.co += slide_vector
|
||||||
|
|
||||||
# An end face is a quad that is on one end of the wall or the other. It must
|
# An end face is a quad that is on one end of the wall or the other. It must
|
||||||
|
|||||||
Reference in New Issue
Block a user