Add direction sense and offset support for slabs

This commit is contained in:
Bruno Perdigão
2025-01-20 17:25:59 -03:00
parent 3740b86678
commit 5cf4740f8e
4 changed files with 67 additions and 9 deletions
@@ -58,6 +58,11 @@ def load_post(*args):
ifcopenshell.api.add_post_listener(
"material.edit_layer", "Bonsai.DumbSlab.RegenerateFromLayer", slab.DumbSlabPlaner().regenerate_from_layer
)
ifcopenshell.api.add_post_listener(
"material.edit_layer_usage",
"Bonsai.DumbSlab.RegenerateFromLayerSetUsage",
slab.DumbSlabPlaner().regenerate_from_layer_set_usage,
)
ifcopenshell.api.add_post_listener(
"type.assign_type", "Bonsai.DumbSlab.RegenerateFromType", slab.DumbSlabPlaner().regenerate_from_type
)
+42 -6
View File
@@ -131,9 +131,9 @@ class DumbSlabGenerator:
matrix_world = Matrix()
matrix_world.translation = self.location
if self.container_obj:
matrix_world.translation.z = self.container_obj.location.z - self.depth
matrix_world.translation.z = self.container_obj.location.z
else:
matrix_world.translation.z -= self.depth
matrix_world.translation.z
obj.matrix_world = Matrix.Rotation(self.x_angle, 4, "X") @ matrix_world
bpy.context.view_layer.update()
@@ -195,6 +195,26 @@ class DumbSlabGenerator:
class DumbSlabPlaner:
def regenerate_from_layer_set_usage(self, usecase_path, ifc_file, settings):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if tool.Model.get_usage_type(element) != "LAYER3":
return
# Called from materil.add_layer or material.remove_layer
material = ifcopenshell.util.element.get_material(element)
material_set_usage = tool.Ifc.get().by_id(material.id())
layer_set = material_set_usage.ForLayerSet
total_thickness = sum([l.LayerThickness for l in layer_set.MaterialLayers])
if not total_thickness:
return
self.change_thickness(element, total_thickness)
def regenerate_from_layer(self, usecase_path, ifc_file, settings):
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
@@ -267,20 +287,38 @@ class DumbSlabPlaner:
self.change_thickness(related_object, new_thickness)
def change_thickness(self, element: ifcopenshell.entity_instance, thickness: float) -> None:
layer_params = tool.Model.get_material_layer_parameters(element)
body_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
obj = tool.Ifc.get_object(element)
if not obj:
return
delta_thickness = (thickness * self.unit_scale) - obj.dimensions.z
if round(delta_thickness, 2) == 0:
if thickness == 0:
return
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
if representation:
extrusion = tool.Model.get_extrusion(representation)
if extrusion:
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
offset = layer_params["offset"]
offset_vector = Vector((0.0, 0.0, offset / self.unit_scale))
if layer_params["direction_sense"] == "POSITIVE":
y = abs(y)
z = abs(z)
if layer_params["direction_sense"] == "NEGATIVE":
y = -abs(y)
z = -abs(z)
offset_vector = -offset_vector
extrusion.ExtrudedDirection.DirectionRatios = (x, y, z)
extrusion.Depth = thickness
if offset != 0.0 and not extrusion.Position:
tool.Model.add_extrusion_position(extrusion, offset)
if extrusion.Position:
extrusion.Position.Location.Coordinates = tuple(offset_vector)
else:
props = bpy.context.scene.BIMModelProperties
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
@@ -330,8 +368,6 @@ class DumbSlabPlaner:
should_sync_changes_first=False,
)
obj.location[2] -= delta_thickness
class EnableEditingSketchExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.enable_editing_sketch_extrusion_profile"
+13
View File
@@ -2044,3 +2044,16 @@ class Model(bonsai.core.tool.Model):
@classmethod
def add_filled_opening(cls, voided_obj: bpy.types.Object, filling_obj: bpy.types.Object) -> None:
FilledOpeningGenerator().generate(filling_obj, voided_obj)
@classmethod
def add_extrusion_position(cls, extrusion: ifcopenshell.entity_instance, offset: float) -> None:
ifc_file = tool.Ifc.get()
position = ifc_file.createIfcAxis2Placement3D(
ifc_file.createIfcCartesianPoint((0.0, 0.0, offset)),
ifc_file.createIfcDirection((0.0, 0.0, 1.0)),
ifc_file.createIfcDirection((1.0, 0.0, 0.0)),
)
extrusion.Position = position
@@ -27,6 +27,8 @@ def add_slab_representation(
file: ifcopenshell.file,
context: ifcopenshell.entity_instance,
depth: float = 0.2,
direction_sense: str = "POSITIVE",
offset: float = 0.0,
x_angle: float = 0.0,
clippings: Optional[list[Union[Clipping, dict[str, Any]]]] = None,
polyline: Optional[list[tuple[float, float]]] = None,
@@ -56,6 +58,8 @@ def add_slab_representation(
usecase.settings = {
"context": context,
"depth": depth,
"direction_sense": direction_sense,
"offset": offset,
"x_angle": x_angle,
"clippings": clippings if clippings is not None else [],
"polyline": polyline,
@@ -80,7 +84,7 @@ class Usecase:
size = self.convert_si_to_unit(1)
points = ((0.0, 0.0), (size, 0.0), (size, size), (0.0, size), (0.0, 0.0))
if self.settings["polyline"]:
points = [(self.convert_si_to_unit(p[0]), self.convert_si_to_unit(p[1])) for p in self.settings["polyline"]]
points = [(self.convert_si_to_unit(p[0]), self.convert_si_to_unit(p[1] * (1 / cos(self.settings["x_angle"])))) for p in self.settings["polyline"]]
if self.file.schema == "IFC2X3":
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
else:
@@ -94,9 +98,9 @@ class Usecase:
position = None
# default position for IFC2X3 where .Position is not optional
if self.file.schema == "IFC2X3":
if self.file.schema == "IFC2X3" or self.settings["offset"] != 0:
position = self.file.createIfcAxis2Placement3D(
self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)),
self.file.createIfcCartesianPoint((0.0, 0.0, self.convert_si_to_unit(self.settings["offset"]))),
self.file.createIfcDirection((0.0, 0.0, 1.0)),
self.file.createIfcDirection((1.0, 0.0, 0.0)),
)