ArcArcTangentArc: correct arc in situation where RadiusArc places center on incorrect side to resolve #983

This commit is contained in:
Jonathan Wagenet 2025-05-28 14:43:30 -04:00
parent da6b3ae005
commit 87048fabc4
2 changed files with 18 additions and 5 deletions

View file

@ -32,7 +32,7 @@ import copy as copy_module
from collections.abc import Iterable
from math import copysign, cos, radians, sin, sqrt
from scipy.optimize import minimize
import sympy # type: ignore
import sympy # type: ignore
from build123d.build_common import WorkplaneList, flatten_sequence, validate_inputs
from build123d.build_enums import (
@ -456,7 +456,7 @@ class Helix(BaseEdgeObject):
defined by cone_angle.
If cone_angle is not 0, radius is the initial helix radius at center. cone_angle > 0
increases the final radius. cone_angle < 0 decreases the final radius.
increases the final radius. cone_angle < 0 decreases the final radius.
Args:
pitch (float): distance between loops
@ -1095,9 +1095,7 @@ class PointArcTangentLine(BaseEdgeObject):
tangent_point = WorkplaneList.localize(point)
if context is None:
# Making the plane validates points and arc are coplanar
coplane = Edge.make_line(tangent_point, arc.arc_center).common_plane(
arc
)
coplane = Edge.make_line(tangent_point, arc.arc_center).common_plane(arc)
if coplane is None:
raise ValueError("PointArcTangentLine only works on a single plane.")
@ -1478,4 +1476,10 @@ class ArcArcTangentArc(BaseEdgeObject):
intersect.reverse()
arc = RadiusArc(intersect[0], intersect[1], radius=radius)
# Check and flip arc if not tangent
_, _, point = start_arc.distance_to_with_closest_points(arc)
if start_arc.tangent_at(point).cross(arc.tangent_at(point)).length > TOLERANCE:
arc = RadiusArc(intersect[0], intersect[1], radius=-radius)
super().__init__(arc, mode)

View file

@ -729,6 +729,15 @@ class BuildLineTests(unittest.TestCase):
self.assertGreater(side_sign * coincident_dir, 0)
self.assertGreater(center_dir, 0)
# Verify arc is tangent for a reversed start arc
c1 = CenterArc((0, 80), 40, 0, -180)
c2 = CenterArc((80, 0), 40, 90, 180)
arc = ArcArcTangentArc(c1, c2, 25, side=Side.RIGHT)
_, _, point = c1.distance_to_with_closest_points(arc)
self.assertAlmostEqual(
c1.tangent_at(point).cross(arc.tangent_at(point)).length, 0, 5
)
## Error Handling
start_arc = CenterArc(start_point, start_r, 0, 360)
end_arc = CenterArc(end_point, end_r, 0, 360)