mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
Add direction sense and offset support for slabs
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user