
    hUi                       S SK Jr  S SKJrJrJrJr  S SKJr  S SK	r	S SK
rS SKJrJrJrJrJrJrJr  / SQr\	R*                  S-  rS*S+S	 jjr S,     S-S jjr S.   S/S jjrS0S jrS1S jrS2S jrS3S jr  S4         S5S jjr   S6       S7S jjrSr  " S S\5      r! " S S5      r"S
\ S.     S8S jjr#S
S
\ S.       S9S jjr$S
\ S.       S:S jjr%          S;S jr& " S S5      r'S<S  jr(S=S! jr)S>S" jr*S?S# jr+\4S@S$ jjr,S1S% jr-\ S&.     SAS' jjr.\ S&.     SBS( jjr/SCS) jr0g)D    )annotations)SequenceIterableOptionalIterator)IntEnumN)Vec3Vec2Matrix44X_AXISY_AXISZ_AXISUVec)is_planar_facesubdivide_facesubdivide_ngonsPlanePlaneLocationStatenormal_vector_3psafe_normal_vectordistance_point_line_3dintersection_line_line_3dintersection_ray_polygon_3dintersection_line_polygon_3dbasic_transformationbest_fit_normalBarycentricCoordinateslinear_vertex_spacinghas_matrix_3d_stretchingspherical_envelopeinscribe_circle_tangent_lengthbending_anglesplit_polygon_by_plane is_face_normal_pointing_outwardsis_vertex_order_ccw_3d       @&.>c                D   [        U 5      S:  a  g[        U 5      S:X  a  gSn[        [        U 5      S-
  5       HN  nXUS-    u  pEn XT-
  R                  Xe-
  5      R                  5       nUc  UnM8  UR                  XqS9(       a  MN    g   Ub  gg! [         a     Md  f = f)zReturns ``True`` if sequence of vectors is a planar face.

Args:
     face: sequence of :class:`~ezdxf.math.Vec3` objects
     abs_tol: tolerance for normals check

   FTN   abs_tol)lenrangecross	normalizeZeroDivisionErrorisclose)facer,   first_normalindexabcnormals           H/var/www/html/env/lib/python3.13/site-packages/ezdxf/math/construct3d.pyr   r   /   s     4y1}
4yA~Ls4y1}%uqy)a	e]]15)335F !L%%f%>> &  ! 		s   #B
BBTc              #  z  #    [        U 5      S:  a  [        S5      e[        U 5      n[        R                  " U 5      U-  n[	        U5       Vs/ s H  o@U   R                  XS-   U-     5      PM      nn[        U 5       H1  u  pgU(       a  XuU   X5US-
     4v   M  XVS-
     Xs4v   XuU   U4v   M3     gs  snf 7f)zSubdivides faces by subdividing edges and adding a center vertex.

Args:
    face: a sequence of :class:`Vec3`
    quads: create quad faces if ``True`` else create triangles

r)   z3 or more vertices required.   N)r-   
ValueErrorr	   sumr.   lerp	enumerate)r3   quadslen_facemid_posisubdiv_locationr5   vertexs           r:   r   r   K   s      4y1}788IHhhtnx'G8=h#8G1QTq5H,-.  # #4%0'5ST9;UUU!!),f==%0'99 )	#s   AB;%B63AB;c              #     #    U  Hm  n[        U5      U::  a  [        R                  " U5      v   M,  [        R                  " U5      [        U5      -  n[	        U5       H  u  pEX$S-
     XS4v   M     Mo     g7f)zSubdivides faces into triangles by adding a center vertex.

Args:
    faces: iterable of faces as sequence of :class:`Vec3`
    max_vertex_count: subdivide only ngons with more vertices

r<   N)r-   r	   tupler>   r@   )facesmax_vertex_countr3   rC   r5   rF   s         r:   r   r   f   sd      t9((**T""hhtns4y0G!*419ov66 "1 s   A5A7c                H    X-
  R                  X -
  5      R                  5       $ )zdReturns normal vector for 3 points, which is the normalized cross
product for: :code:`a->b x a->c`.
)r/   r0   )r6   r7   r8   s      r:   r   r   z   s      E==))++    c                    [        U 5      S:  a  [        S5      eU tpp4 X!-
  R                  X1-
  5      R                  5       $ ! [         a    [        U 5      s $ f = f)zbSafe function to detect the normal vector for a face or polygon defined
by 3 or more `vertices`.

r)   3 or more vertices required)r-   r=   r/   r0   r1   r   )verticesr6   r7   r8   _s        r:   r   r      s`    
 8}q677KA!)}}QU#--// )x(()s   "A AAc                   [         R                  " U 5      n[        U5      S:  a  [        S5      eUS   nUR	                  US   5      (       d  UR                  U5        UR                  u  p4nSnSnSnUSS  H<  n	U	R                  u  pnXeU-   XK-
  -  -  nXsU
-   X\-
  -  -  nXU-   X:-
  -  -  nU
nUnUnM>     [        XgU5      R                  5       $ )zReturns the "best fit" normal for a plane defined by three or more
vertices. This function tolerates imperfect plane vertices. Safe function
to detect the extrusion vector of flat arbitrary polygons.

r)   rN   r           r<   N)r	   listr-   r=   r2   appendxyzr0   )rO   	_verticesfirstprev_xprev_yprev_znxnynzvxyzs                r:   r   r      s     		(#I
9~677aLE==2''"YYFF	B	B	Bqr]%%a
zfj))
zfj))
zfj))  %%''rL   c                    UR                  U5      (       a  [        S5      eX-
  nX!-
  R                  U5      nUR                  UR                  -
  nUS::  a  g[        R
                  " U5      $ )zReturns the normal distance from a `point` to a 3D line.

Args:
    point: point to test
    start: start point of the 3D line
    end: end point of the 3D line

zNot a line.rS   )r2   r1   projectmagnitude_squaremathsqrt)pointstartendv1v2diffs         r:   r   r      sg     }}S..	B
+		r	"B!4!44Ds{ yyrL   c                    SSK JnJn  U" XU5      n[        U5      S:w  a  gUS   nU(       a  U$ U" U 5      R	                  U5      (       a  U" U5      R	                  U5      (       a  U$ g)a  
Returns the intersection point of two 3D lines, returns ``None`` if lines
do not intersect.

Args:
    line1: first line as tuple of two points as :class:`Vec3` objects
    line2: second line as tuple of two points as :class:`Vec3` objects
    virtual: ``True`` returns any intersection point, ``False`` returns only
        real intersection points
    abs_tol: absolute tolerance for comparisons

r   )intersection_ray_ray_3dBoundingBoxr<   N)
ezdxf.mathro   rp   r-   inside)line1line2virtualr,   ro   rp   resrh   s           r:   r   r      sf    $ @
!%
8C
3x1}FE5  ''K,>,E,Ee,L,LrL   c                :   [        U5      u  p4n[        R                  " X4U5      nU(       a  U[        R                  " U5      -  n[        U 5      nUR                  (       d9  U[        R
                  " UR                  UR                  UR                  5      -  nU$ )a  Returns a combined transformation matrix for translation, scaling and
rotation about the z-axis.

Args:
    move: translation vector
    scale: x-, y- and z-axis scaling as float triplet, e.g. (2, 2, 1)
    z_rotation: rotation angle about the z-axis in radians

)	r	   r   scalez_rotateis_null	translater`   ra   rb   )moverx   
z_rotationsxsyszmr{   s           r:   r   r      su     eJBBrr"A	Xz**T
I	X	Y[[)++FFHrL   c                  $    \ rS rSrSrSrSrSrSrg)r      r   r<   r*   r)    N)	__name__
__module____qualname____firstlineno__COPLANARFRONTBACKSPANNING__static_attributes__r   rL   r:   r   r      s    HEDHrL   r   c                     \ rS rSrSrSrSS jr\SS j5       r\SS j5       r	\SS j5       r
\SS j5       r\SS	 j5       rSS
 jr\rS rSS jrSS jrSS jrS S!S jjrS S"S jjrS\S.     S#S jjrS$S jr\4   S%S jjrSrg)&r   i  zConstruction tool for 3D planes.

Represents a plane in 3D space as a normal vector and the perpendicular
distance from the origin.
_normal_distance_from_originc                H    UR                   SL d   S5       eXl        X l        g )NFzinvalid plane normal)rz   r   r   )selfr9   distances      r:   __init__Plane.__init__  s%    ~~&>(>>&%-"rL   c                    U R                   $ )zNormal vector of the plane.)r   r   s    r:   r9   Plane.normal  s     ||rL   c                    U R                   $ )z@The (perpendicular) distance of the plane from origin (0, 0, 0).)r   r   s    r:   distance_from_originPlane.distance_from_origin  s     )))rL   c                4    U R                   U R                  -  $ )zReturns the location vector.r   r   s    r:   vectorPlane.vector  s     ||d8888rL   c                     X!-
  R                  X1-
  5      R                  5       n[	        XDR                  U5      5      $ ! [         a    [        S5      ef = f)z+Returns a new plane from 3 points in space.z"undefined plane: colinear vertices)r/   r0   r1   r=   r   dot)clsr6   r7   r8   ns        r:   from_3pPlane.from_3p#  sW    	Cae$..0A Qa!! ! 	CABB	Cs	   #? Ac                    [        U5      n [        UR                  5       UR                  5      $ ! [         a    [        S5      ef = f)z3Returns a new plane from the given location vector.zinvalid NULL vector)r	   r   r0   	magnituder1   r=   )r   r   r_   s      r:   from_vectorPlane.from_vector,  sD     L	444  	4233	4s	   #1 Ac                N    U R                  U R                  U R                  5      $ )zReturns a copy of the plane.)	__class__r   r   r   s    r:   __copy__Plane.__copy__5  s    ~~dllD,F,FGGrL   c                N    S[        U R                  5       SU R                   S3$ )NzPlane(z, ))reprr   r   r   s    r:   __repr__Plane.__repr__;  s(    T\\*+2d.H.H-IKKrL   c                j    [        U[        5      (       d  [        $ U R                  UR                  :H  $ N)
isinstancer   NotImplementedr   )r   others     r:   __eq__Plane.__eq__>  s(    %''!!{{ell**rL   c                R    U R                   R                  U5      U R                  -
  $ )zReturns signed distance of vertex `v` to plane, if distance is > 0,
`v` is in 'front' of plane, in direction of the normal vector, if
distance is < 0, `v` is at the 'back' of the plane, in the opposite
direction of the normal vector.

)r   r   r   r   r_   s     r:   signed_distance_toPlane.signed_distance_toC  s$     ||"T%?%???rL   c                L    [         R                  " U R                  U5      5      $ )z<Returns absolute (unsigned) distance of vertex `v` to plane.)rf   fabsr   r   s     r:   distance_toPlane.distance_toL  s    yy00344rL   c                *    U R                  U5      U:  $ )zTReturns ``True`` if vertex `v` is coplanar, distance from plane to
vertex `v` is 0.
)r   )r   r_   r,   s      r:   is_coplanar_vertexPlane.is_coplanar_vertexP  s     "W,,rL   c                    U R                   R                  nU" UR                   US9=(       d    U" UR                   * US9$ )zYReturns ``True`` if plane `p` is coplanar, normal vectors in same or
opposite direction.
r+   )r   r2   )r   pr,   
n_is_closes       r:   is_coplanar_planePlane.is_coplanar_planeV  s=     \\))
!))W5 
YYJ:
 	
rL   Tcoplanarr,   c               J   U R                  X5      nU R                  X$5      nXVL a  gU(       d'  U[        R                  L d  U[        R                  L a  gU R                  nU R                  UR                  U5      -
  UR                  X!-
  5      -  nUR                  X(5      $ )zReturns the intersection point of the 3D line from `start` to `end`
and this plane or ``None`` if there is no intersection. If the argument
`coplanar` is ``False`` the start- or end point of the line are ignored
as intersection points.

N)vertex_location_stater   r   r9   r   r   r?   )	r   ri   rj   r   r,   state0state1r   weights	            r:   intersect_linePlane.intersect_line_  s     ++E;++C9(111+444KK++aeeEl:aeeCK>PPzz#&&rL   c                    U R                   n U R                  UR                  U5      -
  UR                  U5      -  nXU-  -   $ ! [         a     gf = f)zReturns the intersection point of the infinite 3D ray defined by
`origin` and the `direction` vector and this plane or ``None`` if there
is no intersection. A coplanar ray does not intersect the plane!

N)r9   r   r   r1   )r   origin	directionr   r   s        r:   intersect_rayPlane.intersect_rayu  s\     KK	//!%%-?155CSSF V+,, ! 		s   0A 
AAc                    U R                   R                  U5      U R                  -
  nX2* :  a  [        R                  $ X2:  a  [        R
                  $ [        R                  $ )zZReturns the :class:`PlaneLocationState` of the given `vertex` in
relative to this plane.

)r   r   r   r   r   r   r   )r   rF   r,   r   s       r:   r   Plane.vertex_location_state  sU     <<##F+d.H.HHh%***%+++%...rL   )r   r   N)r9   r	   r   float)returnr	   r   r   )r6   r	   r7   r	   r8   r	   r   'Plane')r   r   r   r   )r   r   )r   objectr   bool)r_   r	   r   r   r'   )r_   r	   r   r   )r   r   r   r   )ri   r	   rj   r	   r   Optional[Vec3])r   r	   r   r	   r   r   )rF   r	   r   r   )r   r   r   r   __doc__	__slots__r   propertyr9   r   r   classmethodr   r   r   copyr   r   r   r   r   r   PLANE_EPSILONr   r   r   r   r   rL   r:   r   r     s     5I.   * * 9 9 " " 4 4H DL+
@5-
 37'' $'	',- %2//	/ /rL   r   r   c               >   [         R                  n/ n/ n/ n[        U 5      nUR                  n	UR                  n
U H)  nUR                  X5      nXL-  nUR                  U5        M+     U[         R                  :X  a/  U(       a&  [        U5      nU
R                  U5      S:  a  UnGOaUnGO]U[         R                  :X  a  UnGOEU[         R                  :X  a  UnGO-U[         R                  :X  Ga  [        U5      n[        U5       H  nUS-   U-  nX_   nUU   nX   nUU   nU[         R                  :w  a  UR                  U5        U[         R                  :w  a  UR                  U5        UU-  [         R                  :X  d  M  XR                  U5      -
  U
R                  UU-
  5      -  nUR                  UU5      nUR                  U5        UR                  U5        M     [        U5      S:  a  / n[        U5      S:  a  / n[        U5      [        U5      4$ )a#  Split a convex `polygon` by the given `plane`.

Returns a tuple of front- and back vertices (front, back).
Returns also coplanar polygons if the
argument `coplanar` is ``True``, the coplanar vertices goes into either
front or back depending on their orientation with respect to this plane.

r   r<   r)   )r   r   rT   r   r9   r   rU   r   r   r   r   r   r-   r.   r?   rH   )polygonplaner   r,   polygon_typevertex_typesfront_verticesback_verticesrO   wr9   rF   vertex_typepolygon_normallen_verticesr5   
next_indexnext_vertex_typenext_vertexinterpolation_weightplane_intersection_points                        r:   r#   r#     s    &..L-/L!#N "MG}H""A\\F 11&B#K(  )222,X6Nzz.)A-!) (	+11	1!	+00	0 	+44	48}<(E!)|3J&-K+J7_F":.K0555%%f-0666$$V,..3E3N3NN()JJv,>(>&**&(C ($ ,2;;!5,( %%&>?$$%=>% )& ~"N}!M %"666rL   )r   boundaryr,   c                   [        U5      n[        U5      S:  a  [        S5      e [        U5      n[        XwR                  US   5      5      nUR                  XX5S9n	U	c  g[        XXtU5      $ ! [         a     gf = f)a  Returns the intersection point of the 3D line form `start` to `end` and
the given `polygon`.

Args:
    start: start point of 3D line as :class:`Vec3`
    end: end point of 3D line as :class:`Vec3`
    polygon: 3D polygon as iterable of :class:`Vec3`
    coplanar: if ``True`` a coplanar start- or end point as intersection
        point is valid
    boundary: if ``True`` an intersection point at the polygon boundary line
        is valid
    abs_tol: absolute tolerance for comparisons

r)   rN   Nr   r   )	rT   r-   r=   r   r1   r   r   r   (_is_intersection_point_inside_3d_polygon)
ri   rj   r   r   r   r,   rO   r9   r   ips
             r:   r   r     s    . G}H
8}q677#H- &**Xa[12E			e8		MB	z3
f   s   A0 0
A=<A=r   r,   c                  [        U5      n[        U5      S:  a  [        S5      e [        U5      n[        XfR                  US   5      5      nUR                  X5      nUc  g[        XXcU5      $ ! [         a     gf = f)a  Returns the intersection point of the infinite 3D ray defined by `origin`
and the `direction` vector and the given `polygon`.

Args:
    origin: origin point of the 3D ray as :class:`Vec3`
    direction: direction vector of the 3D ray as :class:`Vec3`
    polygon: 3D polygon as iterable of :class:`Vec3`
    boundary: if ``True`` intersection points at the polygon boundary line
        are valid
    abs_tol: absolute tolerance for comparisons

r)   rN   Nr   )	rT   r-   r=   r   r1   r   r   r   r   )	r   r   r   r   r,   rO   r9   r   r   s	            r:   r   r     s    * G}H
8}q677#H- &**Xa[12E			V	/B	z3
f   s   A1 1
A>=A>c                    SSK JnJn  U" U5      n[        R                  " UR                  U5      5      nU" [        UR                  U 5      5      XS9n	U	S:  d  U(       a  U	S:X  a  U $ g )Nr   )is_point_in_polygon_2dOCSr+   )rq   r   r   r
   rT   points_from_wcsfrom_wcs)
r   rO   r9   r   r,   r   r   ocsocs_verticesstates
             r:   r   r   $  s_     7
f+C99S00:;L"S\\"E qyX%1*	rL   c                  6    \ rS rSrSrSS jrS	S jrS
S jrSrg)r   i3  a,  Barycentric coordinate calculation.

The arguments `a`, `b` and `c` are the cartesian coordinates of an arbitrary
triangle in 3D space. The barycentric coordinates (b1, b2, b3) define the
linear combination of `a`, `b` and `c` to represent the point `p`::

    p = a * b1 + b * b2 + c * b3

This implementation returns the barycentric coordinates of the normal
projection of `p` onto the plane defined by (a, b, c).

These barycentric coordinates have some useful properties:

- if all barycentric coordinates (b1, b2, b3) are in the range [0, 1], then
  the point `p` is inside the triangle (a, b, c)
- if one of the coordinates is negative, the point `p` is outside the
  triangle
- the sum of b1, b2 and b3 is always 1
- the center of "mass" has the barycentric coordinates (1/3, 1/3, 1/3) =
  (a + b + c)/3

c                   [        U5      U l        [        U5      U l        [        U5      U l        U R                  U R                  -
  U l        U R                  U R                  -
  U l        U R                  U R                  -
  U l        U R                  R                  U R
                  5      nUR                  5       U l	        UR                  U R                  5      U l        [        U R                  5      S:  a  [        S5      eg )Nr'   zinvalid triangle)r	   r6   r7   r8   _e1_e2_e3r/   r0   _nr   _denomabsr=   )r   r6   r7   r8   e1xe2s        r:   r   BarycentricCoordinates.__init__M  s    aaa66DFF?66DFF?66DFF?txx(//#ii(t{{d"/00 #rL   c                   [        U5      nU R                  nU R                  nXR                  -
  nXR                  -
  nXR
                  -
  nU R                  R                  U5      R                  U5      U-  nU R                  R                  U5      R                  U5      U-  nU R                  R                  U5      R                  U5      U-  n	[        XxU	5      $ r   )r	   r  r  r6   r7   r8   r  r/   r   r	  r
  )
r   r   r   denomd1d2d3b1b2b3s
             r:   from_cartesian%BarycentricCoordinates.from_cartesianZ  s    GGGZZZXX^^B##A&.XX^^B##A&.XX^^B##A&.BBrL   c                    [        U5      R                  u  p#nU R                  U-  U R                  U-  -   U R                  U-  -   $ r   )r	   rV   r6   r7   r8   )r   r7   r  r  r  s        r:   to_cartesian#BarycentricCoordinates.to_cartesianf  s;    !W[[
vv{TVVb[(466B;66rL   )r  r  r	  r
  r  r6   r7   r8   N)r6   r   r7   r   r8   r   )r   r   r   r	   )r7   r   r   r	   )	r   r   r   r   r   r   r  r  r   r   rL   r:   r   r   3  s    21
 7rL   r   c                   US::  a  X/$ X-
  nUR                   (       a  U /U-  $ U /nUR                  UR                  US-
  -  5      n[        SUS-
  5       H  nX-  n UR	                  U 5        M     UR	                  U5        U$ )z=Returns `count` evenly spaced vertices from `start` to `end`.r*   r<   )rz   r0   r   r.   rU   )ri   rj   countr   rO   steprP   s          r:   r   r   k  s    z|{HwwHh00EAI>?D1eai  ! OOCOrL   c                6   U R                  [        5      R                  nU R                  [        5      nU R                  [        5      n[
        R                  " XR                  5      (       + =(       d%    [
        R                  " XR                  5      (       + $ )a   Returns ``True`` if matrix `m` performs a non-uniform xyz-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   re   r   r   rf   r2   )r   
ux_mag_sqruyuzs       r:   r   r   |  st     &&v.??J	
		v	&B	
		v	&B||J(;(;<< DLL''E A rL   c                z   ^ [         R                  " U 5      [        U 5      -  m[        U4S jU  5       5      nTU4$ )zCalculate the spherical envelope for the given points.  Returns the
centroid (a.k.a. geometric center) and the radius of the enclosing sphere.

.. note::

    The result does not represent the minimal bounding sphere!

c              3  F   >#    U  H  nTR                  U5      v   M     g 7fr   )r   ).0r   centroids     r:   	<genexpr>%spherical_envelope.<locals>.<genexpr>  s     6v!""1%%vs   !)r	   r>   r-   max)pointsradiusr(  s     @r:   r    r      s7     xx#f+-H6v66FVrL   c                    U R                  U5      n[        US-  -
  n[        R                  " [	        U5      [        5      (       a  g[	        [        R
                  " U5      U-  5      $ )a  Returns the tangent length of an inscribe-circle of the given `radius`.
The direction `dir1` and `dir2` define two intersection tangents,
The tangent length is the distance from the intersection point of the
tangents to the touching point on the inscribe-circle.

r&   rS   )angle_betweenPI2rf   r2   r  tan)dir1dir2r-  alphabetas        r:   r!   r!     sR     t$E%#+D||CIs##txx~&''rL   c                    U R                  U5      nU R                  U5      nUR                  U5      (       d  UR                  (       a  U$ UR                  U* 5      (       a  U* $ [	        S5      e)zReturns the bending angle from `dir1` to `dir2` in radians.

The normal vector is required to detect the bending orientation,
an angle > 0 bends to the "left" an angle < 0 bends to the "right".

zinvalid normal vector)r/  r/   r2   rz   r=   )r2  r3  r9   anglenns        r:   r"   r"     s`     t$E	D	B	zz&RZZ	VG		v
,
--rL   c                b    SSK Jn  U" U 5      n[        R                  " [	        U5      5      S-  $ )z6Returns a vertex from the "inside" of  the given face.r   )mapbox_earcut_3dg      @)ezdxf.math.triangulationr:  r	   r>   next)rO   r:  its      r:   any_vertex_inside_facer>    s)     :	(	#B88DH##rL   r+   c          	     ^  ^^^	 SUU4S jjm	[        U5      n[        U5      n[        X3R                  U5      5      mU	4S jU  5       n[	        5       nU HK  n[        XCUSTS9nUc  M  TR                  U5      T:  d  M+  UR                  UR                  S5      5        MM     [        U5      $ )zReturns the count of intersections of the normal-vector of the given
`face` with the `faces` in front of this `face`.

A counter-clockwise vertex order is assumed!

c                P   > [        U 5      S:  a  g[        UU4S jU  5       5      $ )Nr)   Fc              3  L   >#    U  H  nTR                  U5      T:  v   M     g 7fr   )r   )r'  r_   r,   detector_planes     r:   r)  Zfront_faces_intersect_face_normal.<locals>.is_face_in_front_of_detector.<locals>.<genexpr>  s!     T8a>44Q7'A8s   !$)r-   any)rO   r,   rB  s    r:   is_face_in_front_of_detectorGfront_faces_intersect_face_normal.<locals>.is_face_in_front_of_detector  s#    x=1T8TTTrL   c              3  F   >#    U  H  nT" U5      (       d  M  Uv   M     g 7fr   r   )r'  frE  s     r:   r)  4front_faces_intersect_face_normal.<locals>.<genexpr>  s     Ge'CA'F11es   !	!Tr      )rO   Sequence[Vec3]r   r   )
r   r>  r   r   setr   r   addroundr-   )
rI   r3   r,   face_normalr   front_facesintersection_pointsr   rB  rE  s
     `     @@r:   !front_faces_intersect_face_normalrR    s    U U %T*K#D)F;(?@N HeGK
 &)U(g
 :,,R07:  ##BHHQK0  "##rL   c               "    [        XUS9S-  S:H  $ )a<  Returns ``True`` if the face-normal for the given `face` of a
closed surface is pointing outwards. A counter-clockwise vertex order is
assumed, for faces with clockwise vertex order the result is inverted,
therefore ``False`` is pointing outwards.

This function does not check if the `faces` are a closed surface.

r+   r*   r   )rR  )rI   r3   r,   s      r:   r$   r$     s     -U'JQNRSSSrL   c                <  ^ ^ [        T 5      S:  a  [        S5      eSUU 4S jjn[        UR                  5      [        UR                  5      [        UR
                  5      4nUR                  [        U5      5      mU" 5       S:  nUT   nU(       a  US:  $ US:  $ )a  Returns ``True`` when the given 3D vertices have a counter-clockwise order around
the given normal vector.

Works for convex and concave shapes. Does not check or care if all vertices are
located in a flat plane or if the normal vector is really perpendicular to the
shape, but the result may be incorrect in that cases.

Args:
    vertices (list): corner vertices of a flat shape (polygon)
    normal (Vec3): normal vector of the shape

Raises:
    ValueError: input has less than 3 vertices

r)   rN   c                 d  > [         R                  " T5      n TS:X  a  U S S 2S4   U S S 2S4   p!O)TS:X  a  U S S 2S4   U S S 2S4   p!OU S S 2S4   U S S 2S4   p![         R                  " U[         R                  " US5      5      [         R                  " U[         R                  " US5      5      -
  $ )Nr   r<   r*   rR   )nparrayr   roll)r   r`   ra   domrO   s      r:   signed_area+is_vertex_order_ccw_3d.<locals>.signed_area  s    ((8$!81a4='!Q$-qAX1a4='!Q$-q1a4='!Q$-qvvaB(266!RWWQ^+DDDrL   r   r   )r-   r=   r  r`   ra   rb   r5   r+  )rO   r9   rZ  abs_axisccwdom_axisrY  s   `     @r:   r%   r%     s      8}q677
E 
E 688}c&((mS]:H
..X
'C
-!
Cc{H8a<0HqL0rL   r   )r3   rK  r   r   )T)r3   rK  rA   r   r   Iterator[Sequence[Vec3]])   )rI   zIterable[Sequence[Vec3]]r   r_  )r6   r	   r7   r	   r8   r	   r   r	   )rO   rK  r   r	   )rO   zIterable[UVec]r   r	   )rh   r	   ri   r	   rj   r	   r   r   )Tg|=)
rs   rK  rt   rK  ru   r   r,   r   r   r   ))r   r   r   )r<   r<   r<   r   )r|   r   rx   r   r}   r   r   r   )r   Iterable[Vec3]r   r   r   z%tuple[Sequence[Vec3], Sequence[Vec3]])ri   r	   rj   r	   r   ra  r   r   )r   r	   r   r	   r   ra  r   r   )
r   r	   rO   
list[Vec3]r9   r	   r   r   r,   r   )ri   r	   rj   r	   r  intr   rb  )r   r   r   r   )r,  zSequence[UVec]r   ztuple[Vec3, float])r2  r	   r3  r	   r-  r   r   r   )r2  r	   r3  r	   r   r   )rI   Sequence[Sequence[Vec3]]r3   rK  r   rc  )rI   rd  r3   rK  r   r   )rO   rb  r9   r	   r   r   )1
__future__r   typingr   r   r   r   enumr   rf   numpyrV  rq   r	   r
   r   r   r   r   r   __all__pir0  r   r   r   r   r   r   r   r   r   r   r   r   r#   r   r   r   r   r   r   r    r!   r"   r>  rR  r$   r%   r   rL   r:   <module>rk     se   # 9 9     0 ggm: )-:
:!%::: 7#7 7(,)(86 	  	
 B 
  	0  J/ J/b C7C7C7 +C7V $$	$ $ $X """ " "J",0<@KP57 57p" ( 28 . $ 	($#($
($
 	($^ 	T#T
T
 
T"'1rL   