
    h+                       S SK Jr  S SKJrJr  S SKJr  S SKrS SKr	S SK
Jr  S SKJrJrJrJrJrJrJr  Sr\R*                  S-  r\R*                  r\S-  rS\R*                  -  r/ S	QrSS
 jrSS jrS S jrS!S jrS"S jrS\4S jr S\4       S#S jjr!\4       S$S jjr"S%S#S jjr#S&S jr$S'S jr%S(S jr&S)S jr'S*S jr(SSS.S+S jjr)S,S jr*g)-    )annotations)IterableSequence)partialN)Vec3Vec2UVecMatrix44X_AXISY_AXISarc_angle_span_radg|=       @g      @)closest_pointconvex_hull_2ddistance_point_line_2dis_convex_polygon_2dis_axes_aligned_rectangle_2dis_point_on_line_2dis_point_left_of_linepoint_to_line_relationenclosing_anglessignareanp_areacircle_radius_3p	TOLERANCEhas_matrix_2d_stretching
decdeg2dmsellipse_param_spanc                    U S:  a  S$ S$ )z2Return sign of float `f` as -1 or +1, 0 returns +1        g      g      ? )fs    H/var/www/html/env/lib/python3.13/site-packages/ezdxf/math/construct2d.pyr   r   0   s    s74$$    c                H    [        U S-  S5      u  p[        US5      u  p1X1U4$ )z<Return decimal degrees as tuple (Degrees, Minutes, Seconds).g      @g      N@)divmod)valuemntsecdegs       r$   r   r   5   s,    efnd+HCc4 HCS=r%   c                >    [        [        U 5      [        U5      5      $ )u  Returns the counter-clockwise params span of an elliptic arc from start-
to end param.

Returns the param span in the range [0, 2π], 2π is a full ellipse.
Full ellipse handling is a special case, because normalization of params
which describe a full ellipse would return 0 if treated as regular params.
e.g. (0, 2π) → 2π, (0, -2π) → 2π, (π, -π) → 2π.
Input params with the same value always return 0 by definition:
(0, 0) → 0, (-π, -π) → 0, (2π, 2π) → 0.

Alias to function: :func:`ezdxf.math.arc_angle_span_rad`

)r   float)start_param	end_params     r$   r   r   <   s     eK0%	2BCCr%   c                    [        U 5      n SnSnU H-  n[        U5      nU R                  U5      nUb  Xb:  d  M)  UnUnM/     U$ )zReturns the closest point to a give `base` point.

Args:
    base: base point as :class:`Vec3` compatible object
    points: iterable of points as :class:`Vec3` compatible object

N)r   distance)basepointsmin_distfoundpointpdists          r$   r   r   M   sS     :D!HEK}}Q$/HE  Lr%   c                   S
S jn[         R                  " [        U 5      5      nUR                  5         [	        U5      S:  a  [        S5      e[	        U5      n[        5       /SU-  -  nSn[        U5       HU  nUS:  aA  U" XES-
     XES-
     X&   5      S::  a'  US-  nUS:  a  U" XES-
     XES-
     X&   5      S::  a  M'  X&   XE'   US-  nMW     US-   n[        US-
  SS5       HS  nXW:  a@  U" XES-
     XES-
     X&   5      S::  a&  US-  nXW:  a  U" XES-
     XES-
     X&   5      S::  a  M&  X&   XE'   US-  nMU     US	U $ )zReturns the 2D convex hull of given `points`.

Returns a closed polyline, first vertex is equal to the last vertex.

Args:
    points: iterable of points, z-axis is ignored

c                ,    X-
  R                  X -
  5      $ N)det)oabs      r$   crossconvex_hull_2d.<locals>.crossl   s    {{15!!r%      z9Convex hull calculation requires 3 or more unique points.   r      r!   N)r=   r   r>   r   r?   r   returnr-   )r   listsetsortlen
ValueErrorrange)r3   r@   verticesnhullkits           r$   r   r   a   sc   " yyV%HMMO
8}qTUU]Ax1q5)DA1X1ftE{DQKELFA 1ftE{DQKEL+	Q	 
 UA1q5"b!ftE{DQKELFA ftE{DQKEL+	Q	 "
 8Or%   Tc                T   [        [        R                  US9nU[        R                  -  nU[        R                  -  nU [        R                  -  nU" Xg5      (       a  U" Xh5      $ Xg:  a  Xhs=:  =(       a    U:  Os  n	OXxs=:  =(       a    U:  Os  (       + n	U(       a  U	$ U	(       + $ )N)abs_tol)r   mathisclosetau)
anglestart_angle	end_angleccwrT   rV   ser>   rs
             r$   r   r      s    dllG4GdhhADHHAAq}}q}uIIAIO1Qr%   c                   U u  pVUu  pxUu  p[         R                  " X-
  U-  X-
  U-  -
  X-  X-  -
  -   5      U:*  nU(       a  U(       a  U$ Xy:  a  XpXt-
  Us=::  a	  X-   ::  d   g  gX:  a  XpX-
  Us=::  a	  X-   ::  d   g  gg)a`  Returns ``True`` if `point` is on `line`.

Args:
    point: 2D point to test as :class:`Vec2`
    start: line definition point as :class:`Vec2`
    end: line definition point as :class:`Vec2`
    ray: if ``True`` point has to be on the infinite ray, if ``False``
        point has to be on the line segment
    abs_tol: tolerance for on the line test

FT)rU   fabs)r6   startendrayrT   point_xpoint_ystart_xstart_yend_xend_yon_lines               r$   r   r      s     GGLE		_'')*02	

 	  c?"U!W?? @?"U!W?? @r%   c                    UR                   UR                   -
  U R                  UR                  -
  -  UR                  UR                  -
  U R                   UR                   -
  -  -
  n[        U5      U::  a  gUS:  a  gg)a  Returns ``-1`` if `point` is left `line`, ``+1`` if `point` is right of
`line` and ``0`` if `point` is on the `line`. The `line` is defined by two
vertices given as arguments `start` and `end`.

Args:
    point: 2D point to test as :class:`Vec2`
    start: line definition point as :class:`Vec2`
    end: line definition point as :class:`Vec2`
    abs_tol: tolerance for minimum distance to line

r   rD   rE   )xyabs)r6   ra   rb   rT   rels        r$   r   r      sm     55577?uww0
1SUUUWW_%''5 C 3x7	qr%   Fc                <    [        XU5      nU(       a  US:  $ US:  $ )ax  Returns ``True`` if `point` is "left of line" defined by `start-` and
`end` point, a colinear point is also "left of line" if argument `colinear`
is ``True``.

Args:
    point: 2D point to test as :class:`Vec2`
    start: line definition point as :class:`Vec2`
    end: line definition point as :class:`Vec2`
    colinear: a colinear point is also "left of line" if ``True``

rD   r   )r   )r6   ra   rb   colinearro   s        r$   r   r      s%     !s
3CQwQwr%   c                    UR                  U5      (       a  [        S5      e[        R                  " X-
  R	                  X -
  5      5      X!-
  R
                  -  $ )zYReturns the normal distance from `point` to 2D line defined by `start-`
and `end` point.
zNot a line.)rV   ZeroDivisionErrorrU   r`   r<   	magnitude)r6   ra   rb   s      r$   r   r      sI    
 }}S..99em((56#+9P9PPPr%   c                    X-
  nX -
  nX!-
  nUR                   UR                   -  UR                   -  nUR                  U5      R                   S-  nXg-  $ )Nr   )rt   r@   )r>   r?   cbacacbupperlowers           r$   r   r      sR    	
B	
B	
BLL2<<'",,6EHHRL""S(E=r%   c           	     \   [         R                  " U 5      n[        U5      S:  a  gUS   R                  US   5      (       d  UR	                  US   5        [        [        R                  " U Vs/ s H  o"R                  UR                  4PM     sn[        R                  S95      $ s  snf )zwReturns the area of a polygon.

Returns the projected area in the xy-plane for any vertices (z-axis will be ignored).

rB   r!   r   rE   )dtype)r   rG   rJ   rV   appendr   nparrayrl   rm   float64)rM   vec2svs      r$   r   r      s     IIhE
5zA~ 8E"I&&U1X2887Acc133Z7rzzJKK7s   0!B)c                    U SS2S4   nU SS2S4   nU SS2S4   nU SS2S4   n[         R                  " [         R                  " X-  X2-  -
  5      5      S-  $ )a  Returns the area of a polygon.

Returns the projected area in the xy-plane, the z-axis will be ignored.
The polygon has to be closed (first vertex == last vertex) and should have 3 or more
corner vertices to return a valid result.

Args:
    vertices: numpy array [:, n], n > 1

NrE   r   rD   g      ?)r   rn   sum)rM   p1xp2xp1yp2ys        r$   r   r     sl     3B36
C
12q5/C
3B36
C
12q5/C66"&&SY./0366r%   c                    U R                  [        5      nU R                  [        5      n[        R                  " UR
                  UR
                  5      (       + $ )a  Returns ``True`` if matrix `m` performs a non-uniform xy-scaling.
Uniform scaling is not stretching in this context.

Does not check if the target system is a cartesian coordinate system, use the
:class:`~ezdxf.math.Matrix44` property :attr:`~ezdxf.math.Matrix44.is_cartesian`
for that.
)transform_directionr   r   rU   rV   magnitude_square)muxuys      r$   r   r      sD     
		v	&B	
		v	&B||B//1D1DEEEr%   gư>)strictepsilonc               .   [        U 5      S:  a  gSnSnU S   nU S   nU  Hg  nUR                  U5      (       a  M  XW-
  R                  Xe-
  5      n[        U5      U:  a  US:  a  SOSnU(       d  UnX4:w  a    gO	U(       a    gUnUnMi     [	        U5      $ )ap  Returns ``True`` if the 2D `polygon` is convex.

This function supports open and closed polygons with clockwise or counter-clockwise
vertex orientation.

Coincident vertices will always be skipped and if argument `strict` is ``True``,
polygons with collinear vertices are not considered as convex.

This solution works only for simple non-self-intersecting polygons!

rB   Fr   rE   r!   rD   )rJ   rV   r<   rn   bool)	polygonr   r   global_signcurrent_signprev	prev_prevvertexr<   s	            r$   r   r   -  s     7|aKL2;DI>>$}!!)"23s8w!$s2L** +	! " r%   c                \   S	S jnS
S jn[        U 5      nU S   R                  U S   5      (       a  US-  nUS:w  a  gU tpEpgnU" XE5      (       a(  U" XV5      (       a  U" Xg5      (       a  U" Xt5      (       a  gU" XV5      (       a(  U" Xg5      (       a  U" Xt5      (       a  U" XE5      (       a  gg)a  Returns ``True`` if the given points represent a rectangle aligned with the
coordinate system axes.

The sides of the rectangle must be parallel to the x- and y-axes of the coordinate
system.  The rectangle can be open or closed (first point == last point) and
oriented clockwise or counter-clockwise.  Only works with 4 or 5 vertices, rectangles
that have sides with collinear edges are not considered rectangles.

.. versionadded:: 1.2.0

c                X    [         R                  " U R                  UR                  5      $ r;   )rU   rV   rm   r>   r?   s     r$   is_horizontal3is_axes_aligned_rectangle_2d.<locals>.is_horizontalb      ||ACC%%r%   c                X    [         R                  " U R                  UR                  5      $ r;   )rU   rV   rl   r   s     r$   is_vertical1is_axes_aligned_rectangle_2d.<locals>.is_verticale  r   r%   r   rE   rD      FT)r>   r   r?   r   rF   r   )r>   r   r?   r   )rJ   rV   )	r3   r   r   countp0p1p2p3_s	            r$   r   r   U  s    && KEay$$
zBBQb"!!b"!!r%   )r#   r-   rF   r-   )r(   r-   rF   ztuple[float, float, float])r.   r-   r/   r-   rF   r-   )r2   r	   r3   Iterable[UVec]rF   zVec3 | None)r3   r   rF   
list[Vec2])r6   r   ra   r   rb   r   rF   r   )r6   r   ra   r   rb   r   rF   int)F)r6   r   ra   r   rb   r   rF   r-   )r>   r   r?   r   rv   r   rF   r-   )rM   r   rF   r-   )rM   znpt.NDArrayrF   r-   )r   r
   rF   r   )r   r   rF   r   )r3   r   rF   r   )+
__future__r   typingr   r   	functoolsr   rU   numpyr   numpy.typingnpt
ezdxf.mathr   r   r	   r
   r   r   r   r   pi
RADIANS_90RADIANS_180RADIANS_270RADIANS_360__all__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r"   r%   r$   <module>r      s   # %       	WWs]
gg3DGGm*%
D"("J 9=i " .29$$$#'$	$P 2;#'2&QL$7$
F 9>t %P'r%   