Ë
    £èhb-  ã                  óŠ  — d dl mZ d dlmZmZ d dlmZ d dlZd dlZ	d dl
mZ d dlmZmZmZmZmZmZmZ dZej*                  dz  Zej*                  Zedz  Zdej*                  z  Zg d	¢Zdd
„Zdd„Zd d„Zd!d„Zd"d„Zdefd„Z def	 	 	 	 	 	 	 d#d„Z!ef	 	 	 	 	 	 	 d$d„Z"d%d#d„Z#d&d„Z$d'd„Z%d(d„Z&d)d„Z'd*d„Z(dddœd+d„Z)d,d„Z*y)-é    )Ú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                ó   — | dk  rdS dS )z2Return sign of float `f` as -1 or +1, 0 returns +1ç        g      ð¿g      ð?© )Úfs    ú6lib/python3.12/site-packages/ezdxf/math/construct2d.pyr   r   0   s   € à�s’7ˆ4Ð$ Ð$ó    c                óN   — t        | dz  d«      \  }}t        |d«      \  }}|||fS )z<Return decimal degrees as tuple (Degrees, Minutes, Seconds).g      ¬@g      N@)Údivmod)ÚvalueÚmntÚsecÚdegs       r$   r   r   5   s2   € ä�e˜f‘n dÓ+�H€CˆÜ�c˜4Ó �H€CˆØ��Sˆ=Ðr%   c                ó>   — t        t        | «      t        |«      «      S )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   € ô œe KÓ0´%¸	Ó2BÓCÐCr%   c                ó‚   — t        | «      } d}d}|D ]*  }t        |«      }| j                  |«      }|�||k  sŒ'|}|}Œ, |S )zÄReturns 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   sU   € ô �‹:€DØ!€HØ€EÛˆÜ�‹KˆØ�}‰}˜QÓˆØÐ $¨£/ØˆHØ‰Eð ð €Lr%   c                ó†  — d
d„}t        j                  t        | «      «      }|j                  «        t	        |«      dk  rt        d«      ‚t	        |«      }t        «       gd|z  z  }d}t        |«      D ]W  }|dk\  rC |||dz
     ||dz
     ||   «      dk  r'|dz  }|dk\  r |||dz
     ||dz
     ||   «      dk  rŒ'||   ||<   |dz  }ŒY |dz   }t        |dz
  dd«      D ]W  }||k\  rC |||dz
     ||dz
     ||   «      dk  r'|dz  }||k\  r |||dz
     ||dz
     ||   «      dk  rŒ'||   ||<   |dz  }ŒY |d	| S )z¾Returns 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                ó0   — || z
  j                  || z
  «      S ©N)Údet)ÚoÚaÚbs      r$   Úcrosszconvex_hull_2d.<locals>.crossl   s   € Ø�A‘�{‰{˜1˜q™5Ó!Ð!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   s‡  € ó"ô �y‰yœ˜V›Ó%€HØ‡M�M„OÜ
ˆ8ƒ}�qÒÜÐTÓUÐUä�‹]€AÜ›�x 1 q¡5Ñ)€DØ€Aä�1ŽXˆØ�1Šf™˜t A¨¡E™{¨D°°Q±©K¸À!¹ÓEÈÒLØ�‰FˆAð �1Šf™˜t A¨¡E™{¨D°°Q±©K¸À!¹ÓEÈÓLà˜1‘+ˆˆQ‰Ø	ˆQ‰‰ð	 ð
 �‰U€AÜ�1�q‘5˜"˜bÖ!ˆØ�1Šf™˜t A¨¡E™{¨D°°Q±©K¸À!¹ÓEÈÒLØ�‰FˆAð �1Šf™˜t A¨¡E™{¨D°°Q±©K¸À!¹ÓEÈÓLà˜1‘+ˆˆQ‰Ø	ˆQ‰‰ð	 "ð
 ��ˆ8€Or%   Tc                ó*  — t        t        j                  |¬«      }|t        j                  z  }|t        j                  z  }| t        j                  z  } |||«      r	 |||«      S ||k  r||cxk  xr |k  nc }	n||cxk  xr |k  nc  }	|r|	S |	 S )N)Úabs_tol)r   ÚmathÚiscloseÚtau)
ÚangleÚstart_angleÚ	end_angleÚccwrS   rU   ÚsÚer>   Úrs
             r$   r   r   †   sƒ   € Ü”d—l‘l¨GÔ4€Gà”d—h‘hÑ€AØ”D—H‘HÑ€AØ”—‘Ñ€AÙˆq�!„}Ù�q˜!‹}Ðàˆ1‚uØ�ŽI�AŒI‰à�Q–˜”ˆOˆÙˆ1Ð˜Q˜Ðr%   c                ó  — | \  }}|\  }}|\  }	}
t        j                  |
|z
  |z  |	|z
  |z  z
  |	|z  |
|z  z
  z   «      |k  }|r|r|S ||	kD  r|	|}	}||z
  |cxk  r|	|z   k  sy y||
kD  r|
|}
}||z
  |cxk  r|
|z   k  sy yy)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)rT   Úfabs)r6   ÚstartÚendÚrayrS   Úpoint_xÚpoint_yÚstart_xÚstart_yÚend_xÚend_yÚon_lines               r$   r   r   –   sá   € ð Ñ€GˆWØÑ€GˆWØ�L€Eˆ5ä�	‰	Ø�W‰_ Ñ'Ø�w‰ 'Ñ)ñ*à�w‰ ¨¡Ñ0ñ2ó	
ð
 ñ	ð ñ ‘cØˆà�UŠ?Ø" G�UˆGØ˜'Ñ! WÔ?°¸±Ò?Øð @ØØ�UŠ?Ø" G�UˆGØ˜'Ñ! WÔ?°¸±Ò?Øð @ØØr%   c                óü   — |j                   |j                   z
  | j                  |j                  z
  z  |j                  |j                  z
  | j                   |j                   z
  z  z
  }t        |«      |k  ry|dk  ryy)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   rC   rD   )ÚxÚyÚabs)r6   r`   ra   rS   Úrels        r$   r   r   ½   sm   € ð �5‰5�5—7‘7‰?˜uŸw™w¨¯©Ñ0Ñ
1°S·U±U¸U¿W¹W±_Ø�‰�%—'‘'Ññ5ñ €Cô ˆ3ƒx�7ÒØØ	ˆqŠØàr%   Fc                ó4   — t        | ||«      }|r|dk  S |dk  S )a˜  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``

    rC   r   )r   )r6   r`   ra   Úcolinearrn   s        r$   r   r   Ö   s'   € ô ! ¨¨sÓ
3€CÙØ�Q‰wˆà�Q‰wˆr%   c                ó®   — |j                  |«      rt        d«      ‚t        j                  || z
  j	                  || z
  «      «      ||z
  j
                  z  S )zaReturns the normal distance from `point` to 2D line defined by `start-`
    and `end` point.
    zNot a line.)rU   ÚZeroDivisionErrorrT   r_   r<   Ú	magnitude)r6   r`   ra   s      r$   r   r   é   sL   € ð
 ‡}�}�SÔÜ Ó.Ð.Ü�9‰9�e˜e‘m×(Ñ(¨¨u©Ó5Ó6¸#À¹+×9PÑ9PÑPÐPr%   c                ó²   — || z
  }|| z
  }||z
  }|j                   |j                   z  |j                   z  }|j                  |«      j                   dz  }||z  S )Nr   )rs   r@   )r>   r?   ÚcÚbaÚcaÚcbÚupperÚlowers           r$   r   r   ó   sZ   € Ø	
ˆQ‰€BØ	
ˆQ‰€BØ	
ˆQ‰€BØ�L‰L˜2Ÿ<™<Ñ'¨"¯,©,Ñ6€EØ�H‰H�R‹L×"Ñ" SÑ(€EØ�5‰=Ðr%   c           	     óN  — t        j                  | «      }t        |«      dk  ry|d   j                  |d   «      s|j	                  |d   «       t        t        j                  |D �cg c]  }|j                  |j                  f‘Œ c}t        j                  ¬«      «      S c c}w )zReturns the area of a polygon.

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

    rA   r!   r   rD   )Údtype)r   rF   rI   rU   Úappendr   ÚnpÚarrayrk   rl   Úfloat64)rL   Úvec2sÚvs      r$   r   r   ü   s€   € ô �I‰I�hÓ€EÜ
ˆ5ƒz�A‚~Øð �‰8×Ñ˜E "™IÔ&Ø�‰�U˜1‘XÔÜ”2—8‘8±Ó7±¨A˜aŸc™c 1§3¡3šZ°Ñ7¼r¿z¹zÔJÓKÐKùÒ7s   Á(B"c                ó²   — | dd…df   }| dd…df   }| dd…df   }| dd…df   }t        j                  t        j                  ||z  ||z  z
  «      «      dz  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

    NrD   r   rC   g      à?)r~   rm   Úsum)rL   Úp1xÚp2xÚp1yÚp2ys        r$   r   r     sp   € ð �3�B�3˜�6Ñ
€CØ
�1‘2�q�5‰/€CØ
�3�B�3˜�6Ñ
€CØ
�1‘2�q�5‰/€CÜ�6‰6”"—&‘&˜˜s™ S¨3¡YÑ.Ó/Ó0°3Ñ6Ð6r%   c                ó¬   — | j                  t        «      }| j                  t        «      }t        j                  |j
                  |j
                  «       S )a3  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   rT   rU   Úmagnitude_square)ÚmÚuxÚuys      r$   r   r      sD   € ð 
×	Ñ	œvÓ	&€BØ	
×	Ñ	œvÓ	&€BÜ�|‰|˜B×/Ñ/°×1DÑ1DÓEÐEÐEr%   g�íµ ÷Æ°>)ÚstrictÚepsilonc               ó  — t        | «      dk  ryd}d}| d   }| d   }| D ]U  }|j                  |«      rŒ||z
  j                  ||z
  «      }t        |«      |k\  r|dk  rdnd}|s|}||k7  r y|r y|}|}ŒW t	        |«      S )aˆ  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!

    rA   Fr   rD   éþÿÿÿr!   rC   )rI   rU   r<   rm   Úbool)	Úpolygonr�   r�   Úglobal_signÚcurrent_signÚprevÚ	prev_prevÚvertexr<   s	            r$   r   r   -  sª   € ô ˆ7ƒ|�aÒØà€KØ€LØ�2‰;€DØ˜‘€IÛˆØ�>‰>˜$ÔØà�f‰}×!Ñ! )¨dÑ"2Ó3ˆÜˆs‹8�wÒØ!$ s¢™2°ˆLÙØ*�à˜lÒ*ÙÙÙàˆ	Ø‰ð! ô" �ÓÐr%   c                ó  — d	d„}d
d„}t        | «      }| d   j                  | d   «      r|dz  }|dk7  ry| ^}}}}} |||«      r |||«      r |||«      r
 |||«      ry |||«      r |||«      r |||«      r
 |||«      ryy)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                óV   — t        j                  | j                  |j                  «      S r;   )rT   rU   rl   ©r>   r?   s     r$   Úis_horizontalz3is_axes_aligned_rectangle_2d.<locals>.is_horizontalb  ó   € Ü�|‰|˜AŸC™C §¡Ó%Ð%r%   c                óV   — t        j                  | j                  |j                  «      S r;   )rT   rU   rk   rœ   s     r$   Úis_verticalz1is_axes_aligned_rectangle_2d.<locals>.is_verticale  rž   r%   r   rD   rC   é   FT)r>   r   r?   r   rE   r“   )r>   r   r?   r   )rI   rU   )	r3   r�   r    ÚcountÚp0Úp1Úp2Úp3Ú_s	            r$   r   r   U  s©   € ó&ó&ô �‹K€EØˆa�y×Ñ˜ ™Ô$Ø�‰
ˆØ�‚zØØÐ€BˆˆB��Qá�b˜"ÔÙ˜˜BÔÙ˜"˜bÔ!Ù˜˜BÔàá�b˜"ÔÙ˜˜BÔÙ˜"˜bÔ!Ù˜˜BÔàØr%   )r#   r-   rE   r-   )r(   r-   rE   ztuple[float, float, float])r.   r-   r/   r-   rE   r-   )r2   r	   r3   úIterable[UVec]rE   zVec3 | None)r3   r¨   rE   ú
list[Vec2])r6   r   r`   r   ra   r   rE   r“   )r6   r   r`   r   ra   r   rE   Úint)F)r6   r   r`   r   ra   r   rE   r-   )r>   r   r?   r   ru   r   rE   r-   )rL   r¨   rE   r-   )rL   znpt.NDArrayrE   r-   )rŒ   r
   rE   r“   )r”   r©   rE   r“   )r3   r©   rE   r“   )+Ú
__future__r   Útypingr   r   Ú	functoolsr   rT   Ú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  ðõ #ß %å Û Û Ý ÷÷ ñ ð €	Ø�W‰W�s‰]€
Ø�g‰g€Ø˜3Ñ€Ø�D—G‘G‰m€ò€ó*%ó
óDó"ó("ðJ 9=Àió ð" .2¸9ð$Øð$Øð$Ø#'ð$à	ó$ðP 2;ðØðØðØ#'ðàóô2ó&QóóLó$7ó$
Fð 9>Àtõ %ôP'r%   