[Arc] fix arc mirroring

This commit is contained in:
Jan Petykiewicz 2026-09-14 21:52:18 -07:00
commit ac61b8bab7
3 changed files with 21 additions and 6 deletions

View file

@ -423,11 +423,10 @@ class Arc(PositionableImpl, Shape):
return self return self
def mirror(self, axis: int = 0) -> 'Arc': def mirror(self, axis: int = 0) -> 'Arc':
if self.angle_ref != ArcAngleRef.Center: # Both external reflections use a local Y reflection; the extra pi
x_major = self.radius_x > self.radius_y # rotation below accounts for the external axis.
y_major = self.radius_y > self.radius_x if self.angle_ref != ArcAngleRef.Center and self.radius_y > self.radius_x:
if (axis == 0 and y_major) or (axis == 1 and x_major): self._swap_focus_ref()
self._swap_focus_ref()
self.rotation *= -1 self.rotation *= -1
self.rotation += axis * pi self.rotation += axis * pi
self.angles *= -1 self.angles *= -1

View file

@ -14,6 +14,21 @@ def test_arc_init() -> None:
assert_equal(a.angles, [0, pi / 2]) assert_equal(a.angles, [0, pi / 2])
assert a.width == 2 assert a.width == 2
@pytest.mark.parametrize('axis', [0, 1])
@pytest.mark.parametrize('radii', [(10, 6), (6, 10), (10, 10)])
@pytest.mark.parametrize('angle_ref', list(Arc.AngleRef))
@pytest.mark.parametrize('rotation', [0, pi / 5])
def test_arc_reflection_preserves_caps_and_bounds(axis: int, radii: tuple, angle_ref: Arc.AngleRef, rotation: float) -> None:
arc = Arc(radii=radii, angles=(-0.3, 1.1), width=1, angle_ref=angle_ref, rotation=rotation)
reflected = arc.deepcopy().mirror(axis)
signs = numpy.ones(2)
signs[1 - axis] = -1
assert_allclose(reflected.get_cap_edges(), arc.get_cap_edges() * signs, atol=1e-12)
expected = arc.get_bounds_single() * signs
assert_allclose(reflected.get_bounds_single(), numpy.sort(expected, axis=0), atol=1e-12)
assert_allclose(reflected.mirror(axis).get_cap_edges(), arc.get_cap_edges(), atol=1e-12)
def test_arc_to_polygons() -> None: def test_arc_to_polygons() -> None:
a = Arc(radii=(10, 10), angles=(0, pi / 2), width=2) a = Arc(radii=(10, 10), angles=(0, pi / 2), width=2)
polys = a.to_polygons(num_vertices=32) polys = a.to_polygons(num_vertices=32)

View file

@ -17,7 +17,8 @@ def test_shape_mirror() -> None:
a = Arc(radii=(10, 5), angles=(0, pi / 4), width=2, angle_ref=Arc.AngleRef.FocusPos) a = Arc(radii=(10, 5), angles=(0, pi / 4), width=2, angle_ref=Arc.AngleRef.FocusPos)
a.mirror(1) a.mirror(1)
assert a.angle_ref == Arc.AngleRef.FocusNeg # The pi rotation already reflects the X-major focus across the Y axis.
assert a.angle_ref == Arc.AngleRef.FocusPos
a = Arc(radii=(5, 10), angles=(0, pi / 4), width=2, angle_ref=Arc.AngleRef.FocusPos) a = Arc(radii=(5, 10), angles=(0, pi / 4), width=2, angle_ref=Arc.AngleRef.FocusPos)
a.mirror(0) a.mirror(0)