Compare commits

...

2 Commits

Author SHA1 Message Date
Dogukan Karatas 1ce1c36a51 updated polyline class and tests 2025-03-12 18:22:31 +01:00
Dogukan Karatas 6f56ecb0c0 fix syntax (#392) 2025-03-11 11:40:25 +01:00
3 changed files with 48 additions and 27 deletions
+2 -3
View File
@@ -49,9 +49,8 @@ class Mesh(
if len(self.vertices) % 3 != 0:
raise ValueError(
f"Invalid vertices list: length ({
len(self.vertices)
}) must be a multiple of 3"
f"Invalid vertices list: length {len(self.vertices)} "
f"must be a multiple of 3"
)
return len(self.vertices) // 3
+16 -11
View File
@@ -4,6 +4,7 @@ from typing import List
from specklepy.objects.base import Base
from specklepy.objects.geometry.point import Point
from specklepy.objects.interfaces import ICurve, IHasUnits
from specklepy.objects.models.units import Units
@dataclass(kw_only=True)
@@ -13,24 +14,28 @@ class Polyline(Base, IHasUnits, ICurve, speckle_type="Objects.Geometry.Polyline"
"""
value: List[float]
closed: bool = False
def __repr__(self) -> str:
return f"{self.__class__.__name__}(value: {self.value}, units: {self.units})"
return (
f"{self.__class__.__name__}("
f"value: {self.value}, "
f"closed: {self.closed}, "
f"units: {self.units})"
)
def is_closed(self, tolerance: float = 1e-6) -> bool:
@staticmethod
def is_closed(points: List[float], tolerance: float = 1e-6) -> bool:
"""
check if the polyline is closed (start point equals end point within tolerance)
check if the polyline is closed
"""
if len(self.value) < 6: # need at least 2 points to be closed
if len(points) < 6: # need at least 2 points to be closed
return False
# compare first and last points
start = Point(
x=self.value[0], y=self.value[1], z=self.value[2], units=self.units
)
end = Point(
x=self.value[-3], y=self.value[-2], z=self.value[-1], units=self.units
)
start = Point(x=points[0], y=points[1], z=points[2], units=Units.m)
end = Point(x=points[-3], y=points[-2], z=points[-1], units=Units.m)
return start.distance_to(end) <= tolerance
@property
@@ -46,7 +51,7 @@ class Polyline(Base, IHasUnits, ICurve, speckle_type="Objects.Geometry.Polyline"
total_length = 0.0
for i in range(len(points) - 1):
total_length += points[i].distance_to(points[i + 1])
if self.is_closed() and points:
if self.closed and points:
total_length += points[-1].distance_to(points[0])
return total_length
+30 -13
View File
@@ -54,6 +54,7 @@ def test_polyline_creation(open_square_coords):
polyline = Polyline(value=open_square_coords, units=Units.m)
assert polyline.value == open_square_coords
assert polyline.units == Units.m.value
assert polyline.closed is False
def test_polyline_domain(sample_polyline):
@@ -63,23 +64,31 @@ def test_polyline_domain(sample_polyline):
def test_polyline_is_closed(open_square_coords, closed_square_coords):
open_poly = Polyline(value=open_square_coords, units=Units.m)
closed_poly = Polyline(value=closed_square_coords, units=Units.m)
# Test the static method
assert not Polyline.is_closed(open_square_coords)
assert Polyline.is_closed(closed_square_coords)
assert not open_poly.is_closed()
assert closed_poly.is_closed()
# Test with closed flag
open_poly = Polyline(value=open_square_coords, units=Units.m)
closed_poly = Polyline(value=closed_square_coords, units=Units.m, closed=True)
assert not open_poly.closed
assert closed_poly.closed
def test_polyline_is_closed_with_tolerance(open_square_coords):
almost_closed = open_square_coords + [
0.0,
0.0,
0.001,
] # last point slightly above start
poly = Polyline(value=almost_closed, units=Units.m)
0.001, # last point slightly above start
]
# Test static method with tolerance
assert not Polyline.is_closed(almost_closed, tolerance=1e-6)
assert Polyline.is_closed(almost_closed, tolerance=0.01)
assert not poly.is_closed(tolerance=1e-6)
assert poly.is_closed(tolerance=0.01)
# Also test with instance
poly = Polyline(value=almost_closed, units=Units.m)
# poly.closed should reflect what was passed in construction, not computed
assert not poly.closed
def test_polyline_length_open(sample_polyline):
@@ -88,14 +97,13 @@ def test_polyline_length_open(sample_polyline):
def test_polyline_length_closed(closed_square_coords):
polyline = Polyline(value=closed_square_coords, units=Units.m)
polyline = Polyline(value=closed_square_coords, units=Units.m, closed=True)
polyline.length = polyline.calculate_length()
assert polyline.length == 4.0
def test_polyline_get_points(sample_polyline):
points = sample_polyline.get_points()
assert len(points) == 4
assert all(isinstance(p, Point) for p in points)
assert all(p.units == Units.m.value for p in points)
@@ -125,16 +133,25 @@ def test_polyline_invalid_coordinates():
def test_polyline_units(open_square_coords):
polyline = Polyline(value=open_square_coords, units=Units.m)
assert polyline.units == Units.m.value
polyline.units = "mm"
assert polyline.units == "mm"
def test_polyline_closed_flag(open_square_coords, closed_square_coords):
# Test default value
poly1 = Polyline(value=open_square_coords, units=Units.m)
assert poly1.closed is False
# Test explicit value
poly2 = Polyline(value=closed_square_coords, units=Units.m, closed=True)
assert poly2.closed is True
def test_polyline_serialization(sample_polyline):
serialized = serialize(sample_polyline)
deserialized = deserialize(serialized)
assert deserialized.value == sample_polyline.value
assert deserialized.units == sample_polyline.units
assert deserialized.domain.start == sample_polyline.domain.start
assert deserialized.domain.end == sample_polyline.domain.end
assert deserialized.closed == sample_polyline.closed