mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Fixing typing
Some checks are pending
benchmarks / benchmarks (macos-13, 3.12) (push) Waiting to run
benchmarks / benchmarks (macos-14, 3.12) (push) Waiting to run
benchmarks / benchmarks (ubuntu-latest, 3.12) (push) Waiting to run
benchmarks / benchmarks (windows-latest, 3.12) (push) Waiting to run
Upload coverage reports to Codecov / run (push) Waiting to run
pylint / lint (3.10) (push) Waiting to run
Run type checker / typecheck (3.10) (push) Waiting to run
Run type checker / typecheck (3.13) (push) Waiting to run
Wheel building and publishing / Build wheel on ubuntu-latest (push) Waiting to run
Wheel building and publishing / upload_pypi (push) Blocked by required conditions
tests / tests (macos-13, 3.10) (push) Waiting to run
tests / tests (macos-13, 3.13) (push) Waiting to run
tests / tests (macos-14, 3.10) (push) Waiting to run
tests / tests (macos-14, 3.13) (push) Waiting to run
tests / tests (ubuntu-latest, 3.10) (push) Waiting to run
tests / tests (ubuntu-latest, 3.13) (push) Waiting to run
tests / tests (windows-latest, 3.10) (push) Waiting to run
tests / tests (windows-latest, 3.13) (push) Waiting to run
Some checks are pending
benchmarks / benchmarks (macos-13, 3.12) (push) Waiting to run
benchmarks / benchmarks (macos-14, 3.12) (push) Waiting to run
benchmarks / benchmarks (ubuntu-latest, 3.12) (push) Waiting to run
benchmarks / benchmarks (windows-latest, 3.12) (push) Waiting to run
Upload coverage reports to Codecov / run (push) Waiting to run
pylint / lint (3.10) (push) Waiting to run
Run type checker / typecheck (3.10) (push) Waiting to run
Run type checker / typecheck (3.13) (push) Waiting to run
Wheel building and publishing / Build wheel on ubuntu-latest (push) Waiting to run
Wheel building and publishing / upload_pypi (push) Blocked by required conditions
tests / tests (macos-13, 3.10) (push) Waiting to run
tests / tests (macos-13, 3.13) (push) Waiting to run
tests / tests (macos-14, 3.10) (push) Waiting to run
tests / tests (macos-14, 3.13) (push) Waiting to run
tests / tests (ubuntu-latest, 3.10) (push) Waiting to run
tests / tests (ubuntu-latest, 3.13) (push) Waiting to run
tests / tests (windows-latest, 3.10) (push) Waiting to run
tests / tests (windows-latest, 3.13) (push) Waiting to run
This commit is contained in:
parent
f0f79fccd4
commit
d8f7da348c
3 changed files with 68 additions and 52 deletions
|
|
@ -37,11 +37,12 @@ from OCP.BRep import BRep_Tool
|
||||||
from OCP.BRepAdaptor import BRepAdaptor_Curve
|
from OCP.BRepAdaptor import BRepAdaptor_Curve
|
||||||
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
|
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
|
||||||
from OCP.GCPnts import GCPnts_AbscissaPoint
|
from OCP.GCPnts import GCPnts_AbscissaPoint
|
||||||
from OCP.Geom import Geom_Plane
|
from OCP.Geom import Geom_Curve, Geom_Plane
|
||||||
from OCP.Geom2d import (
|
from OCP.Geom2d import (
|
||||||
Geom2d_CartesianPoint,
|
Geom2d_CartesianPoint,
|
||||||
Geom2d_Circle,
|
Geom2d_Circle,
|
||||||
Geom2d_Curve,
|
Geom2d_Curve,
|
||||||
|
Geom2d_Point,
|
||||||
Geom2d_TrimmedCurve,
|
Geom2d_TrimmedCurve,
|
||||||
)
|
)
|
||||||
from OCP.Geom2dAdaptor import Geom2dAdaptor_Curve
|
from OCP.Geom2dAdaptor import Geom2dAdaptor_Curve
|
||||||
|
|
@ -73,7 +74,7 @@ from OCP.TopoDS import TopoDS_Edge
|
||||||
from build123d.build_enums import Sagitta, Tangency
|
from build123d.build_enums import Sagitta, Tangency
|
||||||
from build123d.geometry import TOLERANCE, Vector, VectorLike
|
from build123d.geometry import TOLERANCE, Vector, VectorLike
|
||||||
from .zero_d import Vertex
|
from .zero_d import Vertex
|
||||||
from .shape_core import ShapeList
|
from .shape_core import ShapeList, downcast
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from build123d.topology.one_d import Edge
|
from build123d.topology.one_d import Edge
|
||||||
|
|
@ -114,7 +115,7 @@ def _forward_delta(u1: float, u2: float, first: float, period: float) -> float:
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
def _edge_to_qualified_2d(
|
def _edge_to_qualified_2d(
|
||||||
edge: TopoDS_Edge, position_constaint: Tangency
|
edge: TopoDS_Edge, position_constaint: Tangency
|
||||||
) -> tuple[Geom2dGcc_QualifiedCurve, Geom2d_Curve, float, float]:
|
) -> tuple[Geom2dGcc_QualifiedCurve, Geom2d_Curve, float, float, Geom2dAdaptor_Curve]:
|
||||||
"""Convert a TopoDS_Edge into 2d curve & extract properties"""
|
"""Convert a TopoDS_Edge into 2d curve & extract properties"""
|
||||||
|
|
||||||
# 1) Underlying curve + range (also retrieve location to be safe)
|
# 1) Underlying curve + range (also retrieve location to be safe)
|
||||||
|
|
@ -128,7 +129,7 @@ def _edge_to_qualified_2d(
|
||||||
# 2) Apply location if the edge is positioned by a TopLoc_Location
|
# 2) Apply location if the edge is positioned by a TopLoc_Location
|
||||||
if not loc.IsIdentity():
|
if not loc.IsIdentity():
|
||||||
trsf = loc.Transformation()
|
trsf = loc.Transformation()
|
||||||
hcurve3d = hcurve3d.Transformed(trsf)
|
hcurve3d = tcast(Geom_Curve, hcurve3d.Transformed(trsf))
|
||||||
|
|
||||||
# 3) Convert to 2D on Plane.XY (Z-up frame at origin)
|
# 3) Convert to 2D on Plane.XY (Z-up frame at origin)
|
||||||
hcurve2d = GeomAPI.To2d_s(hcurve3d, _pln_xy) # -> Handle_Geom2d_Curve
|
hcurve2d = GeomAPI.To2d_s(hcurve3d, _pln_xy) # -> Handle_Geom2d_Curve
|
||||||
|
|
@ -147,13 +148,17 @@ def _edge_from_circle(h2d_circle: Geom2d_Circle, u1: float, u2: float) -> TopoDS
|
||||||
return BRepBuilderAPI_MakeEdge(arc2d, _surf_xy).Edge()
|
return BRepBuilderAPI_MakeEdge(arc2d, _surf_xy).Edge()
|
||||||
|
|
||||||
|
|
||||||
def _param_in_trim(u: float, first: float, last: float, h2d: Geom2d_Curve) -> bool:
|
def _param_in_trim(
|
||||||
|
u: float | None, first: float | None, last: float | None, h2d: Geom2d_Curve | None
|
||||||
|
) -> bool:
|
||||||
"""Normalize (if periodic) then test [first, last] with tolerance."""
|
"""Normalize (if periodic) then test [first, last] with tolerance."""
|
||||||
|
if u is None or first is None or last is None or h2d is None: # for typing
|
||||||
|
raise TypeError("Invalid parameters to _param_in_trim")
|
||||||
u = _norm_on_period(u, first, h2d.Period()) if h2d.IsPeriodic() else u
|
u = _norm_on_period(u, first, h2d.Period()) if h2d.IsPeriodic() else u
|
||||||
return (u >= first - TOLERANCE) and (u <= last + TOLERANCE)
|
return (u >= first - TOLERANCE) and (u <= last + TOLERANCE)
|
||||||
|
|
||||||
|
|
||||||
def _as_gcc_arg(obj: Edge | Vertex | VectorLike, constaint: Tangency) -> tuple[
|
def _as_gcc_arg(obj: Edge | Vector, constaint: Tangency) -> tuple[
|
||||||
Geom2dGcc_QualifiedCurve | Geom2d_CartesianPoint,
|
Geom2dGcc_QualifiedCurve | Geom2d_CartesianPoint,
|
||||||
Geom2d_Curve | None,
|
Geom2d_Curve | None,
|
||||||
float | None,
|
float | None,
|
||||||
|
|
@ -166,16 +171,18 @@ def _as_gcc_arg(obj: Edge | Vertex | VectorLike, constaint: Tangency) -> tuple[
|
||||||
- Edge -> (QualifiedCurve, h2d, first, last, True)
|
- Edge -> (QualifiedCurve, h2d, first, last, True)
|
||||||
- Vertex/VectorLike -> (CartesianPoint, None, None, None, False)
|
- Vertex/VectorLike -> (CartesianPoint, None, None, None, False)
|
||||||
"""
|
"""
|
||||||
|
if obj.wrapped is None:
|
||||||
|
raise TypeError("Can't create a qualified curve from empty edge")
|
||||||
|
|
||||||
if isinstance(obj.wrapped, TopoDS_Edge):
|
if isinstance(obj.wrapped, TopoDS_Edge):
|
||||||
return _edge_to_qualified_2d(obj.wrapped, constaint)[0:4] + (True,)
|
return _edge_to_qualified_2d(obj.wrapped, constaint)[0:4] + (True,)
|
||||||
|
|
||||||
loc_xyz = obj.position if isinstance(obj, Vertex) else Vector()
|
|
||||||
try:
|
try:
|
||||||
base = Vector(obj)
|
base = Vector(obj)
|
||||||
except (TypeError, ValueError) as exc:
|
except (TypeError, ValueError) as exc:
|
||||||
raise ValueError("Expected Edge | Vertex | VectorLike") from exc
|
raise ValueError("Expected Edge | Vertex | VectorLike") from exc
|
||||||
|
|
||||||
gp_pnt = gp_Pnt2d(base.X + loc_xyz.X, base.Y + loc_xyz.Y)
|
gp_pnt = gp_Pnt2d(base.X, base.Y)
|
||||||
return Geom2d_CartesianPoint(gp_pnt), None, None, None, False
|
return Geom2d_CartesianPoint(gp_pnt), None, None, None, False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -230,8 +237,8 @@ def _make_2tan_rad_arcs(
|
||||||
*tangencies: tuple[Edge, Tangency] | Edge | Vector, # 2
|
*tangencies: tuple[Edge, Tangency] | Edge | Vector, # 2
|
||||||
radius: float,
|
radius: float,
|
||||||
sagitta: Sagitta = Sagitta.SHORT,
|
sagitta: Sagitta = Sagitta.SHORT,
|
||||||
edge_factory: Callable[[TopoDS_Edge], TWrap],
|
edge_factory: Callable[[TopoDS_Edge], Edge],
|
||||||
) -> list[Edge]:
|
) -> ShapeList[Edge]:
|
||||||
"""
|
"""
|
||||||
Create all planar circular arcs of a given radius that are tangent/contacting
|
Create all planar circular arcs of a given radius that are tangent/contacting
|
||||||
the two provided objects on the XY plane.
|
the two provided objects on the XY plane.
|
||||||
|
|
@ -261,11 +268,9 @@ def _make_2tan_rad_arcs(
|
||||||
]
|
]
|
||||||
|
|
||||||
# Build inputs for GCC
|
# Build inputs for GCC
|
||||||
q_o, h_e, e_first, e_last, is_edge = [[None] * 2 for _ in range(5)]
|
results = [_as_gcc_arg(*t) for t in tangent_tuples]
|
||||||
for i in range(len(tangent_tuples)):
|
q_o: tuple[Geom2dGcc_QualifiedCurve, Geom2dGcc_QualifiedCurve]
|
||||||
q_o[i], h_e[i], e_first[i], e_last[i], is_edge[i] = _as_gcc_arg(
|
q_o, h_e, e_first, e_last, is_edge = map(tuple, zip(*results))
|
||||||
*tangent_tuples[i]
|
|
||||||
)
|
|
||||||
|
|
||||||
gcc = Geom2dGcc_Circ2d2TanRad(*q_o, radius, TOLERANCE)
|
gcc = Geom2dGcc_Circ2d2TanRad(*q_o, radius, TOLERANCE)
|
||||||
if not gcc.IsDone() or gcc.NbSolutions() == 0:
|
if not gcc.IsDone() or gcc.NbSolutions() == 0:
|
||||||
|
|
@ -280,7 +285,7 @@ def _make_2tan_rad_arcs(
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
# Solutions
|
# Solutions
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
solutions: list[Edge] = []
|
solutions: list[TopoDS_Edge] = []
|
||||||
for i in range(1, gcc.NbSolutions() + 1):
|
for i in range(1, gcc.NbSolutions() + 1):
|
||||||
circ = gcc.ThisSolution(i) # gp_Circ2d
|
circ = gcc.ThisSolution(i) # gp_Circ2d
|
||||||
|
|
||||||
|
|
@ -322,7 +327,7 @@ def _make_2tan_on_arcs(
|
||||||
*tangencies: tuple[Edge, Tangency] | Edge | Vector, # 2
|
*tangencies: tuple[Edge, Tangency] | Edge | Vector, # 2
|
||||||
center_on: Edge,
|
center_on: Edge,
|
||||||
sagitta: Sagitta = Sagitta.SHORT,
|
sagitta: Sagitta = Sagitta.SHORT,
|
||||||
edge_factory: Callable[[TopoDS_Edge], TWrap],
|
edge_factory: Callable[[TopoDS_Edge], Edge],
|
||||||
) -> ShapeList[Edge]:
|
) -> ShapeList[Edge]:
|
||||||
"""
|
"""
|
||||||
Create all planar circular arcs whose circle is tangent to two objects and whose
|
Create all planar circular arcs whose circle is tangent to two objects and whose
|
||||||
|
|
@ -335,29 +340,29 @@ def _make_2tan_on_arcs(
|
||||||
|
|
||||||
# Unpack optional per-edge qualifiers (default UNQUALIFIED)
|
# Unpack optional per-edge qualifiers (default UNQUALIFIED)
|
||||||
tangent_tuples = [
|
tangent_tuples = [
|
||||||
t if isinstance(t, tuple) else (t, Tangency.UNQUALIFIED) for t in tangencies
|
t if isinstance(t, tuple) else (t, Tangency.UNQUALIFIED)
|
||||||
|
for t in list(tangencies) + [center_on]
|
||||||
]
|
]
|
||||||
|
|
||||||
# Build inputs for GCC
|
# Build inputs for GCC
|
||||||
q_o, h_e, e_first, e_last, is_edge = [[None] * 3 for _ in range(5)]
|
results = [_as_gcc_arg(*t) for t in tangent_tuples]
|
||||||
for i in range(len(tangent_tuples)):
|
q_o: tuple[
|
||||||
q_o[i], h_e[i], e_first[i], e_last[i], is_edge[i] = _as_gcc_arg(
|
Geom2dGcc_QualifiedCurve, Geom2dGcc_QualifiedCurve, Geom2dGcc_QualifiedCurve
|
||||||
*tangent_tuples[i]
|
]
|
||||||
)
|
q_o, h_e, e_first, e_last, is_edge = map(tuple, zip(*results))
|
||||||
|
adapt_on = Geom2dAdaptor_Curve(h_e[2], e_first[2], e_last[2])
|
||||||
# Build center locus ("On") input
|
|
||||||
_, h_on2d, e_first[2], e_last[2], adapt_on = _edge_to_qualified_2d(
|
|
||||||
center_on.wrapped, Tangency.UNQUALIFIED
|
|
||||||
)
|
|
||||||
is_edge[2] = True
|
|
||||||
|
|
||||||
# Provide initial middle guess parameters for all of the edges
|
# Provide initial middle guess parameters for all of the edges
|
||||||
guesses = [(e_last[i] - e_first[i]) / 2 + e_first[i] for i in range(len(is_edge))]
|
guesses: tuple[float, float, float] = tuple(
|
||||||
|
[(e_last[i] - e_first[i]) / 2 + e_first[i] for i in range(len(is_edge))]
|
||||||
|
)
|
||||||
|
|
||||||
if sum(is_edge) > 1:
|
if sum(is_edge) > 1:
|
||||||
gcc = Geom2dGcc_Circ2d2TanOn(*q_o[0:2], adapt_on, TOLERANCE, *guesses)
|
gcc = Geom2dGcc_Circ2d2TanOn(q_o[0], q_o[1], adapt_on, TOLERANCE, *guesses)
|
||||||
else:
|
else:
|
||||||
gcc = Geom2dGcc_Circ2d2TanOn(*q_o[0:2], adapt_on, TOLERANCE)
|
assert isinstance(q_o[0], Geom2d_Point)
|
||||||
|
assert isinstance(q_o[1], Geom2d_Point)
|
||||||
|
gcc = Geom2dGcc_Circ2d2TanOn(q_o[0], q_o[1], adapt_on, TOLERANCE)
|
||||||
|
|
||||||
if not gcc.IsDone() or gcc.NbSolutions() == 0:
|
if not gcc.IsDone() or gcc.NbSolutions() == 0:
|
||||||
raise RuntimeError("Unable to find a tangent arc with center_on constraint")
|
raise RuntimeError("Unable to find a tangent arc with center_on constraint")
|
||||||
|
|
@ -391,7 +396,7 @@ def _make_2tan_on_arcs(
|
||||||
center2d = circ.Location() # gp_Pnt2d
|
center2d = circ.Location() # gp_Pnt2d
|
||||||
|
|
||||||
# Project center onto the (trimmed) 2D locus
|
# Project center onto the (trimmed) 2D locus
|
||||||
proj = Geom2dAPI_ProjectPointOnCurve(center2d, h_on2d)
|
proj = Geom2dAPI_ProjectPointOnCurve(center2d, h_e[2])
|
||||||
if proj.NbPoints() == 0:
|
if proj.NbPoints() == 0:
|
||||||
continue # no projection -> reject
|
continue # no projection -> reject
|
||||||
|
|
||||||
|
|
@ -401,7 +406,7 @@ def _make_2tan_on_arcs(
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Respect the trimmed interval (handles periodic curves too)
|
# Respect the trimmed interval (handles periodic curves too)
|
||||||
if not _param_in_trim(u_on, e_first[2], e_last[2], h_on2d):
|
if not _param_in_trim(u_on, e_first[2], e_last[2], h_e[2]):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Build sagitta arc(s) and select by LengthConstraint
|
# Build sagitta arc(s) and select by LengthConstraint
|
||||||
|
|
@ -422,7 +427,7 @@ def _make_2tan_on_arcs(
|
||||||
def _make_3tan_arcs(
|
def _make_3tan_arcs(
|
||||||
*tangencies: tuple[Edge, Tangency] | Edge | Vector, # 3
|
*tangencies: tuple[Edge, Tangency] | Edge | Vector, # 3
|
||||||
sagitta: Sagitta = Sagitta.SHORT,
|
sagitta: Sagitta = Sagitta.SHORT,
|
||||||
edge_factory: Callable[[TopoDS_Edge], TWrap],
|
edge_factory: Callable[[TopoDS_Edge], Edge],
|
||||||
) -> ShapeList[Edge]:
|
) -> ShapeList[Edge]:
|
||||||
"""
|
"""
|
||||||
Create planar circular arc(s) on XY tangent to three provided objects.
|
Create planar circular arc(s) on XY tangent to three provided objects.
|
||||||
|
|
@ -439,14 +444,16 @@ def _make_3tan_arcs(
|
||||||
]
|
]
|
||||||
|
|
||||||
# Build inputs for GCC
|
# Build inputs for GCC
|
||||||
q_o, h_e, e_first, e_last, is_edge = [[None] * 3 for _ in range(5)]
|
results = [_as_gcc_arg(*t) for t in tangent_tuples]
|
||||||
for i in range(len(tangent_tuples)):
|
q_o: tuple[
|
||||||
q_o[i], h_e[i], e_first[i], e_last[i], is_edge[i] = _as_gcc_arg(
|
Geom2dGcc_QualifiedCurve, Geom2dGcc_QualifiedCurve, Geom2dGcc_QualifiedCurve
|
||||||
*tangent_tuples[i]
|
]
|
||||||
)
|
q_o, h_e, e_first, e_last, is_edge = map(tuple, zip(*results))
|
||||||
|
|
||||||
# Provide initial middle guess parameters for all of the edges
|
# Provide initial middle guess parameters for all of the edges
|
||||||
guesses = [(e_last[i] - e_first[i]) / 2 + e_first[i] for i in range(len(is_edge))]
|
guesses: tuple[float, float, float] = tuple(
|
||||||
|
[(e_last[i] - e_first[i]) / 2 + e_first[i] for i in range(len(is_edge))]
|
||||||
|
)
|
||||||
|
|
||||||
# Generate all valid circles tangent to the 3 inputs
|
# Generate all valid circles tangent to the 3 inputs
|
||||||
gcc = Geom2dGcc_Circ2d3Tan(*q_o, TOLERANCE, *guesses)
|
gcc = Geom2dGcc_Circ2d3Tan(*q_o, TOLERANCE, *guesses)
|
||||||
|
|
@ -505,7 +512,7 @@ def _make_tan_cen_arcs(
|
||||||
tangency: tuple[Edge, Tangency] | Edge | Vector,
|
tangency: tuple[Edge, Tangency] | Edge | Vector,
|
||||||
*,
|
*,
|
||||||
center: VectorLike | Vertex,
|
center: VectorLike | Vertex,
|
||||||
edge_factory: Callable[[TopoDS_Edge], TWrap],
|
edge_factory: Callable[[TopoDS_Edge], Edge],
|
||||||
) -> ShapeList[Edge]:
|
) -> ShapeList[Edge]:
|
||||||
"""
|
"""
|
||||||
Create planar circle(s) on XY whose center is fixed and that are tangent/contacting
|
Create planar circle(s) on XY whose center is fixed and that are tangent/contacting
|
||||||
|
|
@ -530,7 +537,7 @@ def _make_tan_cen_arcs(
|
||||||
# Build fixed center (gp_Pnt2d)
|
# Build fixed center (gp_Pnt2d)
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
if isinstance(center, Vertex):
|
if isinstance(center, Vertex):
|
||||||
loc_xyz = center.position
|
loc_xyz = center.position if center.position is not None else Vector(0, 0)
|
||||||
base = Vector(center)
|
base = Vector(center)
|
||||||
c2d = gp_Pnt2d(base.X + loc_xyz.X, base.Y + loc_xyz.Y)
|
c2d = gp_Pnt2d(base.X + loc_xyz.X, base.Y + loc_xyz.Y)
|
||||||
else:
|
else:
|
||||||
|
|
@ -560,6 +567,7 @@ def _make_tan_cen_arcs(
|
||||||
solutions_topo.append(_edge_from_circle(h2d, 0.0, per))
|
solutions_topo.append(_edge_from_circle(h2d, 0.0, per))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
assert isinstance(q_o1, Geom2dGcc_QualifiedCurve)
|
||||||
# Case B: tangency target is a curve/edge (qualified curve)
|
# Case B: tangency target is a curve/edge (qualified curve)
|
||||||
gcc = Geom2dGcc_Circ2dTanCen(q_o1, Geom2d_CartesianPoint(c2d), TOLERANCE)
|
gcc = Geom2dGcc_Circ2dTanCen(q_o1, Geom2d_CartesianPoint(c2d), TOLERANCE)
|
||||||
if not gcc.IsDone() or gcc.NbSolutions() == 0:
|
if not gcc.IsDone() or gcc.NbSolutions() == 0:
|
||||||
|
|
@ -589,7 +597,7 @@ def _make_tan_on_rad_arcs(
|
||||||
*,
|
*,
|
||||||
center_on: Edge,
|
center_on: Edge,
|
||||||
radius: float,
|
radius: float,
|
||||||
edge_factory: Callable[[TopoDS_Edge], TWrap],
|
edge_factory: Callable[[TopoDS_Edge], Edge],
|
||||||
) -> ShapeList[Edge]:
|
) -> ShapeList[Edge]:
|
||||||
"""
|
"""
|
||||||
Create planar circle(s) on XY that:
|
Create planar circle(s) on XY that:
|
||||||
|
|
|
||||||
|
|
@ -1741,7 +1741,7 @@ class Edge(Mixin1D, Shape[TopoDS_Edge]):
|
||||||
tangency_args = [
|
tangency_args = [
|
||||||
t for t in (tangency_one, tangency_two, tangency_three) if t is not None
|
t for t in (tangency_one, tangency_two, tangency_three) if t is not None
|
||||||
]
|
]
|
||||||
tangencies = []
|
tangencies: list[tuple[Edge, Tangency] | Edge | Vector] = []
|
||||||
for tangency_arg in tangency_args:
|
for tangency_arg in tangency_args:
|
||||||
if isinstance(tangency_arg, Edge):
|
if isinstance(tangency_arg, Edge):
|
||||||
tangencies.append(tangency_arg)
|
tangencies.append(tangency_arg)
|
||||||
|
|
@ -1749,18 +1749,18 @@ class Edge(Mixin1D, Shape[TopoDS_Edge]):
|
||||||
if isinstance(tangency_arg, tuple) and isinstance(tangency_arg[0], Edge):
|
if isinstance(tangency_arg, tuple) and isinstance(tangency_arg[0], Edge):
|
||||||
tangencies.append(tangency_arg)
|
tangencies.append(tangency_arg)
|
||||||
continue
|
continue
|
||||||
# if not Edges or constrained Edges convert to Vectors
|
if isinstance(tangency_arg, Vertex):
|
||||||
|
tangencies.append(Vector(tangency_arg) + tangency_arg.position)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# if not Edges, constrained Edges or Vertex convert to Vectors
|
||||||
try:
|
try:
|
||||||
tangencies.append(Vector(tangency_arg))
|
tangencies.append(Vector(tangency_arg))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise TypeError(f"Invalid tangency: {tangency_arg!r}") from exc
|
raise TypeError(f"Invalid tangency: {tangency_arg!r}") from exc
|
||||||
|
|
||||||
# Sort the tangency inputs so points are always last
|
# # Sort the tangency inputs so points are always last
|
||||||
tangent_tuples = [t if isinstance(t, tuple) else (t, None) for t in tangencies]
|
tangencies = sorted(tangencies, key=lambda x: isinstance(x, Vector))
|
||||||
tangent_tuples = sorted(
|
|
||||||
tangent_tuples, key=lambda t: not issubclass(type(t[0]), Edge)
|
|
||||||
)
|
|
||||||
tangencies = [t[0] if t[1] is None else t for t in tangent_tuples]
|
|
||||||
|
|
||||||
tan_count = len(tangencies)
|
tan_count = len(tangencies)
|
||||||
if not (1 <= tan_count <= 3):
|
if not (1 <= tan_count <= 3):
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,14 @@ def test_tan2_rad_arcs_3():
|
||||||
assert len(tan2_rad_edges) == 2
|
assert len(tan2_rad_edges) == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_tan2_rad_arcs_4():
|
||||||
|
"""edge & 1 points & radius"""
|
||||||
|
# the point should be automatically moved after the edge
|
||||||
|
e1 = Line((0, 0), (1, 0))
|
||||||
|
tan2_rad_edges = Edge.make_constrained_arcs((0, 0.5), e1, radius=0.5)
|
||||||
|
assert len(tan2_rad_edges) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_tan2_center_on_1():
|
def test_tan2_center_on_1():
|
||||||
"""2 tangents & center on"""
|
"""2 tangents & center on"""
|
||||||
c1 = PolarLine((0, 0), 4, -20, length_mode=LengthMode.HORIZONTAL)
|
c1 = PolarLine((0, 0), 4, -20, length_mode=LengthMode.HORIZONTAL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue