mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Fixed zero length segment for vertical alignment. Refactors curve segment transition code
This commit is contained in:
+4
-3
@@ -143,6 +143,9 @@ def _map_circular_arc(file: ifcopenshell.file, design_parameters: entity_instanc
|
||||
end_angle = math.atan(end_gradient)
|
||||
dx = math.cos(start_angle)
|
||||
dy = math.sin(start_angle)
|
||||
|
||||
# start and end angles are for the curve tangents
|
||||
# convert them to be angles of the radii lines
|
||||
if start_angle < end_angle:
|
||||
radius = horizontal_length / (math.sin(end_angle) - math.sin(start_angle))
|
||||
x = -radius * math.sin(start_angle)
|
||||
@@ -158,14 +161,12 @@ def _map_circular_arc(file: ifcopenshell.file, design_parameters: entity_instanc
|
||||
|
||||
parent_curve = file.createIfcCircle(
|
||||
Position=file.createIfcAxis2Placement2D(
|
||||
Location=file.createIfcCartesianPoint((0.0, 0.0)),
|
||||
Location=file.createIfcCartesianPoint((x, y)),
|
||||
RefDirection=file.createIfcDirection((1.0, 0.0)),
|
||||
),
|
||||
Radius=radius,
|
||||
)
|
||||
|
||||
segment_curve_length = radius * math.fabs(end_angle - start_angle)
|
||||
|
||||
curve_segment = file.create_entity(
|
||||
type="IfcCurveSegment",
|
||||
Transition=transition,
|
||||
|
||||
@@ -27,6 +27,7 @@ import math
|
||||
|
||||
from ifcopenshell.api.alignment._get_segment_start_point_label import _get_segment_start_point_label
|
||||
from ifcopenshell.api.alignment._map_alignment_horizontal_segment import _map_alignment_horizontal_segment
|
||||
from ifcopenshell.api.alignment._map_alignment_vertical_segment import _map_alignment_vertical_segment
|
||||
from ifcopenshell.api.alignment._update_curve_segment_transition_code import _update_curve_segment_transition_code
|
||||
|
||||
|
||||
@@ -157,20 +158,35 @@ def add_zero_length_segment(file: ifcopenshell.file, layout: entity_instance, in
|
||||
)
|
||||
elif layout.is_a("IfcAlignmentVertical"):
|
||||
last_segment_dist_along = 0.0
|
||||
last_segment_height = 0.0
|
||||
last_segment_end_gradient = 0.0
|
||||
last_segment = None
|
||||
for rel in layout.IsNestedBy:
|
||||
if 0 < len(rel.RelatedObjects):
|
||||
last_segment = rel.RelatedObjects[-1]
|
||||
last_segment_dist_along = (
|
||||
last_segment.DesignParameters.StartDistAlong + last_segment.DesignParameters.HorizontalLength
|
||||
)
|
||||
last_segment_end_gradient = last_segment.DesignParameters.EndGradient
|
||||
break
|
||||
|
||||
if last_segment:
|
||||
file.begin_transaction()
|
||||
last_segment_dist_along = (
|
||||
last_segment.DesignParameters.StartDistAlong + last_segment.DesignParameters.HorizontalLength
|
||||
)
|
||||
last_segment_end_gradient = last_segment.DesignParameters.EndGradient
|
||||
settings = ifcopenshell.geom.settings()
|
||||
mapped_segments = _map_alignment_vertical_segment(file, last_segment)
|
||||
geometry_segment = mapped_segments[0] if mapped_segments[1] == None else mapped_segments[1]
|
||||
fn = wrapper.map_shape(settings, geometry_segment.wrapped_data)
|
||||
eval = wrapper.function_item_evaluator(settings, fn)
|
||||
e = np.array(eval.evaluate(fn.end()))
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
|
||||
last_segment_height = float(e[1, 3]) / unit_scale
|
||||
|
||||
file.discard_transaction()
|
||||
|
||||
design_parameters = file.createIfcAlignmentVerticalSegment(
|
||||
StartDistAlong=last_segment_dist_along,
|
||||
HorizontalLength=0.0,
|
||||
StartHeight=0.0,
|
||||
StartHeight=last_segment_height,
|
||||
StartGradient=last_segment_end_gradient,
|
||||
EndGradient=last_segment_end_gradient,
|
||||
PredefinedType="CONSTANTGRADIENT",
|
||||
|
||||
+23
-18
@@ -26,47 +26,52 @@ import math
|
||||
|
||||
|
||||
def get_curve_segment_transition_code(
|
||||
prev_segment: entity_instance, segment: entity_instance, tolerance: float = 5.0e-4
|
||||
segment: entity_instance, next_segment: entity_instance, position_tolerance: float = 0.001
|
||||
) -> str:
|
||||
"""
|
||||
Returns the IfcCurveSegment.Transition of prev_segment based on a comparison of
|
||||
the position, ref. direction, and curvature at the end of the prev_segment and the start of segment.
|
||||
Returns the IfcCurveSegment.Transition of segment based on a comparison of
|
||||
the position, ref. direction, and curvature at the end of the segment and the start of next_segment.
|
||||
|
||||
:param segment: segment for which the position curve is being being determined
|
||||
:param next_segment: next segment
|
||||
:param position_tolerance: tolerance used for evaluation positions. The default is 1mm
|
||||
:return: the transition code
|
||||
"""
|
||||
expected_type = "IfcCurveSegment"
|
||||
if not prev_segment.is_a(expected_type):
|
||||
raise TypeError(f"Expected to see '{expected_type}', instead received '{prev_segment.is_a()}'.")
|
||||
|
||||
if not segment.is_a(expected_type):
|
||||
raise TypeError(f"Expected to see '{expected_type}', instead received '{segment.is_a()}'.")
|
||||
|
||||
if len(prev_segment.UsingCurves) != 1:
|
||||
raise TypeError("prev_segment must belong to exactly one curve")
|
||||
if not next_segment.is_a(expected_type):
|
||||
raise TypeError(f"Expected to see '{expected_type}', instead received '{next_segment.is_a()}'.")
|
||||
|
||||
if len(segment.UsingCurves) != 1:
|
||||
raise TypeError("segment must belong to exactly one curve")
|
||||
|
||||
if prev_segment.UsingCurves[0] != segment.UsingCurves[0]:
|
||||
if len(next_segment.UsingCurves) != 1:
|
||||
raise TypeError("next_segment must belong to exactly one curve")
|
||||
|
||||
if segment.UsingCurves[0] != next_segment.UsingCurves[0]:
|
||||
raise TypeError("Both segments must belong to the same curve")
|
||||
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set("COMPUTE_CURVATURE", True)
|
||||
|
||||
prev_segment_fn = ifcopenshell_wrapper.map_shape(settings, prev_segment.wrapped_data)
|
||||
prev_segment_evaluator = ifcopenshell_wrapper.function_item_evaluator(settings, prev_segment_fn)
|
||||
e = prev_segment_evaluator.evaluate(prev_segment_fn.end())
|
||||
segment_fn = ifcopenshell_wrapper.map_shape(settings, segment.wrapped_data)
|
||||
segment_evaluator = ifcopenshell_wrapper.function_item_evaluator(settings, segment_fn)
|
||||
e = segment_evaluator.evaluate(segment_fn.end())
|
||||
end = np.array(e)
|
||||
|
||||
# must add the new segment to the container before mapping it, otherwise the segment doesn't
|
||||
# have enough context to know if it is for horizontal, vertical, cant
|
||||
|
||||
segment_fn = ifcopenshell_wrapper.map_shape(settings, segment.wrapped_data)
|
||||
segment_evaluator = ifcopenshell_wrapper.function_item_evaluator(settings, segment_fn)
|
||||
s = segment_evaluator.evaluate(segment_fn.start())
|
||||
next_segment_fn = ifcopenshell_wrapper.map_shape(settings, next_segment.wrapped_data)
|
||||
next_segment_evaluator = ifcopenshell_wrapper.function_item_evaluator(settings, next_segment_fn)
|
||||
s = next_segment_evaluator.evaluate(next_segment_fn.start())
|
||||
start = np.array(s)
|
||||
|
||||
same_position = True if np.allclose(end[:3, 3], start[:3, 3], atol=tolerance) else False
|
||||
same_gradient = True if np.allclose(end[:3, 0], start[:3, 0], atol=tolerance) else False
|
||||
same_curvature = True if np.allclose(end[3:, :3], start[3:, :3], atol=tolerance) else False
|
||||
same_position = True if np.allclose(end[:3, 3], start[:3, 3], atol=position_tolerance) else False
|
||||
same_gradient = True if np.allclose(end[:3, 0], start[:3, 0]) else False
|
||||
same_curvature = True if np.allclose(end[3:, :3], start[3:, :3]) else False
|
||||
|
||||
transition_code = ""
|
||||
if same_position:
|
||||
|
||||
Reference in New Issue
Block a user