
    Mixo                         S r SSKrSSKJrJrJr  SSKJr  SSKJ	r
  SSKJr  SSK	Jr     SS	 jrS
 rSS jr  SS jr   SS jr   SS jrg)zT
intersections.py
------------------

Primarily mesh-plane intersections (slicing).
    N   )geometrygroupingutil)transformations)	triangles)tol)points_to_barycentricc                 X  ^^ S nUU4S jnS nUU4S jn	[         R                  " T[         R                  S9m[         R                  " T[         R                  S9mTR                  S:w  d  TR                  S:w  a  [	        S5      eUc  U R
                  n
O2[         R                  " U[         R                  S9nU R
                  U   n
Ub  UnO$[         R                  " U R                  T-
  T5      n[         R                  " [        U R                  5      [         R                  S9nSX[        R                  * :  '   S	X[        R                  :  '   X   nU" U5      nXU4n[         R                  " [        X5       VVs/ s H  u  nnU" X   X   U R                  5      PM      snn5      nU(       ah  [         R                   " U Vs/ s H  n[         R"                  " U5      S
   PM     sn5      nUR$                  R&                  S:X  d   eUc  UU4$ UUU   4$ U$ s  snnf s  snf )a  
Find a the intersections between a mesh and a plane,
returning a set of line segments on that plane.

Parameters
---------
mesh : Trimesh object
  Source mesh to slice
plane_normal : (3,) float
  Normal vector of plane to intersect with mesh
plane_origin : (3,) float
  Point on plane to intersect with mesh
return_faces : bool
  If True return face index each line is from
local_faces : None or (m,) int
  Limit section to just these faces.
cached_dots : (n, 3) float
  If an external function has stored dot
  products pass them here to avoid recomputing.

Returns
----------
lines :  (m, 2, 3) float
  List of 3D line segments in space.
face_index : (m,) int
  Index of mesh.faces for each line
  Only returned if return_faces was True
c                 X   [         R                  " U SS9n[         R                  " [        U5      [         R                  S9S-   n[        S5       H  nX!SS2U4   SU-
  -  -  nM     [         R                  " S[        S9nSUS	'   XB   nS
USS& SUS'   XB   nS
USS& SUSS/'   XB   nXvU4$ )a  
Figure out which faces correspond to which intersection
case from the signs of the dot product of each vertex.
Does this by bitbang each row of signs into an 8 bit
integer.

code : signs      : intersects
0    : [-1 -1 -1] : No
2    : [-1 -1  0] : No
4    : [-1 -1  1] : Yes; 2 on one side, 1 on the other
6    : [-1  0  0] : Yes; one edge fully on plane
8    : [-1  0  1] : Yes; one vertex on plane 2 on different sides
12   : [-1  1  1] : Yes; 2 on one side, 1 on the other
14   : [0 0 0]    : No (on plane fully)
16   : [0 0 1]    : Yes; one edge fully on plane
20   : [0 1 1]    : No
28   : [1 1 1]    : No

Parameters
----------
signs: (n,3) int, all values are -1,0, or 1
  Each row contains the dot product of all three vertices
  in a face with respect to the plane

Returns
---------
basic : (n,) bool
  Which faces are in the basic intersection case
one_vertex : (n,) bool
  Which faces are in the one vertex case
one_edge : (n,) bool
  Which faces are in the one edge case
r   axisdtype      N   T   F         )npsortzeroslenint8rangebool)signssigns_sortedcodedikeyone_edge
one_vertexbasics           o/var/www/eduai.edurigo.com/storigo/production/storigo_env/lib/python3.13/site-packages/trimesh/intersections.pytriangle_cases"mesh_plane.<locals>.triangle_cases6   s    F wwu1-\*"'':R?qA!Q$'1q500E  hhr&B: AAZ
 AQG
(**    c                    > XS:H     nXS:g     R                  S5      n[        T	TX$R                     SS9u  pV[        R                  " X#U      U45      R                  S5      nU$ )Nr      Fline_segmentsr-   r.   r   )reshapeplane_linesTr   column_stack)
r   facesverticesvertex_plane	edge_thrupoint_intersectvalidlinesplane_normalplane_origins
           r'   handle_on_vertex$mesh_plane.<locals>.handle_on_vertext   sw     aZ(1*%--g6	!,,(=U"
 u*=!> PQYY
 r*   c                 :    XS:H     R                  S5      nX#   nU$ )Nr   r,   )r2   )r   r6   r7   edgespointss        r'   handle_on_edge"mesh_plane.<locals>.handle_on_edge   s%    qj!))'2r*   c                 l  > [         R                  " U SS/S9n[        R                  " X   U[        R                  " USSS9   X   U[        R                  " USSS9   45      R                  S5      n[        TTX$R                     SS9u  pVUR                  5       (       d   eUR                  S	5      $ )
Nr-   r   )uniquer   r.   r,   Fr/   r1   )	r   unique_value_in_rowr   r5   rollr2   r3   r4   all)	r   r6   r7   unique_elementrB   intersectionsr;   r=   r>   s	          r'   handle_basic mesh_plane.<locals>.handle_basic   s    !55eRGL%bggnaa89%bggnaa89	
 ''
 	  +,(9 

 yy{{{$$Z00r*   r   r   z%Plane origin and normal must be (3,)!r-   r   r   r"   )r   
asanyarrayfloat64shape
ValueErrorr6   int64dotr7   r   r   r   r	   mergevstackziphstacknonzeror   kind)meshr=   r>   return_faceslocal_facescached_dotsr(   r?   rD   rM   r6   dotsr   caseshandlerschr<   indexs    ``                r'   
mesh_planerf      s   J<+|1( ==RZZ@L==RZZ@LT!\%7%74%?@AA

mmKrxx@

;'
 vvdmml2LA HHS'rww7E!E#))
E
LE 5!E?H II:=e:NO:N$!Q58UXt}}	-:NOE 		U;U2::a=+U;<{{3&&&%< k%(((L 	P
 <s   %H!
#H'c           	         [         R                  " U5      n[        R                  " U[        R                  S9n[        R                  " U[        R                  S9n[        R
                  " X R                  U-
  R                  5      n[        R                  " XS9n[        R                  R                  U5      n[        R                  " S5      n/ n/ n/ n	U H  n
XU
-  -   nXJ-
  n[        U UUSUS9u  pXS'   [        R
                  " XV5      n[        R                  R                  U5      nUR                  U5        [        R                   " UR#                  S5      U5      nUSS2SS	24   R#                  S
5      nU	R                  U5        UR                  U5        M     [        R$                  " U[        R                  S9nXU4$ )a  
A utility function for slicing a mesh by multiple
parallel planes which caches the dot product operation.

Parameters
-------------
mesh : trimesh.Trimesh
    Geometry to be sliced by planes
plane_origin : (3,) float
    Point on a plane
plane_normal : (3,) float
    Normal vector of plane
heights : (m,) float
  Offset distances from plane to slice at:
  at `height=0` it will be exactly on the passed plane.

Returns
--------------
lines : (m,) sequence of (n, 2, 2) float
    Lines in space for m planes
to_3D : (m, 4, 4) float
    Transform to move each section back to 3D
face_index : (m,) sequence of (n,) int
    Indexes of mesh.faces for each segment
r   originnormalr   T)r\   r>   r=   r]   r_   )r.   r   r-   r   Nr.   )r-   r.   r.   )r   unitizer   rP   rQ   rU   r7   r4   r   plane_transformlinalginveyerf   appendtftransform_pointsr2   array)r\   r>   r=   heightsvertex_dotsbase_transformtranslation
transforms
face_indexsegmentsheight
new_originnew_dotsr<   re   to_3Dto_2Dlines_2Ds                     r'   mesh_multiplaner      s   6 <<-L==RZZ@LmmG2::6G &&(D'G'GHK --\WNYY]]>2N &&)K JJH !F%:;
'!#% 
 #D~3		e$%  &&u}}W'=uE ArrE?**:6!% A F *BJJ7J++r*   c                 n   [         R                  " U5      n[         R                  " U 5      R                  S5      n [        R                  " US   US   -
  5      n[        R                  " [         R                  " U5      R                  S5      5      n[         R
                  " XUS   -
  R                  5      n[         R
                  " XR                  5      n[         R                  " U5      [        R                  :  nU(       a  [         R
                  " U[         R                  " XS   -
  5      5      n[         R                  " U5      [         R                  " U5      :g  n	[         R                  " [         R                  " U5      [        R                  :  [         R                  " U5      [        R                  :  5      n
[         R                  " Xy5      n[         R                  " Xz5      n[         R                  " XW   Xg   5      nUS   U   nU[         R                  " US5      XG   -  -   nX4$ )a!  
Calculate plane-line intersections

Parameters
---------
plane_origin : (3,) float
    Point on plane
plane_normal : (3,) float
    Plane normal vector
endpoints : (2, n, 3) float
    Points defining lines to be tested
line_segments : bool
    If True, only returns intersections as valid if
    vertices from endpoints are on different sides
    of the plane.

Returns
---------
intersections : (m, 3) float
    Cartesian intersection points
valid : (n, 3) bool
    Indicate whether a valid intersection exists
    for each input line segment
r   r   r   r-   r   )r   rP   r2   r   rl   rU   r4   absr	   zero	transposesign
logical_orlogical_anddivide)r>   r=   	endpointsr0   line_dirtbr;   testdifferent_sidesrZ   dintersections                r'   r3   r3   %  s   2 i(I==.66q9L||IaL9Q<78H<<l ; C CA FGL
|Yq\9<<=A
|ZZ(A
 FF1I EvvlBLL!1L$MN''!*5--q	CHH 4bffTlSXX6MNu6u.
		!(AH%AQ<&L"**Q"88?"JJLr*   c                    [         R                  " U [         R                  S9n [         R                  " U[         R                  S9n[         R                  " U[         R                  S9n[         R                  " U[         R                  S9nX-
  n[        R                  " Xa5      n[        R                  " X15      n[         R
                  " U5      S:  n	[         R                  " Xy   X   5      n
X9   U
R                  S5      -  nXU	   -  nX/nU(       a  UR                  U
5        U(       a  UR                  U5        U$ )a  
Given one line per plane find the intersection points.

Parameters
-----------
plane_origins : (n,3) float
    Point on each plane
plane_normals : (n,3) float
    Normal vector of each plane
line_origins : (n,3) float
    Point at origin of each line
line_directions : (n,3) float
    Direction vector of each line
return_distance : bool
  Return distance from origin to point also
return_denom : bool
  Return denominator, so you can check for small values

Returns
----------
on_plane : (n,3) float
  Points on specified planes
valid : (n,) bool
  Did plane intersect line or not
distance : (n,) float
  [OPTIONAL] Distance from point
denom : (n,) float
  [OPTIONAL] Denominator
r   gh㈵>r   )	r   rP   rQ   r   diagonal_dotr   r   r2   rq   )plane_originsplane_normalsline_originsline_directionsreturn_distancereturn_denomorigin_vectorsprojection_oriprojection_dirr;   distanceon_planeresults                r'   planes_linesr   X  s    N MM-rzzBMMM-rzzBM==RZZ@LmmO2::FO #1N&&~EN&&FNFF>"T)Eyy.0EFH%(8(8(AAHU##HFhn%Mr*   c           	      2   [        U 5      S:X  a  XU4$ USLnUb  X   nUb  UnO[        R                  " X-
  U5      n[        R                  " [        U 5      [        R                  S9n	SX[
        R                  * :  '   SX[
        R                  :  '   X   n	U	R                  S[        R                  S9n
[        R                  " U	5      R                  S[        R                  S9n[        R                  " US:  [        R                  " U
5      S:*  5      nX* :H  nUS:H  nUR                  5       (       aC  [        R                  " XU      5      u  nn[        R                  " X5      nUX'   UX'   US:  X'   X   nX   nUU   nU[        R                  " XS:  5         nU[        R                  " XS:  5         nU	[        R                  " XS:  5         nU	[        R                  " XS:  5         n[        U5      [        U5      -   S:X  a  [        U5      S:X  av  [        R                  " S	[        R                  S9[        R                  " S	[        R                  S9U(       a&  [        R                  " S
[        R                  S94nU$ S4nU$ [        R                   " UR#                  S5      [        U 5      SS9u  nnU U   nUR#                  S5      nU(       a  UU   OSnUUU4$ Un[        R$                  " USSS9U-
  n UU-
  R                  U5      n![        R                  " U U5      n"SU"U"S:H  '   [        R&                  " U!U"5      n#U#SS2SS2S4   U -  U-   n$U n%[        R                  " S	5      n&[        R                  " S	5      n'U$U
S:  U   SS2SS24   n([        U(5      n)U)S:  Gas  [        R(                  " US:H  5      S   n*U[        R*                  " [-        U)5      [-        U)5      4SS9[        R*                  " U*S-   S-  U*S-   S-  4SS94   n+[        R.                  " U+[        R0                  " [        U%5      [        U%5      SU)-  -   5      R#                  U)S5      SS9n,U([        R*                  " [-        U)5      [-        U)5      4SS9[        R*                  " U*S-   S-  R2                  U*R2                  4SS9SS24   R#                  SU)-  S5      n&[        R.                  " U%U&SS9n%[4        R6                  " U,5      n-[        R.                  " UU-SS9nU$U
S:  U   SS2SS24   n.[        U.5      n/U/S:  Ga.  [        R(                  " US:H  5      S   n0U[-        U/5      U04   R#                  U/S5      n1[        R.                  " U1[        R0                  " [        U%5      [        U%5      SU/-  -   5      R#                  U/S5      SS9n2U.[        R*                  " [-        U/5      [-        U/5      4SS9[        R*                  " U0R2                  U0S-   S-  R2                  4SS9SS24   R#                  SU/-  S5      n'[        R.                  " U%U'SS9n%[        R.                  " UU2SS9n[        R                   " UR#                  S5      [        U%5      SS9u  nnU%U   nUR#                  S5      nSnU(       a  [9        [        R:                  " U U   SSS9U&5      n3[9        [        R:                  " U U   SSS9U'5      n4[        R<                  " U3U4/5      n5[        R<                  " UU   UU   /5      n6[        R>                  " S[        R:                  " U6SSS9U55      n7[        R<                  " UU7/5      U   nUUU4$ )a  
Slice a mesh (given as a set of faces and vertices) with a plane, returning a
new mesh (again as a set of faces and vertices) that is the
portion of the original mesh to the positive normal side of the plane.

Parameters
---------
vertices : (n, 3) float
    Vertices of source mesh to slice
faces : (n, 3) int
    Faces of source mesh to slice
plane_normal : (3,) float
    Normal vector of plane to intersect with mesh
plane_origin :  (3,) float
    Point on plane to intersect with mesh
uv : (n, 2) float, optional
    UV coordinates of source mesh to slice
face_index : ((m,) int)
    Indexes of faces to slice. When no mask is provided, the
    default is to slice all faces.
cached_dots : (n, 3) float
    If an external function has stored dot
    products pass them here to avoid recomputing

Returns
----------
new_vertices : (n, 3) float
    Vertices of sliced mesh
new_faces : (n, 3) int
    Faces of sliced mesh
new_uv : (n, 2) int or None
    UV coordinates of sliced mesh
r   Nr   r   r-   )r   r   r.   g        )r   r   )r   r.   T)	minlengthreturn_inverserk   r   g-q=r   z
ijk,ij->ik) r   r   rU   r   r   r	   rV   sumr   r   anytmnormalsrQ   rT   r   unique_bincountr2   rI   r   wherestackr   rq   aranger4   r   triangulate_quadsr
   repeatconcatenateeinsum)8r7   r6   r=   r>   uvrz   r_   have_uvr`   r   	signs_sum
signs_asumonedgeinsider   checkr;   	dot_check	new_facesr   cut_trianglescut_faces_quadcut_faces_tricut_signs_quadcut_signs_triemptyrG   inverse
final_vert
final_facefinal_uvor   numdenomdist
int_pointsnew_verticesnew_quad_verticesnew_tri_verticesquad_int_points	num_quadsquad_int_indsquad_int_vertsnew_quad_facesnew_tri_faces_from_quadstri_int_pointsnum_tristri_int_indstri_int_vertsnew_tri_facesquad_barycentricstri_barycentricsall_barycentricscut_uvnew_uvs8                                                           r'   slice_faces_planer     s5   V 8}""nG !
 vvh-|< HHS]"''2E E#))
 E
LE
 		q	0I"""9J ^^J!ORVVI->!-CDF+%F
 QH||~~ zz(?";<uFF5/	 "$s? I
 If%M2>>&a-@AN"..a@AM2>>&a-@AN"..a@AM >S//14y>Q rzz2rxx06=rzz2E
 L DHE
 L #22b!S]4

 f%
__W-
!(2f:d:x// 	A
2A"A!
 
 
.CFF1l#EE%3,99S% DaDj!A%)J L(xx' !)a-!8!Q!>?OO$I1} 1!45a8'HHeI&i(89BHH}q(A-0AQ/FGaPR
 IIc,'\):Q])JKSS1 
 ,HHeI&i(89BHH)Q.11=??C!L
 '!i-
#	 	 yy/@qI#+#=#=n#M IIi)AJ	  a 8!Q >?N>"H!| xx 34Q7%eHo|&CDLLXWXY 		IIc,'\):Q\)IJRR! 
 *HHeHouX7a@HHlnnq(8A'=&@&@AJ
 '!h,
"	 	 yy/?aHIIiQ?	 .."\):4OFG
 f%J)JH1IIh~.:<M
 1IIh}-qq9;K
 >>+<>N*OP N!3R5F GH<611)EGWX>>2v,/7z8++r*   c           
      j	   U c  gSSK Jn  SSKJn  SSKJn	  SSKJn
  SSKJ	n  [        R                  " U[        R                  S	9n[        R                  " U[        R                  S	9nUR                  S
:H  =(       d    [        R                  " US5      =(       aM    UR                  S
:H  =(       d    [        R                  " US5      =(       a    UR                  UR                  :H  nU(       d  [!        S5      eU R"                  R%                  5       nU R&                  R%                  5       n[)        U R                  S5      =(       aB    [        R                  " U R                  R*                  5      [-        U R"                  5      S4:H  =(       a    U(       + nU(       a$  U R                  R*                  R%                  5       OSnSU;  a  SUS'   [/        UR1                  S5      UR1                  S5      5       GHt  u  nn[3        UUUUUUS9u  pnU(       d  M!  U(       a  [5        S5      e[6        R8                  " U5      u  nnUU   nUU   nUUSS2SS24   USS2SS24   :g  R;                  SS9   n[<        R>                  " UU* S9n[        R@                  RC                  U5      n[D        RF                  " UU5      n[<        RH                  " U5      nURK                  SS9  [        RL                  " USS2S4   5      S:  nUUU   R;                  SS9   nUUSS2S4   USS2S4   :g     n[6        RN                  " USS9n[-        U5      S:  a  GM`  U" U5      nU/nU
RQ                  UU   USS2SS24   5       H  nU	" UUSS9u  nn[D        RF                  " [        RR                  " U5      U5      n URU                  U 5      u  n!n"U!RW                  5       S:  a  [        RX                  R[                  S5        U"U   n#U#SS2SS24   U#SS2SS24   :g  R;                  SS9U#SS2S4   U#SS2S4   :g  -  n$UR]                  U#U$   5        M     [        R^                  " U5      nGMw     U(       a)  U" UU R                  R`                  R%                  5       S9OSn%U" SXU%S.UD6$ )a@  
Slice a mesh with a plane returning a new mesh that is the
portion of the original mesh to the positive normal side
of the plane.

Parameters
---------
mesh : Trimesh object
  Source mesh to slice
plane_normal : (3,) float
  Normal vector of plane to intersect with mesh
plane_origin :  (3,) float
  Point on plane to intersect with mesh
cap : bool
  If True, cap the result with a triangulated polygon
face_index : ((m,) int)
  Indexes of mesh.faces to slice. When no mask is provided, the
  default is to slice all faces.
cached_dots : (n, 3) float
  If an external function has stored dot
  products pass them here to avoid recomputing
engine : None or str
  Triangulation engine passed to `triangulate_polygon`
kwargs : dict
  Passed to the newly created sliced mesh

Returns
----------
new_mesh : Trimesh object
  Sliced mesh
Nr   )cKDTreer   )Trimesh)triangulate_polygon)polygons)TextureVisualsr   rO   rk   z)plane origins and normals must be (n, 3)!r   r.   processF)r7   r6   r   r=   r>   rz   z)face_index and cap can't be used togetherr   rh   g:0yE>)require_countr   T)engineforce_verticesz%triangulate may have inserted vertex!)r   material)r7   r6   visual )1scipy.spatialr   baser   creationr   pathr   r   r   r   rP   rQ   rR   r   is_shaperS   r7   copyr6   hasattrr   r   rX   r2   r   NotImplementedErrorr   unique_rowsrJ   r   rm   rn   ro   rr   rs   faces_to_edgesr   r   
group_rowsedges_to_polygonsstack_3Dquerymaxlogdebugrq   rW   r   )&r\   r=   r>   rz   capr   kwargsr   r   r   r   r   shape_okr7   r6   has_uvr   ri   rj   rG   r   fr   r   vertices_2DrB   r   unique_edgetreepvnfnvn3r   vidnfnf_okr   s&                                         r'   slice_mesh_planer    s<   R | &-& ==RZZ@L==RZZ@L 
		t	#	Kt}}\7'K 	54'O4==w+O	5,"4"44 
 DEE }}!!#HJJOOE 	T"Zrxx'?CDVXYCZ'Z'  #)			dB!y W%|';';G'D 0!
 3)*UVV '228<OFG'HA 1QU8qABx',,!,45A,,FF7KEIIMM%(E--h>K++A.EJJAJvvk!Q$/047H(5/--1-56E%1+q!t45E"--e1EK6{Q8$DCE//k0BKPQSUTUSUPUDVW,QvdSB))$--*;UC $

3#<<>D(HHNN#JKWAqrEbBQBi/44!4<1a4BqRStH@TURY' X IIe$Ew| HN"t{{';';'@'@'BCSW 
 KH&KFKKr*   )FNN)T)FF)NNN)NFN)__doc__numpyr    r   r   r   r   rr   r   r   	constantsr	   r
   rf   r   r3   r   r   r  r   r*   r'   <module>r     ss     & & #   , zzT,n0p @P v,z QLr*   