Ë
    :vžjÿ9  ã                   óô   — d dl ZddlmZ ddlmZ ddlmZ 	 d dlZ	d„ Zdd„Zdd	„Zd
„ Zej$                  dfdedefd„Zd„ Zdd„Z	 dd„Zdd„Zy# e
$ r"ZddlmZ  ej                  e«      Z	Y dZ[ŒVdZ[ww xY w)é    Né   )Úutil)Úlog)ÚNDArray)Ú
exceptionsc                 ó�   — t        |g d¢«      }| �5t        j                  |t        j                  | d«      «      dd  |dd…df<   |S )a™  
    Given the origin and normal of a plane find the transform
    that will move that plane to be coplanar with the XY plane.

    Parameters
    ----------
    origin : (3,) float
        Point that lies on the plane
    normal : (3,) float
        Vector that points along normal of plane

    Returns
    ---------
    transform: (4,4) float
        Transformation matrix to move points onto XY plane
    )r   r   r   Nr   é   )Úalign_vectorsÚnpÚdotÚappend)ÚoriginÚnormalÚ	transforms      úa/workspace/moltex-experiments/.pixi/envs/default/lib/python3.12/site-packages/trimesh/geometry.pyÚplane_transformr      sN   € ô" ˜f¢iÓ0€IØÐÜŸF™F 9¬b¯i©i¸ÀÓ.BÓCÀBÀQÐGÐGˆ	�"�1�"�a�%ÑØÐó    c                 ó¶  — t        j                  | t         j                  ¬«      } t        j                  |t         j                  ¬«      }| j                  dk7  s|j                  dk7  rt	        d«      ‚t         j
                  j                  | j                  d«      «      d   }t         j
                  j                  |j                  d«      «      d   }t         j
                  j                  |«      dk  r|dd…dfxx   dz  cc<   t         j
                  j                  |«      dk  r|dd…dfxx   dz  cc<   t        j                  d	«      }|j                  |j                  «      |dd
…dd
…f<   |rbt        j                  |d   |d   «      }t        j                  t        j                  |dd«      «      }|dk  r|t         j                  z  }||fS |S )aÀ  
    Find the rotation matrix that transforms one 3D vector
    to another.

    Parameters
    ------------
    a : (3,) float
      Unit vector
    b : (3,) float
      Unit vector
    return_angle : bool
      Return the angle between vectors or not

    Returns
    -------------
    matrix : (4, 4) float
      Homogeneous transform to rotate from `a` to `b`
    angle : float
      If `return_angle` angle in radians between `a` and `b`

    ©Údtype)r	   zvectors must be (3,)!©éÿÿÿÿr   r   Nr   ç      ð¿é   r	   ç      ð?gñhãˆµøä¾)r   ÚarrayÚfloat64ÚshapeÚ
ValueErrorÚlinalgÚsvdÚreshapeÚdetÚeyer   ÚTÚarccosÚclipÚpi)ÚaÚbÚreturn_angleÚauÚbuÚmatrixr   Úangles           r   r
   r
   '   sh  € ô, 	�‰�œ"Ÿ*™*Ô%€AÜ
�‰�œ"Ÿ*™*Ô%€AØ‡w�w�$‚˜!Ÿ'™' Tš/ÜÐ0Ó1Ð1ô 
�‰�‰�q—y‘y Ó)Ó	*¨1Ñ	-€BÜ	�‰�‰�q—y‘y Ó)Ó	*¨1Ñ	-€Bä	‡y�y‡}�}�RÓ˜1ÒØ
Š1ˆbˆ5‹	�TÑ‹	Ü	‡y�y‡}�}�RÓ˜1ÒØ
Š1ˆbˆ5‹	�TÑ‹	ô �V‰V�A‹Y€FØ—V‘V˜BŸD™D“\€Fˆ2ˆAˆ2ˆr�ˆrˆ6�Náô �f‰f�R˜‘U˜B˜q™EÓ"ˆä—	‘	œ"Ÿ'™' # t¨SÓ1Ó2ˆØ�Š;Ø”R—U‘U‰NˆEØ�uˆ}Ðà€Mr   c                 ó$  — t        j                  | t         j                  «      } | dd…g d¢f   j                  d«      }|rOt        j                  t        j
                  t        | «      «      d«      j                  j                  d«      }||fS |S )a  
    Given a list of faces (n,3), return a list of edges (n*3,2)

    Parameters
    -----------
    faces : (n, 3) int
      Vertex indices representing faces

    Returns
    -----------
    edges : (n*3, 2) int
      Vertex indices representing edges
    N)r   r   r   é   r1   r   )r   r1   )r	   r   r   )r   Ú
asanyarrayÚint64r"   ÚtileÚarangeÚlenr%   )ÚfacesÚreturn_indexÚedgesÚ
face_indexs       r   Úfaces_to_edgesr;   \   sv   € ô �M‰M˜%¤§¡Ó*€Eð ’!Ò'Ð'Ñ(×0Ñ0°Ó9€Eáä—W‘WœRŸY™Y¤s¨5£zÓ2°FÓ;×=Ñ=×EÑEÀbÓIˆ
Ø�jÐ Ð Ø€Lr   c                 óî  — t        j                  | t         j                  ¬«      } t        | «      dk(  rt        j                  g «      S t        j                  | d«      r| j                  d«      } n!t        j                  | d«      st        d«      ‚t        j                  | dd…df   | dd…df   «      }t        j                  |d	d
«      }t        j                  t        j                  |«      «      }|S )zç
    Find the angles between pairs of unit vectors.

    Parameters
    ----------
    pairs : (n, 2, 3) float
      Unit vector pairs

    Returns
    ----------
    angles : (n,) float
      Angles between vectors in radians
    r   r   ©r1   r	   )r   r1   r	   )r   r1   r=   zpairs must be (n,2,(2|3))!Nr   r   r   )r   r2   r   r6   r   r   Úis_shaper"   r   Údiagonal_dotr'   Úabsr&   )ÚpairsÚdotsÚangless      r   Úvector_anglerD   v   s¸   € ô �M‰M˜%¤r§z¡zÔ2€EÜ
ˆ5ƒz�Q‚Ü�x‰x˜‹|ÐÜ	�‰�u˜fÔ	%Ø—‘˜jÓ)‰Ü�]‰]˜5 /Ô2ÜÐ5Ó6Ð6ô ×Ñ˜U¢1 a 4™[¨%²°1°©+Ó6€Dä�7‰7�4˜˜sÓ#€Dä�V‰V”B—I‘I˜d“OÓ$€Fà€Mr   TÚuse_fanÚreturnc                 ón  — t        | «      dk(  rt        j                  d|¬«      S 	 t        j                  | |¬«      } t        | j                  «      dk(  r#| j                  d   dk(  r| j                  |«      S t        | j                  «      dk(  rJ| j                  d   dk(  r8t        j                  | dd…g d¢f   | dd…g d	¢f   f«      j                  |«      S t        j                  | D �cg c]  }t        |«      ‘Œ c}t        j                  ¬«      }t        j                  t        j                  |dk(  «      d   D �cg c]  }| |   ‘Œ	 c}t        j                  ¬«      }t        j                  t        j                  |dk(  «      d   D �cg c]  }| |   ‘Œ	 c}t        j                  ¬«      }|r,t        j                  |dkD  «      d   D �cg c]  }| |   ‘Œ	 }}ng }t        |«      dk(  rt        |«      dk(  r|j                  |«      S t        |«      dkD  rt        j                  |«      }t        |«      dkD  r)t        j                  |dd…g d¢f   |dd…g d	¢f   f«      }t        j                  |||g«      j                  |«      S # t        $ r Y �ŒÄw xY wc c}w c c}w c c}w c c}w )
aå  
    Given an array of quad faces return them as triangle faces,
    also handles pure triangles and mixed triangles and quads.

    Parameters
    -----------
    quads: (n, 4) int
      Vertex indices of quad faces.
    dtype
      Data type requested for the return
    use_fan
      Triangulate holes larger than quads with fans,
      which may be wrong if the holes are non-convex

    Returns
    -----------
    faces : (m, 3) int
      Vertex indices of triangular faces.
    r   r   r1   r   r	   r   N)r   r   r1   )r1   r	   r   )r6   r   Úzerosr   r   ÚastypeÚvstackr   r3   Únonzeror   Útriangle_fans_to_facesÚvstack_empty)Úquadsr   rE   ÚiÚlengthsÚtriÚquadÚpolys           r   Útriangulate_quadsrT   –   sG  € ô* ˆ5ƒz�Q‚Ü�x‰x˜ Ô'Ð'ðô —‘˜ eÔ,ˆäˆu�{‰{Ó˜qÒ  U§[¡[°¡^°qÒ%8à—<‘< Ó&Ð&äˆu�{‰{Ó˜qÒ  U§[¡[°¡^°qÒ%8ä—9‘9˜e¢A¢y LÑ1°5ººI¸Ñ3FÐGÓH×OÑOÐPUÓVÐVô �h‰h©Ó.© 1œ˜A�¨Ñ.´b·h±hÔ?€Gô �(‰(¤b§j¡j°¸A±Ó&>¸qÒ&AÓBÑ&A �E˜!“HÐ&AÑBÌ"Ï(É(Ô
S€CÜ�8‰8¤r§z¡z°'¸Q±,Ó'?ÀÒ'BÓCÑ'B !�U˜1“XÐ'BÑCÌ2Ï8É8ÔT€Dáä"$§*¡*¨W°q©[Ó"9¸!Ò"<Ó=Ñ"<˜Q��a“Ð"<ˆÑ=ð ˆä
ˆ4ƒy�A‚~œ#˜d›) qš.à�z‰z˜%Ó Ð Ü
ˆ4ƒy�1‚}ä×*Ñ*¨4Ó0ˆÜ
ˆ4ƒy�1‚}ä�y‰y˜$šq¢)˜|Ñ,¨d²1²i°<Ñ.@ÐAÓBˆä×Ñ˜c 4¨Ð.Ó/×6Ñ6°uÓ=Ð=øô; ò âðüò /ùò CùÚCùò >s1   §AJ Á9A!J Ã.J#ÅJ(ÆJ-ÇJ2Ê	J ÊJ c                 óV  — 	 t        j                  |j                  «       | ¬«      }t        |«      | k(  sJ ‚|j                  «       | k  sJ ‚t        j                  dt        j                  |«      dd «      }t        j                  |j                  «       «      |dd…df   z   }|||z   dd…df   k\  j                  t         j                  «       }	 t        j                  j!                  t        |«      t"        ¬	«      }|j%                  |«      j'                  «       d   }|||dk(  <   |S # t        $ rA t	        j
                  d«       t        j                  |j                  «       d¬«      d   }Y �ŒOw xY w# t(        $ r¥ t	        j
                  d
d¬«       t        j*                  |j,                  t         j                  ¬	«      }	|j                  «       }
t/        | «      D ]5  }t        j0                  |
|k(  «      d   dz  ddd…   |	||   ||   ||   z    Œ7 |	||dk(  <   Y |S w xY w)aö  
    Find vertex face indices from the faces array of vertices

    Parameters
    -----------
    vertex_count : int
      The number of vertices faces refer to
    faces : (n, 3) int
      List of vertex indices
    faces_sparse : scipy.sparse.COO
      Sparse matrix

    Returns
    -----------
    vertex_faces : (vertex_count, ) int
      Face indices for every vertex
      Array padded with -1 in each row for all vertices with fewer
      face indices than the max number of face indices.
    )Ú	minlengthzcasting failed, falling back!T)Úreturn_countsr   r   Nr   r   zJvertex_faces falling back to slow loop! mesh probably has degenerate faces©Úexc_infor	   )r   ÚbincountÚflattenÚ	TypeErrorr   ÚwarningÚuniquer6   Úmaxr   Úcumsumr5   rI   r3   ÚscipyÚsparseÚidentityÚintr   rK   ÚBaseExceptionrH   ÚsizeÚrangeÚwhere)Úvertex_countr7   Úfaces_sparseÚcountsÚstartsÚpackÚpaddedrc   Úsorted_facesÚsortÚflatÚvs               r   Úvertex_face_indicesrs   Ú   só  € ð,CÜ—‘˜UŸ]™]›_¸ÔEˆô ˆv‹;˜,Ò&Ð&Ð&Ø�9‰9‹;˜Ò%Ð%Ð%ô �Y‰Y�qœ"Ÿ)™) FÓ+¨C¨RÐ0Ó1€Fä�9‰9�V—Z‘Z“\Ó" VªA¨t¨G¡_Ñ4€Dà˜ ™ª¨D¨Ñ1Ñ1×9Ñ9¼"¿(¹(ÓCÐC€Fð#ä—<‘<×(Ñ(¬¨U«¼3Ð(Ó?ˆØ#×'Ñ'¨Ó1×9Ñ9Ó;¸AÑ>ˆð
 +ˆˆv˜‰{Ñð €MøôK ò Cä�‰Ð3Ô4ä—‘˜5Ÿ=™=›?¸$Ô?ÀÑB‹ð	Cûô0 ò #ä�‰ð3àõ	
ô
 �x‰x˜Ÿ
™
¬"¯(©(Ô3ˆØ�}‰}‹ˆÜ�|Ö$ˆAä79·x±xÀÈÁ	Ó7JÈ1Ñ7MÐQRÑ7RÑTXÐVXÐTXÑ6YˆD�˜‘˜V A™Y¨°©Ñ2Ñ3ð %ð #ˆˆv˜‰{ÒØ€Mð#ús&   ‚%D- ÃAE: Ä-AE7Å6E7Å:B*H(È'H(c                 óÀ   ‡ ‡‡‡— ˆˆˆˆ fd„}ˆˆˆ fd„}	  |«       }t        j                  |«      }|S # t         $ r! t        j                  dd¬«        |«       }Y Œ@w xY w)aË  
    Find vertex normals from the mean of the faces that contain
    that vertex.

    Parameters
    -----------
    vertex_count : int
      The number of vertices faces refer to
    faces : (n, 3) int
      List of vertex indices
    face_normals : (n, 3) float
      Normal vector for each face

    Returns
    -----------
    vertex_normals : (vertex_count, 3) float
      Normals for every vertex
      Vertices unreferenced by faces will be zero.
    c                  óL   •— ‰€t        ‰‰«      } n‰} | j                  ‰«      }|S ©N)Úindex_sparser   )r.   ÚsummedÚface_normalsr7   rb   ri   s     €€€€r   Úsummed_sparsez*mean_vertex_normals.<locals>.summed_sparse/  s.   ø€ ð ˆ>Ü! ,°Ó6‰FàˆFØ—‘˜LÓ)ˆØˆr   c                  óx   •— t        j                  ‰df«      } t        ‰‰«      D ]  \  }}| |xx   |z  cc<   Œ | S ©Nr	   )r   rH   Úzip)rx   Úfacer   ry   r7   ri   s      €€€r   Úsummed_loopz(mean_vertex_normals.<locals>.summed_loop:  s@   ø€ ô —‘˜<¨Ð+Ó,ˆÜ  |Ö4‰LˆD�&Ø�4‹L˜FÑ"ŒLð 5àˆr   ú*unable to use sparse matrix, falling back!TrX   )re   r   r]   r   Úunitize)	ri   r7   ry   rb   Úkwargsrz   r   rx   Úvertex_normalss	   ````     r   Úmean_vertex_normalsr„     sV   û€ ÷*	öðÙ“ˆô —\‘\ &Ó)€NàÐøô ò Ü�‰Ð@È4ÕPÙ“Šðús   •3 ³'AÁAc                 ó2  ‡ ‡‡‡— ˆˆˆˆ fd„}ˆˆˆˆ fd„}‰dz  j                  d¬«      dkD  }‰|   Š‰|   Š‰|   Š|s	 t        j                   |«       «      S t        j                   |«       «      S # t        $ r t	        j
                  dd¬	«       Y Œ<w xY w)
aV  
    Compute vertex normals from the faces that contain that vertex.
    The contribution of a face's normal to a vertex normal is the
    ratio of the corner-angle in which the vertex is, with respect
    to the sum of all corner-angles surrounding the vertex.

    Grit Thuerrner & Charles A. Wuethrich (1998)
    Computing Vertex Normals from Polygonal Facets,
    Journal of Graphics Tools, 3:1, 43-46

    Parameters
    -----------
    vertex_count : int
      The number of vertices faces refer to
    faces : (n, 3) int
      List of vertex indices
    face_normals : (n, 3) float
      Normal vector for each face
    face_angles : (n, 3) float
      Angles at each vertex in the face

    Returns
    -----------
    vertex_normals : (vertex_count, 3) float
      Normals for every vertex
      Vertices unreferenced by faces will be zero.
    c                  ó^   •— t        ‰‰‰j                  «       ¬«      } | j                  ‰«      S )N)Údata)rw   Úravelr   )r.   Úface_anglesry   r7   ri   s    €€€€r   rz   z.weighted_vertex_normals.<locals>.summed_sparsem  s+   ø€ ô
 ˜l¨E¸×8IÑ8IÓ8KÔLˆØ�z‰z˜,Ó'Ð'r   c                  ó&  •— t        j                  ‰dft         j                  «      } t        j                  ‰«      D ]Q  }t        j                  ‰|k(  «      \  }}‰||f   }t        j
                  ||j                  «       z  ‰|   «      | |<   ŒS | S r|   )r   rH   r   r5   rh   r   Úsum)	rx   Ú
vertex_idxÚ	face_idxsÚinface_idxsÚsurrounding_anglesr‰   ry   r7   ri   s	        €€€€r   r   z,weighted_vertex_normals.<locals>.summed_loopu  sŒ   ø€ Ü—‘˜<¨Ð+¬R¯Z©ZÓ8ˆÜŸ)™) LÖ1ˆJô &(§X¡X¨e°zÑ.AÓ%BÑ"ˆI�{Ø!,¨Y¸Ð-CÑ!DÐÜ!#§¡Ø"Ð%7×%;Ñ%;Ó%=Ñ=¸|ÈIÑ?Vó"ˆF�:Òð 2ð ˆr   r1   r   )Úaxisg      à?r€   TrX   )r‹   r   r�   re   r   r]   )ri   r7   ry   r‰   Úuse_looprz   r   Úface_oks   ````    r   Úweighted_vertex_normalsr“   N  s—   û€ ÷>(÷ð ˜Q‰×#Ñ#¨Ð#Ó+¨cÑ1€Gà�'‰N€EØ Ñ(€LØ˜gÑ&€Káð	UÜ—<‘<¡£Ó0Ð0ô �<‰<™›Ó&Ð&øô ò 	UÜ�K‰KÐDÈt×Tð	Uús   ¿A3 Á3 BÂBc                 óT  — t        j                  |«      }t        | «      } |j                  d«      }t        j                  t        j
                  t        |«      «      j                  d«      d|j                  d   f«      j                  d«      }| t        |«      f}|€%t        j                  t        |«      t        ¬«      }n"t        |«      t        |«      k7  rt        d«      ‚|�|j                  |«      }t        j                  j                  |||ff||j                  ¬«      S )aÏ  
    Return a sparse matrix for which vertices are contained in which faces.
    A data vector can be passed which is then used instead of booleans

    Parameters
    ------------
    columns : int
      Number of columns, usually number of vertices
    indices : (m, d) int
      Usually mesh.faces

    Returns
    ---------
    sparse: scipy.sparse.coo_matrix of shape (columns, len(faces))
            dtype is boolean

    Examples
     ----------
    In [1]: sparse = faces_sparse(len(mesh.vertices), mesh.faces)

    In [2]: sparse.shape
    Out[2]: (12, 20)

    In [3]: mesh.faces.shape
    Out[3]: (20, 3)

    In [4]: mesh.vertices.shape
    Out[4]: (12, 3)

    In [5]: dense = sparse.toarray().astype(int)

    In [6]: dense
    Out[6]:
    array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
           [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0],
           [0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1],
           [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0],
           [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1],
           [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1]])

    In [7]: dense.sum(axis=0)
    Out[7]: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])
    r   r   r   r   zdata incorrect length)r   r   )r   r2   rd   r"   r4   r5   r6   r   ÚonesÚboolr   rI   ra   rb   Ú
coo_matrixr   )ÚcolumnsÚindicesr‡   r   ÚrowÚcolr   s          r   rw   rw   “  sõ   € ôd �m‰m˜GÓ$€GÜ�'‹l€Gð �/‰/˜"Ó
€CÜ
�'‰'Ü
�	‰	”#�g“,Ó×'Ñ'¨Ó0°1°g·m±mÀAÑ6FÐ2Góç�gˆbƒkð ð ”c˜'“lÐ#€EØ€|Ü�w‰w”s˜3“x¤tÔ,‰Ü	ˆT‹”c˜#“hÒ	ÜÐ0Ó1Ð1àÐØ�{‰{˜5Ó!ˆô �<‰<×"Ñ" D¨3°¨*Ð#5¸UÈ$Ï*É*Ð"ÓUÐUr   )Frv   )NN)Únumpyr   Ú r   Ú	constantsr   Útypedr   Úscipy.sparsera   re   ÚEr   ÚExceptionWrapperr   r
   r;   rD   r3   r–   rT   rs   r„   r“   rw   © r   r   Ú<module>r¤      s›   ðÛ å Ý Ý ð+Ûòó.2ójò4ð@ $&§8¡8¸Tñ A>°dð A>Àgó A>òH=ó@1ðj >CóB'ôJEVøðU ò +Ýð (ˆJ×'Ñ'¨Ó*…Eûð	+ús   ˜A ÁA7ÁA2Á2A7