mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +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(
|
ifcopenshell.api.add_post_listener(
|
||||||
"material.edit_layer", "Bonsai.DumbSlab.RegenerateFromLayer", slab.DumbSlabPlaner().regenerate_from_layer
|
"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(
|
ifcopenshell.api.add_post_listener(
|
||||||
"type.assign_type", "Bonsai.DumbSlab.RegenerateFromType", slab.DumbSlabPlaner().regenerate_from_type
|
"type.assign_type", "Bonsai.DumbSlab.RegenerateFromType", slab.DumbSlabPlaner().regenerate_from_type
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -131,9 +131,9 @@ class DumbSlabGenerator:
|
|||||||
matrix_world = Matrix()
|
matrix_world = Matrix()
|
||||||
matrix_world.translation = self.location
|
matrix_world.translation = self.location
|
||||||
if self.container_obj:
|
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:
|
else:
|
||||||
matrix_world.translation.z -= self.depth
|
matrix_world.translation.z
|
||||||
obj.matrix_world = Matrix.Rotation(self.x_angle, 4, "X") @ matrix_world
|
obj.matrix_world = Matrix.Rotation(self.x_angle, 4, "X") @ matrix_world
|
||||||
bpy.context.view_layer.update()
|
bpy.context.view_layer.update()
|
||||||
|
|
||||||
@@ -195,6 +195,26 @@ class DumbSlabGenerator:
|
|||||||
|
|
||||||
|
|
||||||
class DumbSlabPlaner:
|
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):
|
def regenerate_from_layer(self, usecase_path, ifc_file, settings):
|
||||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
|
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
|
||||||
|
|
||||||
@@ -267,20 +287,38 @@ class DumbSlabPlaner:
|
|||||||
self.change_thickness(related_object, new_thickness)
|
self.change_thickness(related_object, new_thickness)
|
||||||
|
|
||||||
def change_thickness(self, element: ifcopenshell.entity_instance, thickness: float) -> None:
|
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")
|
body_context = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
|
||||||
obj = tool.Ifc.get_object(element)
|
obj = tool.Ifc.get_object(element)
|
||||||
if not obj:
|
if not obj:
|
||||||
return
|
return
|
||||||
|
|
||||||
delta_thickness = (thickness * self.unit_scale) - obj.dimensions.z
|
if thickness == 0:
|
||||||
if round(delta_thickness, 2) == 0:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||||
if representation:
|
if representation:
|
||||||
extrusion = tool.Model.get_extrusion(representation)
|
extrusion = tool.Model.get_extrusion(representation)
|
||||||
if extrusion:
|
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
|
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:
|
else:
|
||||||
props = bpy.context.scene.BIMModelProperties
|
props = bpy.context.scene.BIMModelProperties
|
||||||
x_angle = 0 if tool.Cad.is_x(props.x_angle, 0, tolerance=0.001) else props.x_angle
|
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,
|
should_sync_changes_first=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
obj.location[2] -= delta_thickness
|
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingSketchExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingSketchExtrusionProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.enable_editing_sketch_extrusion_profile"
|
bl_idname = "bim.enable_editing_sketch_extrusion_profile"
|
||||||
|
|||||||
@@ -2044,3 +2044,16 @@ class Model(bonsai.core.tool.Model):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def add_filled_opening(cls, voided_obj: bpy.types.Object, filling_obj: bpy.types.Object) -> None:
|
def add_filled_opening(cls, voided_obj: bpy.types.Object, filling_obj: bpy.types.Object) -> None:
|
||||||
FilledOpeningGenerator().generate(filling_obj, voided_obj)
|
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,
|
file: ifcopenshell.file,
|
||||||
context: ifcopenshell.entity_instance,
|
context: ifcopenshell.entity_instance,
|
||||||
depth: float = 0.2,
|
depth: float = 0.2,
|
||||||
|
direction_sense: str = "POSITIVE",
|
||||||
|
offset: float = 0.0,
|
||||||
x_angle: float = 0.0,
|
x_angle: float = 0.0,
|
||||||
clippings: Optional[list[Union[Clipping, dict[str, Any]]]] = None,
|
clippings: Optional[list[Union[Clipping, dict[str, Any]]]] = None,
|
||||||
polyline: Optional[list[tuple[float, float]]] = None,
|
polyline: Optional[list[tuple[float, float]]] = None,
|
||||||
@@ -56,6 +58,8 @@ def add_slab_representation(
|
|||||||
usecase.settings = {
|
usecase.settings = {
|
||||||
"context": context,
|
"context": context,
|
||||||
"depth": depth,
|
"depth": depth,
|
||||||
|
"direction_sense": direction_sense,
|
||||||
|
"offset": offset,
|
||||||
"x_angle": x_angle,
|
"x_angle": x_angle,
|
||||||
"clippings": clippings if clippings is not None else [],
|
"clippings": clippings if clippings is not None else [],
|
||||||
"polyline": polyline,
|
"polyline": polyline,
|
||||||
@@ -80,7 +84,7 @@ class Usecase:
|
|||||||
size = self.convert_si_to_unit(1)
|
size = self.convert_si_to_unit(1)
|
||||||
points = ((0.0, 0.0), (size, 0.0), (size, size), (0.0, size), (0.0, 0.0))
|
points = ((0.0, 0.0), (size, 0.0), (size, size), (0.0, size), (0.0, 0.0))
|
||||||
if self.settings["polyline"]:
|
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":
|
if self.file.schema == "IFC2X3":
|
||||||
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
|
curve = self.file.createIfcPolyline([self.file.createIfcCartesianPoint(p) for p in points])
|
||||||
else:
|
else:
|
||||||
@@ -94,9 +98,9 @@ class Usecase:
|
|||||||
|
|
||||||
position = None
|
position = None
|
||||||
# default position for IFC2X3 where .Position is not optional
|
# 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(
|
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((0.0, 0.0, 1.0)),
|
||||||
self.file.createIfcDirection((1.0, 0.0, 0.0)),
|
self.file.createIfcDirection((1.0, 0.0, 0.0)),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user