mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Refactor ChangeExtrusionXAngle to support obtuse x_angle for slabs.
To support obtuse x_angle a refactoring had to be made, which helped improve the general code for slab addition. This is challenging because there are a few features that interact with each other to create slabs, like `depth`, `direction_sense`, `offset` and `x_angle`. In addition, these interactions can happen in different parts of the code. This commit addresses `ChangeExtrusionXAngle` in `model/wall.py`. See e8e88c25fdcef55826443fe6b000aec1baa6f25a for more information.
This commit is contained in:
@@ -304,16 +304,17 @@ class DumbSlabPlaner:
|
||||
perpendicular_offset = layer_params["offset"] * abs(1 / cos(existing_x_angle)) / self.unit_scale
|
||||
|
||||
# Check angle and z direction to determine whether the extrusion direction is positive or negative
|
||||
if (existing_x_angle < (pi / 2) and direction_ratios.z > 0) or (
|
||||
existing_x_angle > (pi / 2) and direction_ratios.z < 0
|
||||
if (abs(existing_x_angle) < (pi / 2) and direction_ratios.z > 0) or (
|
||||
abs(existing_x_angle) > (pi / 2) and direction_ratios.z < 0
|
||||
):
|
||||
# The extrusion direction is positive. If the layer_parameter is set to negative,
|
||||
# then the we change the extrusion direction.
|
||||
# The offset direction must always be positive, so we keep it.
|
||||
if layer_params["direction_sense"] == "NEGATIVE":
|
||||
direction_ratios *= -1
|
||||
elif (existing_x_angle > (pi / 2) and direction_ratios.z > 0) or (
|
||||
existing_x_angle < (pi / 2) and direction_ratios.z < 0
|
||||
# offset_direction *= -1
|
||||
elif (abs(existing_x_angle )> (pi / 2) and direction_ratios.z > 0) or (
|
||||
abs(existing_x_angle )< (pi / 2) and direction_ratios.z < 0
|
||||
):
|
||||
# The extrusion direction is negative. If the layer_parameter is set to positive,
|
||||
# then the we change the extrusion direction.
|
||||
|
||||
@@ -232,50 +232,66 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
extrusion = tool.Model.get_extrusion(representation)
|
||||
if not extrusion:
|
||||
return
|
||||
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
|
||||
existing_x_angle = tool.Model.get_existing_x_angle(extrusion)
|
||||
perpendicular_depth = extrusion.Depth / (1 / cos(existing_x_angle))
|
||||
if tool.Model.get_usage_type(element) == "LAYER2":
|
||||
extrusion.Depth = abs(perpendicular_depth * (1 / cos(x_angle)))
|
||||
if tool.Model.get_usage_type(element) == "LAYER3":
|
||||
# TODO support angles between 91 and 179
|
||||
if x_angle > radians(90) or x_angle < -radians(90):
|
||||
return
|
||||
extrusion.Depth = perpendicular_depth * (1 / cos(x_angle))
|
||||
extrusion.ExtrudedDirection.DirectionRatios = (0.0, sin(x_angle), cos(x_angle))
|
||||
if tool.Model.get_usage_type(element) == "LAYER2":
|
||||
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
|
||||
existing_x_angle = tool.Model.get_existing_x_angle(extrusion)
|
||||
perpendicular_depth = extrusion.Depth / (1 / cos(existing_x_angle))
|
||||
if tool.Model.get_usage_type(element) == "LAYER2":
|
||||
extrusion.Depth = abs(perpendicular_depth * (1 / cos(x_angle)))
|
||||
extrusion.ExtrudedDirection.DirectionRatios = (0.0, sin(x_angle), cos(x_angle))
|
||||
layer2_objs.append(obj)
|
||||
else:
|
||||
if tool.Model.get_usage_type(element) == "LAYER3":
|
||||
existing_x_angle = tool.Model.get_existing_x_angle(extrusion)
|
||||
existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, 0, tolerance=0.001) else existing_x_angle
|
||||
existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, pi, tolerance=0.001) else existing_x_angle
|
||||
x_angle = 0 if tool.Cad.is_x(x_angle, 0, tolerance=0.001) else x_angle
|
||||
x_angle = 0 if tool.Cad.is_x(x_angle, pi, tolerance=0.001) else x_angle
|
||||
|
||||
# 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
|
||||
(p[0], p[1] * abs(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
|
||||
(p[0], p[1] * abs(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 if that's the case
|
||||
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
|
||||
direction_ratios = Vector((0.0, sin(x_angle), cos(x_angle)))
|
||||
# direction_ratios = Vector(extrusion.ExtrudedDirection.DirectionRatios)
|
||||
layer_params = tool.Model.get_material_layer_parameters(element)
|
||||
perpendicular_offset = layer_params["offset"] * (1 / cos(x_angle))
|
||||
offset_vector = Vector((0.0, 0.0, perpendicular_offset / unit_scale))
|
||||
if layer_params["direction_sense"] == "NEGATIVE":
|
||||
y = -abs(y) if x_angle > 0 else abs(y)
|
||||
z = -abs(z)
|
||||
extrusion.ExtrudedDirection.DirectionRatios = (x, y, z)
|
||||
perpendicular_depth= layer_params["thickness"] * abs(1 / cos(x_angle)) / unit_scale
|
||||
perpendicular_offset = layer_params["offset"] * abs(1 / cos(x_angle)) / unit_scale
|
||||
offset_direction = direction_ratios.copy()
|
||||
|
||||
if perpendicular_offset != 0.0 and not extrusion.Position:
|
||||
tool.Model.add_extrusion_position(extrusion, perpendicular_offset)
|
||||
# Check angle and z direction to determine whether the extrusion direction is positive or negative
|
||||
if (abs(x_angle) < (pi / 2) and direction_ratios.z > 0) or (
|
||||
abs(x_angle) > (pi / 2) and direction_ratios.z < 0
|
||||
):
|
||||
# The extrusion direction is positive. If the layer_parameter is set to negative,
|
||||
# then the we change the extrusion direction.
|
||||
# The offset direction must always be positive, so we keep it.
|
||||
if layer_params["direction_sense"] == "NEGATIVE":
|
||||
direction_ratios *= -1
|
||||
elif ((x_angle) > (pi / 2) and direction_ratios.z > 0) or (
|
||||
(x_angle) < (pi / 2) and direction_ratios.z < 0
|
||||
):
|
||||
# The extrusion direction is negative. If the layer_parameter is set to positive,
|
||||
# then the we change the extrusion direction.
|
||||
# The offset direction must always be positive, so we change it too.
|
||||
if layer_params["direction_sense"] == "POSITIVE":
|
||||
direction_ratios *= -1
|
||||
offset_direction *= -1
|
||||
|
||||
# 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)
|
||||
extrusion.ExtrudedDirection.DirectionRatios = tuple(direction_ratios)
|
||||
extrusion.Depth = perpendicular_depth
|
||||
|
||||
if extrusion.Position or perpendicular_offset != 0:
|
||||
position = offset_direction * perpendicular_offset
|
||||
tool.Model.add_extrusion_position(extrusion, position)
|
||||
|
||||
bonsai.core.geometry.switch_representation(
|
||||
tool.Ifc,
|
||||
@@ -288,11 +304,8 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
|
||||
# Object rotation
|
||||
local_rot_mat = obj.rotation_euler.to_matrix()
|
||||
rot_mat = mathutils.Matrix.Rotation(x_angle - existing_x_angle, 4, "X")
|
||||
new_rot_mat = local_rot_mat.to_4x4() @ rot_mat
|
||||
new_rot_euler = new_rot_mat.to_euler()
|
||||
obj.rotation_euler = new_rot_euler
|
||||
rot_mat = mathutils.Matrix.Rotation(x_angle, 4, "X")
|
||||
obj.rotation_euler = rot_mat.to_euler()
|
||||
|
||||
if layer2_objs:
|
||||
DumbWallRecalculator().recalculate(layer2_objs)
|
||||
|
||||
Reference in New Issue
Block a user