
    'jUi                       d dl mZ d dlmZmZmZmZ d dlmZ d dl	Z	d dl
Zd dlmZmZmZmZmZmZmZ g dZe	j        dz  Zd^d_dZ	 d`dadZ	 dbdcdZdddZdedZdfdZdgd#Z	 	 dhdid*Z	 	 	 djdkd2ZdZ  G d3 d4e          Z! G d5 d6          Z"de d7dld<Z#dde d=dmd>Z$de d?dndBZ%dodGZ& G dH dI          Z'dpdLZ(dqdNZ)drdRZ*dsdVZ+efdtdWZ,dedXZ-e dYdud[Z.e dYdvd\Z/dwd]Z0dS )x    )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       @&.>faceSequence[Vec3]returnboolc                   t          |           dk     rdS t          |           dk    rdS d}t          t          |           dz
            D ]q}| ||dz            \  }}}	 ||z
                      ||z
                                            }n# t          $ r Y Nw xY w||}W|                    ||          s dS r|dS dS )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)r(   r0   first_normalindexabcnormals           P/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/math/construct3d.pyr   r   /   s     4yy1}}u
4yyA~~tLs4yy1}%% 	 	uuqy()1a	!e]]1q5))3355FF  	 	 	H	!LL%%fg%>> 	55	t5s    -B
BBTquadsIterator[Sequence[Vec3]]c              #  n   K   t                     dk     rt          d          t                     t          j                   z  } fdt	                    D             }t                     D ]<\  }}|r|||         |||dz
           fV  ||dz
           ||fV  |||         |fV  =dS )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.c                ^    g | ])}|                              |d z   z                     *S )   )lerp).0ir(   len_faces     r=   
<listcomp>z"subdivide_face.<locals>.<listcomp>Z   sD     # # #34QT1q5H,-..# # #    rB   N)r1   
ValueErrorr	   sumr2   	enumerate)r(   r>   mid_possubdiv_locationr8   vertexrF   s   `     @r=   r   r   K   s      4yy1}}7888IIHhtnnx'G# # # # #8=h# # #O #4 : :v 	:/%0'?5ST9;UUUUUU!%!),fg====/%0'99999: :rH      facesIterable[Sequence[Vec3]]c              #     K   | D ]u}t          |          |k    rt          j        |          V  ,t          j        |          t          |          z  }t	          |          D ]\  }}||dz
           ||fV  vdS )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

    rB   N)r1   r	   tuplerJ   rK   )rP   max_vertex_countr(   rL   r8   rN   s         r=   r   r   f   s        7 7t99(((*T""""""htnns4yy0G!*4 7 7v519ovw6666677 7rH   r9   r	   r:   r;   c                \    || z
                       || z
                                            S )zlReturns normal vector for 3 points, which is the normalized cross
    product for: :code:`a->b x a->c`.
    )r3   r4   )r9   r:   r;   s      r=   r   r   z   s*     E==Q))+++rH   verticesc                    t          |           dk     rt          d          | ^}}}}	 ||z
                      ||z
                                            S # t          $ r t          |           cY S w xY w)zjSafe function to detect the normal vector for a face or polygon defined
    by 3 or more `vertices`.

    r-   3 or more vertices required)r1   rI   r3   r4   r5   r   )rV   r9   r:   r;   _s        r=   r   r      s    
 8}}q6777KAq!a)A}}QU##--/// ) ) )x((((()s   ,A A32A3Iterable[UVec]c                   t          j        |           }t          |          dk     rt          d          |d         }|                    |d                   s|                    |           |j        \  }}}d}d}d}|dd         D ]=}	|	j        \  }
}}|||z   ||z
  z  z  }|||
z   ||z
  z  z  }|||z   ||
z
  z  z  }|
}|}|}>t          |||                                          S )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-   rX   r           rB   N)r	   listr1   rI   r6   appendxyzr4   )rV   	_verticesfirstprev_xprev_yprev_znxnynzvxyzs                r=   r   r      s    	(##I
9~~6777aLE==2''  "YFFF	B	B	Bqrr]  %1a
vzfqj))
vzfqj))
vzfqj))B%%'''rH   pointstartendfloatc                    |                     |          rt          d          | |z
  }||z
                      |          }|j        |j        z
  }|dk    rdS t	          j        |          S )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.r]   )r6   r5   projectmagnitude_squaremathsqrt)rm   rn   ro   v1v2diffs         r=   r   r      st     }}S /...	B
+		r	"	"B!44Ds{{ syrH   绽|=line1line2virtualr0   Optional[Vec3]c                    ddl m}m}  || ||          }t          |          dk    rdS |d         }|r|S  ||                               |          r  ||                              |          r|S dS )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BoundingBoxrB   N)
ezdxf.mathr   r   r1   inside)rz   r{   r|   r0   r   r   resrm   s           r=   r   r      s    $ @???????
!
!%
8
8C
3xx1}}tFE {5  '' KK,>,>,E,Ee,L,L 4rH   r   r   r   rB   rB   rB   mover   scale
z_rotationr   c                   t          |          \  }}}t          j        |||          }|r|t          j        |          z  }t          |           }|j        s(|t          j        |j        |j        |j                  z  }|S )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   r   z_rotateis_null	translaterj   rk   rl   )r   r   r   sxsyszmr   s           r=   r   r      s     eJBBr2r""A +	Xz***T

I G	X	Y[)+FFFHrH   c                      e Zd ZdZdZdZdZdS )r   r   rB   r.   r-   N)__name__
__module____qualname__COPLANARFRONTBACKSPANNING rH   r=   r   r      s"        HEDHHHrH   r   c                      e Zd ZdZdZd.dZed/d	            Zed0d
            Zed/d            Z	e
d1d            Ze
d2d            Zd3dZeZd Zd4dZd5dZd5dZd6d7dZd6d8d Zd!ed"d9d&Zd:d)Zefd;d,Zd-S )<r   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_originr<   r	   distancerp   c                H    |j         du s
J d            || _        || _        d S )NFzinvalid plane normal)r   r   r   )selfr<   r   s      r=   __init__zPlane.__init__  s3    ~&&&(>&&&%-"""rH   r*   c                    | j         S )zNormal vector of the plane.)r   r   s    r=   r<   zPlane.normal  s     |rH   c                    | j         S )z@The (perpendicular) distance of the plane from origin (0, 0, 0).)r   r   s    r=   distance_from_originzPlane.distance_from_origin  s     ))rH   c                     | j         | j        z  S )zReturns the location vector.r   r   s    r=   vectorzPlane.vector  s     |d888rH   r9   r:   r;   'Plane'c                    	 ||z
                       ||z
                                            }n# t          $ r t          d          w xY wt	          ||                    |                    S )z+Returns a new plane from 3 points in space.z"undefined plane: colinear vertices)r3   r4   r5   rI   r   dot)clsr9   r:   r;   ns        r=   from_3pzPlane.from_3p#  sw    	CQa!e$$..00AA  	C 	C 	CABBB	CQa!!!s	   -0 A
r   r   c                    t          |          }	 t          |                                |j                  S # t          $ r t          d          w xY w)z3Returns a new plane from the given location vector.zinvalid NULL vector)r	   r   r4   	magnituder5   rI   )r   r   ri   s      r=   from_vectorzPlane.from_vector,  sX     LL	4444  	4 	4 	42333	4s	   &8 Ac                B    |                      | j        | j                  S )zReturns a copy of the plane.)	__class__r   r   r   s    r=   __copy__zPlane.__copy__5  s    ~~dlD,FGGGrH   c                B    dt          | j                   d| j         dS )NzPlane(z, ))reprr   r   r   s    r=   __repr__zPlane.__repr__;  s(    KT\**KKd.HKKKKrH   otherobjectr+   c                Z    t          |t                    st          S | j        |j        k    S N)
isinstancer   NotImplementedr   )r   r   s     r=   __eq__zPlane.__eq__>  s)    %'' 	"!!{el**rH   ri   c                F    | j                             |          | j        z
  S )a  Returns 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   ri   s     r=   signed_distance_tozPlane.signed_distance_toC  s"     |""T%???rH   c                P    t          j        |                     |                    S )z<Returns absolute (unsigned) distance of vertex `v` to plane.)rt   fabsr   r   s     r=   distance_tozPlane.distance_toL  s     y0033444rH   r'   c                4    |                      |          |k     S )zdReturns ``True`` if vertex `v` is coplanar, distance from plane to
        vertex `v` is 0.
        )r   )r   ri   r0   s      r=   is_coplanar_vertexzPlane.is_coplanar_vertexP  s     ""W,,rH   pc                d    | j         j        } ||j         |          p ||j          |          S )ziReturns ``True`` if plane `p` is coplanar, normal vectors in same or
        opposite direction.
        r/   )r   r6   )r   r   r0   
n_is_closes       r=   is_coplanar_planezPlane.is_coplanar_planeV  sH     \)
z!)W555 
YJ:
 :
 :
 	
rH   Tcoplanarr0   rn   ro   r}   c               L   |                      ||          }|                      ||          }||u rdS |s|t          j        u s|t          j        u rdS | j        }| j        |                    |          z
  |                    ||z
            z  }|                    ||          S )a  Returns 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   r<   r   r   rC   )	r   rn   ro   r   r0   state0state1r   weights	            r=   intersect_linezPlane.intersect_line_  s     ++E7;;++C99V4 	(111+4444K+aeeEll:aeeC%K>P>PPzz#v&&&rH   origin	directionc                    | j         }	 | j        |                    |          z
  |                    |          z  }n# t          $ r Y dS w xY w|||z  z   S )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)r<   r   r   r5   )r   r   r   r   r   s        r=   intersect_rayzPlane.intersect_rayu  sl     K	/!%%--?155CSCSSFF  	 	 	44	V+,,s   3= 
A
ArN   r   c                    | j                             |          | j        z
  }|| k     rt          j        S ||k    rt          j        S t          j        S )zjReturns the :class:`PlaneLocationState` of the given `vertex` in
        relative to this plane.

        )r   r   r   r   r   r   r   )r   rN   r0   r   s       r=   r   zPlane.vertex_location_state  sT     <##F++d.HHwh%**%++%..rH   N)r<   r	   r   rp   )r*   r	   r*   rp   )r9   r	   r:   r	   r;   r	   r*   r   )r   r   r*   r   )r*   r   )r   r   r*   r+   )ri   r	   r*   rp   r'   )ri   r	   r*   r+   )r   r   r*   r+   )rn   r	   ro   r	   r*   r}   )r   r	   r   r	   r*   r}   )rN   r	   r*   r   )r   r   r   __doc__	__slots__r   propertyr<   r   r   classmethodr   r   r   copyr   r   r   r   r   r   PLANE_EPSILONr   r   r   r   rH   r=   r   r     s         5I. . . .    X * * * X* 9 9 9 X9 " " " [" 4 4 4 [4H H H H DL L L+ + + +
@ @ @ @5 5 5 5- - - - -
 
 
 
 
 37' ' ' ' ' ',- - - - %2/ / / / / / /rH   r   r   polygonIterable[Vec3]plane%tuple[Sequence[Vec3], Sequence[Vec3]]c               ~   t           j        }g }g }g }t          |           }|j        }	|j        }
|D ]2}|                    ||          }||z  }|                    |           3|t           j        k    r2|r.t          |          }|
                    |          dk    r|}n~|}nz|t           j	        k    r|}nf|t           j
        k    r|}nR|t           j        k    rAt          |          }t          |          D ]}|dz   |z  }||         }||         }||         }||         }|t           j
        k    r|                    |           |t           j	        k    r|                    |           ||z  t           j        k    rq|	|
                    |          z
  |
                    ||z
            z  }|                    ||          }|                    |           |                    |           t          |          dk     rg }t          |          dk     rg }t          |          t          |          fS )a7  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   rB   r-   )r   r   r^   r   r<   r   r_   r   r   r   r   r   r1   r2   rC   rS   )r   r   r   r0   polygon_typevertex_typesfront_verticesback_verticesrV   wr<   rN   vertex_typepolygon_normallen_verticesr8   
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B#K(((( )222 	),X66Nzz.))A--!) (	+1	1	1!	+0	0	0 	+4	4	48}}<(( 	? 	?E!)|3J&u-K+J7e_F":.K0555%%f---0666$$V,,,..3E3NNN()FJJv,>,>(>&**&(C C ($ ,2;;!5, ,( %%&>???$$%=>>>~""N}!!M  %"6"666rH   )r   boundaryr0   c               Z   t          |          }t          |          dk     rt          d          	 t          |          }n# t          $ r Y dS w xY wt          ||                    |d                             }|                    | |||          }	|	dS t          |	||||          S )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-   rX   Nr   r   )	r^   r1   rI   r   r5   r   r   r   (_is_intersection_point_inside_3d_polygon)
rn   ro   r   r   r   r0   rV   r<   r   ips
             r=   r   r     s    . G}}H
8}}q6777#H--   tt&&**Xa[1122E			eS8W		M	MB	zt3
Hfh     A 
AAr   r0   r   r   c               T   t          |          }t          |          dk     rt          d          	 t          |          }n# t          $ r Y dS w xY wt          ||                    |d                             }|                    | |          }|dS t          |||||          S )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-   rX   Nr   )	r^   r1   rI   r   r5   r   r   r   r   )	r   r   r   r   r0   rV   r<   r   r   s	            r=   r   r     s    * G}}H
8}}q6777#H--   tt&&**Xa[1122E			VY	/	/B	zt3
Hfh  r   r   
list[Vec3]r<   r   c                    ddl m}m}  ||          }t          j        |                    |                    } |t          |                    |                     ||          }	|	dk    s|r|	dk    r| S d S )Nr   )is_point_in_polygon_2dOCSr/   )r   r   r   r
   r^   points_from_wcsfrom_wcs)
r   rV   r<   r   r0   r   r   ocsocs_verticesstates
             r=   r   r   $  s     76666666
#f++C9S00::;;L""S\\"g  E qyyXy%1**	4rH   c                  *    e Zd ZdZddZdd
ZddZdS )r   ah  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

    r9   r   r:   r;   c                   t          |          | _        t          |          | _        t          |          | _        | j        | j        z
  | _        | j        | j        z
  | _        | j        | j        z
  | _        | j                            | j                  }|                                | _	        |
                    | j	                  | _        t          | j                  dk     rt          d          d S )Nr'   zinvalid triangle)r	   r9   r:   r;   _e1_e2_e3r3   r4   _nr   _denomabsrI   )r   r9   r:   r;   e1xe2s        r=   r   zBarycentricCoordinates.__init__M  s    aaa6DF?6DF?6DF?tx((//##ii((t{d""/000 #"rH   r   r*   r	   c                   t          |          }| j        }| j        }|| j        z
  }|| j        z
  }|| j        z
  }| j                            |                              |          |z  }| j	                            |                              |          |z  }| j
                            |                              |          |z  }	t          |||	          S r   )r	   r  r  r9   r:   r;   r  r3   r   r  r  )
r   r   r   denomd1d2d3b1b2b3s
             r=   from_cartesianz%BarycentricCoordinates.from_cartesianZ  s    GGGZZZX^^B##A&&.X^^B##A&&.X^^B##A&&.BBrH   c                r    t          |          j        \  }}}| j        |z  | j        |z  z   | j        |z  z   S r   )r	   r`   r9   r:   r;   )r   r:   r  r  r  s        r=   to_cartesianz#BarycentricCoordinates.to_cartesianf  s7    !WW[
Bv{TVb[(46B;66rH   N)r9   r   r:   r   r;   r   )r   r   r*   r	   )r:   r   r*   r	   )r   r   r   r   r   r  r  r   rH   r=   r   r   3  sZ         21 1 1 1
  
  
  
 7 7 7 7 7 7rH   r   countintc                   |dk    r| |gS || z
  }|j         r| g|z  S | g}|                    |j        |dz
  z            }t          d|dz
            D ]}| |z  } |                    |            |                    |           |S )z=Returns `count` evenly spaced vertices from `start` to `end`.r.   rB   )r   r4   r   r2   r_   )rn   ro   r  r   rV   steprY   s          r=   r   r   k  s    zzs|U{H wwHh0EAI>??D1eai    OOCOrH   r   c                   |                      t                    j        }|                      t                    }|                      t                    }t          j        ||j                   pt          j        ||j                   S )a4  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   rs   r   r   rt   r6   )r   
ux_mag_sqruyuzs       r=   r   r   |  s}     &&v..?J	
		v	&	&B	
		v	&	&B|J(;<<< DLB'E E A rH   pointsSequence[UVec]tuple[Vec3, float]c                    t          j        |           t          |           z  t          fd| D                       }|fS )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  B   K   | ]}                     |          V  d S r   )r   )rD   r   centroids     r=   	<genexpr>z%spherical_envelope.<locals>.<genexpr>  s1      66!""1%%666666rH   )r	   rJ   r1   max)r  radiusr$  s     @r=   r    r      sL     x#f++-H6666v66666FVrH   dir1dir2r'  c                    |                      |          }t          |dz  z
  }t          j        t	          |          t                    rdS t	          t          j        |          |z            S )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&   r]   )angle_betweenPI2rt   r6   r	  tan)r(  r)  r'  alphabetas        r=   r!   r!     s_     t$$E%#+D|CIIs## stx~~&'''rH   c                    |                      |          }|                     |          }|                    |          s|j        r|S |                    |           r| S t	          d          )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+  r3   r6   r   rI   )r(  r)  r<   anglenns        r=   r"   r"     sv     t$$E	D		B	zz& RZ 	VG		 v
,
-
--rH   c                l    ddl m}  ||           }t          j        t	          |                    dz  S )z6Returns a vertex from the "inside" of  the given face.r   )mapbox_earcut_3dg      @)ezdxf.math.triangulationr4  r	   rJ   next)rV   r4  its      r=   any_vertex_inside_facer8    sA     :99999		(	#	#B8DHH##rH   r/   Sequence[Sequence[Vec3]]c                 	 dfd	t          |          }t          |          }t          ||                    |                    	fd| D             }t	                      }|D ]Z}t          |||d          }|                    |          k    r(|                    |                    d
                     [t          |          S )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!

    rV   r)   r*   r+   c                f    t          |           dk     rdS t          fd| D                       S )Nr-   Fc              3  J   K   | ]}                     |          k    V  d S r   )r   )rD   ri   r0   detector_planes     r=   r%  zZfront_faces_intersect_face_normal.<locals>.is_face_in_front_of_detector.<locals>.<genexpr>  s6      TTa>44Q77'ATTTTTTrH   )r1   any)rV   r0   r=  s    r=   is_face_in_front_of_detectorzGfront_faces_intersect_face_normal.<locals>.is_face_in_front_of_detector  s?    x==15TTTTT8TTTTTTrH   c              3  2   K   | ]} |          |V  d S r   r   )rD   fr?  s     r=   r%  z4front_faces_intersect_face_normal.<locals>.<genexpr>  s4      GG'C'CA'F'FG1GGGGGGrH   Tr   N   )rV   r)   r*   r+   )
r   r8  r   r   setr   r   addroundr1   )
rP   r(   r0   face_normalr   front_facesintersection_pointsr   r=  r?  s
     `     @@r=   !front_faces_intersect_face_normalrI    s   U U U U U U U %T**K#D))F;(?(?@@N HGGGeGGGK
 &)UU 	1 	1(Kg
 
 
 :,,R007::  ##BHHQKK000"###rH   c               4    t          | ||          dz  dk    S )aP  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   )rI  )rP   r(   r0   s      r=   r$   r$     s$     -UD'JJJQNRSSSrH   c                Z    t                     dk     rt          d          d fd}t          |j                  t          |j                  t          |j                  f}|                    t          |                     |            dk    }|         }|r|dk    n|dk     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-   rX   r*   rp   c                 z   t          j                  } dk    r| d d df         | d d df         }}n7dk    r| d d df         | d d df         }}n| d d df         | d d df         }}t          j        |t          j        |d                    t          j        |t          j        |d                    z
  S )Nr   rB   r.   r\   )nparrayr   roll)r   rj   rk   domrV   s      r=   signed_areaz+is_vertex_order_ccw_3d.<locals>.signed_area  s    (8$$!88111a4='!!!Q$-qAAAXX111a4='!!!Q$-qAA111a4='!!!Q$-qAvaB((26!RWQ^^+D+DDDrH   r   r   )r1   rI   r	  rj   rk   rl   r8   r&  )rV   r<   rQ  abs_axisccwdom_axisrP  s   `     @r=   r%   r%     s      8}}q6777
E 
E 
E 
E 
E 
E 
E 68}}c&(mmS]]:H
..X
'
'C
+--!
Cc{H08a<<HqL0rH   r   )r(   r)   r*   r+   )T)r(   r)   r>   r+   r*   r?   )rO   )rP   rQ   r*   r?   )r9   r	   r:   r	   r;   r	   r*   r	   )rV   r)   r*   r	   )rV   rZ   r*   r	   )rm   r	   rn   r	   ro   r	   r*   rp   )Try   )
rz   r)   r{   r)   r|   r+   r0   rp   r*   r}   )r   r   r   )r   r   r   r   r   rp   r*   r   )r   r   r   r   r*   r   )rn   r	   ro   r	   r   r   r*   r}   )r   r	   r   r	   r   r   r*   r}   )
r   r	   rV   r   r<   r	   r   r+   r0   rp   )rn   r	   ro   r	   r  r  r*   r   )r   r   r*   r+   )r  r   r*   r!  )r(  r	   r)  r	   r'  rp   r*   rp   )r(  r	   r)  r	   r*   rp   )rP   r9  r(   r)   r*   r  )rP   r9  r(   r)   r*   r+   )rV   r   r<   r	   r*   r+   )1
__future__r   typingr   r   r   r   enumr   rt   numpyrM  r   r	   r
   r   r   r   r   r   __all__pir,  r   r   r   r   r   r   r   r   r   r   r   r   r#   r   r   r   r   r   r   r    r!   r"   r8  rI  r$   r%   r   rH   r=   <module>r[     s   # " " " " " 9 9 9 9 9 9 9 9 9 9 9 9                              0 gm    : )-: : : : :: 7 7 7 7 7(, , , ,) ) ) )( ( ( (8   6 	    B     0        J/ J/ J/ J/ J/ J/ J/ J/b C7 C7 C7 C7 C7 C7V $ $ $ $ $ $X " " " " " "J   57 57 57 57 57 57 57 57p   "       ( ( ( ( 28 . . . . . $ $ $ $ 	($ ($ ($ ($ ($ ($^ 	T T T T T T"'1 '1 '1 '1 '1 '1rH   