Adding tests for positions with deflection

This commit is contained in:
gumyr 2025-11-25 11:27:17 -05:00
parent 7f6d44249b
commit 2d82b2ca5c
2 changed files with 69 additions and 3 deletions

View file

@ -373,7 +373,10 @@ class Mixin1D(Shape[TOPODS]):
def _to_param(edge_wire: Mixin1D, value: float | VectorLike, name: str) -> float:
"""Convert a float or VectorLike into a curve parameter."""
if isinstance(value, (int, float)):
return float(value)
if edge_wire.is_forward:
return float(value)
else:
return 1.0 - float(value)
try:
point = Vector(value)
except TypeError as exc:
@ -1209,7 +1212,9 @@ class Mixin1D(Shape[TOPODS]):
curve: BRepAdaptor_Curve | BRepAdaptor_CompCurve = self.geom_adaptor()
# GCPnts_UniformDeflection provides the best results but is limited
if curve.Continuity() in (GeomAbs_C2, GeomAbs_C3, GeomAbs_CN):
discretizer = GCPnts_UniformDeflection()
discretizer: (
GCPnts_UniformDeflection | GCPnts_QuasiUniformDeflection
) = GCPnts_UniformDeflection()
else:
discretizer = GCPnts_QuasiUniformDeflection()

View file

@ -28,6 +28,7 @@ license:
import math
import unittest
from unittest.mock import patch
from build123d.build_enums import (
CenterOf,
@ -106,13 +107,73 @@ class TestMixin1D(unittest.TestCase):
5,
)
def test_positions(self):
def test_positions_with_distances(self):
e = Edge.make_line((0, 0, 0), (1, 1, 1))
distances = [i / 4 for i in range(3)]
pts = e.positions(distances)
for i, position in enumerate(pts):
self.assertAlmostEqual(position, (i / 4, i / 4, i / 4), 5)
def test_positions_deflection_line(self):
"""Deflection sampling on a straight line should yield exactly 2 points."""
e = Edge.make_line((0, 0, 0), (10, 0, 0))
pts = e.positions(deflection=0.1)
self.assertEqual(len(pts), 2)
self.assertAlmostEqual(pts[0], (0, 0, 0), 7)
self.assertAlmostEqual(pts[1], (10, 0, 0), 7)
def test_positions_deflection_circle(self):
"""Deflection on a C2 curve (circle) should produce multiple points."""
radius = 5
e = Edge.make_circle(radius)
pts = e.positions(deflection=0.1)
# Should produce more than just two points
self.assertGreater(len(pts), 2)
# Endpoints should match curve endpoints
first, last = pts[0], pts[-1]
curve = e.geom_adaptor()
p0 = Vector(curve.Value(curve.FirstParameter()))
p1 = Vector(curve.Value(curve.LastParameter()))
self.assertAlmostEqual(first, p0, 7)
self.assertAlmostEqual(last, p1, 7)
def test_positions_deflection_resolution(self):
"""Smaller deflection tolerance should produce more points."""
e = Edge.make_circle(10)
pts_coarse = e.positions(deflection=0.5)
pts_fine = e.positions(deflection=0.05)
self.assertGreater(len(pts_fine), len(pts_coarse))
def test_positions_deflection_C0_curve(self):
"""C0 spline should use QuasiUniformDeflection and still succeed."""
e = Polyline((0, 0), (1, 2), (2, 0))._to_bspline() # C0
pts = e.positions(deflection=0.1)
self.assertGreater(len(pts), 2)
def test_positions_missing_arguments(self):
e = Edge.make_line((0, 0, 0), (1, 0, 0))
with self.assertRaises(ValueError):
e.positions()
def test_positions_deflection_failure(self):
e = Edge.make_circle(1.0)
with patch("build123d.edge.GCPnts_UniformDeflection") as MockDefl:
instance = MockDefl.return_value
instance.IsDone.return_value = False
instance.NbPoints.return_value = 0
with self.assertRaises(RuntimeError):
e.positions(deflection=0.1)
def test_tangent_at(self):
self.assertAlmostEqual(
Edge.make_circle(1, start_angle=0, end_angle=90).tangent_at(1.0),