
    jxo                         d Z ddlZddlmZmZmZ ddlmZ ddlm	Z
 ddlmZ ddl	mZ 	 	 	 dd	Zd
 ZddZ	 	 ddZ	 	 	 ddZ	 	 	 ddZy)zT
intersections.py
------------------

Primarily mesh-plane intersections (slicing).
    N   )geometrygroupingutil)transformations)	triangles)tol)points_to_barycentricc                 H   d }fd}d }fd}	t        j                  t         j                        t        j                  t         j                        j                  dk7  sj                  dk7  rt	        d      || j
                  }
n4t        j                  |t         j                        }| j
                  |   }
||}n#t        j                  | j                  z
        }t        j                  t        | j                        t         j                        }d||t        j                   k  <   d	||t        j                  kD  <   ||
   } ||      }|	||f}t        j                  t        ||      D cg c]  \  }} |||   |
|   | j                        ! c}}      }|rat        j                   |D cg c]  }t        j"                  |      d
    c}      }|j$                  j&                  dk(  sJ |||fS |||   fS |S c c}}w c c}w )aH  
    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                 j   t        j                  | d      }t        j                  t        |      t         j                        dz   }t        d      D ]  }||dd|f   d|z
  z  z  } t        j                  dt              }d|d	<   ||   }d
|dd d|d<   ||   }d
|dd d|ddg<   ||   }|||fS )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           B/DATA/.local/lib/python3.12/site-packages/trimesh/intersections.pytriangle_casesz"mesh_plane.<locals>.triangle_cases6   s    F wwu1-\*"'':R?qA\!Q$'1q500E  hhr&Bu: AAZ
 AQGE
j(**    c                     || dk(     }|| dk7     j                  d      }t        	||j                     d      \  }}t        j                  |||      |f      j                  d      }|S )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_vertexz$mesh_plane.<locals>.handle_on_vertext   s     UaZ(%1*%--g6	!,,(=U"
 ,u*=!> PQYY
 r)   c                 >    || dk(     j                  d      }||   }|S )Nr   r+   )r1   )r   r5   r6   edgespointss        r'   handle_on_edgez"mesh_plane.<locals>.handle_on_edge   s)    eqj!))'2%r)   c                 z   t        j                  | ddg      }t        j                  ||   |t        j                  |dd         ||   |t        j                  |dd         f      j                  d      }t        ||j                     d      \  }}|j                         sJ |j                  d	      S )
Nr,   r   )uniquer   r-   r+   Fr.   r0   )	r   unique_value_in_rowr   r4   rollr1   r2   r3   all)	r   r5   r6   unique_elementr@   intersectionsr:   r<   r=   s	          r'   handle_basicz mesh_plane.<locals>.handle_basic   s    !55eRGLn%bggnaa89n%bggnaa89	
 ''
 	  +,(9 
u
 yy{{$$Z00r)   r   r   z%Plane origin and normal must be (3,)!r,   r   r   r"   )r   
asanyarrayfloat64shape
ValueErrorr5   int64dotr6   r   r   r   r	   mergevstackziphstacknonzeror   kind)meshr<   r=   return_faceslocal_facescached_dotsr(   r>   rB   rJ   r5   dotsr   caseshandlerschr;   indexs    ``                r'   
mesh_planerb      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:=eX:NO:N$!Q58U1Xt}}	-:NOE 		U;U2::a=+U;<{{3&&&%< k%(((L 	P
 <s   $H
	Hc                    t        j                  |      }t        j                  |t        j                        }t        j                  |t        j                        }t        j
                  || j                  |z
  j                        }t        j                  ||      }t        j                  j                  |      }t        j                  d      }g }g }g }	|D ]  }
|||
z  z   }||
z
  }t        | ||d|      \  }}|
|d<   t        j
                  ||      }t        j                  j                  |      }|j                  |       t        j                   |j#                  d      |      }|dddd	f   j#                  d
      }|	j                  |       |j                  |        t        j$                  |t        j                        }|	||fS )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)rX   r=   r<   rY   r[   )r-   r   r,   r   Nr-   )r,   r-   r-   )r   unitizer   rL   rM   rQ   r6   r3   r   plane_transformlinalginveyerb   appendtftransform_pointsr1   array)rX   r=   r<   heightsvertex_dotsbase_transformtranslation
transforms
face_indexsegmentsheight
new_originnew_dotsr;   ra   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%:;
'!#% 
u #D~{3		e$%  &&u}}W'=uE ArrE?**:6!% A F *BJJ7JZ++r)   c                 P   t        j                  |      }t        j                  |       j                  d      } t        j                  |d   |d   z
        }t        j                  t        j                  |      j                  d            }t        j
                  || |d   z
  j                        }t        j
                  ||j                        }t        j                  |      t        j                  kD  }|rt        j
                  |t        j                  | |d   z
              }t        j                  |      t        j                  |      k7  }	t        j                  t        j                  |      t        j                  kD  t        j                  |      t        j                  kD        }
t        j                  ||	      }t        j                  ||
      }t        j                  ||   ||         }|d   |   }|t        j                  |d      ||   z  z   }||fS )au  
    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   rL   r1   r   rh   rQ   r3   absr	   zero	transposesign
logical_orlogical_anddivide)r=   r<   	endpointsr/   line_dirtbr:   testdifferent_sidesrV   dintersections                r'   r2   r2   %  s   2 i(I==.66q9L||IaL9Q<78H<<l ; C CA FGL
|lYq\9<<=A
|XZZ(A
 FF1I EvvlBLL	!1L$MN''!*5--q	CHH 4bffTlSXX6MNuo6ug.
		!E(AeH%AQ<&L"**Q"88E?"JJLr)   c                    t        j                  | t         j                        } t        j                  |t         j                        }t        j                  |t         j                        }t        j                  |t         j                        }| |z
  }t        j                  ||      }t        j                  ||      }t        j
                  |      dkD  }	t        j                  ||	   ||	         }
||	   |
j                  d      z  }|||	   z  }||	g}|r|j                  |
       |r|j                  |       |S )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   rL   rM   r   diagonal_dotr   r   r1   rm   )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.u0EFHu%(8(8(AAHU##HFhn%Mr)   c           	      V   t        |       dk(  r| ||fS |du}|||   }||}nt        j                  | |z
  |      }t        j                  t        |       t        j                        }	d|	|t
        j                   k  <   d|	|t
        j                  kD  <   |	|   }	|	j                  dt        j                        }
t        j                  |	      j                  dt        j                        }t        j                  |dk\  t        j                  |
      dk        }|
| k(  }|dk(  }|j                         rFt        j                  | ||            \  }}t        j                  ||      }|||<   |||<   |dk  ||<   ||   }| |   }||   }|t        j                  ||
dk           }|t        j                  ||
dk\           }|	t        j                  ||
dk           }|	t        j                  ||
dk\           }t        |      t        |      z   dk(  rt        |      dk(  rwt        j                  d	t        j                        t        j                  d	t        j                        |r(t        j                  d
t        j                        f}|S df}|S t        j                   |j#                  d      t        |       d      \  }}| |   }|j#                  d      }|r||   nd}|||fS |}t        j$                  |dd      |z
  } ||z
  j                  |      }!t        j                  | |      }"d|"|"dk(  <   t        j&                  |!|"      }#|#dddddf   | z  |z   }$| }%t        j                  d	      }&t        j                  d	      }'|$|
dk  |   ddddf   }(t        |(      })|)dkD  r~t        j(                  |dk(        d   }*|t        j*                  t-        |)      t-        |)      fd      t        j*                  |*dz   dz  |*dz   dz  fd      f   }+t        j.                  |+t        j0                  t        |%      t        |%      d|)z  z         j#                  |)d      d      },|(t        j*                  t-        |)      t-        |)      fd      t        j*                  |*dz   dz  j2                  |*j2                  fd      ddf   j#                  d|)z  d      }&t        j.                  |%|&d      }%t5        j6                  |,      }-t        j.                  ||-d      }|$|
dk\  |   ddddf   }.t        |.      }/|/dkD  r6t        j(                  |dk(        d   }0|t-        |/      |0f   j#                  |/d      }1t        j.                  |1t        j0                  t        |%      t        |%      d|/z  z         j#                  |/d      d      }2|.t        j*                  t-        |/      t-        |/      fd      t        j*                  |0j2                  |0dz   dz  j2                  fd      ddf   j#                  d|/z  d      }'t        j.                  |%|'d      }%t        j.                  ||2d      }t        j                   |j#                  d      t        |%      d      \  }}|%|   }|j#                  d      }d}|rt9        t        j:                  | |   dd      |&      }3t9        t        j:                  | |   dd      |'      }4t        j<                  |3|4g      }5t        j<                  ||   ||   g      }6t        j>                  dt        j:                  |6dd      |5      }7t        j<                  ||7g      |   }|||fS )aS  
    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_inverserg   r   g-q=r   z
ijk,ij->ik) r   r   rQ   r   r   r	   rR   sumr   r   anytmnormalsrM   rP   r   unique_bincountr1   rF   r   wherestackr   rm   aranger3   r   triangulate_quadsr
   repeatconcatenateeinsum)8r6   r5   r<   r=   uvrv   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emptyrD   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     sW   V 8}""nG j!
 vvh-|< HHS]"''2E E$#))
 E$
%LE
 		q	0I"""9J ^^J!ORVVI->!-CDF:+%F
 QH||~ zz(5?";<uFF5,/	 x"$s?x f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           	      	   | yddl m} ddlm} ddlm}	 ddlm}
 ddlm	} t        j                  |t        j                  	      }t        j                  |t        j                  	      }|j                  d
k(  xs t        j                  |d      xrB |j                  d
k(  xs t        j                  |d      xr |j                  |j                  k(  }|st!        d      | j"                  j%                         }| j&                  j%                         }t)        | j                  d      xrA t        j                  | j                  j*                        t-        | j"                        dfk(  xr | }|r$| j                  j*                  j%                         nd}d|vrd|d<   t/        |j1                  d      |j1                  d            D ]s  \  }}t3        ||||||      \  }}}|s|rt5        d      t7        j8                  |      \  }}||   }||   }||ddddf   |ddddf   k7  j;                  d         }t=        j>                  ||       }t        j@                  jC                  |      }tE        jF                  ||      }t=        jH                  |      }|jK                  d       t        jL                  |dddf         dk  }|||   j;                  d         }||dddf   |dddf   k7     }t7        jN                  |d      }t-        |      dk  r` ||      }|g}|
jQ                  ||   |ddddf         D ]  } |	||d      \  }}tE        jF                  t        jR                  |      |      } |jU                  |       \  }!}"|!jW                         dkD  rt        jX                  j[                  d       |"|   }#|#ddddf   |#ddddf   k7  j;                  d      |#dddf   |#dddf   k7  z  }$|j]                  |#|$           t        j^                  |      }v |r, ||| j                  j`                  j%                               nd}% |d|||%d|S )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   rK   rg   z)plane origins and normals must be (n, 3)!r   r-   processF)r6   r5   r   r<   r=   rv   z)face_index and cap can't be used togetherr   rd   g:0yE>)require_countr   T)engineforce_verticesz%triangulate may have inserted vertex!)r   material)r6   r5   visual )1scipy.spatialr   baser   creationr   pathr   r   r   r   rL   rM   rN   r   is_shaperO   r6   copyr5   hasattrr   r   rT   r1   r   NotImplementedErrorr   unique_rowsrG   r   ri   rj   rk   rn   ro   faces_to_edgesr   r   
group_rowsedges_to_polygonsstack_3Dquerymaxlogdebugrm   rS   r   )&rX   r<   r=   rv   capr   kwargsr   r   r   r   r   shape_okr6   r5   has_uvr   re   rf   rD   r   fr|   r{   vertices_2Dr@   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!
% )*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 
 KHE&KFKKr)   )FNN)T)FF)NNN)NFN)__doc__numpyr    r   r   r   r   rn   r   r   	constantsr	   r
   rb   r~   r2   r   r   r  r   r)   r'   <module>r     ss     & & #   , zzT,n0p @P v,z QLr)   