
    ^j                   B   d Z ddlmZ ddlZddlZddlmZmZm	Z	 ddl
mZ ddlmZmZmZmZmZmZmZ ddlmZmZ ddlZddlZddlmZ dd	lmZ dd
lmZm Z m!Z! ddl"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6m7Z7m8Z8m9Z9m:Z: ddl;m<Z<m=Z= dSdZ> G d de6      Z? G d de:      Z@ G d de7      ZA G d de@      ZB G d deA      ZC G d deA      ZD G d deA      ZE G d d eA      ZF G d! d"e?      ZG G d# d$e?      ZH G d% d&eA      ZI G d' d(eA      ZJ G d) d*eA      ZK G d+ d,eA      ZL G d- d.eA      ZM G d/ d0eA      ZN G d1 d2e@      ZO G d3 d4eA      ZP G d5 d6eA      ZQ G d7 d8eA      ZR G d9 d:eA      ZS G d; d<e@      ZT G d= d>eA      ZU G d? d@eA      ZV G dA dBeA      ZW G dC dDeA      ZX G dE dFeA      ZY edG       G dH dIeA             ZZ edJ       G dK dLeA             Z[ edM       G dN dOeA             Z\ edP       G dQ dReA             Z]y)Ta  
Curve Objects

name: objects_curve.py
by:   Gumyr
date: March 22nd 2023

desc:
    This python module contains objects (classes) that create 1D Curves.

license:

    Copyright 2023 Gumyr

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    )annotationsN)CallableIterableSequence)product)atan2copysigncosdegreesradianssinsqrt)Literaloverload)minimize)
deprecated)WorkplaneListflatten_sequencevalidate_inputs)	AngularDirectionContinuityLevelGeomTypeKeep
LengthModeModeSagittaSideTangency)	BuildLine)	TOLERANCEAxisLocationPlaneVector
VectorLike)CurveEdgeFaceVertexWire)Shape	ShapeListc                   t        j                  d      }|mt        |t               r\t        | t              r|j	                  | |       yt        | t
        t        f      r! |j                  | j                         d|i yyyy)zHelper function to add a curve to the context.

    Args:
        curve (Edge | Wire | Curve): curve to add to the context (either a Wire or an Edge)
        mode (Mode): combination mode
    F)logNmoder0   )r   _get_context
isinstancer'   _add_to_contextr&   r*   edges)curver0   contexts      P/opt/ringagent/.cad-venv/lib/python3.12/site-packages/build123d/objects_curve.py_add_curve_to_contextr8   =   sv     !* 6 65 AGz'9=eT"##E#5t}-#G##U[[]>> .  >    c                  V     e Zd ZdZej
                  gZej                  fd fdZ	 xZ
S )BaseCurveObjectzBaseCurveObject specialized for Curve.

    Args:
        curve (Wire): wire to create
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c                j    t        ||       |j                  t        |   |j                         y y Nr8   wrappedsuper__init__selfr5   r0   	__class__s      r7   rA   zBaseCurveObject.__init__W   -    eT*==$GU]]+ %r9   )r5   r&   r0   r   __name__
__module____qualname____doc__r   _tag_applies_tor   ADDrA   __classcell__rD   s   @r7   r;   r;   M   s'     >>"K26(( , ,r9   r;   c                  V     e Zd ZdZej
                  gZej                  fd fdZ	 xZ
S )BaseLineObjectzBaseLineObject specialized for Wire.

    Args:
        curve (Wire): wire to create
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c                j    t        ||       |j                  t        |   |j                         y y r=   r>   rB   s      r7   rA   zBaseLineObject.__init__h   rE   r9   )r5   r*   r0   r   rF   rO   s   @r7   rQ   rQ   ^   s'     >>"K15 , ,r9   rQ   c                  V     e Zd ZdZej
                  gZej                  fd fdZ	 xZ
S )BaseEdgeObjectzBaseEdgeObject specialized for Edge.

    Args:
        curve (Edge): edge to create
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c                P    t        ||       t        | 	  |j                         y r=   )r8   r@   rA   r?   rB   s      r7   rA   zBaseEdgeObject.__init__y   s    eT*'r9   )r5   r'   r0   r   rF   rO   s   @r7   rT   rT   o   s'     >>"K15 ( (r9   rT   c                       e Zd ZdZej
                  gZedd       Zdde	j                  f	 	 	 	 	 	 	 d fdZed	d       Z xZS )
Airfoila3  
    Create an airfoil described by a 4-digit (or fractional) NACA airfoil
    (e.g. '2412' or '2213.323').

    The NACA four-digit wing sections define the airfoil_code by:
    - First digit describing maximum camber as percentage of the chord.
    - Second digit describing the distance of maximum camber from the airfoil leading edge
    in tenths of the chord.
    - Last two digits describing maximum thickness of the airfoil as percent of the chord.

    Args:
        airfoil_code : str
            The NACA 4-digit (or fractional) airfoil code (e.g. '2213.323').
        n_points : int
            Number of points per upper/lower surface.
        finite_te : bool
            If True, enforces a finite trailing edge (default False).
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    c                |   t        |       j                  dd      j                         }d|v rX|j                  dd      \  }}t	        |d         dz  }t	        |d         dz  }t        t	        |dd	       d
d|       dz  }n3t	        |d         dz  }t	        |d         dz  }t	        |dd	       dz  }|||fS )zR
        Parse NACA 4-digit (or fractional) airfoil code into parameters.
        NACA .   r   d   
      N02)strreplacestripsplitintfloat)valuesint_part	frac_partmpts          r7   parse_naca4zAirfoil.parse_naca4   s    
 Jvr*002!8"#''#q/HiHQK 3&AHQK 2%AXab\*2.a	{;<sBAAaD	CAAaD	BAAabE
S A!Qwr9   2   Fc                   t        j                  |       }t        ||        t        j	                  |      \  }}}t        j                  dt
        j                  |      }	dt        j                  |	      z
  dz  }
d\  }}}}|rdnd}d|z  |t        j                  |
      z  ||
z  z   ||
dz  z  z   ||
dz  z  z   ||
d	z  z  z   z  }|d
k(  s
|d
k(  s|dk(  r+t        j                  |
      }t        j                  |
      }nt        j                  |
      }t        j                  |
      }|
|k  }||dz  z  d|z  |
|   z  |
|   dz  z
  z  ||<   |d|z
  dz  z  dd|z  z
  d|z  |
|    z  z   |
|    dz  z
  z  || <   d|z  |dz  z  ||
|   z
  z  ||<   d|z  d|z
  dz  z  ||
|    z
  z  || <   t        j                  |      }t        |
|      D cg c]  \  }}t        ||       c}}| _        |
|t        j                   |      z  z
  }||t        j                  |      z  z   }|
|t        j                   |      z  z   }||t        j                  |      z  z
  }t        ||      D 
cg c]  \  }
}t        |
|       }}
}t        ||      D 
cg c]  \  }
}t        |
|       }}
}t#        t$        j'                  |d d d   |z               }t)        j*                  ||       }|r*t)        j,                  |d
z  |dz        } t/        || g      }!nt/        |g      }!t0        "| e  |!|       || _        || _        || _        || _        || _        y c c}}w c c}}
w c c}}
w )N        r\   r_   )gqh ?gT㥛 gQIֿg-1?gClgݓ         r   )periodicr/   )r   r1   r   rW   rn   nplinspacepir
   r   
zeros_like
empty_likearctanzipr$   _camber_pointsr   listdictfromkeysr'   make_spline	make_liner*   r@   rA   code
max_camber
camber_pos	thickness	finite_te)#rC   airfoil_coden_pointsr   r0   r6   rk   rl   rm   betaxa0a1a2a3a4ytycdyc_dxmaskthetaxiyixuyuxlyly
upper_pnts
lower_pntsunique_pointssurfacetrailing_edgeairfoil_profilerD   s#                                     r7   rA   zAirfoil.__init__   sr   " %.$:$:4$@&%%l31a {{3x0" :BB!WwUb2771:oQ.ad:R!Q$YFaQRdRS 6Q!VqAvq!B]]1%Fq!B]]1%Fq5D1a4x1q51T7?QtW\#ABBtHQUqL QQY!a%!TE(2B$BQuXQR]$RS uI q51a4<1qw;7F4LEQUqL0A4%LAFD5M		&!<?2JG&"bvb"~G bffUm##"rvve}$$bffUm##"rvve}$$/22r{;tq!fQl;
;/22r{;tq!fQl;
; z$B$/*<=> 	 ""=y=I NN7Q;!DM"G]#;<O"G9oOt4 &	!"!" !(7 H <;s   M1M$M*c                @    t        j                  | j                        S )z&Camber line of the airfoil as an Edge.)r'   r   r~   )rC   s    r7   camber_linezAirfoil.camber_line   s      3 344r9   )rg   zstr | floatreturnztuple[float, float, float])r   ra   r   re   r   boolr0   r   )r   r'   )rG   rH   rI   rJ   r   rK   rL   staticmethodrn   r   rM   rA   propertyr   rN   rO   s   @r7   rW   rW      s|    * >>"K & XXJ)J) J) 	J)
 J)X 5 5r9   rW   c                  d     e Zd ZdZej
                  gZdej                  d	 	 	 	 	 d fdZ	 xZ
S )Beziera  Line Object: Bezier Curve

    Create a non-rational bezier curve defined by a sequence of points and include optional
    weights to create a rational bezier curve. The number of weights must match the number
    of control points.

    Args:
        cntl_pnts (sequence[VectorLike]): points defining the curve
        weights (list[float], optional): control point weights. Defaults to None
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    N)weightsr0   c                   t        j                  |       }t        ||        t        | }t	        j
                  | }t        j                  |d|i}t        | %  ||       y )Nr   r/   )
r   r1   r   r   r   localizer'   make_bezierr@   rA   )	rC   r   r0   	cntl_pntsr6   cntl_pnt_listpollsr5   rD   s	           r7   rA   zBezier.__init__	  s`     %.$:$:4$@&()4&&6  %99T*r9   )r   r%   r   zlist[float] | Noner0   r   rF   rO   s   @r7   r   r      sH    
 >>"K
 '+XX	++ $+ 	+ +r9   r   c                  l     e Zd ZdZej
                  ddej                  f	 	 	 	 	 	 	 	 	 	 	 d fdZ xZ	S )
BlendCurveuN  Line Object: BlendCurve

    Create a smooth Bézier-based transition curve between two existing edges.

    The blend is constructed as a cubic (C1) or quintic (C2) Bézier curve
    whose control points are determined from the position, first derivative,
    and (for C2) second derivative of the input curves at the chosen endpoints.
    Optional scalar multipliers can be applied to the endpoint tangents to
    control the "tension" of the blend.

    Args:
        curve0 (Edge): First curve to blend from.
        curve1 (Edge): Second curve to blend to.
        continuity (ContinuityLevel, optional):
            Desired geometric continuity at the join:
            - ContinuityLevel.C0: position match only (straight line)
            - ContinuityLevel.C1: match position and tangent direction (cubic Bézier)
            - ContinuityLevel.C2: match position, tangent, and curvature (quintic Bézier)
            Defaults to ContinuityLevel.C2.
        end_points (tuple[VectorLike, VectorLike] | None, optional):
            Pair of points specifying the connection points on `curve0` and `curve1`.
            Each must coincide (within TOLERANCE) with the start or end of the
            respective curve. If None, the closest pair of endpoints is chosen.
            Defaults to None.
        tangent_scalars (tuple[float, float] | None, optional):
            Scalar multipliers applied to the first derivatives at the start
            of `curve0` and the end of `curve1` before computing control points.
            Useful for adjusting the pull/tension of the blend without altering
            the base curves. Defaults to (1.0, 1.0).
        mode (Mode, optional): Boolean operation mode when used in a
            BuildLine context. Defaults to Mode.ADD.

    Raises:
        ValueError: `tangent_scalars` must be a pair of float values.
        ValueError: If specified `end_points` are not coincident with the start
            or end of their respective curves.

    Example:
        >>> blend = BlendCurve(curve_a, curve_b, ContinuityLevel.C1, tangent_scalars=(1.2, 0.8))
        >>> show(blend)
    Nc                .   |dn|}t        |      dk7  rt        d      |4t        t        |j	                         |j	                               d       n|}||f}	ddg}
t        |      D ]z  \  }}|	|   j                  d      }|	|   j                  d      }t        |      }||z
  j                  t        k  rd|
|<   U||z
  j                  t        k  rd|
|<   qt        d       |j                  |
d         }|j                  |
d         }|j                  |
d   d      |d   z  }|j                  |
d   d      |d   z  }|t        j                  k(  rt        ||      }n|t        j                  k(  r||d	z  z   }||d	z  z
  }||||g}t        | }nl|j                  |
d   d      }|j                  |
d   d      }||d
z  z   }|d|z  d
z  z   |dz  z   }||d
z  z
  }|d|z  d
z  z
  |dz  z   }||||||g}t        | }t         | E  ||       y )N)      ?r   r_   z+tangent_scalars must be a (start, end) pairc                0    | d   j                  | d         S )Nr   r\   )distance_to)pairs    r7   <lambda>z%BlendCurve.__init__.<locals>.<lambda>X  s    a!4!4T!W!= r9   keyr   r\   z8end_points must be at either the start or end of a curvers   rr      r/   )len
ValueErrorminr   vertices	enumerateposition_atr$   lengthr    derivative_atr   C0LineC1r   r@   rA   )rC   curve0curve1
continuity
end_pointstangent_scalarsr0   tan_scalarsend_pntscurves
end_paramsiend_pntcurve_start_pntcurve_end_pntgiven_end_pnt	start_posend_posstart_deriv	end_derivjoining_curve	cntl_pnt1	cntl_pnt4r   
start_curvend_curv	cntl_pnt2	cntl_pnt3rD   s                               r7   rA   zBlendCurve.__init__D  s    %4$;j{q JKK !	 )6??+<==
  	 &,V$4V
#H- 	JAw$Qi33A6O"1I11!4M"7OM/77)C !
1-/77)C !
1 N 	n &&z!}5	$$Z]3
 **:a=!<{1~M((A:[^K	+++ G4M?---!K!O3I)a-/I"Iy'BI"I.M--jmQ?J++JqM1=H!K!O3I!Q_$99JOKI)a-/I1y=A"552EII #I.MT2r9   )r   r'   r   r'   r   r   r   z$tuple[VectorLike, VectorLike] | Noner   ztuple[float, float] | Noner0   r   )
rG   rH   rI   rJ   r   C2r   rM   rA   rN   rO   s   @r7   r   r     sm    (\ '6&8&8;?6:XXu3u3 u3 $	u3
 9u3 4u3 u3 u3r9   r   c                  V     e Zd ZdZddej
                  f	 	 	 	 	 	 	 	 	 	 	 d fdZ xZS )BSplineaW  Line Object: BSpline

    An exact B-spline edge defined directly from control points and knot data.

    BSpline creates an exact B-spline from control points, a knot sequence, and
    optional weights. Control points define the control polygon that pulls the curve,
    but the curve does not generally pass through them. Knots define the parameter-space
    structure of the spline: they determine where polynomial spans begin and
    end and how smoothly those spans join. Repeated knot values indicate knot multiplicity.
    For a spline of degree p, a knot with multiplicity m has continuity
    C^(p-m) at that location, so increasing multiplicity reduces smoothness. Repeating the
    first and last knots degree + 1 times creates a clamped spline that
    starts and ends at the first and last control points. Optional weights create a
    rational B-spline, allowing some control points to pull more strongly than
    others and enabling exact representation of conic sections.`

    Unlike :class:`~build123d.objects_curve.Spline`, which creates an interpolated curve
    through a set of points using ``GeomAPI_Interpolate``, ``BSpline`` preserves
    the supplied spline definition by building the underlying OCCT
    ``Geom_BSplineCurve`` from its poles, knot vector, optional weights,
    degree, and periodic flag.

    Args:
        control_points (Iterable[VectorLike]): Control points (poles) defining the
            spline shape. These are not generally points on the curve.
        knots (Iterable[float]): Knot sequence for the spline. Repeated knot
            values are allowed and are converted internally into unique knot
            values plus multiplicities as required by OCCT.
        degree (int): Polynomial degree of the spline.
        weights (Iterable[float] | None, optional): Optional per-control-point
            weights for rational B-splines. If omitted, the spline is
            non-rational.
        periodic (bool, optional): Whether to create a periodic spline. Defaults
            to ``False``.
        mode (Mode, optional): Builder combination mode. Defaults to ``Mode.ADD``.

    NFc                    t        j                  |       }t        ||        t        j                  t        j                  | ||||      }t        	| !  ||       y )N)r   rv   r/   )	r   r1   r   r'   make_bspliner   r   r@   rA   )
rC   control_pointsknotsdegreer   rv   r0   r6   splinerD   s
            r7   rA   zBSpline.__init__  s]     %.$:$:4$@&""""N3
 	d+r9   )r   zIterable[VectorLike]r   zIterable[float]r   re   r   Iterable[float] | Nonerv   r   r0   r   )rG   rH   rI   rJ   r   rM   rA   rN   rO   s   @r7   r   r     s\    $V +/XX,,, , 	,
 (, , , ,r9   r   c                  l     e Zd ZdZej
                  gZej                  f	 	 	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )	CenterArcus  Line Object: Center Arc

    Create a circular arc defined by a center point and radius.

    Args:
        center (VectorLike): center point of arc
        radius (float): arc radius
        start_angle (float): arc starting angle from x-axis
        arc_size (float | Shape | Axis | Location | Plane | VectorLike): angular size
            of arc or an arc limit.

            When a limit object is provided instead of a numeric angular size, CenterArc
            constructs the valid arc(s) from the given start point, trims them at their
            first intersection with the limit, and returns the one requiring the shortest
            travel from the start. Therefore, one can only generate arcs < 180° using a limit.
            If neither valid arc intersects the limit, a ValueError is raised.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c                ,   t        j                  |       }t        ||        t        j                  |      }|t
        j                  }n4t        j                  t        j                         j                  d         }||_
        t        |t              rt        |      n|}	t        |	t        t        f      rV|	dkD  rt         j"                  nt         j$                  }
|	dz   dz  }||z   }|dk(  r|n|}t'        j(                  |||||
      }n|j*                  j-                  t/        d|j0                        |      |z  }t        j                  |      }||_
        ||_        t'        j(                  ||      }|j3                  d      }|j5                  |	      }|j5                  |	      }||t7        d|       t9        ||fD cg c]  }||	 c}      j;                  t&        j<                        d   }t>        |   ||       y c c}w )	Nr   g     v@)start_angle	end_angleangular_directionr   r   r   Treconstructz&CenterArc doesn't intersect arc limit r/   )!r   r1   r   r   r   r#   XYcopy_modulecopy
workplanesoriginr2   r   r$   re   rf   r   COUNTER_CLOCKWISE	CLOCKWISEr'   make_circlex_dirrotater!   z_dirreversedtrim_to_otherr   r,   sort_byr   r@   rA   )rC   centerradiusr   arc_sizer0   r6   center_pointcircle_workplane
arc_factorarc_directionnormalized_arc_sizer   arcstart_radius_vectorcircle_planearc2trimmed_arctrimmed_arc2arD   s                       r7   rA   zCenterArc.__init__  s    %.$:$:4$@&$--f5?$xx*//**,77:  #/)3Hh)GVH%X
j3,/ > !22%// 
 $.#5">#&99I':e'C)K"" '#"/C !&&--$4$:$:;[    '++,<=L".L!4L""6<8C<<D<1D++J7K--j9L"|'; #I(!TUU(,7Iq1=Igdkk"1&C 	4( Js   HH)r  r%   r  rf   r   rf   r  4float | Shape | Axis | Location | Plane | VectorLiker0   r   r   NonerF   rO   s   @r7   r   r     sl    & >>"K XX@)@) @) 	@)
 G@) @) 
@) @)r9   r   c                      e Zd ZdZej
                  gZeej                  d e
j                  d	 	 	 	 	 	 	 	 	 	 	 dd       Zeej                  d e
j                  d	 	 	 	 	 	 	 	 	 	 	 dd       Zeej                  d e
j                  d	 	 	 	 	 	 	 	 	 	 	 dd       Zed	 e
j                  d
	 	 	 	 	 	 	 dd       Zed e
j                  d
	 	 	 	 	 	 	 	 	 dd       Z fdZ xZS )ConstrainedArcsa  Line Object: Arc(s) constrained by other geometric objects.

    The result is always a Curve containing one or more Edges. If you need
    to access Edge-specific properties or methods (such as ``arc_center``),
    extract the edge or edges first::

        result = ConstrainedArcs(...)
        arc = result.edge()           # extract the Edge
        center = arc.arc_center       # now Edge methods are available

    Note that in Builder mode the ``selector`` parameter must be provided or
    all results will be combined into the BuildLine context. In Algebra mode
    the selector can be applied as a parameter or in the normal way to the
    ConstrainedArcs object. The content of the selector is the same in both cases.

    Examples:
        An arc built from three edge constraints.

        Algebra::

            l4 = PolarLine((0, 0), 4, 60)
            l5 = PolarLine((0, 0), 4, 40)
            a3 = CenterArc((0, 0), 4, 0, 90)
            ex_a3 = (
                ConstrainedArcs(l4, l5, a3, sagitta=Sagitta.BOTH).edges().sort_by(Edge.length)[0]
            )

        Builder::

            with BuildLine() as arc_ex3:
                l4 = PolarLine((0, 0), 4, 60)
                l5 = PolarLine((0, 0), 4, 40)
                a3 = CenterArc((0, 0), 4, 0, 90)
                ex_a3 = ConstrainedArcs(
                    l4,
                    l5,
                    a3,
                    sagitta=Sagitta.BOTH,
                    selector=lambda arcs: arcs.sort_by(Edge.length)[0],
                )

    c                    | S r=    arcss    r7   r   zConstrainedArcs.<lambda>       r9   )sagittaselectorr0   c                    y)a5  
        Create all planar circular arcs of a given radius that are tangent/contacting
        the two provided objects on the XY plane.

        Args:
            tangency_one, tangency_two
                (tuple[Axis | Edge, PositionConstraint] | Axis | Edge | Vertex | VectorLike):
                Geometric entities to be contacted/touched by the circle(s)
            radius (float): arc radius
            sagitta (LengthConstraint, optional): returned arc selector
                (i.e. either the short, long or both arcs). Defaults to
                LengthConstraint.SHORT.
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda arcs: arcs.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            Accept all results (default behaviour)::

                a1 = CenterArc((-5, 0), 4, 0, 360)
                a2 = CenterArc((5, 0), 3, 0, 360)
                arcs = ConstrainedArcs(a1, a2, radius=10, selector=lambda arcs: arcs)
        Nr  )rC   tangency_onetangency_twor  r  r  r0   s          r7   rA   zConstrainedArcs.__init__      r9   c                    | S r=   r  r  s    r7   r   zConstrainedArcs.<lambda>  r  r9   c                    y)a  
        Create all planar circular arcs whose circle is tangent to two objects and whose
        CENTER lies on a given locus (line/circle/curve) on the XY plane.

        Args:
            tangency_one, tangency_two
                (tuple[Axis | Edge, PositionConstraint] | Axis | Edge | Vertex | VectorLike):
                Geometric entities to be contacted/touched by the circle(s)
            center_on (Axis | Edge): center must lie on this object
            sagitta (LengthConstraint, optional): returned arc selector
                (i.e. either the short, long or both arcs). Defaults to
                LengthConstraint.SHORT.
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda arcs: arcs.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            Pick just the first result::

                l2 = PolarLine((0, 0), 4, -20, length_mode=LengthMode.HORIZONTAL)
                l3 = Line((4, -2), (4, 2))
                arcs = ConstrainedArcs(
                    l2, l3, center_on=Axis((3, 0), (0, 1)), selector=lambda arcs: arcs[0]
                )
        Nr  )rC   r  r  	center_onr  r  r0   s          r7   rA   zConstrainedArcs.__init__  r   r9   c                    | S r=   r  r  s    r7   r   zConstrainedArcs.<lambda>  r  r9   c                    y)a^  
        Create planar circular arc(s) on XY tangent to three provided objects.

        Args:
            tangency_one, tangency_two, tangency_three
                (tuple[Axis | Edge, PositionConstraint] | Axis | Edge | Vertex | VectorLike):
                Geometric entities to be contacted/touched by the circle(s)
            sagitta (LengthConstraint, optional): returned arc selector
                (i.e. either the short, long or both arcs). Defaults to
                LengthConstraint.SHORT.
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda arcs: arcs.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            Pick the shortest one::

                l4 = PolarLine((0, 0), 4, 60)
                l5 = PolarLine((0, 0), 4, 40)
                a3 = CenterArc((0, 0), 4, 0, 90)
                arcs = ConstrainedArcs(
                    l4, l5, a3, sagitta=Sagitta.BOTH,
                    selector=lambda arcs: arcs.sort_by(Edge.length)[0]
                )

        Nr  )rC   r  r  tangency_threer  r  r0   s          r7   rA   zConstrainedArcs.__init__  r   r9   c                    | S r=   r  r  s    r7   r   zConstrainedArcs.<lambda>  r  r9   r  r0   c                    y)a  
        Create planar circle(s) on XY whose center is fixed and that are tangent/contacting
        a single object.

        Args:
            tangency_one
                (tuple[Axis | Edge, PositionConstraint] | Axis | Edge | Vertex | VectorLike):
                Geometric entity to be contacted/touched by the circle(s)
            center (VectorLike): center position
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda arcs: arcs.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.


        Example:
            Pick the only result::

                arcs = ConstrainedArcs(Axis.Y, center=(-2, 1), selector=lambda arcs: arcs[0])

        Nr  )rC   r  r  r  r0   s        r7   rA   zConstrainedArcs.__init__  r   r9   c                    | S r=   r  r  s    r7   r   zConstrainedArcs.<lambda>  r  r9   c                    y)a  

        Create planar circle(s) on XY that:
        - are tangent/contacting a single object, and
        - have a fixed radius, and
        - have their CENTER constrained to lie on a given locus curve.

        Args:
            tangency_one
                (tuple[Axis | Edge, PositionConstraint] | Axis | Edge | Vertex | VectorLike):
                Geometric entity to be contacted/touched by the circle(s)
            radius (float): arc radius
            center_on (Axis | Edge): center must lie on this object
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda arcs: arcs.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            There is only one result so a selector isn't helpful::

                l6 = PolarLine((0, 0), 5, -20)
                l7 = Line((3, -2), (3, 2))
                arcs = ConstrainedArcs(l6, radius=1, center_on=l7)

        Nr  )rC   r  r  r#  r  r0   s         r7   rA   zConstrainedArcs.__init__  r   r9   c                h   t        j                  |       }t        ||        |j                  dd       }|j                  dt        j
                        }t        j                  |i |} ||      }||st        d      t        |t              r|gn|}t        |      }t        	| 1  ||       y )Nr  c                    | S r=   r  r  s    r7   r   z*ConstrainedArcs.__init__.<locals>.<lambda>E  s    t r9   r0   7selector must return an Edge or list of Edges, not Noner/   )r   r1   r   popr   rM   r'   make_constrained_arcsr   r2   r&   r@   rA   )
rC   argskwargsr6   r  r0   r  selected_arcsr5   rD   s
            r7   rA   zConstrainedArcs.__init__<  s     %.$:$:4$@&::j*;<zz&$((+))4:6: ! VWW  *->]OM 	 m$T*r9   )r  @tuple[Axis | Edge, Tangency] | Axis | Edge | Vertex | VectorLiker  r4  r  rf   r  r   r  3Callable[[ShapeList[Edge]], Edge | ShapeList[Edge]]r0   r   )r  r4  r  r4  r#  zAxis | Edger  r   r  r5  r0   r   )r  r4  r  r4  r&  r4  r  r   r  r5  r0   r   )r  r4  r  r%   r  r5  r0   r   )
r  r4  r  rf   r#  r'   r  r5  r0   r   )rG   rH   rI   rJ   r   rK   rL   r   r   SHORTr   rM   rA   rN   rO   s   @r7   r  r  R  s   )V >>"K #== XX"V" W"
 " "
" " "H  #== XX$V$ W$
 $ $
$ $ $L  #== XX'V' W'
 M' '
' ' 'R  XXV 	

  >  XX#V# 	#
 #
# # #J+ +r9   r  c                      e Zd ZdZej
                  gZed ej                  d	 	 	 	 	 	 	 dd       Z
ed ej                  d	 	 	 	 	 	 	 dd       Z
eddd ej                  d		 	 	 	 	 	 	 	 	 	 	 dd
       Z
d fdZ
 xZS )ConstrainedLinesa  Line Object: Lines(s) constrained by other geometric objects.

    The result is always a Curve containing one or more Edges. If you need
    to access Edge-specific properties or methods (such as ``length``),
    extract the edge or edges first::

        result = ConstrainedLines(...)
        lines = result.edges()      # extract the Edges
        length = lines[1].length    # now Edge methods are available

    Note that in Builder mode the ``selector`` parameter must be provided or
    all results will be combined into the BuildLine context. In Algebra mode
    the selector can be applied as a parameter or in the normal way to the
    ConstrainedArcs object. The content of the selector is the same in both cases.
    c                    | S r=   r  liness    r7   r   zConstrainedLines.<lambda>q      % r9   r(  c                    y)a  
        Create all planar line(s) on the XY plane tangent to two provided curves.

        Args:
            tangency_one, tangency_two
                (tuple[Edge, Tangency] | Axis | Edge):
                Geometric entities to be contacted/touched by the line(s).
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda lines: lines.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            Accept all results (default behaviour)::

                a1 = CenterArc((-5, 0), 4, 0, 360)
                a2 = CenterArc((5, 0), 3, 0, 360)
                lines = ConstrainedLines(a1, a2, selector=lambda lines: lines)
        Nr  rC   r  r  r  r0   s        r7   rA   zConstrainedLines.__init__i  r   r9   c                    | S r=   r  r:  s    r7   r   zConstrainedLines.<lambda>  r<  r9   c                    y)a-  
        Create all planar line(s) on the XY plane tangent to one curve and passing
        through a fixed point.

        Args:
            tangency_one
                (tuple[Edge, Tangency] | Edge):
                Geometric entity to be contacted/touched by the line(s).
            tangency_two (VectorLike):
                Fixed point through which the line(s) must pass.
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda lines: lines.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            Pick just the first result::

                a1 = CenterArc((-5, 0), 4, 0, 360)
                lines = ConstrainedLines(a1, (0, 6), selector=lambda lines: lines[0])
        Nr  r>  s        r7   rA   zConstrainedLines.__init__  r   r9   Nc                    | S r=   r  r:  s    r7   r   zConstrainedLines.<lambda>  r<  r9   )angle	directionr  r0   c                    y)a  
        Create all planar line(s) on the XY plane tangent to one curve with a
        fixed orientation, defined either by an angle measured from a reference
        axis or by a direction vector.

        Args:
            tangency_one (Edge): edge that line will be tangent to
            tangency_two (Axis): reference axis from which the angle is measured
            angle : float, optional
                Line orientation in degrees (measured CCW from the X-axis).
            direction : VectorLike, optional
                Direction vector for the line (only X and Y components are used).
            Note: one of angle or direction must be provided
            selector (Callable, optional): typically a lambda which chooses one or more of the
                results. Defaults to lambda lines: lines.
            mode (Mode, optional): combination mode. Defaults to Mode.ADD.

        Example:
            Pick the arc whose midpoint is closest to a given point::

                a1 = CenterArc((-5, 0), 4, 0, 360)
                lines = ConstrainedLines(
                    a1,
                    Axis.Y,
                    angle=30,
                    selector=lambda lines: lines.sort_by_distance((0, 0))[0],
                )
        Nr  )rC   r  r  rB  rC  r  r0   s          r7   rA   zConstrainedLines.__init__  r   r9   c                h   t        j                  |       }t        ||        |j                  dd       }|j                  dt        j
                        }t        j                  |i |} ||      }||st        d      t        |t              r|gn|}t        |      }t        	| 1  ||       y)z
        Create planar line(s) on XY subject to tangency/contact constraints.

        Supported cases
        ---------------
        1. Tangent to two curves
        2. Tangent to one curve and passing through a given point
        r  c                    | S r=   r  r:  s    r7   r   z+ConstrainedLines.__init__.<locals>.<lambda>  s     r9   r0   Nr.  r/   )r   r1   r   r/  r   rM   r'   make_constrained_linesr   r2   r&   r@   rA   )
rC   r1  r2  r6   r  r0   r;  selected_linesr5   rD   s
            r7   rA   zConstrainedLines.__init__  s     %.$:$:4$@&::j*=>zz&$((+++T<V< "%!VWW !+>4 @^n 	 n%T*r9   )r  #tuple[Edge, Tangency] | Axis | Edger  rI  r  r5  r0   r   )r  tuple[Edge, Tangency] | Edger  r%   r  r5  r0   r   )r  rJ  r  r!   rB  float | NonerC  VectorLike | Noner  r5  r0   r   )r   r  )rG   rH   rI   rJ   r   rK   rL   r   r   rM   rA   rN   rO   s   @r7   r8  r8  V  s     >>"K  XX9 :

  :   XX2 !

  >  #'+  XX'2' '
 ' %'
' ' 'R+ +r9   r8  c                  ~     e Zd ZdZej
                  gZej                  e	j                  f	 	 	 	 	 	 	 	 	 d fdZ xZS )DoubleTangentArca  Line Object: Double Tangent Arc

    Create a circular arc defined by a point/tangent pair and another line find a tangent to.

    The arc specified with TOP or BOTTOM depends on the geometry and isn't predictable.

    Contains a solver.

    Args:
        pnt (VectorLike): start point
        tangent (VectorLike): tangent at start point
        other (Curve | Edge | Wire): line object to tangent
        keep (Keep, optional): specify which arc if more than one, TOP or BOTTOM.
            Defaults to Keep.TOP
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        RunTimeError: no double tangent arcs found
    c           	     
   t        j                  |       }t        ||        |t        j                  t        j
                  fvrt        d|       t        j                  |      t        j                  |      j                         }t        j                         "t        j                         j                  d   }nD t        j                  |z         j                  j                          }|t        d      | }t        d|j                         }	dj#                         j%                        j&                  z  }
fd}g }dD ]  }|j)                  |	|      }t+        |d|d	d|
fgt,        
      }|j.                  d   }||z  z   }t        j0                  |t3        ||	j4                              }j7                  |      \  }}}|t,        kD  rt        |j9                  |            }t        ||j9                  |            }|j;                  |d      s|j=                  |        t?        |      dk(  rtA        d      |t        j                  k(  r|dd }n|t        j
                  k(  r|dd  }t               5 }|D ]%  }j7                  |      \  }}}tC        ||       ' 	 d d d        jE                         }tG        |t              sJ tH        |   ||       y # 1 sw Y   =xY w)Nz1Only the TOP or BOTTOM options are supported not r   z-DoubleTangentArc only works on a single planer   r^   c                X    || d   z  z   }j                  |      }t        || z
        S )Nr   )r   abs)r  perpendicular_bisectorr  
separationarc_ptothers       r7   funcz'DoubleTangentArc.__init__.<locals>.func#  s7    4vay@@F**62JzF*++r9   )Z   rq   Nelder-Meadx0r1  methodboundstolr   g?zNo double tangent arcs foundr\   ru   tangentr/   )&r   r1   r   r   TOPBOTTOMr   r   r   
normalizedr   r'   r   common_planer4   r!   r   bounding_boxadddiagonalr   r   r    r   r   r#   rC  distance_to_with_closest_points
tangent_atis_parallelappendr   RuntimeError
TangentArcedger2   r@   rA   )rC   pntra  rU  keepr0   r6   arc_tangent	workplanerotation_axismax_sizerV  arc_centersrB  rR  result
arc_radius
arc_centercircledistp1p2
other_axiscircle_axisdoubler  _double_edgerT  rD   s      `                        @r7   rA   zDoubleTangentArc.__init__  s    %.$:$:4$@&$++..PQUPVWXX'',#,,W5@@B%%'3%224??BIQvv/CDQQI   !PQQ"
IY	8**,008AAA	,  	/E%0%7%7u%M"+$h(F  !J"8:"EEJ %%E*M4K4KLF !@@HLD"bib%"2"22"67Jr6#4#4R#89K%%k48"":./	/2 {q =>> 488%a*KT[[ %bc*K[ 	<F% < @@H2q62{;<	<
 kkm+t,,,40	< 	<s   +K99L)
rp  r%   ra  r%   rU  Curve | Edge | Wirerq  r   r0   r   )rG   rH   rI   rJ   r   rK   rL   r   rb  r   rM   rA   rN   rO   s   @r7   rN  rN    sg    ( >>"K XXXXN1N1 N1 #	N1
 N1 N1 N1r9   rN  c                       e Zd ZdZej
                  gZ	 	 ddddej                  d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )	EllipticalCenterArcuZ  Line Object: Elliptical Center Arc

    Create an elliptical arc defined by a center point, x- and y- radii.

    Args:
        center (VectorLike): ellipse center
        x_radius (float): x radius of the ellipse (along the x-axis of plane)
        y_radius (float): y radius of the ellipse (along the y-axis of plane)
        start_angle (float, optional): arc start angle from x-axis.
            Defaults to 0.0
        end_angle (float | None): arc end angle from x-axis.
            Defaults to None
        arc_size (float | Shape | Axis | Location | Plane | VectorLike): angular size
            of arc (negative to change direction) or an arc limit.

            When a limit object is provided instead of a numeric angular size,
            EllipticalCenterArc constructs the valid arc(s) from the given start
            point, trims them at their first intersection with the limit, and
            returns the one requiring the shortest travel from the start.
            Therefore, one can only generate arcs < 180° using a limit. If
            neither valid arc intersects the limit, a ValueError is raised.
        rotation (float, optional): angle to rotate arc. Defaults to 0.0
        angular_direction (AngularDirection | None): arc direction.
            Defaults to None.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    rq   N     V@r  rotationr   r0   c                  t        j                  |       }
t        |
|        d}| d}|}t        j                  dt
        d       | d}|}t        j                  dt
        d       t        j                  |      }|
t        j                  }n4t        j                  t        j                         j                  d         }||_        t        |j                  |j                        }t!        |t"              rt%        |      n|}|rNt!        |t&        t(        f      st+        d      t-        j.                  ||||	      j1                  ||      }nt!        |t&        t(        f      rV||z   }|dk\  rt2        j4                  nt2        j6                  }t-        j.                  ||||||	      j1                  ||      }nt-        j.                  |||
      j1                  ||      }|j9                  |      }|j;                  d      j9                  |      }||t+        d|       t=        ||fD cg c]  }||	 c}      j?                  t,        j@                        d   }tB        |   ||	       y c c}w )NFThThe 'end_angle' parameter is deprecated and will be removed in a future version. Use 'arc_size' instead.r_   
stacklevelpThe 'angular_direction' parameter is deprecated and will be removed in a future version. Use 'arc_size' instead.r   znEllipticalCenterArc limit arc_size can't be used with deprecated 'end_angle' or 'angular_direction' parametersx_radiusy_radiusplaner   r   r   )r  r  r  r   z0EllipticalCenterArc doesn't intersect arc limit r/   )#r   r1   r   warningswarnDeprecationWarningr   r   r#   r   r   r   r   r   r!   r   r2   r   r$   re   rf   r   r'   make_ellipser   r   r   r   r  r   r,   r  r   r@   rA   )rC   r  r  r  r   r   r  r  r   r0   r6   deprecated_parameterend_arC  
center_pntellipse_workplanerotate_axisr  r5   trimmed_curvetrimmed_curve2r  rD   s                         r7   rA   zEllipticalCenterArc.__init__u  s    %.$:$:4$@&$ #' EMM+"	 (#' )IMMG"	 #++F3
? % + 0 0**,77:! $. ,335F5L5LM)3Hh)GVH%X
j3,7 D 
 %%!!''"+ f[(+  
S%L1*,E ? !22%//  %%!!''"+ f[(+  %%!!' f[(+	  "//
;M"^^^=KKJWN$)? FxjQ  *N;Mqq}Mgdkk"1&E 	T* Ns   <JJrq   N)r  r%   r  rf   r  rf   r   rf   r   rK  r  r  r  rf   r   AngularDirection | Noner0   r   r   r  rF   rO   s   @r7   r  r  V  s    8 >>"K !"&d+ JN59XXd+d+ d+ 	d+
 d+  d+ Gd+ d+ 3d+ d+ 
d+ d+r9   r  c                  z     e Zd ZdZej
                  gZddej                  d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )EllipticalStartArca  Line Object: EllipticalStartArc

    Create a circular arc defined by a start point/tangent pair, radius and arc size.

    Args:
        start_pnt (VectorLike): start point
        start_tangent (VectorLike): tangent at start point
        x_radius (float): x radius of the ellipse (along the x-axis of plane)
        y_radius (float): y radius of the ellipse (along the y-axis of plane)
        arc_size (float): angular size of arc (negative to change direction)
        start_angle (float): angular position of the start point
        major_axis_dir (VectorLike): direction of ellipse x-axis
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Note:
        One of start_angle or major_axis_dir must be provided.
    N)r   major_axis_dirr0   c                  d	d}	t        j                  |       }
t        |
|        t        j                  |      }|
t
        j                  }n4t        j                  t        j                         j                  d         }||_
        t        |t              rCt        |      dk(  r5t        |      j                  |j                   d      j#                         }nt        |      j#                         }|j$                  }|t'        |      } |	||      j#                         }| t)        |      z  }|t+        |      z  }||z  ||j-                  |      z  z
  ||z  ||z  z   z  }|j#                         }|j-                  |      }|||t+        |      z  z  z
  ||t)        |      z  z  z
  }n| |	t        |      |      j#                         }|j-                  |      } |	||      }|j/                  |      }|j/                  |      }t1        ||z   ||z        }|||t+        |      z  z  z
  ||t)        |      z  z  z
  }t3        |      }nt5        d      t        |||      }||z   }|dk\  rt6        j8                  nt6        j:                  }t=        j>                  ||||||      }t@        |   ||       y )
Nc                P    |j                         }| || j                  |      z  z
  S r=   )rd  dot)vns     r7   proj_to_planez2EllipticalStartArc.__init__.<locals>.proj_to_plane  s$    Aq1558|##r9   r   r_   Tis_directionz5Either start_angle or major_axis_dir must be provided)r   r   r/   )r  r$   r  r$   r   r$   )"r   r1   r   r   r   r#   r   r   r   r   r   r2   tupler   r$   	transformreverse_transformrd  r   r   r   r
   crossr  r   r   r   r   r   r   r'   r  r@   rA   )rC   	start_pntstart_tangentr  r  r  r   r  r0   r  r6   rs  
pln_normalstart_angle_radpln_tangenta_radiusb_radiusr   	pln_x_dir	pln_y_dir
pln_originpln_x_radiuspln_y_radiusplnr   rC  r  rD   s                              r7   rA   zEllipticalStartArc.__init__  s   	$ %.$:$:4$@&!**95	 ?I#(()C)C)E)P)PQR)STI$	 mU+M0Ba0G}%966TJ  #=1<<>M__
"%k2O'zBMMOK y3#77H#o"66H ;&Z5E5Ek5R)SSH$x('::<E ((*I"((3I x#o*>>?@x#o*>>?@ 
 '%f^&<jITTVI"((3I'zBK&??95L&??95L#)*\H-DO x#o*>>?@x#o*>>?@ 
 "/2KTUUJizB(*	 1} ..!++ 	
 h[)Y
 	4(r9   )r  r%   r  r%   r  rf   r  rf   r  rf   r   rK  r  rL  r0   r   rF   rO   s   @r7   r  r    s    $ >>"K %),0XXY)Y) "Y) 	Y)
 Y) Y) "Y) *Y) Y) Y)r9   r  c                       e Zd ZdZej
                  gZ	 	 ddddej                  d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )	ParabolicCenterArca  Line Object: Parabolic Center Arc

    Create a parabolic arc defined by a vertex point and focal length
    (distance from focus to vertex).

    Args:
        vertex (VectorLike): parabola vertex
        focal_length (float): focal length the parabola (distance from the
            vertex to focus along the x-axis of plane)
        start_angle (float, optional): arc start angle.
            Defaults to 0.0
        end_angle (float | None, optional): arc end angle.
            Defaults to None
        arc_size (float | Shape | Axis | Location | Plane | VectorLike): angular size
            of arc (negative to change direction) or an arc limit.

            When a limit object is provided instead of a numeric angular size,
            ParabolicCenterArc constructs candidate arcs from the given start
            point, trims them at their first intersection with the limit, and
            returns the one requiring the shortest travel from the start. If
            neither valid arc intersects the limit, a ValueError is raised.
        rotation (float, optional): angle to rotate arc. Defaults to 0.0
        angular_direction (AngularDirection | None, optional): arc direction.
            Defaults to None
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    rq   Nr  r  c               .   t        j                  |       }	t        |	|        d}
| d}
|}t        j                  dt
        d       | d}
|}t        j                  dt
        d       t        j                  |      }|	t        j                  }n4t        j                  t        j                         j                  d         }||_        t        |j                  |j                        }t!        |t"              rt%        |      n|}|
rMt!        |t&        t(        f      st+        d      t-        j.                  |||	      j1                  ||      }n(t!        |t&        t(        f      rU||z   }|dk\  rt2        j4                  nt2        j6                  }t-        j.                  |||||	      j1                  ||      }nt-        j.                  ||||d
z   t2        j4                  	      j1                  ||      }|j9                  |      }|j;                  d      j9                  |      }||t+        d|       t=        ||fD cg c]  }||	 c}      j?                  t,        j@                        d   }tB        |   ||       y c c}w )NFTr  r_   r  r  r   zmParabolicCenterArc limit arc_size can't be used with deprecated 'end_angle' or 'angular_direction' parameters)focal_lengthr  r   r   r        f@r   z/ParabolicCenterArc doesn't intersect arc limit r/   )#r   r1   r   r  r  r  r   r   r#   r   r   r   r   r   r!   r   r2   r   r$   re   rf   r   r'   make_parabolar   r   r   r   r  r   r,   r  r   r@   rA   )rC   vertexr  r   r   r  r  r   r0   r6   r  r  rC  
vertex_pntparabola_workplaner  r  r5   r  r  r  rD   s                        r7   rA   zParabolicCenterArc.__init__k  s    %.$:$:4$@&$ #' EMM+"	 (#' )IMMG"	 #++F3
?!&!,!1!1**,77:" %/!-446H6N6NO)3Hh)GVH%X
j3,7 D 
 &&)('"+ f[(+  
S%L1*,E ? !22%//  &&)('"+ f[(+  &&)('%-"2"D"D f[(+  "//
;M"^^^=KKJWN$)? EhZP  *N;Mqq}Mgdkk"1&E 	T* Ns   JJr  )r  r%   r  rf   r   rf   r   rK  r  r  r  rf   r   r  r0   r   rF   rO   s   @r7   r  r  M  s    6 >>"K !"&c+ JN59XXc+c+ c+ 	c+
  c+ Gc+ c+ 3c+ c+ c+r9   r  c                       e Zd ZdZej
                  gZ	 	 ddddej                  d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )	HyperbolicCenterArcaF  Line Object: Hyperbolic Center Arc

    Create a hyperbolic arc defined by a center point and focal length
    (distance from focus to vertex).

    Args:
        center (VectorLike): hyperbola center
        x_radius (float): x radius of the ellipse (along the x-axis of plane)
        y_radius (float): y radius of the ellipse (along the y-axis of plane)
        start_angle (float, optional): arc start angle from x-axis.
            Defaults to 0.0
        end_angle (float | None, optional): arc end angle from x-axis.
            Defaults to None
        arc_size (float | Shape | Axis | Location | Plane | VectorLike): angular size
            of arc (negative to change direction) or an arc limit.

            When a limit object is provided instead of a numeric angular size,
            HyperbolicCenterArc constructs candidate arcs from the given start
            point, trims them at their first intersection with the limit, and
            returns the one requiring the shortest travel from the start. If
            neither valid arc intersects the limit, a ValueError is raised.
        rotation (float, optional): angle to rotate arc. Defaults to 0.0
        angular_direction (AngularDirection | None, optional): arc direction.
            Defaults to None
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    rq   Nr  r  c               4   t        j                  |       }
t        |
|        d}| d}|}t        j                  dt
        d       | d}|}t        j                  dt
        d       t        j                  |      }|
t        j                  }n4t        j                  t        j                         j                  d         }||_        t        |j                  |j                        }t!        |t"              rt%        |      n|}|rNt!        |t&        t(        f      st+        d      t-        j.                  ||||	      j1                  ||      }n*t!        |t&        t(        f      rV||z   }|dk\  rt2        j4                  nt2        j6                  }t-        j.                  ||||||	      j1                  ||      }nt-        j.                  |||||d
z   t2        j4                  	      j1                  ||      }|j9                  |      }|j;                  d      j9                  |      }||t+        d|       t=        ||fD cg c]  }||	 c}      j?                  t,        j@                        d   }tB        |   ||	       y c c}w )NFTr  r_   r  r  r   znHyperbolicCenterArc limit arc_size can't be used with deprecated 'end_angle' or 'angular_direction' parametersr  r  r   z0HyperbolicCenterArc doesn't intersect arc limit r/   )#r   r1   r   r  r  r  r   r   r#   r   r   r   r   r   r!   r   r2   r   r$   re   rf   r   r'   make_hyperbolar   r   r   r   r  r   r,   r  r   r@   rA   )rC   r  r  r  r   r   r  r  r   r0   r6   r  r  rC  r  hyperbola_workplaner  r  r5   r  r  r  rD   s                         r7   rA   zHyperbolicCenterArc.__init__  s    %.$:$:4$@&$ #' EMM+"	 (#' )IMMG"	 #++F3
?"'(("-"2"2**,77:# &0".557J7P7PQ)3Hh)GVH%X
j3,7 D 
 ''!!)'"+ f[(+  
S%L1*,E ? !22%//  ''!!)'"+ f[(+  ''!!)'%-"2"D"D f[(+  "//
;M"^^^=KKJWN$)? FxjQ  *N;Mqq}Mgdkk"1&E 	T* Ns   JJr  )r  r%   r  rf   r  rf   r   rf   r   rK  r  r  r  rf   r   r  r0   r   rF   rO   s   @r7   r  r    s    6 >>"K !"&g+ JN59XXg+g+ g+ 	g+
 g+  g+ Gg+ g+ 3g+ g+ g+r9   r  c                  |     e Zd ZdZej
                  gZddddej                  f	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )HelixaA  Line Object: Helix

    Create a helix defined by pitch, height, and radius. The helix may have a taper
    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.

    Args:
        pitch (float): distance between loops
        height (float): helix height
        radius (float): helix radius
        center (VectorLike, optional): center point. Defaults to (0, 0, 0)
        direction (VectorLike, optional): direction of central axis. Defaults to (0, 0, 1)
        cone_angle (float, optional): conical angle from direction.
            Defaults to 0
        lefthand (bool, optional): left handed helix. Defaults to False
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    r   )r   r   r\   r   Fc	           	         t        j                  |       }	t        |	|        t        j                  |      }
t        j                  ||||
|||      }t        | !  ||       y )Nr/   )	r   r1   r   r   r   r'   
make_helixr@   rA   )rC   pitchheightr  r  rC  
cone_anglelefthandr0   r6   r  helixrD   s               r7   rA   zHelix.__init__p  s`     %.$:$:4$@&"++F3
66:y*h
 	T*r9   )r  rf   r  rf   r  rf   r  r%   rC  r%   r  rf   r  r   r0   r   rF   rO   s   @r7   r  r  Y  s    ( >>"K ' )XX++ + 	+
 + + + + + +r9   r  c                  h     e Zd ZdZej
                  gZdej                  d	 	 	 	 	 	 	 d fdZ	 xZ
S )FilletPolylinea  Line Object: Fillet Polyline
    Create a sequence of straight lines defined by successive points that are filleted
    to a given radius.

    Args:
        pts (VectorLike | Iterable[VectorLike]): sequence of two or more points
        radius (float | Iterable[float]): radius to fillet at each vertex or a
            single value for all vertices.
            A radius of 0 will create a sharp corner (vertex without fillet).

        close (bool, optional): close end points with extra Edge and corner fillets.
            Defaults to False

        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Two or more points not provided
        ValueError: radius must be non-negative
    Fcloser0   c               
   t        j                  |       }t        ||        t        | }t	        |d         t	        |d         z
  j
                  t        k  rd}|j                  d       t        |      dk  rt        d      t        |t        t        f      r|gt        |      z  }nft        |      }t        |      t        |      t        |       dz  z
  k7  r4t        dt        |       dt        |      t        |       dz  z
   d      |D ]  }|dk  s	t        d	| d
       t        j                  | }	t!        t        |	      dz
        D 
cg c]!  }
t#        j$                  |	|
   |	|
dz            # }}
|rO|d   dz  |d   dz  z
  j
                  dkD  r1|j'                  t#        j$                  |d   dz  |d   dz               t)        |      }g }|	D ]m  }|j+                         D ci c]!  }|t	        |      t	        | z
  j
                  # }}|j'                  t-        |j/                         d       d   d          o |D ci c]4  }||j1                         D cg c]  }||j+                         v s| c}6 }}}g }t3        |j/                               D ]  \  }
\  }}t        |      dk7  r||
t        |       z
     }|dk(  r|j'                  d        A|D ch c]  }|j+                         D ]
  }||k7  s	| ! }}}t#        j$                  | }t5        t)        ||gz               j7                  ||g      }|j'                  |j1                         j9                  t:        j<                        d           |rqg }t!        t        |            D ]U  }
||
dz
     }||
   }|
dz
  }|
}|||   } n|dz  } |||   }!n|dz  }!|j'                  t#        j$                  | |!             W g }"ng }t!        t        |      dz
        D ][  }
||
dz      }#||
   }|
}|
dz   }$|	||dz      } n|dz  } |#	||$dz      }!n|#dz  }!|j'                  t#        j$                  | |!             ] |d   t#        j$                  |dz  |d         }%nt#        j$                  |dz  |d   dz        }%|d   t#        j$                  |d   |dz        }&nt#        j$                  |d   dz  |dz        }&|%|&g}"|D 'cg c]  }'|'|'	 }(}'t)        |"|z   |(z         })t>        *|   |)|       y c c}
w c c}w c c}w c c}}w c c}}w c c}'w )Nr   ru   Tr_   z'FilletPolyline requires two or more ptszradius list length (z) must match angle count ()zradius z must be non-negativer\   h㈵>c                    | d   S )Nr\   r  )r   s    r7   r   z)FilletPolyline.__init__.<locals>.<lambda>  s
    1Q4 r9   r   r/   )!r   r1   r   r   r$   r   r    r/  r   r   r2   re   rf   r   r   r   ranger'   r   rl  r*   r   sorteditemsr4   r   r(   	fillet_2d	filter_byr   CIRCLEr@   rA   )+rC   r  r  r0   ptsr6   pointsradius_listr	lines_ptsr   	new_edgeswire_of_linesordered_verticespntsr  distanceevertex_to_edgesfilletsr  r4   current_radiusveother_vertices
third_edgefillet_faceinterior_edgesprev_filletcurr_filletprev_idxcurr_idxstart_ptend_pt	end_edgesnext_filletnext_idx
start_edgeend_edgefactual_filletsnew_wirerD   s+                                             r7   rA   zFilletPolyline.__init__  s    %.$:$:4$@&!3' 6!9vbz 22::YFEJJrNv;?FGGfsEl+!(S[0K v,K;3v;Y!1C#CC K() *Fce)nq&889<   	EA1u 71#-B!CDD	E "**F3	 3y>A-.
 NN9Q<1q5)9:
	 

 ilQ&2)::BBTIT^^IbMA,=y|a?OPQY *, 	XD?L?U?U?W:;F4L61:-555H  ##F8>>+;$PQR$STU$VW		X &
 =..0FaA4EFF
 
 &("+O,A,A,C"D 	RA5zQ(SU^);<N"t$ !&"

"*,fB"" " "^^^<
"4(<#=>HH"VH {002<<X__MaPQ#	R( N3w<( H%a!en%ajq5&0@0JH*QH&.>x.HF(1_F%%dnnXv&FGH" I  N3w<!+, H%a!en%ajq5&/ 1 H  +QH&-hl;F(1_F%%dnnXv&FG#H( qz!!^^MA,=?OPQ?RS
!^^MA,=wqzA~N
r{">>*:2*>PQ@QR>>'"+/=1;LM#X.I &->!>>	N2^CD-[
 G
$"D ?sB   &T94&T>U,UUU1UUUUU)r  !VectorLike | Iterable[VectorLike]r  zfloat | Iterable[float]r  r   r0   r   rF   rO   s   @r7   r  r    sX    ( >>"K XXU./U. (U. 	U.
 U. U.r9   r  c                  h     e Zd ZdZej
                  gZej                  f	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )JernArca  Line Object: Jern Arc

    Create a circular arc defined by a start point/tangent pair, radius and arc size or arc limit.

    Args:
        start (VectorLike): start point
        tangent (VectorLike): tangent at start point
        radius (float): arc radius
        arc_size (float | Shape | Axis | Location | Plane | VectorLike): angular size
            of arc (negative to change direction) or an arc limit.

            When a limit object is provided instead of a numeric angular size, JernArc
            constructs the valid tangent arc(s) from the given start point and tangent,
            trims them at their first intersection with the limit, and returns the one
            requiring the shortest travel from the start. If neither valid arc intersects
            the limit, a ValueError is raised.
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Attributes:
        start (Vector): start point
        end_of_arc (Vector): end point of arc
        center_point (Vector): center of arc
    c                @   t        j                  |       }t        ||        t        j                  |      }|| _        |t        j                  }n4t        j                  t        j                         j                  d         }||_        t        |t              rCt        |      dk(  r5t        |      j!                  |j"                  d      j%                         }nt        |      j%                         }t        |t&              rt        |      n|}	t        |	t(        t*        f      rt-        d|	      }
|	}nd}
d}||j/                  t1        ||j2                        |
dz        t5        |      z  z   }|||z
  j/                  t1        ||j2                        |      z   }t5        |      dk\  rt        j                  |      }||_        | j
                  |j                  z
  |_        t9        j:                  ||      }||j/                  t1        ||j2                        |
 dz        t5        |      z  z   }t        j                  |      }||_        | j
                  |j                  z
  |_        t9        j:                  ||      }|j=                  d      j?                  |      dk  r*|jA                  d	      }nt9        jB                  |||      }t        |	t(        t*        f      st|jE                  |	      }jE                  |	      }||tG        d
|       tI        ||fD cg c]  }||	 c}      jK                  t8        jL                        }|d   }|jN                  | _(        |jS                  d      | _*        tV        |   ||       y c c}w )Nr   r_   Tr  r   r\   h  rW  r   z$JernArc doesn't intersect arc limit r/   )-r   r1   r   r   r   startr#   r   r   r   r   r   r2   r  r   r$   r  r  rd  r   re   rf   r	   r   r!   r   rQ  r   r'   r   rj  r  r   make_tangent_arcr  r   r,   r  r   ry  r  r   
end_of_arcr@   rA   )rC   r  ra  r  r  r0   r6   jern_workplaner  r  r	  arc_untrimed_sizer  r	  r  r  center_point2circle_plane2r  r  r  r  r  rD   s                          r7   rA   zJernArc.__init__O  sA    %.$:$:4$@&&&u-
?"XXN(--**,77:N !&gu%#g,!*; w>;;$O  #7O668M)3Hh)GVH%X
j3,/$S*5M *M #}33,,-}r/A 
K   "U\%9$A$A,,-/@%
 

  !S(&++N;L".L!%l.A.A!AL""6<8C!M$8$8UN001M>B3F%F% M (,,^<M#0M "&**}/C/C"CM##FM:Dq!%%m4q8}}}6 ''}jIC*sEl3++J7K--j9L"|'; #Gz!RSS(,7Iq1=Igdkk"  q'CNN//!,4( Js   -N5N)
r  r%   ra  r%   r  rf   r  r  r0   r   rF   rO   s   @r7   r  r  4  sa    0 >>"K XXM)M) M) 	M)
 GM) M) M)r9   r  c                  X     e Zd ZdZej
                  gZej                  dd fdZ	 xZ
S )r   a  Line Object: Line

    Create a straight line defined by two points.

    Args:
        pts (VectorLike | Iterable[VectorLike]): sequence of two points
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Two point not provided
    r/   c               B   t        | }t        |      dk7  rt        d      t        j                  |       }t        ||        t        j                  | }|D cg c]  }t        |       }}t        j                  |d   |d         }t        	| 1  ||       y c c}w )Nr_   zLine requires two ptsr   r\   r/   )r   r   r   r   r1   r   r   r   r$   r'   r   r@   rA   )
rC   r0   r  r  r6   points_localizedrl   r  new_edgerD   s
            r7   rA   zLine.__init__  s    !3'v;!455$-$:$:4$@&(116:(891VAY9	9>>)A,	!=- :s   Br  r  r0   r   rF   rO   s   @r7   r   r     s'    
 >>"KMQXX . .r9   r   c                  d     e Zd ZdZej
                  gZej                  f	 	 	 	 	 	 	 d fdZ	 xZ
S )IntersectingLinea`  Intersecting Line Object: Line

    Create a straight line defined by a point/direction pair and another line to intersect.

    Args:
        start (VectorLike): start point
        direction (VectorLike): direction to make line
        other (Edge): line object to intersect
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    c                   t        j                  |       }t        ||        t        j                  |      }t        j                  |      j                         }t        ||      }|j                         D cg c]  }|j                  |      D ]  }|  }	}}|	st        d      |	D 
cg c]  }
||
z
  j                   }}
t        |      }t        j                  ||||z  z         }t        | =  ||       y c c}}w c c}
w )NzNo intersections foundr/   )r   r1   r   r   r   rd  r!   r4   find_intersection_pointsr   r   r   r'   r   r@   rA   )rC   r  rC  rU  r0   r6   axisro  r   intersection_pntsrl   	distancesr   r  rD   s                 r7   rA   zIntersectingLine.__init__  s    %.$:$:4$@&&&u-!**95@@B	E9%  ++-
1N1Nt1T
,-A

 
 !5661BCAeai''C	CY>>%V1C)CD-
 Ds   :C>-D)r  r%   rC  r%   rU  r  r0   r   rF   rO   s   @r7   r  r    sO    
 >>"K XX.. . #	.
 . .r9   r  c                       e Zd ZdZej
                  gZddej                  e	j                  f	 	 	 	 	 	 	 	 	 	 	 d fdZ xZS )	PolarLineaf  Line Object: Polar Line

    Create a straight line defined by a start point, length, and angle.
    The length can specify the DIAGONAL, HORIZONTAL, or VERTICAL component of the triangle
    defined by the angle.

    Alternatively, the length parameter can contain a limit to the length of the line
    in the form of another object. If the PolarLine doesn't contact the limit an error
    will be generated.

    Example:

        p = PolarLine(start=(2, 0), length=Axis.Y, angle=135)

    Args:
        start (VectorLike): start point
        length (float | Shape | Axis | Location | Plane | VectorLike): line length (float) or
            limit limit
        angle (float, optional): angle from the local x-axis
        direction (VectorLike, optional): vector direction to determine angle
        length_mode (LengthMode, optional): how length defines the line.
            Defaults to LengthMode.DIAGONAL
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Either angle or direction must be provided
        ValueError: Polar line doesn't intersect length limit

    Nc           	        t        j                  |       }t        ||        t        j                  |      }|t
        j                  }n4t        j                  t        j                         j                  d         }|@t        j                  |      j                         }	t        ddd      j                  |	      }n>|1|j                  j                  t        d|j                         |      }	nt#        d      t%        |t&              rt        |      n|}
|
xxt(        d x\   n xt*        d x\   n  n  |t,        j.                  k(  r|	|
z  }nZ|t,        j0                  k(  r$|	t3        |
t5        t7        |            z        z  }n#|	t3        |
t9        t7        |            z        z  }t;        j<                  |||z         }nxt>        d xl\    |
jA                         jC                  |      jD                  }t;        j<                  |||	|z  z         }|jG                  |
      }|t#        d|       |}n xt        d x\   n- xt
        d x\   n xtH        d x\   n xt        d x\   n  nn t        ||	      }|jK                  |
      }t%        |t              r2||z
  jM                  |	      tN        kD  rt;        j<                  ||      }nt#        d|       tP        |   |       y )Nr   r\   r   z*Either angle or direction must be providedr  z*Polar line doesn't intersect length limit r/   )*r   r1   r   r   r   r#   r   r   r   r   rd  r$   	get_angler   r   r!   r   r   r2   r   rf   re   r   DIAGONAL
HORIZONTALrQ  r
   r   r   r'   r   r+   rf  rg  rh  r  r"   	intersectr  r    r@   rA   )rC   r  r   rB  rC  length_moder0   r6   polar_workplanedirection_localizedlength_factorlength_vectorr  
max_length	long_edgetrimmed_edge
polar_axiscontactrD   s                     r7   rA   zPolarLine.__init__  s    %.$:$:4$@&&&u-?#hhO)..**,77:O  "/"8"8"C"N"N"P1aO--.ABE"1"7"7">">Y 5 56#
 IJJ*4VX*FvF 535*"5"55$7-$GM J$9$99$7#%GEN(;;; %M %8#%GEN(;;; %M  >>%1FG*779==eDMM
 NN5#6#CC	  )66}E'$DVHM  (  '%'JHJ9!%)<=
$..}= w/ 5--.ABYN#~~eW=H$DVHM  	-r9   )r  r%   r   r  rB  rK  rC  rL  r!  r   r0   r   )rG   rH   rI   rJ   r   rK   rL   r   r  r   rM   rA   rN   rO   s   @r7   r  r    s{    < >>"K #'+","5"5XXF.F. EF. 	F.
 %F.  F. F. F.r9   r  c                  d     e Zd ZdZej
                  gZdej                  d	 	 	 	 	 d fdZ	 xZ
S )Polylinea  Line Object: Polyline

    Create a sequence of straight lines defined by successive points.

    Args:
        pts (VectorLike | Iterable[VectorLike]): sequence of two or more points
        close (bool, optional): close by generating an extra Edge. Defaults to False
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Two or more points not provided
    Fr  c          	     *   t        j                  |       }t        ||        t        | }t	        |      dk  rt        d      t        j                  | }t        t	        |      dz
        D cg c]!  }t        j                  ||   ||dz            # }}|rO|d   dz  |d   dz  z
  j                  dkD  r1|j                  t        j                  |d   dz  |d   dz               t        	| 9  t        j                   |      d   |       y c c}w )Nr_   z!Polyline requires two or more ptsr\   r   ru   r  r/   )r   r1   r   r   r   r   r   r   r  r'   r   r   rl  r@   rA   r*   combine)
rC   r  r0   r  r6   r  r  r   r  rD   s
            r7   rA   zPolyline.__init__a  s    %.$:$:4$@&!3'v;?@AA!**F3	 3y>A-.
 NN9Q<1q5)9:
	 
 ilQ&2)::BBTIT^^IbMA,=y|a?OPQi03$?
s   /&D)r  r  r  r   r0   r   rF   rO   s   @r7   r,  r,  Q  sM     >>"K
 XX	@/@ @ 	@ @r9   r,  c                  j     e Zd ZdZej
                  gZdej                  f	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )	RadiusArca  Line Object: Radius Arc

    Create a circular arc defined by two points and a radius.

    Args:
        start_point (VectorLike): start point
        end_point (VectorLike): end point
        radius (float): arc radius
        short_sagitta (bool): If True selects the short sagitta (height of arc from
            chord), else the long sagitta crossing the center. Defaults to True
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Insufficient radius to connect end points
    Tc                b   t        j                  |       }t        ||        t        j                  ||      \  }}|j                  |      j                  dz  }		 |r!t        |      t        |dz  |	dz  z
        z
  }
n!t        |       t        |dz  |	dz  z
        z
  }
|dkD  rt        |||
t        j                        }nt        |||
 t        j                        }|j                         }t        |t              sJ t         | E  ||       y # t        $ r}t        d      |d }~ww xY w)Ng       @r_   z6Arc radius is not large enough to reach the end point.r   r/   )r   r1   r   r   r   subr   rQ  r   r   
SagittaArcr   PRIVATEro  r2   r'   r@   rA   )rC   start_point	end_pointr  short_sagittar0   r6   r  endr   r  	exceptionr  arc_edgerD   s                 r7   rA   zRadiusArc.__init__  s    %.$:$:4$@&"++KC
s&&,	f+VQY-B(CCv;,fai&!).C)DD A:UCt||DCUC'EC88:(D)))-  	H	s   AD 	D.D))D.)
r5  r%   r6  r%   r  rf   r7  r   r0   r   rF   rO   s   @r7   r0  r0  z  s\      >>"K #XX . .  . 	 .
  .  .  .r9   r0  c                  d     e Zd ZdZej
                  gZej                  f	 	 	 	 	 	 	 d fdZ	 xZ
S )r3  ae  Line Object: Sagitta Arc

    Create a circular arc defined by two points and the sagitta (height of the arc from chord).

    Args:
        start_point (VectorLike): start point
        end_point (VectorLike): end point
        sagitta (float): arc height from chord between points
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c                n   t        j                  |       }t        ||        t        j                  ||      \  }}||z   dz  }|t
        j                  }	n4t        j                  t        j                         j                  d         }	||z
  j                         t        |      z  }
|
j                  t        |	j                  |	j                        |dkD  rdnd      }
||
z   }t!        |||t"        j$                        }|j'                         }t)        |t*              sJ t,        | ]  ||       y )Ng      ?r   rW  rX  r/   )r   r1   r   r   r   r#   r   r   r   r   rd  rQ  r   r!   r   r   ThreePointArcr   r4  ro  r2   r'   r@   rA   )rC   r5  r6  r  r0   r6   r  r8  	mid_pointsagitta_workplanesagitta_vector	sag_pointr  r:  rD   s                 r7   rA   zSagittaArc.__init__  s    %.$:$:4$@&"++KC
s5[C'	? % + 0 0**,77:! #&+!9!9!;c'l!J'.."))+<+B+BCA+B3

 .	E9cE88:(D)))-r9   )r5  r%   r6  r%   r  rf   r0   r   rF   rO   s   @r7   r3  r3    sO    	 >>"K XX.. . 	.
 . .r9   r3  c                  p     e Zd ZdZej
                  gZdddej                  d	 	 	 	 	 	 	 	 	 d fdZ	 xZ
S )Splinea  Line Object: Spline

    Create a spline defined by a sequence of points, optionally constrained by tangents.
    Tangents and tangent scalars must have length of 2 for only the end points or a length
    of the number of points.

    Args:
        pts (VectorLike | Iterable[VectorLike]): sequence of two or more points
        tangents (Iterable[VectorLike], optional): tangent directions. Defaults to None
        tangent_scalars (Iterable[float], optional): tangent scales. Defaults to None
        periodic (bool, optional): make the spline periodic (closed). Defaults to False
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    NF)tangentsr   rv   r0   c                  t        | }t        j                  |       }t        ||        t	        j
                  | }|r1|D 	cg c]%  }	t	        j
                  |	      j                         ' }
}	nd }
||dgt        t        |            z  }n|t        |      ng }t        j                  |D cg c]  }t        |t              r|nt        |  c}|
r=t        |
|      D cg c]%  \  }}t        |t              r||z  n
t        | |z  ' c}}nd ||d u       }t        | =  ||       y c c}	w c c}w c c}}w )Nr   )rD  rv   scaler/   )r   r   r1   r   r   r   rd  r   r   r'   r   r2   r$   r}   r@   rA   )rC   rD  r   rv   r0   r  r  r6   
spline_ptsra  spline_tangentsscalarsrl   rm   rh   r   rD   s                   r7   rA   zSpline.__init__  sI    "3'$-$:$:4$@&"++V4
LTAH&&w/::<O  #OO$;ec$x.11G/>/Jd?+PRG!!AKLA*Q'QVQZ7L # !$OW =1 (62AE
QF
 !T)
 	d+1 Ms   *D01!D5%*D:)
r  r  rD  zIterable[VectorLike] | Noner   r   rv   r   r0   r   rF   rO   s   @r7   rC  rC    sb     >>"K
 1526XX',/', .', 0	',
 ', ', ',r9   rC  c                  h     e Zd ZdZej
                  gZdej                  d	 	 	 	 	 	 	 d fdZ	 xZ
S )rn  a  Line Object: Tangent Arc

    Create a circular arc defined by two points and a tangent.

    Args:
        pts (VectorLike | Iterable[VectorLike]): sequence of two points
        tangent (VectorLike): tangent to constrain arc
        tangent_from_first (bool, optional): apply tangent to first point. Applying
            tangent to end point will flip the orientation of the arc. Defaults to True
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Two points are required
    T)tangent_from_firstr0   c               h   t        | }t        j                  |       }t        ||        t	        |      dk7  rt        d      t        j                  | }t        j                  |      j                         }|rdnd}	t        j                  ||	d      |||	d            }
t        | 1  |
|       y )Nr_   ztangent_arc requires two points)r   ru   )ru   r   r   r\   r/   )r   r   r1   r   r   r   r   r   rd  r'   r  r@   rA   )rC   ra  rK  r0   r  r  r6   arc_ptsrr  point_indicesr  rD   s              r7   rA   zTangentArc.__init__+	  s     "3'$-$:$:4$@&v;!>??((&1#,,W5@@B#57##M!$%{GM!<L4M
 	4(r9   )r  r  ra  r%   rK  r   r0   r   rF   rO   s   @r7   rn  rn  	  sR     >>"K $(XX)/) ) !	)
 ) )r9   rn  c                  X     e Zd ZdZej
                  gZej                  dd fdZ	 xZ
S )r=  a/  Line Object: Three Point Arc

    Create a circular arc defined by three points.

    Args:
        pts (VectorLike | Iterable[VectorLike]): sequence of three points
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Three points must be provided
    r/   c                   t        j                  |       }t        ||        t        | }t	        |      dk7  rt        d      t        j                  | }t        j                  | }t        | -  ||       y )Nrs   z#ThreePointArc requires three pointsr/   )r   r1   r   r   r   r   r   r   r'   make_three_point_arcr@   rA   )rC   r0   r  r6   r  r  r  rD   s          r7   rA   zThreePointArc.__init__R	  ss    $-$:$:4$@&!3'v;!BCC(116:'')9:4(r9   r  rF   rO   s   @r7   r=  r=  C	  s'    
 >>"KMQXX 
) 
)r9   r=  zuThe 'PointArcTangentLine' object is deprecated and will be removed in a future version. Use ConstrainedLines instead.c                  z     e Zd ZdZej
                  gZej                  e	j                  f	 	 	 	 	 	 	 d fdZ xZS )PointArcTangentLinea  Line Object: Point Arc Tangent Line

    Create a straight, tangent line from a point to a circular arc.

    Args:
        point (VectorLike): intersection point for tangent
        arc (Curve | Edge | Wire): circular arc to tangent, must be GeomType.CIRCLE
        side (Side, optional): side of arcs to place tangent arc center, LEFT or RIGHT.
            Defaults to Side.LEFT
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c           	     `   t         j                  dt         j                  di}t        j                  |       }t        ||        |j                  t        j                  k7  rt        d      t        j                  |      }|bt        j                  ||j                        j                  |      }|t        d      t!        |j"                  |j%                               }	n4t'        j(                  t        j                         j*                  d         }	|j                  }
|j,                  }||
z
  }|j.                  |k  rt        d      |j1                  |	j2                        }t5        |j.                  dz  |dz  z
        }t        j                  ||f      j1                  |	j2                        }||   |z  |z   }t        j                  |t7        t9        |            z  |t;        t9        |            z  f      |
z   }t        j                  ||      }t<        | }  ||       y )	Nru   r\   zArc must have GeomType.CIRCLE.z1PointArcTangentLine only works on a single plane.r_  r   z/Cannot find tangent for point on or inside arc.r_   ) r   LEFTRIGHTr   r1   r   	geom_typer   r  r   r   r   r'   r   ry  re  r#   r   normalr   r   r   r  r   get_signed_angler   r   r
   r   r   r@   rA   )rC   pointr  sider0   	side_signr6   tangent_pointcoplaners  ry  r  midlinephi	other_legr   rB  r   ra  rD   s                      r7   rA   zPointArcTangentLine.__init__r	  s    IIrJJ
	
 %.$:$:4$@&==HOO+=>>%..u5?nn]CNNCPPQTUG !TUUgnnCJJLAI#(()C)C)E)P)PQR)STI^^
*,>>V#NOO &&y7*VQY67	&&	':;LLOO
 $%'#-""#gen--vGEN8K/KL  	 ..	:$'r9   )rZ  r%   r  r  r[  r   r0   r   rG   rH   rI   rJ   r   rK   rL   r   rU  r   rM   rA   rN   rO   s   @r7   rS  rS  _	  sV    

 >>"K YYXX6(6( !6( 	6(
 6( 6(r9   rS  zsThe 'PointArcTangentArc' object is deprecated and will be removed in a future version. Use ConstrainedArcs instead.c                  ~     e Zd ZdZej
                  gZej                  e	j                  f	 	 	 	 	 	 	 	 	 d fdZ xZS )PointArcTangentArca  Line Object: Point Arc Tangent Arc

    Create an arc defined by a point/tangent pair and another line which the other end
    is tangent to.

    Args:
        point (VectorLike): starting point of tangent arc
        direction (VectorLike): direction at starting point of tangent arc
        arc (Union[Curve, Edge, Wire]): ending arc, must be GeomType.CIRCLE
        side (Side, optional): select which arc to keep Defaults to Side.LEFT
        mode (Mode, optional): combination mode. Defaults to Mode.ADD

    Raises:
        ValueError: Arc must have GeomType.CIRCLE
        ValueError: Point is already tangent to arc
        RuntimeError: No tangent arc found
    c                   t        j                  |       }t        ||        j                  t        j
                  k7  rt        d      t        j                  |      t        j                  |      j                         }|[t        j                  |z         j                        }|t        d      t        |j                  j                               }	n4t!        j"                  t        j                         j$                  d         }	t'        |      j)                  |	j*                  d      j                         }
j,                  z
  }|j.                  j0                  k(  rt        d      |j.                  j0                  k  rt3        d      |
j5                  |	j6                        }j,                  z
  j9                  |
       }||
z  j,                  z   }|z
  j9                  |      }|t:        j<                  k(  rd	nd
}||z  j0                  k(  rt        d      |dk  rd
nd	}t?        |      j0                  k  rd
}|dz  }|d
kD  r| }n|dz  }||j<                  k(  r| }n|}djA                         jC                        jD                  z  }dfd}tG        |	j                  |	j6                        }|
jI                  ||      }tK        |d||fdd|fgtL              }|jN                  d   }||z  z   }||k(  rtQ        d      j,                  |z
  j                         }||j5                  |	j6                        z  }||z  |z   }t?        j0                  |j,                  z
  j.                  z
        tL        kD  rtQ        d      jS                  |      }|j5                  |      j.                  tL        kD  rtQ        d      tU        ||
      tV         |   |       y )NzArc must have GeomType.CIRCLEz0PointArcTangentArc only works on a single plane.r_  r   Tr  z%Cannot find tangent for point on arc.z%Point inside arc not yet implemented.ru   r\   z2Point is already tangent to arc, use tangent line.rX  i  c                    || d   z  z   }j                   |z
  j                  j                  z
  }|dk(  rt        || z
        }|S |dk(  rt        || z
  j                  dz  z         }S )Nr   r\   ru   r_   )ry  r   r  rQ  )r  rR  minimize_typer  rS  targetr  	arc_points         r7   rV  z)PointArcTangentArc.__init__.<locals>.func
  s}    !7&)!CCF..6199CJJFJ!Z&01 M "$Z&03::>ABMr9   rY  rq   rZ  z0Arc radius very large. Can tangent line be used?z-No tangent arc found, no tangent point found.z5No tangent arc found, found tangent out of tolerance.r`  r/   )rg  zLiteral[-1, 1])-r   r1   r   rW  r   r  r   r   r   rd  r'   r   re  r#   r   rX  r   r   r   r$   r  r  ry  r   r  NotImplementedErrorr  r   r  r   rU  rQ  rf  rg  rh  r!   r   r   r    r   rm  rj  rn  r@   rA   )!rC   rZ  rC  r  r[  r0   r6   
wp_tangentr^  rs  rr  r_  tangent_perp	ref_scalerefref_to_point	keep_signr\  arc_typerB  ru  rV  rt  rR  rw  tangent_radiustangent_centertangent_normaltangent_dirr]  arc_dirri  rD   s!      `                           @r7   rA   zPointArcTangentArc.__init__	  s    %.$:$:4$@&==HOO+<==!**51	"++I6AAC
?nnY	J0FGTTG  !STTgnnCJJLAI#(()C)C)E)P)PQR)STI 9Yy22YFZ\ 	 cnn,>>SZZ'DEE>>SZZ'%&MNN
 #((9^^i/44k\B	+%6!C,,\:$))+B	|#szz1QRR &)Ar	|szz)HOE1} OEtyy %:$ #**,00;DDD
	 Y--y?!,!3!3M5!I((3 (O$
  !"%;n%LL X%QRR ..>9EEG!5!5ioo!FF&7.H szz]S^^;CCCDyPNOO ../W%,,y8VWWM;G4(r9   )
rZ  r%   rC  r%   r  r  r[  r   r0   r   rb  rO   s   @r7   rd  rd  	  sg    
$ >>"K YYXX|)|) |) !	|)
 |) |) |)r9   rd  zsThe 'ArcArcTangentLine' object is deprecated and will be removed in a future version. Use ConstrainedLines instead.c                       e Zd ZdZej
                  gZej                  e	j                  ej                  f	 	 	 	 	 	 	 	 	 d fdZ xZS )ArcArcTangentLinea  Line Object: Arc Arc Tangent Line

    Create a straight line tangent to two arcs.

    Args:
        start_arc (Curve | Edge | Wire): starting arc, must be GeomType.CIRCLE
        end_arc (Curve | Edge | Wire): ending arc, must be GeomType.CIRCLE
        side (Side): side of arcs to place tangent arc center, LEFT or RIGHT.
            Defaults to Side.LEFT
        keep (Keep): which tangent arc to keep, INSIDE or OUTSIDE.
            Defaults to Keep.INSIDE
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    c                ^   t        j                  |       }t        ||        |j                  t        j
                  k7  rt        d      |j                  t        j
                  k7  rt        d      |D|j                  |      }|t        d      t        |j                  |j                               }n4t        j                  t        j                         j                  d         }|t        j                   k(  rdnd}	||g}
|
D cg c]  }|j"                   }}|
D cg c]  }|j$                   }}|d   |d   z
  }|j&                  t)        |d   |d   z
        k  rt        d      |t*        j,                  k(  rF|j&                  t/        |      k  rt        d	      |j&                  t/        |      k(  rt        d
      |j1                  |j2                        }|t*        j,                  k(  r|d   |d   z   n
|d   |d   z
  }t5        |j&                  dz  |dz  z
        }t        j6                  ||f      j1                  |j2                        }|	|z  |z   }g }t9        t;        |
            D ]{  }|t*        j,                  k(  r|dz  |z   n|}|j=                  t        j6                  ||   t?        tA        |            z  ||   tC        tA        |            z  f      ||   z          } tE        jF                  |d   |d         }tH        |   ||       y c c}w c c}w )N$Start arc must have GeomType.CIRCLE."End arc must have GeomType.CIRCLE.z/ArcArcTangentLine only works on a single plane.r_  r   r\   ru   z4Cannot find tangent when one arc contains the other.z0Cannot find INSIDE tangent for overlapping arcs.z,Cannot find INSIDE tangent for tangent arcs.r_      )&r   r1   r   rW  r   r  r   re  r#   r   rX  r   r   r   r   r   rU  ry  r  r   rQ  r   INSIDEsumrY  r   r   r   r  r   rl  r
   r   r   r'   r   r@   rA   )rC   	start_arcend_arcr[  rq  r0   r6   r^  rs  r\  r  r  r  radiir_  r`  r  ra  r   rB  r   r   ra  rD   s                          r7   rA   zArcArcTangentLine.__init__X
  s    %.$:$:4$@&(//1CDD/ABB?,,W5G !RSSgnnI4D4D4FGI#(()C)C)E)P)PQR)STI*A	7#,01S#..11'+,,,)fQi'>>SqE!H!455STT4;;~~E
* !STT~~U+ !OPP &&y7(,(;qE!H$qERSHAT*VQY67	&&	':;LLOO
 E!C'	s4y! 	A'+t{{':AGeOE&&1XGEN 33U1XGEN@S5ST )	 ..1y|<$'S 2,s   L%%L*)
r  r  r  r  r[  r   rq  r   r0   r   rG   rH   rI   rJ   r   rK   rL   r   rU  r   r}  r   rM   rA   rN   rO   s   @r7   rx  rx  C
  sn    
 >>"K YY[[XXF(&F( %F( 	F(
 F( F( F(r9   rx  zqThe 'ArcArcTangentArc' object is deprecated and will be removed in a future version. Use ConstrainedArcs instead.c                       e Zd ZdZej
                  gZej                  e	j                  e	j                  fdej                  f	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ xZS )ArcArcTangentArca.  Line Object: Arc Arc Tangent Arc

    Create an arc tangent to two arcs and a radius.

    keep specifies tangent arc position with a Keep pair: (placement, type)

    - placement: start_arc is tangent INSIDE or OUTSIDE the tangent arc. BOTH is a
      special case for overlapping arcs with type INSIDE
    - type: tangent arc is INSIDE or OUTSIDE start_arc and end_arc

    Args:
        start_arc (Curve | Edge | Wire): starting arc, must be GeomType.CIRCLE
        end_arc (Curve | Edge | Wire): ending arc, must be GeomType.CIRCLE
        radius (float): radius of tangent arc
        side (Side): side of arcs to place tangent arc center, LEFT or RIGHT.
            Defaults to Side.LEFT
        keep (Keep | tuple[Keep, Keep]): which tangent arc to keep, INSIDE or OUTSIDE.
            Defaults to (Keep.INSIDE, Keep.INSIDE)
        short_sagitta (bool): If True selects the short sagitta (height of arc from
            chord), else the long sagitta crossing the center. Defaults to True
        mode (Mode, optional): combination mode. Defaults to Mode.ADD
    Tc                   t        |t              r||fn|\  }}	t        j                  |       }
t	        |
|        |t        j
                  k(  r|	t        j                  k7  rt        d      |j                  t        j                  k7  rt        d      |j                  t        j                  k7  rt        d      |
D|j                  |      }|t        d      t        |j                  |j                               }n4t        j                   t#        j                         j$                  d         }||g}|D cg c]  }|j&                   }}|D cg c]  }|j(                   }}|t*        j,                  k(  rdnd}|t        j.                  k(  rdnd}|d   |d   k  rdnd}|d   |d   z
  }||j1                  |j2                        z  }|j4                  t6        k  rt        d	      t9        |j4                  t;        |      z
        t6        k  r|	t        j                  k(  rt        d
      t9        |j4                  t9        |d   |d   z
        z
        t6        k  r|t        j                  k(  rt        d      d}d }ddg}d}|j4                  t9        |d   |d   z
        kD  rV|	t        j.                  k(  rC||d   z  |z   ||d   z  |z   g}||g}|j4                  ||d   |d   z   z  z
  dz  }|dk  rdn|}n|j4                  |d   |d   z   kD  rv|	t        j                  k(  rct9        |d   ||z  z         t9        |d   ||z  z
        g}|t        j.                  k(  rddgnddg}|j4                  ||d   |d   z
  z  z
  dz  }n|j4                  t9        |d   |d   z
        k  rd}|t        j.                  k(  r[|d   ||z  z   |d   ||z  z
  g}|j4                   ||d   z  z
  ||d   z  z   dz  }|j4                  ||d   z  z
  ||d   z  z   dz  }nk|t        j                  k(  rWt9        |d   |z
        t9        |d   |z
        g}|j4                   |d   z   |d   z   dz  }|j4                  |d   z   |d   z   dz  }|d   |d   k  rddg}nddg}nd}|t        j
                  k(  r?t9        |d   |z
        t9        |d   |z
        g}|j4                   |d   z   |d   z   dz  }n|t        j.                  k(  r8|d   ||z  z   |d   ||z  z
  g}|j4                  ||d   z  z
  ||d   z  z   dz  }nJ|t        j                  k(  r7|d   ||z  z
  |d   ||z  z   g}|j4                  ||d   z  z   ||d   z  z
  dz  }||k\  rt        d| d      |||k  rt        d| d      |D cg c]  }|j=                  |       }}t?        tA        |            D cg c]I  }tC        jD                  tC        jF                  ||   jH                  ||   jJ                        |         K }}tM        tC        jN                  | D cg c]i  }|jQ                  tS        tU        tC        jV                  |jX                              tU        tC        jV                  |jZ                                          k c}      }|j]                  t_        |d   |            |   } t?        tA        |            D cg c]3  }||   ||   ||   z  tS        |       ||   z
  ja                         z  z   5 }!}|t*        j,                  k(  r|!jc                          te        |!d   |!d   ||tf        jh                        }tk        |j&                  |j(                  ddtf        jh                        }"|"jm                  |      \  }#}#}$|"jo                  |$      j1                  |jo                  |$            j4                  t6        kD  r%te        |!d   |!d   | |tf        jh                        }tp        %|   ||       y c c}w c c}w c c}w c c}w c c}w c c}w )NzEKeep.BOTH can only be used in configuration: (Keep.BOTH, Keep.INSIDE)rz  r{  z.ArcArcTangentArc only works on a single plane.r_  r   r\   ru   z(Cannot find tangent for concentric arcs.zNCannot find tangent type Keep.INSIDE for non-overlapping arcs already tangent.zZCannot find tangent placement Keep.INSIDE for completely overlapping arcs already tangent.rq   r_   z4The arc radius is too small. Should be greater than r[   z1The arc radius is too large. Should be less than )r  r7  r0   r  r/   ):r2   r   r   r1   r   BOTHr}  r   rW  r   r  re  r#   r   rX  r   r   r   r   ry  r  r   rU  OUTSIDEr  r   r   r    rQ  r~  to_local_coordsr  r   sympyCirclePointXYr,   intersectionfrom_local_coordsr$   rf   Nr   r   r  r!   rd  reverser0  r   r4  r   ri  rj  r@   rA   )&rC   r  r  r  r[  rq  r7  r0   keep_placement	keep_typer6   r^  rs  r  r  r  r  r\  rp  r_signr_  rX  
min_radius
max_radiusx_sign
pick_index	ref_radiirl   localr   ref_circlesref_intersectionsry  r   start_circler  rZ  rD   s&                                        r7   rA   zArcArcTangentArc.__init__
  s    5?tT4JT4LPT!	$-$:$:4$@&TYY&9+CW  (//1CDD/ABB?,,W5G !QRRgnnI4D4D4FGI#(()C)C)E)P)PQR)STI7#,01S#..11'+,,,*A	'4<<7AR	Ahq)r )fQi'W]]9??;;>>I%GHHw~~E
*+i7I<T#  U1Xa%8!99:YF$++-4  

Q
>>Ca58 344dll9R"U1X-6	E!H8Lv8UVI+F!..9a588K+LLPQQJ(1n*J^^eAhq11i4;;6N E!Hy6112E!Hy6112I !/$,, >aWRGF!..9a588K+LLPQQJ^^s58eAh#677J-"1X7qFVO9ST	^^OfuQx&77&58:KK
 NNVeAh%66%(9JJ
  4;;. qF!23SqF9J5KL	&~~oa858CqH
%nnuQx7%(BaG
8eAh& !WFWF J* qF!23SqF9J5KL	&~~oa858CqH
4<</"1X7qFVO9ST	NNVeAh%66%(9JJ
  4;;."1X7qFVO9ST	NNVeAh%66%(9JJ
 FzlRST  !jF&:CJ<qQ  8>>!**1->> 3t9%
 LLU1XZZq<ilK
 

 &
 ++[9	  ++5.eggaccl0CD
 '..tF1Iv/FG
S
 3t9%
  1IQi%("fZ&86!9&D%P%P%RRS
	 
 499aLaL'
 !  )"2"2As
 #BB3G1e##E*001FGNN !!w+\\C 	d#I 2,` ?

s&   ?aa?a/AaA.a8a)r  r  r  r  r  rf   r[  r   rq  zKeep | tuple[Keep, Keep]r7  r   r0   r   r  rO   s   @r7   r  r  
  s    
. >>"K YY*.++t{{)C"XXI$&I$ %I$ 	I$
 I$ 'I$ I$ I$ I$r9   r  )r5   zEdge | Wire | Curver0   r   )^rJ   
__future__r   r   r   r  collections.abcr   r   r   	itertoolsr   mathr   r	   r
   r   r   r   r   typingr   r   numpyrw   r  scipy.optimizer   typing_extensionsr   build123d.build_commonr   r   r   build123d.build_enumsr   r   r   r   r   r   r   r   r   build123d.build_liner   build123d.geometryr    r!   r"   r#   r$   r%   build123d.topologyr&   r'   r(   r)   r*   build123d.topology.shape_corer+   r,   r8   r;   rQ   rT   rW   r   r   r   r   r  r8  rN  r  r  r  r  r  r  r  r   r  r  r,  r0  r3  rC  rn  r=  rS  rd  rx  r  r  r9   r7   <module>r     s|  8 #   8 8  B B B $   # ( S S
 
 
 + S S > > :? ,e ,",T ,"(T ( x5n x5v+^ +>`3 `3F:,n :,zV) V)rA+o A+HU+ U+pe1~ e1PC+. C+Ln) n)bA+ A+HE+. E+P)+N )+Xl.^ l.^h)n h)V.> .>&.~ &.Rg. g.T&@~ &@R3. 3.l+. +.\8,^ 8,v') ')T)N )8 %E(. E(	E(P $Q) Q)	Q)h %W( W(	W(t $c$~ c$	c$r9   