Updates segment_vertices function

Renamed PI and CC to TI and NI
Fixes handling of units (now works correctly with US and SI units)
Changed tests to use US feet units
Fixed documentation
This commit is contained in:
Richard Brice
2026-02-23 08:08:48 -08:00
parent c3f325861c
commit 798ed0d502
2 changed files with 117 additions and 60 deletions
@@ -23,32 +23,35 @@ import ifcopenshell
import ifcopenshell.util.unit
from ifcopenshell import entity_instance, ifcopenshell_wrapper
def _intersect_lines(p1,d1,p2,d2):
x1,y1 = p1
dx1,dy1 = d1
x2,y2 = p2
dx2,dy2 = d2
det = dx1*dy2 - dy1*dx2
def _intersect_lines(p1, d1, p2, d2):
x1, y1 = p1
dx1, dy1 = d1
x2, y2 = p2
dx2, dy2 = d2
det = dx1 * dy2 - dy1 * dx2
if abs(det) < 1e-12:
return None # lines are parallel
t = ((x2 - x1) * dy2 - (y2 - y1) * dx2)/det
return None # lines are parallel
x = x1 + t*dx1
y = y1 + t*dy1
t = ((x2 - x1) * dy2 - (y2 - y1) * dx2) / det
return (x,y)
x = x1 + t * dx1
y = y1 + t * dy1
return (x, y)
def segment_vertices(file: ifcopenshell.file, curve_segment: entity_instance):
def segment_vertices(curve_segment: entity_instance):
"""
Genererates segment vertices. Segment vertices are the points where the tangents
at the start and end of the segment intersect (the PI point) and where lines
perpendicular to the start and end of the segment intersect (CC).
Generates segment vertices. Segment vertices are at the start and end as well as the points where the tangents
at the start and end of the segment intersect (the TI point) and where lines
normal (perpendicular) to the start and end of the segment intersect (NI).
TI and NI are None if intersection points do not exist, such as in the case of a line.
:param curve_segment: A curve segment
:return: tuples for Start, End, PI, CC
:return: tuples for Start, End, TI, NI
"""
supported_segment_types = ["IFCCURVESEGMENT"]
segment_type = curve_segment.is_a().upper()
@@ -56,8 +59,6 @@ def segment_vertices(file: ifcopenshell.file, curve_segment: entity_instance):
raise NotImplementedError(
f"Expected entity type to be one of {[_ for _ in supported_segment_types]}, got '{segment_type}"
)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
settings = ifcopenshell.geom.settings()
segment_fn = ifcopenshell_wrapper.map_shape(settings, curve_segment.wrapped_data)
@@ -65,26 +66,25 @@ def segment_vertices(file: ifcopenshell.file, curve_segment: entity_instance):
s = segment_evaluator.evaluate(segment_fn.start())
start = np.array(s)
sx = float(start[0, 3]) / unit_scale
sy = float(start[1, 3]) / unit_scale
sx = float(start[0, 3])
sy = float(start[1, 3])
sdx = float(start[0, 0])
sdy = float(start[1, 0])
sdy = float(start[1, 0])
e = segment_evaluator.evaluate(segment_fn.end())
end = np.array(e)
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
ex = float(end[0, 3]) / unit_scale
ey = float(end[1, 3]) / unit_scale
ex = float(end[0, 3])
ey = float(end[1, 3])
edx = float(end[0, 0])
edy = float(end[1, 0])
pi = _intersect_lines((sx,sy),(sdx,sdy),(ex,ey),(edx,edy))
ti = _intersect_lines((sx, sy), (sdx, sdy), (ex, ey), (edx, edy)) # tangent intersection
sdx = float(start[0, 1])
sdy = float(start[1, 1])
sdy = float(start[1, 1])
edx = float(end[0, 1])
edy = float(end[1, 1])
cc = _intersect_lines((sx,sy),(sdx,sdy),(ex,ey),(edx,edy))
ni = _intersect_lines((sx, sy), (sdx, sdy), (ex, ey), (edx, edy)) # normal intersection
return (sx,sy), (ex,ey), pi, cc
return (sx, sy), (ex, ey), ti, ni