
    l0jo                         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dS )zT
intersections.py
------------------

Primarily mesh-plane intersections (slicing).
    N   )geometrygroupingutil)transformations)	triangles)tol)points_to_barycentricFc                 v    d }fd}d }fd}	t          j        t           j                  t          j        t           j                  j        dk    sj        dk    rt	          d          | j        n-t          j        |t           j                  } j        |         ||}
nt          j         j        z
            }
t          j	        t           j                  t           j                  d	|
t          j         k     <   d
|
t          j        k    <             |          }|	||f}t          j         fdt          ||          D                       }|r@t          j        d |D                       }|j        j        dk    sJ |||fS |||         fS |S )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                    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           X/home/wildlama/miniconda3/envs/lam/lib/python3.11/site-packages/trimesh/intersections.pytriangle_casesz"mesh_plane.<locals>.triangle_cases6   s    F wu1---\**"':::R?q 	1 	1A\!!!Q$'1q500EE hr&&&Bu: AAAAZ
 AAAQGE
j(**    c                 
   || dk             }|| dk                                  d          }t          	||j                 d          \  }}t          j        |||                  |f                               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6	!,,(=U"
 "
 "
 ,u*=!> PQQYY
 
 r)   c                 T    || dk                                  d          }||         }|S )Nr   r+   )r1   )r   r5   r6   edgespointss        r'   handle_on_edgez"mesh_plane.<locals>.handle_on_edge   s,    eqj!))'22%r)   c                    t          j        | ddg          }t          j        ||         |t          j        |dd                   ||         |t          j        |dd                   f                              d          }t          ||j                 d          \  }}|                                s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    !5eRGLLLn%bgnaa8889n%bgnaa8889	
 
 ''

 	  +,(9 
  
  
u
 yy{{{$$Z000r)   r   r   z%Plane origin and normal must be (3,)!Nr,   r   c                 R    g | ]#\  }} ||         |         j                   $S  )r6   ).0chr5   meshr   s      r'   
<listcomp>zmesh_plane.<locals>.<listcomp>   s5    OOO$!Q58U1Xt}	-	-OOOr)   c                 B    g | ]}t          j        |          d          S )r   )r   nonzero)rN   rO   s     r'   rR   zmesh_plane.<locals>.<listcomp>   s%    ;;;2:a==+;;;r)   r"   )r   
asanyarrayfloat64shape
ValueErrorr5   int64dotr6   r   r   r   r	   mergevstackziphstackr   kind)rQ   r<   r=   return_faceslocal_facescached_dotsr(   r>   rB   rJ   dotscaseshandlersr;   indexr5   r   s   ```            @@r'   
mesh_planerg      s   J<+ <+ <+|       1 1 1 1 1 1( =RZ@@@L=RZ@@@LT!!\%74%?%?@AAA
mKrx@@@
;'
 vdml2LAA HS''rw777E!E$#)
E$
%LE N5!!E.?H IOOOOOO#eX:N:NOOO E  )	;;U;;;<<{3&&&&%< k%(((Lr)   c                    t          j        |          }t          j        |t          j                  }t          j        |t          j                  }t          j        || j        |z
  j                  }t          j	        ||          }t          j
                            |          }t          j        d          }g }g }g }	|D ]}
|||
z  z   }||
z
  }t          | ||d|          \  }}|
|d<   t          j        ||          }t          j
                            |          }|                    |           t          j        |                    d          |          }|dddd	f                             d
          }|	                    |           |                    |           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)rQ   r=   r<   r`   rb   )r-   r   r,   r   Nr-   )r,   r-   r-   )r   unitizer   rU   rV   rZ   r6   r3   r   plane_transformlinalginveyerg   appendtftransform_pointsr1   array)rQ   r=   r<   heightsvertex_dotsbase_transformtranslation
transforms
face_indexsegmentsheight
new_originnew_dotsr;   rf   to_3Dto_2Dlines_2Ds                     r'   mesh_multiplaner      s   6 <--L=RZ@@@LmG2:666G &(D'GHHK -\,WWWNY]]>22N &))K JJH   !  !!\F%:;
'!#% 
 
 
u #D~{33	e$$%    &u}}W'='=uEE AAArrE?**:66!!!%     *BJ777JZ++r)   Tc                 L   t          j        |          }t          j        |                               d          } t          j        |d         |d         z
            }t          j        t          j        |                              d                    }t          j        || |d         z
  j                  }t          j        ||j                  }t          j        |          t          j	        k    }|rt          j        |t          j
        | |d         z
                      }t          j        |          t          j        |          k    }	t          j        t          j        |          t          j	        k    t          j        |          t          j	        k              }
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   rU   r1   r   rm   rZ   r3   absr	   zero	transposesign
logical_orlogical_anddivide)r=   r<   	endpointsr/   line_dirtbr:   testdifferent_sidesrT   dintersections                r'   r2   r2   %  s   2 i((I=..66q99L|IaL9Q<788H<l ; ; C CA F FGGL
|lYq\9<==A
|XZ((A
 F1II E /vlBL	!1L$M$MNN'!**5-q		CH 4bfTllSX6MNNuo66ug..
	!E(AeH%%AQ<&L"*Q"8"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k    }	t          j        ||	         ||	                   }
||	         |
                    d          z  }|||	         z  }||	g}|r|                    |
           |r|                    |           |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   rU   rV   r   diagonal_dotr   r   r1   rr   )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 M-rzBBBMM-rzBBBM=RZ@@@LmO2:FFFO #\1N&~}EEN&FFNF>""T)Ey.u0EFFHu%(8(8(A(AAHU##HF  h &n%%%Mr)   c           	         t          |           dk    r| ||fS |du}|||         }||}nt          j        | |z
  |          }t          j        t          |           t          j                  }	d|	|t
          j         k     <   d|	|t
          j        k    <   |	|         }	|	                    dt          j                  }
t          j        |	                              dt          j                  }t          j	        |dk    t          j        |
          dk              }|
| k    }|dk    }|
                                rKt          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    ret          j        d	t          j                  t          j        d	t          j                  |r t          j        d
t          j                  ndf}|S t          j        |                    d          t          |           d          \  }}| |         }|                    d          }|r||         nd}|||fS |}t          j        |dd          |z
  } ||z
                      |          }!t          j        | |          }"d|"|"dk    <   t          j        |!|"          }#t          j        d|#|           |z   }$| }%t          j        d	          }&t          j        d	          }'|$|
dk     |         ddddf         }(t          |(          })|)dk    rt          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          j        t          |%          t          |%          d|)z  z                                 |)d          d          },|(t          j        t/          |)          t/          |)          fd          t          j        |*dz   dz  j        |*j        fd          ddf                             d|)z  d          }&t          j        |%|&d          }%t7          j        |,          }-t          j        ||-d          }|$|
dk    |         ddddf         }.t          |.          }/|/dk    rOt          j        |dk              d         }0|t/          |/          |0f                             |/d          }1t          j        |1t          j        t          |%          t          |%          d|/z  z                                 |/d          d          }2|.t          j        t/          |/          t/          |/          fd          t          j        |0j        |0dz   dz  j        fd          ddf                             d|/z  d          }'t          j        |%|'d          }%t          j        ||2d          }t          j        |                    d          t          |%          d          \  }}|%|         }|                    d          }d}|rt;          t          j        | |         dd          |&          }3t;          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_inverserl   r   g-q=zij,ijk->ijkr   z
ijk,ij->ik) r   r   rZ   r   r   r	   r[   sumr   r   anytmnormalsrV   rY   r   unique_bincountr1   rF   r   einsumwherestackr   rr   aranger3   r   triangulate_quadsr
   repeatconcatenate)8r6   r5   r<   r=   uvr{   rb   have_uvrc   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     sH   V 8}}""nG j!
 vh-|<< HS]]"'222E E$#)
 E$
%LE
 		q	00I"""99J ^J!ORVI->->!-CDDF:+%F
 QH||~~ + z(5?";<<uF5,//	 x"$s?x fI
 If%M2>&)a-@@AN".a@@AM2>&)a-@@AN".a@@AM >S///144y>>Q rz222rx0006=Grz22224E
 L #2b!!S]]4
 
 

 f%
__W--
!(22f::d:x// 	A
2A"A!
 
 
.
.CF1l##EE%3,9S%  D=$22Q6J L((x'' !)a-!8!!!QQQ!>?OO$$I1}} 1!455a8'HeI&&i(8(89BBBH}q(A-0AQ/FGaPPPR
 Ic,''\):):Q])JKKSS1  
 
 
 ,HeI&&i(8(89BBBH)Q.1=?C!LLLAA
 '!i-
#
#	 	 y/@qIII#+#=n#M#M Ii)AJJJ	  a 8!!!QQQ >?N>""H!|| x 344Q7%eHoo|&CDLLXWXYY 	Ic,''\):):Q\)IJJRR!  
 
 
 *HeHoouX7a@@@Hlnq(8A'=&@AJJJAA
 '!h,
"
"	 	 y/?aHHHIiQ???	 ."\):):4  OFG
 f%J))JH 81Ih~.:::<M
 
 1Ih}-qq999;K
 
 >+<>N*OPP N!3R5F GHH<611)E)E)EGWXX>2v,//7z8++r)   c           	      r	   | dS 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    st          j        |d          o/|j        d
k    pt          j        |d          o|j        |j        k    }|st!          d          | j                                        }| j                                        }t)          | j        d          o5t          j        | j        j                  t-          | j                  dfk    o| }|r| j        j                                        nd}d|vrd|d<   t/          |                    d          |                    d                    D ]\  }}t3          ||||||          \  }}}|r|rt5          d          t7          j        |          \  }}||         }||         }||ddddf         |ddddf         k                        d                   }t=          j        ||           }t          j         !                    |          }tE          j#        ||          }t=          j$        |          }|%                    d           t          j&        |dddf                   dk     }|||                             d                   }||dddf         |dddf         k             }t7          j'        |d          }t-          |          dk     r ||          }|g}|
(                    ||         |ddddf                   D ]} |	||          \  }}tE          j#        t          j)        |          |          } |*                    |           \  }!}"|!+                                dk    rt          j,        -                    d           |"|         }#|#ddddf         |#ddddf         k                        d          |#dddf         |#dddf         k    z  }$|.                    |#|$                    t          j/        |          }|r) ||| j        j0                                                  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   rl   z)plane origins and normals must be (n, 3)!r   r-   processF)r6   r5   r   r<   r=   r{   z)face_index and cap can't be used togetherr   ri   g:0yE>)require_countr   )enginez%triangulate may have inserted vertex!)r   material)r6   r5   visualrM   )1scipy.spatialr   baser   creationr   pathr   r   r   r   rU   rV   rW   r   is_shaperX   r6   copyr5   hasattrr   r   r]   r1   r   NotImplementedErrorr   unique_rowsrG   r   rn   ro   rp   rs   rt   faces_to_edgesr   r   
group_rowsedges_to_polygonsstack_3Dquerymaxlogdebugrr   r\   r   )&rQ   r<   r=   r{   capr   kwargsr   r   r   r   r   shape_okr6   r5   has_uvr   rj   rk   rD   r   fr   r   vertices_2Dr@   r   unique_edgetreepvnfnvn3r   vidnfnf_okr   s&                                         r'   slice_mesh_planer
    sB   R |t &%%%%%------&&&&&& =RZ@@@L=RZ@@@L 
	t	#	Kt}\7'K'K 	54'O4=w+O+O	5,"44 
  FDEEE }!!##HJOOE 	T""Zrx'?'?CDVDVXYCZ'Z'  #)	2					dB!y W%%|';';G'D'D  :% :% 0!
 
 
%  -	% W)*UVVV '28<<OFG'HA 1QQQU8qABBx',,!,445A,FF7KKKEIMM%((E-h>>K+A..EJJAJvk!!!Q$/0047H(5/--1-556E%1+qqq!t45E"-e1EEEK6{{Q78$$DCE//k0BKPQPQPQSUTUSUPUDVWW ( (,,Qv>>>B)$-*;*;UCC $

3#<<>>D((HNN#JKKKWAAAqrrEbBQBi/44!4<<111a4BqqqRStH@TURY''''Ie$$E HNW"t{';'@'@'B'BCCCCSW 
 7KHE&KKFKKKr)   )FNN)T)FF)NNN)NFN)__doc__numpyr    r   r   r   r   rs   r   r   	constantsr	   r
   rg   r   r2   r   r   r
  rM   r)   r'   <module>r     sI        & & & & & & & & & & # # # # # #             , , , , , , z z z zzT, T, T,n0 0 0 0p @ @ @ @P v, v, v, v,z PL PL PL PL PL PLr)   