Add support for direction sense and offset in slabs with x_angle

This commit is contained in:
Bruno Perdigão
2025-01-20 19:00:44 -03:00
parent 372654267c
commit c72f17068c
4 changed files with 74 additions and 13 deletions
+13 -5
View File
@@ -30,6 +30,7 @@ import bonsai.core.type
import bonsai.core.geometry import bonsai.core.geometry
import bonsai.core.root import bonsai.core.root
import bonsai.tool as tool import bonsai.tool as tool
from math import cos, radians
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from bonsai.bim.module.geometry.helper import Helper from bonsai.bim.module.geometry.helper import Helper
from bonsai.bim.module.model.decorator import ProfileDecorator, PolylineDecorator, ProductDecorator from bonsai.bim.module.model.decorator import ProfileDecorator, PolylineDecorator, ProductDecorator
@@ -134,7 +135,7 @@ class DumbSlabGenerator:
matrix_world.translation.z = self.container_obj.location.z matrix_world.translation.z = self.container_obj.location.z
else: else:
matrix_world.translation.z matrix_world.translation.z
obj.matrix_world = Matrix.Rotation(self.x_angle, 4, "X") @ matrix_world obj.matrix_world = matrix_world @ Matrix.Rotation(self.x_angle, 4, "X")
bpy.context.view_layer.update() bpy.context.view_layer.update()
element = bonsai.core.root.assign_class( element = bonsai.core.root.assign_class(
@@ -305,13 +306,15 @@ class DumbSlabPlaner:
extrusion = tool.Model.get_extrusion(representation) extrusion = tool.Model.get_extrusion(representation)
if extrusion: if extrusion:
x, y, z = extrusion.ExtrudedDirection.DirectionRatios x, y, z = extrusion.ExtrudedDirection.DirectionRatios
existing_x_angle = tool.Model.get_existing_x_angle(extrusion)
perpendicular_depth = thickness * (1 / cos(existing_x_angle))
offset = layer_params["offset"] offset = layer_params["offset"]
offset_vector = Vector((0.0, 0.0, offset / self.unit_scale)) offset_vector = Vector((0.0, 0.0, offset / self.unit_scale))
if layer_params["direction_sense"] == "POSITIVE": if layer_params["direction_sense"] == "POSITIVE":
y = abs(y) y = abs(y) if existing_x_angle > 0 else -abs(y)
z = abs(z) z = abs(z)
if layer_params["direction_sense"] == "NEGATIVE": elif layer_params["direction_sense"] == "NEGATIVE":
y = -abs(y) y = -abs(y) if existing_x_angle > 0 else abs(y)
z = -abs(z) z = -abs(z)
offset_vector = -offset_vector offset_vector = -offset_vector
extrusion.ExtrudedDirection.DirectionRatios = (x, y, z) extrusion.ExtrudedDirection.DirectionRatios = (x, y, z)
@@ -319,8 +322,12 @@ class DumbSlabPlaner:
if offset != 0.0 and not extrusion.Position: if offset != 0.0 and not extrusion.Position:
tool.Model.add_extrusion_position(extrusion, offset) tool.Model.add_extrusion_position(extrusion, offset)
# Update the extrusion's location based on its current rotation angle and offset
if extrusion.Position: if extrusion.Position:
extrusion.Position.Location.Coordinates = tuple(offset_vector) rot_matrix = Matrix.Rotation(existing_x_angle, 4, "X")
rot_offset = offset_vector @ rot_matrix
extrusion.Position.Location.Coordinates = tuple(rot_offset)
else: else:
@@ -373,6 +380,7 @@ class DumbSlabPlaner:
) )
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"
bl_label = "Enable Editing Sketch Extrusion Profile" bl_label = "Enable Editing Sketch Extrusion Profile"
+39 -7
View File
@@ -36,7 +36,7 @@ import bonsai.core.geometry
import bonsai.core.model as core import bonsai.core.model as core
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from math import pi, sin, cos, degrees from math import pi, sin, cos, degrees, radians
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from bonsai.bim.module.model.opening import FilledOpeningGenerator from bonsai.bim.module.model.opening import FilledOpeningGenerator
from bonsai.bim.module.model.decorator import PolylineDecorator, ProductDecorator from bonsai.bim.module.model.decorator import PolylineDecorator, ProductDecorator
@@ -235,13 +235,43 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
if not extrusion: if not extrusion:
return return
x, y, z = extrusion.ExtrudedDirection.DirectionRatios x, y, z = extrusion.ExtrudedDirection.DirectionRatios
existing_x_angle = Vector((0, 1)).angle_signed(Vector((y, z))) existing_x_angle = tool.Model.get_existing_x_angle(extrusion)
perpendicular_depth = extrusion.Depth / (1 / cos(existing_x_angle)) perpendicular_depth = extrusion.Depth / (1 / cos(existing_x_angle))
extrusion.Depth = perpendicular_depth * (1 / cos(x_angle)) extrusion.Depth = perpendicular_depth * (1 / cos(x_angle))
extrusion.ExtrudedDirection.DirectionRatios = (0.0, sin(x_angle), cos(x_angle)) extrusion.ExtrudedDirection.DirectionRatios = (0.0, sin(x_angle), cos(x_angle))
if tool.Model.get_usage_type(element) == "LAYER2": if tool.Model.get_usage_type(element) == "LAYER2":
layer2_objs.append(obj) layer2_objs.append(obj)
else: else:
if tool.Model.get_usage_type(element) == "LAYER3":
# Reset the transformation and returns to the original points with 0 degrees
extrusion.SweptArea.OuterCurve.Points.CoordList = [(p[0], p[1] * (cos(existing_x_angle))) for p in extrusion.SweptArea.OuterCurve.Points.CoordList]
# Apply the transformation for the new x_angle
extrusion.SweptArea.OuterCurve.Points.CoordList = [(p[0], p[1] * (1 / cos(x_angle))) for p in extrusion.SweptArea.OuterCurve.Points.CoordList]
# The extrusion direction calculated previously default to the positive direction
# Here we set the extrusion direction to negative it that's the case
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
layer_params = tool.Model.get_material_layer_parameters(element)
offset = layer_params["offset"]
offset_vector = Vector((0.0, 0.0, offset / unit_scale))
if layer_params["direction_sense"] == "NEGATIVE":
y = -abs(y) if x_angle > 0 else abs(y)
z = -abs(z)
offset_vector = -offset_vector
extrusion.ExtrudedDirection.DirectionRatios = (x, y, z)
if offset != 0.0 and not extrusion.Position:
tool.Model.add_extrusion_position(extrusion, offset)
# Update the extrusion's location based on its current rotation angle
if extrusion.Position:
rot_matrix = Matrix.Rotation(x_angle, 4, "X")
rot_offset = offset_vector @ rot_matrix
extrusion.Position.Location.Coordinates = tuple(rot_offset)
bonsai.core.geometry.switch_representation( bonsai.core.geometry.switch_representation(
tool.Ifc, tool.Ifc,
tool.Geometry, tool.Geometry,
@@ -252,11 +282,13 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
should_sync_changes_first=False, should_sync_changes_first=False,
) )
euler = obj.matrix_world.to_euler() # Object rotation
euler.x = x_angle local_rot_mat = obj.rotation_euler.to_matrix()
new_matrix = euler.to_matrix().to_4x4() rot_mat = mathutils.Matrix.Rotation(x_angle - existing_x_angle, 4, 'X')
new_matrix.translation = obj.matrix_world.translation new_rot_mat = local_rot_mat.to_4x4() @ rot_mat
obj.matrix_world = new_matrix new_rot_euler = new_rot_mat.to_euler()
obj.rotation_euler = new_rot_euler
if layer2_objs: if layer2_objs:
DumbWallRecalculator().recalculate(layer2_objs) DumbWallRecalculator().recalculate(layer2_objs)
return {"FINISHED"} return {"FINISHED"}
+16 -1
View File
@@ -36,7 +36,7 @@ import bonsai.core.geometry
import bonsai.core.tool import bonsai.core.tool
import bonsai.tool as tool import bonsai.tool as tool
import bonsai.core.geometry as geometry import bonsai.core.geometry as geometry
from math import atan, degrees from math import atan, degrees, radians
from mathutils import Matrix, Vector from mathutils import Matrix, Vector
from copy import deepcopy from copy import deepcopy
from functools import partial from functools import partial
@@ -2057,3 +2057,18 @@ class Model(bonsai.core.tool.Model):
extrusion.Position = position extrusion.Position = position
@classmethod
def get_existing_x_angle(cls, extrusion):
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
# The existing angle result can change when the direction sense in Negative because the DirectionRatios may have negative y and z.
# For instance, a 30 degree angled slab, with negative direction will show as -150 degrees. To prevent that we do the following transformations
existing_x_angle = Vector((0, 1)).angle_signed(Vector((y, z)))
existing_x_angle = (
existing_x_angle + radians(180) if existing_x_angle < -radians(90) else existing_x_angle
)
existing_x_angle = (
existing_x_angle - radians(180) if existing_x_angle > radians(90) else existing_x_angle
)
return existing_x_angle
@@ -93,8 +93,14 @@ class Usecase:
extrusion_direction = self.file.createIfcDirection( extrusion_direction = self.file.createIfcDirection(
(0.0, sin(self.settings["x_angle"]), cos(self.settings["x_angle"])) (0.0, sin(self.settings["x_angle"]), cos(self.settings["x_angle"]))
) )
if self.settings["direction_sense"] == "NEGATIVE":
extrusion_direction = self.file.createIfcDirection(
(0.0, -sin(self.settings["x_angle"]), -cos(self.settings["x_angle"]))
)
else: else:
extrusion_direction = self.file.createIfcDirection((0.0, 0.0, 1.0)) extrusion_direction = self.file.createIfcDirection((0.0, 0.0, 1.0))
if self.settings["direction_sense"] == "NEGATIVE":
extrusion_direction = self.file.createIfcDirection((0.0, 0.0, -1.0))
position = None position = None
# default position for IFC2X3 where .Position is not optional # default position for IFC2X3 where .Position is not optional