
    'j+                    R   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"dAd?d'Z#dBd(Z$dCd-Z%dDd/Z&dEd1Z'dFd4Z(d&d5d6dGd8Z)dHd9Z*dS )I    )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_spanffloatreturnc                    | dk     rdndS )z2Return sign of float `f` as -1 or +1, 0 returns +1        g      g      ? )r    s    P/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/math/construct2d.pyr   r   0   s    s7744$    valuetuple[float, float, float]c                ^    t          | dz  d          \  }}t          |d          \  }}|||fS )z<Return decimal degrees as tuple (Degrees, Minutes, Seconds).g      @g      N@)divmod)r(   mntsecdegs       r&   r   r   5   s8    efnd++HCc4  HCS=r'   start_param	end_paramc                V    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   r!   )r/   r0   s     r&   r   r   <   s$     eK00%	2B2BCCCr'   baser	   pointsIterable[UVec]Vec3 | Nonec                    t          |           } d}d}|D ]2}t          |          }|                     |          }|||k     r|}|}3|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)r2   r3   min_distfoundpointpdists          r&   r   r   M   sb     ::D!HE  KK}}Q$//HELr'   
list[Vec2]c                @   dd}t          j        t          |                     }|                                 t	          |          dk     rt          d	          t	          |          }t                      gd
|z  z  }d}t          |          D ]u}|d
k    r] |||d
z
           ||dz
           ||                   dk    r4|dz  }|d
k    r) |||d
z
           ||dz
           ||                   dk    4||         ||<   |dz  }v|dz   }t          |d
z
  dd          D ]u}||k    r] |||d
z
           ||dz
           ||                   dk    r4|dz  }||k    r) |||d
z
           ||dz
           ||                   dk    4||         ||<   |dz  }v|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

    or   abr"   r!   c                8    || z
                       || z
            S N)det)r?   r@   rA   s      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   rA   r   r"   r!   )r   listsetsortlen
ValueErrorrange)r3   rE   verticesnhullkits           r&   r   r   a   s   " " " " yV%%HMMOOO
8}}qTUUU]]Ax1q5)DA1XX  1fftAE{DQK!EELLFA 1fftAE{DQK!EELL1+Q	QUA1q5"b!!  1fftAE{DQK!EELLFA 1fftAE{DQK!EEL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     o|k     nc }	n||cxk     o|k     nc  }	|r|	n|	 S )N)abs_tol)r   mathisclosetau)
anglestart_angle	end_angleccwrW   rY   ser@   rs
             r&   r   r      s    dlG444GdhADHAAwq!}} wq!}}1uuIIIIAIIIIQO11Qr'   r:   r   startendboolc                   | \  }}|\  }}|\  }	}
t          j        |
|z
  |z  |	|z
  |z  z
  |	|z  |
|z  z
  z             |k    }|r|r|S ||	k    r|	|}	}||z
  |cxk    r	|	|z   k    sn dS ||
k    r|
|}
}||z
  |cxk    r	|
|z   k    sn dS dS )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)rX   fabs)r:   rb   rc   rayrW   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????????5U??"GUG'!W????????5tr'   intc                    |j         |j         z
  | j        |j        z
  z  |j        |j        z
  | j         |j         z
  z  z
  }t          |          |k    rdS |dk     rdS dS )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   rH   rI   )xyabs)r:   rb   rc   rW   rels        r&   r   r      sj     557?uw0
1SUUW_%'5 C 3xx7q	qrrr'   Fc                @    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``

    rH   r   )r   )r:   rb   rc   colinearrt   s        r&   r   r      s/     !s
3
3C QwQwr'   c                    |                     |          rt          d          t          j        || z
                      || z
                      ||z
  j        z  S )zaReturns the normal distance from `point` to 2D line defined by `start-`
    and `end` point.
    zNot a line.)rY   ZeroDivisionErrorrX   rf   rD   	magnitude)r:   rb   rc   s      r&   r   r      sX    
 }}S /...9eem((u5566#+9PPPr'   r@   r   rA   cc                    || z
  }|| z
  }||z
  }|j         |j         z  |j         z  }|                    |          j         dz  }||z  S )Nr   )ry   rE   )r@   rA   rz   bacacbupperlowers           r&   r   r      sS    	
QB	
QB	
QBL2<'",6EHHRLL"S(E5=r'   rP   c                :   t          j        |           }t          |          dk     rdS |d                             |d                   s|                    |d                    t          t          j        d |D             t          j                            S )zReturns the area of a polygon.

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

    rF   r$   r   rI   c                *    g | ]}|j         |j        fS r%   )rq   rr   ).0vs     r&   
<listcomp>zarea.<locals>.<listcomp>  s     777Aac13Z777r'   )dtype)	r   rJ   rM   rY   appendr   nparrayfloat64)rP   vec2ss     r&   r   r      s     IhE
5zzA~~s 8E"I&& U1X2877777rzJJJKKKr'   npt.NDArrayc                    | 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

    NrI   r   rH   g      ?)r   rs   sum)rP   p1xp2xp1yp2ys        r&   r   r     sv     3B36
C
122q5/C
3B36
C
122q5/C6"&sS3Y.//00366r'   mr
   c                    |                      t                    }|                      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   rX   rY   magnitude_square)r   uxuys      r&   r   r      sE     
		v	&	&B	
		v	&	&B|B/1DEEEEr'   gư>)strictepsilonpolygonc               F   t          |           dk     rdS d}d}| d         }| d         }| D ]g}|                    |          r||z
                      ||z
            }t          |          |k    r|dk     rdnd}|s|}||k    r dS n|r dS |}|}ht	          |          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!

    rF   Fr   rI   r$   rH   )rM   rY   rD   rs   rd   )	r   r   r   global_signcurrent_signprev	prev_prevvertexrD   s	            r&   r   r   -  s     7||auKL2;DI  >>$ 	f}!!)d"233s88w!$s22L +*l**uu + 	55	r'   c                f   dd}dd}t          |           }| d                             | d	                   r|d
z  }|dk    rdS | ^}}}}} |||          r& |||          r |||          r |||          rdS  |||          r& |||          r |||          r |||          rdS dS )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

    r@   r   rA   r"   rd   c                @    t          j        | j        |j                  S rC   )rX   rY   rr   r@   rA   s     r&   is_horizontalz3is_axes_aligned_rectangle_2d.<locals>.is_horizontalb      |AC%%%r'   c                @    t          j        | j        |j                  S rC   )rX   rY   rq   r   s     r&   is_verticalz1is_axes_aligned_rectangle_2d.<locals>.is_verticale  r   r'   r   rI   rH      FT)r@   r   rA   r   r"   rd   )r@   r   rA   r   )rM   rY   )	r3   r   r   countp0p1p2p3_s	            r&   r   r   U  s7   & & & && & & & KKEay$$ 
zzuBBQb"KB M"b!! KB	 tb"KB M"b!! KB	 t5r'   )r    r!   r"   r!   )r(   r!   r"   r)   )r/   r!   r0   r!   r"   r!   )r2   r	   r3   r4   r"   r5   )r3   r4   r"   r=   )r:   r   rb   r   rc   r   r"   rd   )r:   r   rb   r   rc   r   r"   ro   )F)r:   r   rb   r   rc   r   r"   r!   )r@   r   rA   r   rz   r   r"   r!   )rP   r4   r"   r!   )rP   r   r"   r!   )r   r
   r"   rd   )r   r=   r"   rd   )r3   r=   r"   rd   )+
__future__r   typingr   r   	functoolsr   rX   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   # " " " " " % % % % % % % %                                   	Ws]
g3DGm  *% % % %
   D D D D"   (" " " "J 9=i    " .29$ $ $ $ $P 2;    2    &Q Q Q Q   L L L L$7 7 7 7$
F 
F 
F 
F 9>t % % % % % %P' ' ' ' ' 'r'   