
    Og+                       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    [/var/www/html/public_html/myphp/venv/lib/python3.12/site-packages/ezdxf/math/construct2d.pyr   r   0   s    s74$$    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    efnd+HCc4 HC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     eK0%	2BCCr%   c                    t        |       } d}d}|D ]*  }t        |      }| j                  |      }|||k  s'|}|}, |S )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   sZ     :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 )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                0    || z
  j                  || z
        S N)det)oabs      r$   crosszconvex_hull_2d.<locals>.crossl   s    A{{1q5!!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   " yyV%HMMO
8}qTUU]Ax1q5)DA1X 1ftAE{DQK!ELFA 1ftAE{DQK!EL1+Q	Q	
 UA1q5"b! 1ftAE{DQK!ELFA 1ftAE{DQK!EL1+Q	Q	
 8Or%   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    dllG4GdhhADHHAAq!}q!}1uIAI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     GWGWLE5		W_'w')*w02	

 	  cU?"GUG'!W?? @U?"GUG'!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     55577?uww0
1SUUUWW_%''5 C 3x7	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
3CQwQw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..99eem((u56#+9P9P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LL2<<'",,6EHHRL""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|     IIhE
5zA~ 8E"I&U1X2887Aacc133Z7rzz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     3B36
C
12q5/C
3B36
C
12q5/C66"&&sS3Y./03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//1D1D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s8w!$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      ||ACC%%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    && KEay$
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   # %       	WWs]
gg3DGGm*%
D"("J 9=i " .29$$$#'$	$P 2;#'2&QL$7$
F 9>t %P'r%   