mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 02:31:09 +00:00
Fix #6366. Improve extrusion x_angle and direction handling.
This solution brings new questions to #5938. Currently, we lack a reliable way to calculate the existing x_angle only based solely on the extrusion direction. For example, a 30 degree angled extrusion with positive direction has the same extrusion direction as a -150 degree angled extrusion with negative direction. The difference lies in the object's rotation. This means that things can get messy if the user changes the object x angle somehow. We may need to explore alternative approaches.
This commit is contained in:
@@ -297,14 +297,16 @@ class DumbSlabPlaner:
|
|||||||
if representation:
|
if representation:
|
||||||
extrusion = tool.Model.get_extrusion(representation)
|
extrusion = tool.Model.get_extrusion(representation)
|
||||||
if extrusion:
|
if extrusion:
|
||||||
existing_x_angle = tool.Model.get_existing_x_angle(extrusion)
|
# TODO Right now we don't have a reliable way to calculate the existing x_angle only based solely on the extrusion direction.
|
||||||
|
# For instances, a 30 degrees angled extrusion with positive direction has the same extrusion direction as a
|
||||||
|
# -150 degrees angled extrusion with negative direction. The difference lies in the object's rotation.
|
||||||
|
# This means that things can get messy if the user changes the object x angle somehow. We have to figure out an alternative approach.
|
||||||
|
existing_x_angle = obj.rotation_euler.x
|
||||||
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, 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
|
existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, pi, tolerance=0.001) else existing_x_angle
|
||||||
existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, 2 * pi, tolerance=0.001) else existing_x_angle
|
existing_x_angle = 0 if tool.Cad.is_x(existing_x_angle, 2 * pi, tolerance=0.001) else existing_x_angle
|
||||||
direction_ratios = Vector(extrusion.ExtrudedDirection.DirectionRatios)
|
direction_ratios = Vector(extrusion.ExtrudedDirection.DirectionRatios)
|
||||||
offset_direction = Vector(
|
offset_direction = direction_ratios.copy()
|
||||||
(abs(direction_ratios.x), abs(direction_ratios.y), abs(direction_ratios.z))
|
|
||||||
) # The offset direction doesn't change with direction sense
|
|
||||||
perpendicular_depth = thickness * abs(1 / cos(existing_x_angle))
|
perpendicular_depth = thickness * abs(1 / cos(existing_x_angle))
|
||||||
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
|
||||||
|
|
||||||
@@ -320,7 +322,9 @@ class DumbSlabPlaner:
|
|||||||
abs(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 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. And the offset direction should remain positive
|
||||||
|
# for either direction sense, so we change it.
|
||||||
|
offset_direction *= -1
|
||||||
if layer_params["direction_sense"] == "POSITIVE":
|
if layer_params["direction_sense"] == "POSITIVE":
|
||||||
direction_ratios *= -1
|
direction_ratios *= -1
|
||||||
|
|
||||||
|
|||||||
@@ -307,6 +307,9 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
extrusion.Depth = perpendicular_depth
|
extrusion.Depth = perpendicular_depth
|
||||||
else:
|
else:
|
||||||
if tool.Model.get_usage_type(element) == "LAYER3":
|
if tool.Model.get_usage_type(element) == "LAYER3":
|
||||||
|
existing_x_angle = obj.rotation_euler.x
|
||||||
|
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
|
||||||
# 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] * abs(cos(existing_x_angle)))
|
(p[0], p[1] * abs(cos(existing_x_angle)))
|
||||||
@@ -325,9 +328,7 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
layer_params = tool.Model.get_material_layer_parameters(element)
|
layer_params = tool.Model.get_material_layer_parameters(element)
|
||||||
perpendicular_depth = layer_params["thickness"] * abs(1 / cos(x_angle)) / unit_scale
|
perpendicular_depth = layer_params["thickness"] * abs(1 / cos(x_angle)) / unit_scale
|
||||||
perpendicular_offset = layer_params["offset"] * abs(1 / cos(x_angle)) / unit_scale
|
perpendicular_offset = layer_params["offset"] * abs(1 / cos(x_angle)) / unit_scale
|
||||||
offset_direction = Vector(
|
offset_direction = direction_ratios.copy()
|
||||||
(abs(direction_ratios.x), abs(direction_ratios.y), abs(direction_ratios.z))
|
|
||||||
) # The offset direction doesn't change with direction sense
|
|
||||||
|
|
||||||
# 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 (abs(x_angle) < (pi / 2) and direction_ratios.z > 0) or (
|
if (abs(x_angle) < (pi / 2) and direction_ratios.z > 0) or (
|
||||||
@@ -342,6 +343,9 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
):
|
):
|
||||||
# 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.
|
||||||
|
# then the we change the extrusion direction. And the offset direction should remain positive
|
||||||
|
# for either direction sense, so we change it.
|
||||||
|
offset_direction *= -1
|
||||||
if layer_params["direction_sense"] == "POSITIVE":
|
if layer_params["direction_sense"] == "POSITIVE":
|
||||||
direction_ratios *= -1
|
direction_ratios *= -1
|
||||||
|
|
||||||
@@ -363,9 +367,10 @@ class ChangeExtrusionXAngle(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Object rotation
|
# Object rotation
|
||||||
|
current_z_rot = obj.rotation_euler.z
|
||||||
rot_mat = mathutils.Matrix.Rotation(x_angle, 4, "X")
|
rot_mat = mathutils.Matrix.Rotation(x_angle, 4, "X")
|
||||||
rot_mat = obj.matrix_world @ rot_mat
|
|
||||||
obj.rotation_euler = rot_mat.to_euler()
|
obj.rotation_euler = rot_mat.to_euler()
|
||||||
|
obj.rotation_euler.z = current_z_rot
|
||||||
|
|
||||||
if layer2_objs:
|
if layer2_objs:
|
||||||
DumbWallRecalculator().recalculate(layer2_objs)
|
DumbWallRecalculator().recalculate(layer2_objs)
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ class Collector(bonsai.core.tool.Collector):
|
|||||||
# Note that tool.Geometry.is_locked is only checked within the if
|
# Note that tool.Geometry.is_locked is only checked within the if
|
||||||
# statements for efficiency as it is a slow check.
|
# statements for efficiency as it is a slow check.
|
||||||
tool.Geometry.lock_scale(obj)
|
tool.Geometry.lock_scale(obj)
|
||||||
|
if element.is_a("IfcSlab"):
|
||||||
|
tool.Geometry.lock_rotation(obj, x=True)
|
||||||
|
|
||||||
|
|
||||||
if element.is_a("IfcGridAxis"):
|
if element.is_a("IfcGridAxis"):
|
||||||
if tool.Geometry.is_locked(element):
|
if tool.Geometry.is_locked(element):
|
||||||
|
|||||||
@@ -177,6 +177,10 @@ class Geometry(bonsai.core.tool.Geometry):
|
|||||||
def unlock_scale(cls, obj: bpy.types.Object) -> None:
|
def unlock_scale(cls, obj: bpy.types.Object) -> None:
|
||||||
obj.lock_scale = (False, False, False)
|
obj.lock_scale = (False, False, False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def lock_rotation(cls, obj: bpy.types.Object, x: bool=False, y: bool=False, z: bool=False,) -> None:
|
||||||
|
obj.lock_rotation = (x, y, z)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unlock_scale_object_with_openings(cls, obj: bpy.types.Object) -> None:
|
def unlock_scale_object_with_openings(cls, obj: bpy.types.Object) -> None:
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
|||||||
Reference in New Issue
Block a user