
    jV                        d Z ddlmZ ddlmZ ddlZddlmZ ddl	m
Z
 ddlmZ dd	lmZmZmZ dd
lmZmZ  ee      ZdedefdZddZddZd Zd Zd Ze G d d             Z	 ddefdZd Zd ZddZd dZ d Z!d!dZ"d Z#d Z$y)"z`
triangles.py
-------------

Functions for dealing with triangle soups in (n, 3, 3) float form.
    )	dataclass)	getLoggerN   )util)tol)point_plane_distance)NDArrayOptionalfloat64)diagonal_dotunitize	trianglesreturnc                 h   | ddddddf   | ddddddf   z
  }| j                   d   dk(  r$t        j                  |dddf   |dddf         S | j                   d   dk(  r9|dddf   }|dddf   }|dddf   |dddf   z  |dddf   |dddf   z  z
  S t        | j                         )a  
    Returns the cross product of two edges from input triangles

    Parameters
    --------------
    triangles: (n, 3, 3) float
      Vertices of triangles

    Returns
    --------------
    crosses : (n, 3) float
      Cross product of two edge vectors
    Nr         r   )shapenpcross
ValueError)r   vectorsabs       >/DATA/.local/lib/python3.12/site-packages/trimesh/triangles.pyr   r      s     12q!Ia!Qh$77GqQxx1wq!t}55		q	 AqDMAqDMAw1a4 1QT7Qq!tW#444
Y__
%%    c                    |.t        t        j                  | t        j                              }t	        |j
                        dk(  rt        j                  |      dz  S t        j                  |dz  j                  d            dz  S )a  
    Calculates the sum area of input triangles

    Parameters
    ----------
    triangles : (n, 3, 3) float
      Vertices of triangles
    crosses : (n, 3) float or None
      As a speedup don't re- compute cross products
    sum : bool
      Return summed area or individual triangle area

    Returns
    ----------
    area : (n,) float or float
      Individual or summed area depending on `sum` argument
    dtyper   g       @r   axis)	r   r   
asanyarrayr   lenr   abssqrtsum)r   crossess     r   arear'   0   sl    $ irzzBC
7==Qvvg$$77GQJ###+,s22r   c                 T   | t        j                  | t         j                        } | j                  d   dk(  rOt        j                  g d| j                  d   df      }t        j
                  t        |       t              }||fS |t        |       }t        |d      \  }}||fS )	aV  
    Calculates the normals of input triangles

    Parameters
    ------------
    triangles : (n, 3, 3) float
      Vertex positions
    crosses : (n, 3) float
      Cross products of edge vectors

    Returns
    ------------
    normals : (m, 3) float
      Normal vectors
    valid : (n,) bool
      Was the face nonzero area or not
    r   r   )        r*         ?r   r   T)check_valid)
r   r!   r   r   tileonesr"   boolr   r   )r   r&   unitvalids       r   normalsr2   J   s    $ MM)2::>	??2!#77?Y__Q-?,CDDGGC	N$7E;	"'t4KD%;r   c                    t        j                  | t         j                        } t        | dddf   | dddf   z
        }t        | dddf   | dddf   z
        }t        | dddf   | dddf   z
        }t        j                  t        |       dft         j                        }t        j                  t        j                  t        ||      dd            |dddf<   t        j                  t        j                  t        | |      dd            |dddf<   t         j                  |dddf   z
  |dddf   z
  |dddf<   d||t        j                  k  j                  d	      ddf<   |S )
a   
    Calculates the angles of input triangles.

    Parameters
    ------------
    triangles : (n, 3, 3) float
      Vertex positions

    Returns
    ------------
    angles : (n, 3) float
      Angles at vertex positions in radians
      Degenerate angles will be returned as zero
    r   Nr   r   r   r   r)   r*   r   )r   r!   r   r   zerosr"   arccosclipr   pir   mergeany)r   uvwresults        r   anglesr>   j   sD     irzz:I 		!Q$)AqD/12A	!Q$)AqD/12A	!Q$)AqD/12A XXs9~q)<F99RWW\!Q%7Q?@F1a4L99RWW\1"a%8"a@AF1a4L556!Q$<'&A,6F1a4L 36FFSYY###+Q./Mr   c                 p   t        j                  | t         j                        } t        j                  | d      st        d      t        |       d   }| d   d   }t        | dd j                  d      ||      }t        j                  t        j                  |      t        j                  k        }|S )	a   
    Check to see if a list of triangles are all coplanar

    Parameters
    ----------------
    triangles: (n, 3, 3) float
      Vertices of triangles

    Returns
    ---------------
    all_coplanar : bool
      True if all triangles are coplanar
    r   r)   r   r   Triangles must be (n, 3, 3)!r   r   Nr)   r   pointsplane_normalplane_origin)r   r!   r   r   is_shaper   r2   r   reshapeallr#   r   zero)r   test_normaltest_vertex	distancesall_coplanars        r   rN   rN      s     irzz:I==J/788)$Q'KA,q/K$}$$W-  I
 66"&&+chh67Lr   c           	         t        j                  | t         j                        } t        j                  | d      st        d      t        |       d   }| d   d   }t        | dd j                  d      ||      }t        j                  t        j                  t        j                  |j                  d      t        j                  k        d	            }|S )
z
    For a list of triangles if the FIRST triangle is coplanar
    with ANY of the following triangles, return True.
    Otherwise, return False.
    r   r@   rA   r   r   NrB   rC   r   )r   r!   r   r   rG   r   r2   r   rH   r9   rI   r#   r   rJ   )r   rK   rL   rM   any_coplanars        r   rP   rP      s     irzz:I==J/788)$Q'KA,q/K$}$$W-  I
 66"&&	(9(9'(BSXX(M!NUVWXLr   c                   b    e Zd ZU eed<   eed<   eed<   ee   ed<   dZeee      ed<   de	fdZ
y)	MassPropertiesdensitymassvolumecenter_massNinertiaitemc                     t        | |      S N)getattr)selfrX   s     r   __getitem__zMassProperties.__getitem__   s    tT""r   )__name__
__module____qualname__float__annotations__r	   r   rW   r
   strr]    r   r   rR   rR      sF     N K M !! +/GXgg&'.# #r   rR   c                 H   t        j                  | t         j                        } t        j                  | d      st        d      |t        |       }|d}| dddddf   | dddddf   z   | dddddf   z   }| dddddf   dz  | dddddf   dz  z   | dddddf   | dddddf   z  z   | dddddf   |z  z   }| dddddf   d	z  | dddddf   dz  | dddddf   z  z   | dddddf   | dddddf   dz  z  z   | dddddf   d	z  z   | dddddf   |z  z   }|| dddddf   |z   | dddddf   z  z   }|| dddddf   |z   | dddddf   z  z   }	|| dddddf   |z   | dddddf   z  z   }
t        j                  d
t        |      f      }|dddf   |dddf   z  |d<   ||z  j                  |dd ||z  j                  |dd t        d	      D ]i  }t        j                  |dz   d	      }|dd|f   | ddd|f   |dd|f   z  | ddd|f   |	dd|f   z  z   | ddd|f   |
dd|f   z  z   z  ||dz   <   k |j                  d      t        j                  g dt         j                        z  }|d   }|Ct        j                  |      t        j                   k  rt"        j%                  d       |dd |z  }t'        |||z  ||      }|r|S t        j                  d      }|d   |d   z   ||ddg   dz  j                         z  z
  |d<   |d   |d   z   ||ddg   dz  j                         z  z
  |d<   |d   |d   z   ||ddg   dz  j                         z  z
  |d<   |d   |t        j(                  |ddg         z  z
   |d<   |d   |t        j(                  |ddg         z  z
   |d<   |d   |t        j(                  |ddg         z  z
   |d<   |d   |d<   |d   |d<   |d   |d<   ||z  |_        |S )aL  
    Calculate the mass properties of a group of triangles.

    Implemented from:
    http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf

    Parameters
    ----------
    triangles : (n, 3, 3) float
      Triangle vertices in space
    crosses : (n,) float
      Optional cross products of triangles
    density : float
      Optional override for density
    center_mass :  (3,) float
      Optional override for center mass
    skip_inertia : bool
      if True will not return moments matrix

    Returns
    ---------
    info : dict
      Mass properties
    r   r@   rA   Nr+   r   r   r   r   
         r   )
      rj   rj   <   rk   rk   x   rl   rl   z@volume is negative center of mass is almost certain to be wrong!)rS   rT   rU   rV   )r   r      ri   )r   r   )r   r   )r   r   )r   r      )r   r   	   )r   r   )r   r   )r   r   )r   r   )r   r!   r   r   rG   r   r   r4   r"   Trangemodr%   arrayr#   r   rJ   logdebugrR   prodrW   )r   r&   rS   rV   skip_inertiaf1f2f3g0g1g2integrali
triangle_i
integratedrU   r=   rW   s                     r   mass_propertiesr      s   6 irzz:I==J/788	" 
1a7	i1a0	09Q1W3E	EB 	!Q'a
Aq!G

!	"
Aq!G
yAq1
1	2 Aq!G
r
!	"  
1a7	q	 Q1W"yAq'9
:	;Q1W)Aq!G"4"9
:	; Q1W"	$ Q1W"		$  
yAq!B&)Aq!G*<<	<B	yAq!B&)Aq!G*<<	<B	yAq!B&)Aq!G*<<	<BxxSW&H!Q$-"QT(*HQKr\$$HQqMr\$$HQqM1XVVAE1%
!!Q$-q!Z'(2ad83Az)*R1X57Az)*R1X57
Q  1%2"**) J ]F 66&>CHH$IIXY 1o.v	F hhvG1
1%;1v3F!3K2P2P2R)RS DM 	1
1%;1v3F!3K2P2P2R)RS DM 	1
1%;1v3F!3K2P2P2R)RS DM !mvQF8K0L'LMNGDM mvQF8K0L'LMNGDM mvQF8K0L'LMNGDMDMGDMDMGDMDMGDMw&FNMr   c                    t        j                  | t         j                        } t        j                  | dd      st        d| j                        t        j                  |t         j                        }t        |       \  }}|j                  dk(  rt        j                  ||      }nt        |||         }t        j                  t        |       t              }|dkD  ||<   |S )a^  
    Given a list of triangles and a list of normals determine if the
    two are aligned

    Parameters
    ----------
    triangles : (n, 3, 3) float
      Vertex locations in space
    normals_compare : (n, 3) float
      List of normals to compare

    Returns
    ----------
    aligned : (n,) bool
      Are normals aligned with triangles
    r   r@   T)allow_zerosz)triangles must have shape (n, 3, 3), got )r   r*   )r   r!   r   r   rG   r   r   r2   dotr   r4   r"   r/   )r   normals_compare
calculatedr1   
differencealigneds         r   windings_alignedr   O  s    " irzz:I==JDADY__DWXYYmmO2::FO	*J$VVJ8
 "*oe.DE
hhs9~T2G#%GENNr   c                 *   t        j                  | t         j                        } t        j                  | d      st        d      t        j                  | j                  d      | j                  d      f      }t        j                  |      }|S )a  
    Given a list of triangles, create an r-tree for broad- phase
    collision detection

    Parameters
    ---------
    triangles : (n, 3, 3) float
      Triangles in space

    Returns
    ---------
    tree : rtree.Rtree
      One node per triangle
    r   )r)   r   )r   r   rA   r   r   )
r   r!   r   r   rG   r   column_stackminmaxbounds_tree)r   triangle_boundstrees      r   r   r   s  ss     irzz:I==O4788 ooy}}!}'<immQRm>S&TUOO,DKr   c                     t        j                  | t         j                        } t        j                  | d      st        d      |t        j                  }t        | |      |kD  j                  d      }|S )a  
    Find all triangles which have an oriented bounding box
    where both of the two sides is larger than a specified height.

    Degenerate triangles can be when:
    1) Two of the three vertices are colocated
    2) All three vertices are unique but colinear


    Parameters
    ----------
    triangles : (n, 3, 3) float
      Triangles in space
    height : float
      Minimum edge length of a triangle to keep

    Returns
    ----------
    nondegenerate : (n,) bool
      True if a triangle meets required minimum height
    r   r@   rA   )r   areasr   r   )
r   r!   r   r   rG   r   r   r8   extentsrI   )r   r   heightoks       r   nondegenerater     sf    , irzz:I==J/788~ IU
3f
<	A	Aq	A	IBIr   c                 f   t        j                  | t         j                        } t        j                  | d      st        d      |t        |       }| dddf   | dddf   z
  }| dddf   | dddf   z
  }|dz  j                  d	      d
z  }|dz  j                  d	      d
z  }|t        j                  kD  }|t        j                  kD  }t        j                  t        |       dft         j                        }||   dz  ||   z  |dddf   |<   ||   dz  ||   z  |dddf   |<   |S )a@  
    Return the 2D bounding box size of each triangle.

    Parameters
    ----------
    triangles : (n, 3, 3) float
      Triangles in space
    areas : (n,) float
      Optional area of input triangles

    Returns
    ----------
    box :  (n, 2) float
      The size of each triangle's 2D oriented bounding box
    r   r@   rA   N)r   r   r   r   r   g      ?)r   r!   r   r   rG   r   r'   r%   r   r8   r4   r"   )	r   r   r   r   length_alength_b	nonzero_a	nonzero_bboxs	            r   r   r     s9     irzz:I==J/788}y) 	!Q$)AqD/)A!Q$)AqD/)A 1zzqz!S(H1zzqz!S(H 399$I399$I
 ((C	NA&bjj
9C!),q0HY4GGC1Ii!),q0HY4GGC1IiJr   c                 *   t        j                  |t         j                        }t        j                  | t         j                        } ||j	                  d      j                  d      z  }| |j                  d      z  j	                  d      }|S )aG  
    Convert a list of barycentric coordinates on a list of triangles
    to cartesian points.

    Parameters
    ------------
    triangles : (n, 3, 3) float
      Triangles in space
    barycentric : (n, 2) float
      Barycentric coordinates

    Returns
    -----------
    points : (m, 3) float
      Points in space
    r   r   r   r)   r   )r)   r   r   )r   rs   r   r!   r%   rH   )r   barycentricrD   s      r   barycentric_to_pointsr     sv    " ((;bjj9Kirzz:I ;???*227;;K+--j99>>A>FFMr   c                 R     fd} fd}t        j                   t         j                         t        j                  |t         j                        }t         j                        dk7  rt        d       j                  d   }t        |j                        dk7  s1|j                  d   |k7  s|j                  d    j                  d   k7  rt        d	       d
d
dd
f    d
d
d
df   z
  | d
d
df   j                  d|f      z
  |dk(  r |       S  |       S )a;  
    Find the barycentric coordinates of points relative to triangles.

    The Cramer's rule solution implements:
        http://blackpawn.com/texts/pointinpoly

    The cross product solution implements:
        https://www.cs.ubc.ca/~heidrich/Papers/JGT.05.pdf


    Parameters
    -----------
    triangles : (n, 3, 2 | 3) float
      Triangles vertices in space
    points : (n, 2 | 3) float
      Point in space associated with a triangle
    method :  str
      Which method to compute the barycentric coordinates with:
        - 'cross': uses a method using cross products, roughly 2x slower but
                  different numerical robustness properties
        - anything else: uses a cramer's rule solution

    Returns
    -----------
    barycentric : (n, 3) float
      Barycentric coordinates of each point
    c                     t        j                  d d df   d d df         } t        | |       }t        j                  t	              dft         j
                        }t        t        j                  d d df         |       |z  |d d df<   t        t        j                  d d df         |       |z  |d d df<   d|d d df   z
  |d d df   z
  |d d df<   |S )Nr   r   r   r   r   )r   r   r   r4   r"   r   )ndenominatorr   edge_vectorsr   r<   s      r   method_crossz+points_to_barycentric.<locals>.method_cross  s    HH\!Q$'ad);<"1a(hhI2"**E(,q!t2Da)H!L{ZAqD(!\!Q$5G)H!L{ZAqDAqD 11K14EEAqDr   c                     t        d d df   d d df         } t        d d df   d d df         }t        d d df   	      }t        d d df   d d df         }t        d d df   	      }d| |z  ||z  z
  z  }t        j                  t              dft        j                        }| |z  ||z  z
  |z  |d d df<   ||z  ||z  z
  |z  |d d df<   d|d d df   z
  |d d df   z
  |d d df<   |S )Nr   r   r+   r   r   r   )r   r   r4   r"   r   )
dot00dot01dot02dot11dot12inverse_denominatorr   r   r   r<   s
          r   method_cramerz,points_to_barycentric.<locals>.method_cramer  s.   \!Q$/ad1CD\!Q$/ad1CD\!Q$/3\!Q$/ad1CD\!Q$/3!UU]UU]%BChhI2"**E"U]UU]:>QQAqD"U]UU]:>QQAqDAqD 11K14EEAqDr   r   r   triangles shape incorrectr   r   r   z$triangles and points must correspondNr)   r   )r   r!   r   r"   r   r   rH   )r   rD   methodr   r   dimr   r<   s   `     @@r   points_to_barycentricr     s   :  irzz:I]]64F 9??q 455 //!
CFLLQ<<?c!<<?iooa00?@@QU#i2A2&66L1a4(("c33A~?r   c                 	   t        j                  | t         j                        } t        j                  |t         j                        }t        j                  | d      st        d      t        j                  |t        |       df      st        d      t        j                  |      }t        j                  t        |      t              }g d}| dddddf   }| ddd	ddf   }| ddd
ddf   }||z
  }||z
  }	||z
  }
t        j                  ||
z  |      }t        j                  |	|
z  |      }t        j                  |t        j                  k  |t        j                  k        }t        |      r||   ||<   d||<   ||z
  }t        j                  ||z  |      }t        j                  |	|z  |      }|t        j                   kD  ||k  z  |z  }t        |      r||   ||<   d||<   ||z  ||z  z
  }|t        j                  k  |t        j                   kD  z  |t        j                  k  z  |z  }t        |      r6||   ||   ||   z
  z  j                  d      }||   |||   z  z   ||<   d||<   ||z
  }t        j                  ||z  |      }t        j                  |	|z  |      }|t        j                   kD  ||k  z  |z  }t        |      r||   ||<   d||<   ||z  ||z  z
  }|t        j                  k  |t        j                   kD  z  |t        j                  k  z  |z  }t        |      r6||   ||   ||   z
  z  j                  d      }||   ||	|   z  z   ||<   d||<   ||z  ||z  z
  }|t        j                  k  ||z
  t        j                   kD  z  ||z
  t        j                   kD  z  |z  }t        |      rG||   ||   z
  }||||   ||   z
  z   z  j                  d      }||   |||   ||   z
  z  z   ||<   d||<   t        |      r\d||   ||   z   ||   z   z  }||   |z  j                  d      }||   |z  j                  d      }||   ||   |z  z   |	|   |z  z   ||<   |S )a  
    Return the closest point on the surface of each triangle for a
    list of corresponding points.

    Implements the method from "Real Time Collision Detection" and
    use the same variable names as "ClosestPtPointTriangle" to avoid
    being any more confusing.


    Parameters
    ----------
    triangles : (n, 3, 3) float
      Triangle vertices in space
    points : (n, 3) float
      Points in space

    Returns
    ----------
    closest : (n, 3) float
      Point on each triangle closest to each point
    r   r@   r   r   z)need same number of triangles and points!)r+   r+   r+   Nr   r   r   Fr   r+   )r   r!   r   r   rG   r   r"   
zeros_liker.   r/   r   logical_andr   rJ   r9   rH   ) r   rD   r=   remainr.   r   r   cabacapd1d2is_abpd3d4is_bvcis_abr;   cpd5d6is_cvbis_acr<   vais_bcd43denoms                                    r   closest_pointr   G  s   0 irzz:I]]64F==J/455==#i.!!45DEE ]]6"FWWS[-F D 	!Q'A!Q'A!Q'A 
QB	
QB	!B 
R	B	R	B >>"sxx-chh7D
4ywtt 
!B	R	B	R	B #((NrRx(61D
4ywtt r'b2g	B#((]rSXXI~."sxx-@6IE
5zY"U)bi/099'B%A5	M2uu 
!B	R	B	R	B#((NrRx(61D
4ywtt r'b2g	B#((]rSXXI~."sxx-@6IE
5zY"U)bi/099'B%1r%y=0uu r'b2g	B#((]RCHH945"r'chhY9NORXXE
5zi"U)#C2e9r%y012;;GD%1%1U8(;#<<uu 6{r&zBvJ.F;<Z%((1Z%((16bj1n5FaHvMr   c                    t        j                  | t         j                        } t        j                  | d      st        d      | j                  d      }t        j                  t        |            j                  d      }||d}|S )a  
    Convert a list of triangles to the kwargs for the Trimesh
    constructor.

    Parameters
    ---------
    triangles : (n, 3, 3) float
      Triangles in space

    Returns
    ---------
    kwargs : dict
      Keyword arguments for the trimesh.Trimesh constructor
      Includes keys 'vertices' and 'faces'

    Examples
    ---------
    >>> mesh = trimesh.Trimesh(**trimesh.triangles.to_kwargs(triangles))
    r   r@   rA   rB   )verticesfaces)	r   r!   r   r   rG   r   rH   aranger"   )r   r   r   kwargss       r   	to_kwargsr     sn    ( irzz:I==J/788  )HIIc(m$,,W5E"U3FMr   )NN)NNNFrZ   )cramer)%__doc__dataclassesr   loggingr   numpyr    r   	constantsr   rD   r   typedr	   r
   r   r   r   r^   rt   r   r'   r2   r>   rN   rP   rR   r   r   r   r   r   r   r   r   r   rd   r   r   <module>r      s    "     ( - - '&W & &434@#L:* # # #. KPssl!H2!H*Z6L^slr   