mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 22:43:41 +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
|
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
|
# 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 (
|
if (abs(existing_x_angle) < (pi / 2) and direction_ratios.z > 0) or (
|
||||||
existing_x_angle > (pi / 2) and direction_ratios.z < 0
|
abs(existing_x_angle) > (pi / 2) and direction_ratios.z < 0
|
||||||
):
|
):
|
||||||
# The extrusion direction is positive. If the layer_parameter is set to negative,
|
# The extrusion direction is positive. If the layer_parameter is set to negative,
|
||||||
# then the we change the extrusion direction.
|
# then the we change the extrusion direction.
|
||||||
# The offset direction must always be positive, so we keep it.
|
# The offset direction must always be positive, so we keep it.
|
||||||
if layer_params["direction_sense"] == "NEGATIVE":
|
if layer_params["direction_sense"] == "NEGATIVE":
|
||||||
direction_ratios *= -1
|
direction_ratios *= -1
|
||||||
elif (existing_x_angle > (pi / 2) and direction_ratios.z > 0) or (
|
# offset_direction *= -1
|
||||||
existing_x_angle < (pi / 2) and direction_ratios.z < 0
|
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,
|
# The extrusion direction is negative. If the layer_parameter is set to positive,
|
||||||
# then the we change the extrusion direction.
|
# 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)
|
extrusion = tool.Model.get_extrusion(representation)
|
||||||
if not extrusion:
|
if not extrusion:
|
||||||
return
|
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":
|
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)
|
layer2_objs.append(obj)
|
||||||
else:
|
else:
|
||||||
if tool.Model.get_usage_type(element) == "LAYER3":
|
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
|
# Reset the transformation and returns to the original points with 0 degrees
|
||||||
extrusion.SweptArea.OuterCurve.Points.CoordList = [
|
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
|
# Apply the transformation for the new x_angle
|
||||||
extrusion.SweptArea.OuterCurve.Points.CoordList = [
|
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
|
# The extrusion direction calculated previously default to the positive direction
|
||||||
# Here we set the extrusion direction to negative if that's the case
|
# 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)
|
layer_params = tool.Model.get_material_layer_parameters(element)
|
||||||
perpendicular_offset = layer_params["offset"] * (1 / cos(x_angle))
|
perpendicular_depth= layer_params["thickness"] * abs(1 / cos(x_angle)) / unit_scale
|
||||||
offset_vector = Vector((0.0, 0.0, perpendicular_offset / unit_scale))
|
perpendicular_offset = layer_params["offset"] * abs(1 / cos(x_angle)) / unit_scale
|
||||||
if layer_params["direction_sense"] == "NEGATIVE":
|
offset_direction = direction_ratios.copy()
|
||||||
y = -abs(y) if x_angle > 0 else abs(y)
|
|
||||||
z = -abs(z)
|
|
||||||
extrusion.ExtrudedDirection.DirectionRatios = (x, y, z)
|
|
||||||
|
|
||||||
if perpendicular_offset != 0.0 and not extrusion.Position:
|
# Check angle and z direction to determine whether the extrusion direction is positive or negative
|
||||||
tool.Model.add_extrusion_position(extrusion, perpendicular_offset)
|
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
|
extrusion.ExtrudedDirection.DirectionRatios = tuple(direction_ratios)
|
||||||
if extrusion.Position:
|
extrusion.Depth = perpendicular_depth
|
||||||
rot_matrix = Matrix.Rotation(x_angle, 4, "X")
|
|
||||||
rot_offset = offset_vector @ rot_matrix
|
if extrusion.Position or perpendicular_offset != 0:
|
||||||
extrusion.Position.Location.Coordinates = tuple(rot_offset)
|
position = offset_direction * perpendicular_offset
|
||||||
|
tool.Model.add_extrusion_position(extrusion, position)
|
||||||
|
|
||||||
bonsai.core.geometry.switch_representation(
|
bonsai.core.geometry.switch_representation(
|
||||||
tool.Ifc,
|
tool.Ifc,
|
||||||
@@ -288,11 +304,8 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Object rotation
|
# Object rotation
|
||||||
local_rot_mat = obj.rotation_euler.to_matrix()
|
rot_mat = mathutils.Matrix.Rotation(x_angle, 4, "X")
|
||||||
rot_mat = mathutils.Matrix.Rotation(x_angle - existing_x_angle, 4, "X")
|
obj.rotation_euler = rot_mat.to_euler()
|
||||||
new_rot_mat = local_rot_mat.to_4x4() @ rot_mat
|
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user