
    l0j܎                       d Z ddlZddlZddlZddlmZmZmZ ddlm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ ddlm Z m!Z!m"Z"m#Z# ddl$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lm/Z/ ddl0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; ddl<m=Z=m>Z>m?Z? 	 ddl@mAZA ddlBmCZC n(# eD$ r ZE e(eE          ZC e(eE          ZAY dZE[EndZE[Eww xY w	 ddlFmGZG n# eD$ rZE e(eE          ZGY dZE[EndZE[Eww xY w	 ddlHmIZI n# eD$ rZE e(eE          ZIY dZE[EndZE[Eww xY w	 ddlJmKZKmLZL n(# eD$ r ZE e(eE          ZK e(eE          ZLY dZE[EndZE[Eww xY w G d de,          ZMdS )z
github.com/mikedh/trimesh
----------------------------

Library for importing, exporting and doing simple operations on triangular meshes.
    N)float64int64ndarray   )boolean
comparisonconvex	curvaturedecompositiongeometrygraphgroupinginertiaintersections	permutateposes	proximityrayregistrationremeshrepairsampletransformations	trianglesunitsutil)Cache	DataStoreTrackedArraycache_decorator)logtol)ExceptionWrapperexport_mesh)
Geometry3DScene)MassProperties)Any	ArrayLikeDictFloatingIntegerListNDArrayNumberOptionalSequenceUnion)ColorVisualsTextureVisualscreate_visual)
coo_matrix)cKDTree)Graph)Index)Path2DPath3Dc            $          e Zd Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddee         dee         dee         dee         dee         d	ee         d
eeeef                  deeeef                  deeeef                  dededee         dee         dedeeee	f                  dee
eef                  ddf"dZ	 	 	 ddedee         dee         dd fdZedefd            Zej        deddfd            Zedefd            Zej        dee         ddfd            Zedefd            Zedee         fd            Zej        dee         ddfd            Zedefd             Zej        dee         fd!            Zedee         fd"            Zej        deddfd#            Zedee         fd$            Zedeee                  fd%            Zedeee                  fd&            Zedee         fd'            Z edee         fd(            Z!e!j        deddfd)            Z!ede"fd*            Z#e#j        de$ddfd+            Z#edefd,            Z%edefd-            Z&edee         fd.            Z'd/edee         fd0Z(edee         fd1            Z)edee         fd2            Z*edee         fd3            Z+edee         fd4            Z,edeee                  fd5            Z-edeee                  fd6            Z.edee         fd7            Z/ede0fd8            Z1edee         fd9            Z2edee         fd:            Z3edee         fd;            Z4edee         fd<            Z5edee         fd=            Z6edee         fd>            Z7edee         fd?            Z8edee         fd@            Z9ede:fdA            Z;edefdB            Z<ede=fdC            Z>edee         fdD            Z?ede=fdE            Z@edeeAjB                 fdF            ZCddGedHedd fdIZD	 	 	 	 	 ddee         dee         dJeeE         dKeeE         dLeeE         ddfdMZF	 ddNedOee         ddfdPZGdNeddfdQZHddRZIdeeAjB                 fdSZJddTZKddUZLdeMd          fdVZNedee         fdW            ZOedee         fdX            ZPedee         fdY            ZQede:fdZ            ZRedee         fd[            ZSedee         fd\            ZTedeeAjB                 fd]            ZUedee         fd^            ZVedee         fd_            ZWedee         fd`            ZXedefda            ZYedeZfdb            Z[edeMeMe                  fdc            Z\edefdd            Z]edefde            Z^edefdf            Z_edefdg            Z`edefdh            Zaede:fdi            Zbecjd        fdje"ddfdkZeecjd        fdje"deeAjB                 fdlZfedeMee                  fdm            Zgedee         fdn            Zhedee         fdo            Ziedee         fdp            ZjedeMee                  fdq            ZkedeeAjB                 fdr            Zlddsee         ddfdtZmdefduZndve
eoef         fdwZp	 	 	 	 ddzeee                  d{e"d|e=d}e"fd~Zqddee         dd fdZrddZsddZtd Zued             Zved             Zwewj        d             Zwdededeex         fdZydedededeMeez                  fdZ{	 	 	 ddZ|ddZ}edd            Z~	 	 dde=dedeee                  fdZddZddZdedd fdZddZ	 	 	 ddee         deeE         deeE         dd fdZddeee                  dexfdZdezfdZedefd            Zedee         fd            Zedefd            ZddZdefdZd Zdee         de
d eMd          f         fdZedee         fd            Zedefd            Z	 	 ddee         fdZdeee
eeMeMe"                  eMeMe=                  f         f         fdZdeMd          fdZ	 	 ddvd dee         dedd fdZ	 	 ddvd dee         dedd fdZ	 	 ddvd dee         dedd fdZdedeeAjB                 fdZedee         fd            Zedefd            Zedee         fd            Zedee         fd            Zede0fd            Zddededd fdZddZddZdefdZddZdS )TrimeshNTFverticesfacesface_normalsvertex_normalsface_colorsvertex_colorsface_attributesvertex_attributesmetadataprocessvalidate	merge_tex
merge_norm
use_embreeinitial_cachevisualreturnc                    t                      | _        t          | j        j        d          | _        || j                            |           || _        || _        |t          |||           | _	        n|| _	        ||| _
        ||| _        t          j        r'|r%t          j                            |           | _        n$t          j                            |           | _        t#          j        |           | _        t'          j        |           | _        i | _        t/          |	t0                    r| j                            |	           n|	t3          d|	          i | _        i | _        || j                            |           || j                            |           |
s|r|                     |||           dS dS )a  
        A Trimesh object contains a triangular 3D mesh.

        Parameters
        ------------
        vertices : (n, 3) float
          Array of vertex locations
        faces : (m, 3) or (m, 4) int
          Array of triangular or quad faces (triangulated on load)
        face_normals : (m, 3) float
          Array of normal vectors corresponding to faces
        vertex_normals : (n, 3) float
          Array of normal vectors for vertices
        metadata : dict
          Any metadata about the mesh
        process : bool
          if True, Nan and Inf values will be removed
          immediately and vertices will be merged
        validate : bool
          If True, degenerate and duplicate faces will be
          removed immediately, and some functions will alter
          the mesh to ensure consistent results.
        use_embree : bool
          If True try to use pyembree raytracer.
          If pyembree is not available it will automatically fall
          back to a much slower rtree/numpy implementation
        initial_cache : dict
          A way to pass things to the cache in case expensive
          things were calculated before creating the mesh object.
        visual : ColorVisuals or TextureVisuals
          Assigned to self.visual
        T)id_functionforce_immutableN)rD   rE   meshz'metadata should be a dict or None, got )rJ   rK   rL   )r   _datar   __hash___cacheupdater@   rA   r7   rO   rB   rC   r   
has_embreeray_pyembreeRayMeshIntersectorray_triangler   
Permutatorr   ProximityQuerynearestrH   
isinstancedict
ValueErrorrF   rG   rI   )selfr@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   kwargss                     O/home/wildlama/miniconda3/envs/lam/lib/python3.11/site-packages/trimesh/base.py__init__zTrimesh.__init__T   s   x [[
 
(;TRRR$K}---
 ! 
 >''}4  DKK !DK
 # ,D %"0D
 > 	Aj 	A'::4@@DHH '::4@@DH #-d33 !/55 h%% 	UM  ****!SxSSTTT  "!#& ''888("))*;<<<  	Xh 	XLL(iJLWWWWW	X 	X    c                    | j         r| S | j        5  |rR|                                 |                                 z  }|                     |           |                                  |                                  |                     ||           | j                            ddh           ddd           n# 1 swxY w Y   d| j	        d<   | S )a  
        Do processing to make a mesh useful.

        Does this by:
            1) removing NaN and Inf values
            2) merging duplicate vertices
        If validate:
            3) Remove triangles which have one edge
               of their 2D oriented bounding box
               shorter than tol.merge
            4) remove duplicated triangles
            5) Attempt to ensure triangles are consistently wound
               and normals face outwards.

        Parameters
        ------------
        validate : bool
          Remove degenerate and duplicate faces.

        Returns
        ------------
        self: trimesh.Trimesh
          Current mesh
        )rK   rL   rB   rC   excludeNT	processed)
is_emptyrW   unique_facesnondegenerate_facesupdate_facesfix_normalsremove_infinite_valuesmerge_verticesclearrH   )rc   rJ   rK   rL   masks        re   rI   zTrimesh.process   s4   > = 	K [ 	J 	J  #((**T-E-E-G-GG!!$'''  """ ''))))
KKKK~7G&HIII	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J" &*k"s   BB::B>B>c                     | j         j        S )z
        Is the current mesh allowed to be altered in-place?

        Returns
        -------------
        mutable
          If data is allowed to be set for the mesh.
        rU   mutablerc   s    re   rw   zTrimesh.mutable  s     z!!rg   valuec                     || j         _        dS )z
        Set the mutability of the current mesh.

        Parameters
        ----------
        value
          Change whether the current mesh is allowed to be altered in-place.
        Nrv   rc   ry   s     re   rw   zTrimesh.mutable  s     #
rg   c                     | j         d         S )a  
        The faces of the mesh.

        This is regarded as core information which cannot be
        regenerated from cache and as such is stored in
        `self._data` which tracks the array for changes and
        clears cached values of the mesh altered.

        Returns
        ----------
        faces : (n, 3) int64
          References for `self.vertices` for triangles.
        rA   rU   rx   s    re   rA   zTrimesh.faces+  s     z'""rg   valuesc                 .   |t          j        dt                    }nt          j        |t                    }t	          |j                  dk    r9|j        d         dk    r(t          j        d           t          j	        |          }|| j
        d	<   dS )
z
        Set the vertex indexes that make up triangular faces.

        Parameters
        --------------
        values : (n, 3) int64
          Indexes of self.vertices
        Nr      shapedtyper      r   r   ztriangulating facesrA   )npzerosr   
asanyarraylenr   r!   infor   triangulate_quadsrU   rc   r~   s     re   rA   zTrimesh.faces<  s     >XF%888FF]6777F v|!!fl1o&:&:H*+++/77F$
7rg   c                 \    t          j        t          | j                  | j                  S )z
        A sparse matrix representation of the faces.

        Returns
        ----------
        sparse : scipy.sparse.coo_matrix
          Has properties:
          dtype : bool
          shape : (len(self.vertices), len(self.faces))
        )columnsindices)r   index_sparser   r@   rA   rx   s    re   faces_sparsezTrimesh.faces_sparseS  s&     $S-?-?TTTTrg   c                 <   | j         d         }d| j        v r| j        j        d         }nd}|t          |          dk    r.t	          j        g t                                        d          S t	          j        |          t	          j        |          k    r|S t          j
        | j	        | j                  \  }}|                                r|| j         d<   |S t	          j        t          | j	                  dft                    }|||<   || j         d<   |S )	a>  
        Return the unit normal vector for each face.

        If a face is degenerate and a normal can't be generated
        a zero magnitude unit vector will be returned for that face.

        Returns
        -----------
        normals : (len(self.faces), 3) float64
          Normal vectors of each face
        rB   rA   Nr   r   r   )r   crossesr   )rW   rU   datar   r   arrayr   reshaper   r   normalstriangles_crossallr   )rc   cachedrA   r   validpaddeds         re   rB   zTrimesh.face_normalsa  s    ^,dj  JOG,EEE =CJJ!OO8Bg...66v>>> 8Frx..M #*nd.B
 
 

 99;; 	*1DK'N 3t~..2'BBBu '-N#rg   c                    |dS t          j        |dt                    }t          |          dk    s|j        | j        j        k    rt          j        d           dS t          j        |          }t          j	        |          st          j        d           dS |t          j        k     rt          j        d           dS t          j        | j                            t           j                  | j        dd                            \  }}t          j        t          |          d	f          }|||<   t          j        ||dd                   st          j        d
           dS || j        d<   dS )z
        Assign values to face normals.

        Parameters
        -------------
        values : (len(self.faces), 3) float
          Unit face normals. If None will clear existing normals.
        NCorderr   r   z'face_normals incorrect shape, ignoring!z#face_normals contain NaN, ignoring!z face_normals all zero, ignoring!   r   z.face_normals didn't match triangles, ignoring!rB   )r   r   r   r   r   rA   r!   debugptpisfiniter"   merger   r   r@   viewr   r   allcloserW   )rc   r~   r   checkr   compares         re   rB   zTrimesh.face_normals  sV    >FvS@@@v;;!v|tz/???I?@@@F fVnn{3 	I;<<<F??I8999F !(););BJ)G)G
SVTVSV)XYYu(CJJ?++{7F3B3K00 	IFGGGF '-N###rg   c                     | j         d         S )a  
        The vertices of the mesh.

        This is regarded as core information which cannot be
        generated from cache and as such is stored in self._data
        which tracks the array for changes and clears cached
        values of the mesh if this is altered.

        Returns
        ----------
        vertices : (n, 3) float
          Points in cartesian space referenced by self.faces
        r@   r}   rx   s    re   r@   zTrimesh.vertices  s      z*%%rg   c                     |t          j        dt                    }t          j        |dt                    | j        d<   dS )z
        Assign vertex values to the mesh.

        Parameters
        --------------
        values : (n, 3) float
          Points in space
        Nr   r   r   r   r@   )r   r   r   r   rU   r   s     re   r@   zTrimesh.vertices  s@     >XF':::F!#vS!P!P!P
:rg   c                     t          | j        d          sJ t          j        t	          | j                  | j        | j        | j                  S )a  
        The vertex normals of the mesh. If the normals were loaded
        we check to make sure we have the same number of vertex
        normals and vertices before returning them. If there are
        no vertex normals defined or a shape mismatch we  calculate
        the vertex normals from the mean normals of the faces the
        vertex is used in.

        Returns
        ----------
        vertex_normals : (n, 3) float
          Represents the surface normal at each vertex.
          Where n == len(self.vertices)
        dot)vertex_countrA   rB   face_angles)	hasattrr   r   weighted_vertex_normalsr   r@   rA   rB   r   rx   s    re   rC   zTrimesh.vertex_normals  sU    " t(%00000/T]++**(	
 
 
 	
rg   c                     |st          j        |dt                    }|j        | j        j        k    rDt          j        |          t          j        k     rt          j	        d           || j
        d<   dS dS dS )z
        Assign values to vertex normals.

        Parameters
        -------------
        values : (len(self.vertices), 3) float
          Unit normal vectors for each vertex
        Nr   r   zvertex_normals are all zero!rC   )r   r   r   r   r@   r   r"   r   r!   r   rW   r   s     re   rC   zTrimesh.vertex_normals  sy     ]6GDDDF|t}2226&>>CI--I<===06,--- 22rg   c                 l    t          j        t          | j                  | j        | j                  }|S )a  
        A representation of the face indices that correspond to each vertex.

        Returns
        ----------
        vertex_faces : (n,m) int
          Each row contains the face indices that correspond to the given vertex,
          padded with -1 up to the max number of faces corresponding to any one vertex
          Where n == len(self.vertices), m == max number of faces for a single vertex
        )r   rA   r   )r   vertex_face_indicesr   r@   rA   r   )rc   vertex_facess     re   r   zTrimesh.vertex_faces	  s;      3T]++**
 
 

 rg   c                     | j         | j                 }t          |          dk    rdS t          j        |                    d          |                    d          g          S )z
        The axis aligned bounds of the faces of the mesh.

        Returns
        -----------
        bounds : (2, 3) float or None
          Bounding box with [min, max] coordinates
          If mesh is empty will return None
        r   Naxis)r@   referenced_verticesr   r   r   minmax)rc   in_meshs     re   boundszTrimesh.bounds  sZ     - 89w<<14x!,,gkkqk.A.ABCCCrg   c                 N    | j         dS t          j        | j         d          }|S )a  
        The length, width, and height of the axis aligned
        bounding box of the mesh.

        Returns
        -----------
        extents : (3, ) float or None
          Array containing axis aligned [length, width, height]
          If mesh is empty returns None
        Nr   r   )r   r   r   )rc   extentss     re   r   zTrimesh.extents/  s,     ;4&1---rg   c                     	 t          j        | j        | j        d          }n+# t          $ r | j                            d          }Y nw xY w|S )aT  
        The point in space which is the average of the triangle
        centroids weighted by the area of each triangle.

        This will be valid even for non-watertight meshes,
        unlike self.center_mass

        Returns
        ----------
        centroid : (3, ) float
          The average vertex weighted by face area
        r   )weightsr   r   )r   averagetriangles_center
area_facesBaseExceptionmean)rc   centroids     re   r   zTrimesh.centroidB  sd    "	:z$"7WXYYYHH 	: 	: 	:,11q199HHH	: s   !$ %AAc                     | j         j        S )z
        The point in space which is the center of mass/volume.

        Returns
        -----------
        center_mass : (3, ) float
           Volumetric center of mass of the mesh.
        )mass_propertiescenter_massrx   s    re   r   zTrimesh.center_massZ  s     #//rg   c                     t          j        |t                    }|j        dk    rt	          d          || j        d<   | j                            d           dS )z
        Override the point in space which is the center of mass and volume.

        Parameters
        -----------
        center_mass : (3, ) float
           Volumetric center of mass of the mesh.
        r   )r   zshape must be (3,) float!r   r   N)r   r   r   r   rb   rU   rW   deleter{   s     re   r   zTrimesh.center_massf  s]     g...;$8999$)
=!,-----rg   c                 4    t          | j        j                  S )z
        The density of the mesh used in inertia calculations.

        Returns
        -----------
        density
          The density of the primitive.
        )floatr   densityrx   s    re   r   zTrimesh.densityv  s     T)1222rg   c                 h    t          |          | j        d<   | j                            d           dS )z
        Set the density of the primitive.

        Parameters
        -------------
        density
          Specify the density of the primitive to be
          used in inertia calculations.
        r   r   N)r   rU   rW   r   r{   s     re   r   zTrimesh.density  s3     !&e
9,-----rg   c                     | j         j        S )z
        Volume of the current mesh calculated using a surface
        integral. If the current mesh isn't watertight this is
        garbage.

        Returns
        ---------
        volume : float
          Volume of the current mesh
        )r   volumerx   s    re   r   zTrimesh.volume  s     #**rg   c                     | j         j        S )z
        Mass of the current mesh, based on specified density and
        volume. If the current mesh isn't watertight this is garbage.

        Returns
        ---------
        mass : float
          Mass of the current mesh
        )r   massrx   s    re   r   zTrimesh.mass  s     #((rg   c                     | j         j        S )a  
        Return the moment of inertia matrix of the current mesh.
        If mesh isn't watertight this is garbage. The returned
        moment of inertia is *axis aligned* at the mesh's center
        of mass `mesh.center_mass`. If you want the moment at any
        other frame including the origin call:
        `mesh.moment_inertia_frame`

        Returns
        ---------
        inertia : (3, 3) float
          Moment of inertia of the current mesh at the center of
          mass and aligned with the cartesian axis.
        )r   r   rx   s    re   moment_inertiazTrimesh.moment_inertia  s      #++rg   	transformc                     | j         }t          j        d          }|d          |dddf<   t          j        |d         t          j        ||          |d         d          S )	a  
        Get the moment of inertia of this mesh with respect to
        an arbitrary frame, versus with respect to the center
        of mass as returned by `mesh.moment_inertia`.

        For example if `transform` is an identity matrix `np.eye(4)`
        this will give the moment at the origin.

        Uses the parallel axis theorum to move the center mass
        tensor to this arbitrary frame.

        Parameters
        ------------
        transform : (4, 4) float
          Homogeneous transformation matrix.

        Returns
        -------------
        inertia : (3, 3)
          Moment of inertia in the requested frame.
           r   Nr   r   r   T)inertia_tensorr   r   parallel_axis)r   r   eyer   transform_inertiar   )rc   r   propsoffsets       re   moment_inertia_framezTrimesh.moment_inertia_frame  sq    . $ }--rr1u ( +fVY//v	
 
 
 	
rg   c                 R    t          j        | j                  \  }}|| j        d<   |S )z
        Return the principal components of inertia

        Ordering corresponds to mesh.principal_inertia_vectors

        Returns
        ----------
        components : (3, ) float
          Principal components of inertia
        principal_inertia_vectors)r   principal_axisr   rW   )rc   
componentsvectorss      re   principal_inertia_componentsz$Trimesh.principal_inertia_components  s/     &4T5HII
G3:/0rg   c                 *    | j         }| j        d         S )a*  
        Return the principal axis of inertia as unit vectors.
        The order corresponds to `mesh.principal_inertia_components`.

        Returns
        ----------
        vectors : (3, 3) float
          Three vectors pointing along the
          principal axis of inertia directions
        r   )r   rW   rc   _s     re   r   z!Trimesh.principal_inertia_vectors  s     -{677rg   c                 ^   t          j        | j                  dd         ddd         }| j        |         }t          j        |t          j        | f          }t          j        d          }||ddddf<   t          j        || j	                  }|dddfxx         | j	        z  cc<   |S )a  
        A transform which moves the current mesh so the principal
        inertia vectors are on the X,Y, and Z axis, and the centroid is
        at the origin.

        Returns
        ----------
        transform : (4, 4) float
          Homogeneous transformation matrix
        r   Nr   r   )matrixpoint)
r   argsortr   r   vstackcrossr   r   transform_aroundr   )rc   r   r   r   s       re   principal_inertia_transformz#Trimesh.principal_inertia_transform  s     
4<==abbA$$B$G07)Wbh&89::F1II	#	"1"bqb&#4DM
 
 
	 	"1"a%DM)rg   c                 ^    t          j        |           \  }}}|| j        d<   || j        d<   |S )z
        Check whether a mesh has rotational symmetry around
        an axis (radial) or point (spherical).

        Returns
        -----------
        symmetry : None, 'radial', 'spherical'
          What kind of symmetry does the mesh have.
        symmetry_axissymmetry_section)r   radial_symmetryrW   )rc   symmetryr   sections       re   r   zTrimesh.symmetry  s9     #*"9$"?"?$'+O$*1&'rg   c                 .    | j         dS | j        d         S )z
        If a mesh has rotational symmetry, return the axis.

        Returns
        ------------
        axis : (3, ) float
          Axis around which a 2D profile was revolved to create this mesh.
        Nr   r   rW   rx   s    re   r   zTrimesh.symmetry_axis.  s     = 4{?++rg   c                 .    | j         dS | j        d         S )z
        If a mesh has rotational symmetry return the two
        vectors which make up a section coordinate frame.

        Returns
        ----------
        section : (2, 3) float
          Vectors to take a section along
        Nr   r   rx   s    re   r   zTrimesh.symmetry_section<  s     = 4{-..rg   c                 `    | j                             t          j                  | j                 S )z
        Actual triangles of the mesh (points, not indexes)

        Returns
        ---------
        triangles : (n, 3, 3) float
          Points of triangle vertices
        )r@   r   r   r   rA   rx   s    re   r   zTrimesh.trianglesK  s#     }!!"*--dj99rg   c                 4    t          j        | j                   S )z
        An R-tree containing each face of the mesh.

        Returns
        ----------
        tree : rtree.index
          Each triangle in self.faces has a rectangular cell
        )r   bounds_treerx   s    re   triangles_treezTrimesh.triangles_treeZ  s     $T^444rg   c                 8    | j                             d          S )z
        The center of each triangle (barycentric [1/3, 1/3, 1/3])

        Returns
        ---------
        triangles_center : (len(self.faces), 3) float
          Center of each triangular face
        r   r   )r   r   rx   s    re   r   zTrimesh.triangles_centerf  s     ~"""***rg   c                 8    t          j        | j                   }|S )z
        The cross product of two edges of each triangle.

        Returns
        ---------
        crosses : (n, 3) float
          Cross product of each triangle
        )r   r   )rc   r   s     re   r   zTrimesh.triangles_crossr  s     /$.11rg   c                     t          j        | j                            t          j                  d          \  }}|| j        d<   |S )z
        Edges of the mesh (derived from faces).

        Returns
        ---------
        edges : (n, 2) int
          List of vertex indices making up edges
        T)return_index
edges_face)r   faces_to_edgesrA   r   r   r   rW   )rc   edgesindexs      re   r  zTrimesh.edges  sG      .JOOBJ''d
 
 
u %*L!rg   c                 *    | j         }| j        d         S )z
        Which face does each edge belong to.

        Returns
        ---------
        edges_face : (n, ) int
          Index of self.faces
        r  )r  rW   r   s     re   r  zTrimesh.edges_face  s     J{<((rg   c                     t          j        | j                  \  }}| j        |         }|| j        d<   || j        d<   |S )z
        The unique edges of the mesh.

        Returns
        ----------
        edges_unique : (n, 2) int
          Vertex indices for unique edges
        edges_unique_idxedges_unique_inverse)r   unique_rowsedges_sortedrW   )rc   uniqueinverseedges_uniques       re   r  zTrimesh.edges_unique  sJ     #.t/@AA(0 +1&'.5*+rg   c                 t    t          j        | j        | j        j                  }t          j        |          }|S )z
        How long is each unique edge.

        Returns
        ----------
        length : (len(self.edges_unique), ) float
          Length of each unique edge
        )r   subtractr@   r  Tr   row_norm)rc   vectorlengths      re   edges_unique_lengthzTrimesh.edges_unique_length  s1     dmD,=,?@Av&&rg   c                 *    | j         }| j        d         S )aY  
        Return the inverse required to reproduce
        self.edges_sorted from self.edges_unique.

        Useful for referencing edge properties:
        mesh.edges_unique[mesh.edges_unique_inverse] == m.edges_sorted

        Returns
        ----------
        inverse : (len(self.edges), ) int
          Indexes of self.edges_unique
        r  )r  rW   r   s     re   r  zTrimesh.edges_unique_inverse  s     {122rg   c                 <    t          j        | j        d          }|S )z
        Edges sorted along axis 1

        Returns
        ----------
        edges_sorted : (n, 2)
          Same as self.edges but sorted along axis 1
        r   r   )r   sortr  )rc   r  s     re   r  zTrimesh.edges_sorted  s      wtz222rg   c                 *    t          | j                  S )z
        A KDTree for mapping edges back to edge index.

        Returns
        ------------
        tree : scipy.spatial.cKDTree
          Tree when queried with edges will return
          their index in mesh.edges_sorted
        )r9   r  rx   s    re   edges_sorted_treezTrimesh.edges_sorted_tree  s     t()))rg   c                 `    t          j        | j        t          | j                            }|S )z
        Edges in sparse bool COO graph format where connected
        vertices are True.

        Returns
        ----------
        sparse: (len(self.vertices), len(self.vertices)) bool
          Sparse graph in COO format
        )count)r   edges_to_coor  r   r@   )rc   sparses     re   edges_sparsezTrimesh.edges_sparse  s*     #DJc$-6H6HIIIrg   c                 n    t           j                            | j        dd          \  }}|| j        d<   |S )a8  
        How many connected groups of vertices exist in this mesh.
        Note that this number may differ from result in mesh.split,
        which is calculated from FACE rather than vertex adjacency.

        Returns
        -----------
        count : int
          Number of connected vertex groups
        FT)directedreturn_labelsvertices_component_label)r   csgraphconnected_componentsr"  rW   )rc   r  labelss      re   
body_countzTrimesh.body_count  sB     ::T ; 
 
v 39./rg   c                 T    | j         }| j        d                             d          }|S )a  
        For each face return which indexes in mesh.unique_edges constructs
        that face.

        Returns
        ---------
        faces_unique_edges : (len(self.faces), 3) int
          Indexes of self.edges_unique that
          construct self.faces

        Examples
        ---------
        In [0]: mesh.faces[:2]
        Out[0]:
        TrackedArray([[    1,  6946, 24224],
                      [ 6946,  1727, 24225]])

        In [1]: mesh.edges_unique[mesh.faces_unique_edges[:2]]
        Out[1]:
        array([[[    1,  6946],
                [ 6946, 24224],
                [    1, 24224]],
               [[ 1727,  6946],
                [ 1727, 24225],
                [ 6946, 24225]]])
        r  r   r   )r  rW   r   )rc   r   results      re   faces_unique_edgeszTrimesh.faces_unique_edges  s,    : 34<<WEErg   c                     t          | j                                        t          | j                  z
  t          | j                  z             S )a#  
        Return the Euler characteristic (a topological invariant) for the mesh
        In order to guarantee correctness, this should be called after
        remove_unreferenced_vertices

        Returns
        ----------
        euler_number : int
          Topological invariant
        )intr   sumr   r  rA   rx   s    re   euler_numberzTrimesh.euler_number*  sE     $((**S1B-C-CCc$*ooU
 
 	
rg   c                 t    t          j        t          | j                  t                    }d|| j        <   |S )z
        Which vertices in the current mesh are referenced by a face.

        Returns
        -------------
        referenced : (len(self.vertices), ) bool
          Which vertices are referenced by a face
        r   T)r   r   r   r@   boolrA   )rc   
referenceds     re   r   zTrimesh.referenced_vertices:  s4     Xc$-00===
!%
4:rg   desiredguessc                 2    t          j        | ||           | S )aB  
        Convert the units of the mesh into a specified unit.

        Parameters
        ------------
        desired : string
          Units to convert to (eg 'inches')
        guess : boolean
          If self.units are not defined should we
          guess the current units of the document and then convert?
        )r   _convert_units)rc   r6  r7  s      re   convert_unitszTrimesh.convert_unitsH  s     	T7E222rg   digits_vertexdigits_norm	digits_uvc                 :    t          j        | |||||           dS )a  
        Removes duplicate vertices grouped by position and
        optionally texture coordinate and normal.

        Parameters
        -------------
        mesh : Trimesh object
          Mesh to merge vertices on
        merge_tex : bool
          If True textured meshes with UV coordinates will
          have vertices merged regardless of UV coordinates
        merge_norm : bool
          If True, meshes with vertex normals will have
          vertices merged ignoring different normals
        digits_vertex : None or int
          Number of digits to consider for vertex position
        digits_norm : int
          Number of digits to consider for unit normals
        digits_uv : int
          Number of digits to consider for UV coordinates
        )rT   rK   rL   r;  r<  r=  N)r   rr   )rc   rK   rL   r;  r<  r=  s         re   rr   zTrimesh.merge_verticesW  s:    : 	!'#	
 	
 	
 	
 	
 	
rg   rt   r  c                 r   | j         rdS t          j        |          }|j        j        dk    r|                                st          |          dk    s| j         rdS |t          j        t          | j                  t                    }|j        j
        dk    r*t          j        |                                          ||<   n7|j        j
        dk    r%t          j        t          |                    ||<   nd}|Rt          j        | j        d          r8|| j                            d                                       d          | _        | j                            |           | j        d	         }t          | j                  }| j                                        D ]H\  }}	 t          |          |k    rt-                      n# t,          $ r Y 4w xY w||         | j        |<   I| j        |         | _        t          j        |d          r!	 ||         | _        dS # t0          $ r Y dS w xY wdS )
a3  
        Update vertices with a mask.

        Parameters
        ------------
        vertex_mask : (len(self.vertices)) bool
          Array of which vertices to keep
        inverse : (len(self.vertices)) int
          Array to reconstruct vertex references
          such as output by np.unique
        Nr4  r   r   bir,  r   rC   )rl   r   r   r   namer   r   r   r@   r   kindaranger1  r   is_shaperA   r   rO   update_verticesrW   rG   items	TypeErrorrC   r   )rc   rt   r  cached_normalsr  keyry   s          re   rF  zTrimesh.update_vertices}  s;   " = 	F }T""JOv%%$((**%Ta4=F ?hs4=11???Gz#%% "	$((** 5 5C'' "	#d)) 4 4 4=W#E#E !3!3B!7!78@@IIDJ 	##D)))%56 DM""06688 	6 	6JCu::&&#++% '    +0+D"3'' d+ =11 	&4T&:###    	 	s$   ,!G
GGH& &
H43H4c                    | j         rdS t          j        |          }|j        j        dk    r|                                rdS | j        d         }| j        d         }t          j	        |d          s| j        d         }t          | j                  }| j                                        D ]H\  }}	 t          |          |k    rt                      n# t          $ r Y 4w xY w||         | j        |<   I||         | _        | j                            |           t          j	        |d          r||         | _        dS dS )a  
        In many cases, we will want to remove specific faces.
        However, there is additional bookkeeping to do this cleanly.
        This function updates the set of faces with a validity mask,
        as well as keeping track of normals and colors.

        Parameters
        ------------
        valid : (m) int or (len(self.faces)) bool
          Mask to remove faces
        Nr4  rB   rA   r,  )rl   r   r   r   rB  r   rW   rU   r   rE  r   rA   rF   rG  rH  rO   ro   rB   )rc   rt   rI  rA   r  rJ  ry   s          re   ro   zTrimesh.update_faces  sc    = 	F}T"":?f$$$F ^4
7# }UG,, 	)K(E DJ.4466 	4 	4JCu::&&#++% '    ).dD %% 4[
 	  &&& =11 	5 .t 4D	5 	5s   3!C
C"!C"c                 z   t          j        | j        d          rBt          j        | j                                      d          }|                     |           t          j        | j        d          rDt          j        | j                                      d          }|                     |           dS dS )z
        Ensure that every vertex and face consists of finite numbers.
        This will remove vertices or faces containing np.nan and np.inf

        Alters `self.faces` and `self.vertices`
        r,  r   r   N)	r   rE  rA   r   r   r   ro   r@   rF  )rc   	face_maskvertex_masks      re   rq   zTrimesh.remove_infinite_values  s     =W-- 	)DJ//333;;Ii(((=00 	.+dm4488a8@@K  -----	. 	.rg   c                     t          j        t          | j                  t                    }d|t          j        t          j        | j        d                    d         <   |S )z
        On the current mesh find which faces are unique.

        Returns
        --------
        unique : (len(faces),) bool
          A mask where the first occurrence of a unique face is true.
        r   Tr   r   r   )r   r   r   rA   r4  r   r  r  )rc   rt   s     re   rm   zTrimesh.unique_faces  sP     xDJt444EIX!"'$*1"="="=>>qABrg   c                     t          j        dt          d           |                     |                                            dS )ze
        DERECATED MARCH 2024 REPLACE WITH:
        `mesh.update_faces(mesh.unique_faces())`
        z`remove_duplicate_faces` is deprecated and will be removed in March 2024: replace with `mesh.update_faces(mesh.unique_faces())`r   category
stacklevelN)warningswarnDeprecationWarningro   rm   rx   s    re   remove_duplicate_faceszTrimesh.remove_duplicate_faces  sS    
 	F (	
 	
 	
 	
 	$++--.....rg   c                 L    |                      | j        d         dz             dS )zo
        Translate the mesh so that all vertex vertices are positive.

        Alters `self.vertices`.
        r         N)apply_translationr   rx   s    re   rezerozTrimesh.rezero!  s)     	t{1~455555rg   c                 &    t          j        | fi |S )a  
        Returns a list of Trimesh objects, based on face connectivity.
        Splits into individual components, sometimes referred to as 'bodies'

        Parameters
        ------------
        only_watertight : bool
          Only return watertight meshes and discard remainder
        adjacency : None or (n, 2) int
          Override face adjacency with custom values

        Returns
        ---------
        meshes : (n, ) trimesh.Trimesh
          Separate bodies from original mesh
        )r   splitrc   rd   s     re   r]  zTrimesh.split)  s    " {4**6***rg   c                 L    t          j        | d          \  }}|| j        d<   |S )aV  
        Find faces that share an edge i.e. 'adjacent' faces.

        Returns
        ----------
        adjacency : (n, 2) int
          Pairs of faces which share an edge

        Examples
        ---------

        In [1]: mesh = trimesh.load('models/featuretype.STL')

        In [2]: mesh.face_adjacency
        Out[2]:
        array([[   0,    1],
               [   2,    3],
               [   0,    3],
               ...,
               [1112,  949],
               [3467, 3475],
               [1113, 3475]])

        In [3]: mesh.faces[mesh.face_adjacency[0]]
        Out[3]:
        TrackedArray([[   1,    0,  408],
                      [1239,    0,    1]], dtype=int64)

        In [4]: import networkx as nx

        In [5]: graph = nx.from_edgelist(mesh.face_adjacency)

        In [6]: groups = nx.connected_components(graph)
        T)rT   return_edgesface_adjacency_edges)r   face_adjacencyrW   )rc   	adjacencyr  s      re   rb  zTrimesh.face_adjacency<  s2    H !/TMMM	5.3*+rg   c                 *    t          j        |           S )z
        Find faces that share a vertex i.e. 'neighbors' faces.

        Returns
        ----------
        neighborhood : (n, 2) int
          Pairs of faces which share a vertex
        )r   face_neighborhoodrx   s    re   re  zTrimesh.face_neighborhoodd  s     &t,,,rg   c                 *    | j         }| j        d         S )z
        Returns the edges that are shared by the adjacent faces.

        Returns
        --------
        edges : (n, 2) int
           Vertex indices which correspond to face_adjacency
        ra  )rb  rW   r   s     re   ra  zTrimesh.face_adjacency_edgesp  s     {122rg   c                 *    t          | j                  S )z
        A KDTree for mapping edges back face adjacency index.

        Returns
        ------------
        tree : scipy.spatial.cKDTree
          Tree when queried with SORTED edges will return
          their index in mesh.face_adjacency
        )r9   ra  rx   s    re   face_adjacency_edges_treez!Trimesh.face_adjacency_edges_tree~  s     t0111rg   c                 R    | j         | j                 }t          j        |          }|S )z
        Return the angle between adjacent faces

        Returns
        --------
        adjacency_angle : (n, ) float
          Angle between adjacent faces
          Each value corresponds with self.face_adjacency
        )rB   rb  r   vector_angle)rc   pairsangless      re   face_adjacency_angleszTrimesh.face_adjacency_angles  s)     !$"56&u--rg   c                 .    t          j        |           }|S )a  
        The projection of the non-shared vertex of a triangle onto
        its adjacent face

        Returns
        ----------
        projections : (len(self.face_adjacency), ) float
          Dot product of vertex
          onto plane of adjacent triangle.
        )r	   adjacency_projections)rc   projectionss     re   face_adjacency_projectionsz"Trimesh.face_adjacency_projections  s     2488rg   c                 ,    | j         t          j        k     S )a  
        Return faces which are adjacent and locally convex.

        What this means is that given faces A and B, the one vertex
        in B that is not shared with A, projected onto the plane of A
        has a projection that is zero or negative.

        Returns
        ----------
        are_convex : (len(self.face_adjacency), ) bool
          Face pairs that are locally convex
        )rq  r"   r   rx   s    re   face_adjacency_convexzTrimesh.face_adjacency_convex  s     .::rg   c                 *    t          j        |           S )z
        Return the vertex index of the two vertices not in the shared
        edge between two adjacent faces

        Returns
        -----------
        vid_unshared : (len(mesh.face_adjacency), 2) int
          Indexes of mesh.vertices
        )r   face_adjacency_unsharedrx   s    re   ru  zTrimesh.face_adjacency_unshared  s     ,T222rg   c                 F    t          j        |           \  }| j        d<   |S )z
        The approximate radius of a cylinder that fits inside adjacent faces.

        Returns
        ------------
        radii : (len(self.face_adjacency), ) float
          Approximate radius formed by triangle pair
        rT   face_adjacency_span)r   face_adjacency_radiusrW   )rc   radiis     re   ry  zTrimesh.face_adjacency_radius  s*     5:4OUY4Z4Z4Z1t{01rg   c                 *    | j         }| j        d         S )a;  
        The approximate perpendicular projection of the non-shared
        vertices in a pair of adjacent faces onto the shared edge of
        the two faces.

        Returns
        ------------
        span : (len(self.face_adjacency), ) float
          Approximate span between the non-shared vertices
        rx  )ry  rW   r   s     re   rx  zTrimesh.face_adjacency_span  s     &{011rg   c                     t           j                            t          j        | j        | j        j                  d          }| j        |z                                  dz  S )z
        The integral mean curvature, or the surface integral of the mean curvature.

        Returns
        ---------
        area : float
          Integral mean curvature of mesh
        r   r   g      ?)	r   linalgnormr  r@   ra  r  rm  r1  )rc   edges_lengths     re   integral_mean_curvaturezTrimesh.integral_mean_curvature  sX     y~~Kt'@'BCD1 & 
 
 *\9>>@@3FFrg   c                 ,    t          j        |           S )aQ  
        Returns a networkx graph representing the vertices and their connections
        in the mesh.

        Returns
        ---------
        graph: networkx.Graph
          Graph representing vertices and edges between
          them where vertices are nodes and edges are edges

        Examples
        ----------
        This is useful for getting nearby vertices for a given vertex,
        potentially for some simple smoothing techniques.

        mesh = trimesh.primitives.Box()
        graph = mesh.vertex_adjacency_graph
        graph.neighbors(0)
        > [1, 2, 3, 4]
        rw  )r   vertex_adjacency_graphrx   s    re   r  zTrimesh.vertex_adjacency_graph  s    . +6666rg   c                 \    t          j        | j        t          | j                            S )aX  
        The vertex neighbors of each vertex of the mesh, determined from
        the cached vertex_adjacency_graph, if already existent.

        Returns
        ----------
        vertex_neighbors : (len(self.vertices), ) int
          Represents immediate neighbors of each vertex along
          the edge of a triangle

        Examples
        ----------
        This is useful for getting nearby vertices for a given vertex,
        potentially for some simple smoothing techniques.

        >>> mesh = trimesh.primitives.Box()
        >>> mesh.vertex_neighbors[0]
        [1, 2, 3, 4]
        )r  	max_index)r   	neighborsr  r   r@   rx   s    re   vertex_neighborszTrimesh.vertex_neighbors  s&    * T%6#dmBTBTUUUUrg   c                 <    | j         rdS | j        }| j        d         S )a$  
        Does the mesh have consistent winding or not.
        A mesh with consistent winding has each shared edge
        going in an opposite direction from the other in the pair.

        Returns
        --------
        consistent : bool
          Is winding is consistent or not
        Fis_winding_consistent)rl   is_watertightrW   r   s     re   r  zTrimesh.is_winding_consistent#  s)     = 	5{233rg   c                 r    | j         rdS t          j        | j        | j                  \  }}|| j        d<   |S )z
        Check if a mesh is watertight by making sure every edge is
        included in two faces.

        Returns
        ----------
        is_watertight : bool
          Is mesh watertight or not
        F)r  r  r  )rl   r   r  r  r  rW   )rc   
watertightwindings      re   r  zTrimesh.is_watertight5  sN     = 	5#1*4+<
 
 

G 07+,rg   c                     t          | j        o<| j        o5t          j        | j                                                  o
| j        dk              }|S )aW  
        Check if a mesh has all the properties required to represent
        a valid volume, rather than just a surface.

        These properties include being watertight, having consistent
        winding and outward facing normals.

        Returns
        ---------
        valid : bool
          Does the mesh represent a volume
                )r4  r  r  r   r   r   r   r   )rc   r   s     re   	is_volumezTrimesh.is_volumeH  s]      "*"D,--1133" c!	
 
 rg   c                 4    | j                                         S )z
        Does the current mesh have data defined.

        Returns
        --------
        empty : bool
          If True, no data is set on the current mesh
        )rU   rl   rx   s    re   rl   zTrimesh.is_empty^  s     z""$$$rg   c                 Z    | j         rdS t          t          j        |                     }|S )z
        Check if a mesh is convex or not.

        Returns
        ----------
        is_convex: bool
          Is mesh convex or not
        F)rl   r4  r	   	is_convex)rc   r  s     re   r  zTrimesh.is_convexj  s1     = 	5)$//00	rg   c                 d    t          | j                            t          j                            S )z
        Return a scipy.spatial.cKDTree of the vertices of the mesh.
        Not cached as this lead to observed memory issues and segfaults.

        Returns
        ---------
        tree : scipy.spatial.cKDTree
          Contains mesh.vertices
        )r9   r@   r   r   r   rx   s    re   kdtreezTrimesh.kdtreez  s$     t}))"*55666rg   heightc                     t          j        dt          d           |                     |                     |                     dS )zy
        DERECATED MARCH 2024 REPLACE WITH:
        `self.update_faces(self.nondegenerate_faces(height=height))`
        z`remove_degenerate_faces` is deprecated and will be removed in March 2024 replace with `self.update_faces(self.nondegenerate_faces(height=height))`r   rQ  )r  N)rT  rU  rV  ro   rn   rc   r  s     re   remove_degenerate_faceszTrimesh.remove_degenerate_faces  sX    
 	M (	
 	
 	
 	
 	$22&2AABBBBBrg   c                 D    t          j        | j         | j        |          S )a  
        Identify degenerate faces (faces without 3 unique vertex indices)
        in the current mesh.

        Usage example for removing them:
        `mesh.update_faces(mesh.nondegenerate_faces())`

        If a height is specified, it will identify any face with a 2D oriented
        bounding box with one edge shorter than that height.

        If not specified, it will identify any face with a zero normal.

        Parameters
        ------------
        height : float
          If specified identifies faces with an oriented bounding
          box shorter than this on one side.

        Returns
        -------------
        nondegenerate : (len(self.faces), ) bool
          Mask that can be used to remove faces
        )areasr  )r   nondegenerater   r  s     re   rn   zTrimesh.nondegenerate_faces  s)    0 &N$/&
 
 
 	
rg   c                 .    t          j        |           }|S )z
        Return a list of face indices for coplanar adjacent faces.

        Returns
        ---------
        facets : (n, ) sequence of (m, ) int
          Groups of indexes of self.faces
        )r   facets)rc   r  s     re   r  zTrimesh.facets  s     d##rg   c                 n    | j         t          j        fd| j        D             t                    }|S )z
        Return an array containing the area of each facet.

        Returns
        ---------
        area : (len(self.facets), ) float
          Total area of each facet (group of faces)
        c                 :    g | ]}t          |                   S  )r1  .0rA  r   s     re   
<listcomp>z'Trimesh.facets_area.<locals>.<listcomp>  s%    BBB#jm,,BBBrg   r   )r   r   r   r  r   )rc   r  r   s     @re   facets_areazTrimesh.facets_area  s>     _

 BBBBdkBBB'RRRrg   c                 *   t          | j                  dk    rt          j        g           S | j        t          j        fd| j        D                       }| j        |         }| j        | j        dddf         |                  }|| j        d<   |S )z
        Return the normal of each facet

        Returns
        ---------
        normals: (len(self.facets), 3) float
          A unit normal vector for each facet
        r   c                 P    g | ]"}||                                                   #S r  )argmaxr  s     re   r  z)Trimesh.facets_normal.<locals>.<listcomp>  s.    III!JqM00223IIIrg   Nfacets_origin)	r   r  r   r   r   rB   r@   rA   rW   )rc   r  r   originsr   s       @re   facets_normalzTrimesh.facets_normal  s     t{q  8B<<_
 IIIIT[IIIJJ#E*-
111a4 0 78'.O$rg   c                 *    | j         }| j        d         S )z
        Return a point on the facet plane.

        Returns
        ------------
        origins : (len(self.facets), 3) float
          A point on each facet plane
        r  )r  rW   r   s     re   r  zTrimesh.facets_origin  s     {?++rg   c                 z    | j                             d          fd| j        D             }d |D             }|S )z
        Return the edges which represent the boundary of each facet

        Returns
        ---------
        edges_boundary : sequence of (n, 2) int
          Indices of self.vertices
        )r      c                 F    g | ]}|                              d           S ))r   r   )r   )r  rA  r  s     re   r  z+Trimesh.facets_boundary.<locals>.<listcomp>  s+    FFFQuQx''00FFFrg   c                 F    g | ]}|t          j        |d                    S )r   )require_count)r   
group_rows)r  rA  s     re   r  z+Trimesh.facets_boundary.<locals>.<listcomp>  s-    ZZZ!H/CCCDZZZrg   )r  r   r  )rc   edges_facetedges_boundaryr  s      @re   facets_boundaryzTrimesh.facets_boundary  sO     !))'22FFFF$+FFFZZkZZZrg   c                 @   t          | j                  dk    rt          j        g t                    S | j        }| j        }| j        j        	                    t          j
                                                  }t          j        t          | j                  t                    }t          t          t          |                    ||          D ]H\  }}}t          j        |||z
  j                  }|t"          j        k                                     ||<   I|S )z
        Find which facets of the mesh are on the convex hull.

        Returns
        ---------
        on_hull : (len(mesh.facets), ) bool
          is A facet on the meshes convex hull or not
        r   r   )r   r  r   r   r4  r  r  convex_hullr@   r   r   copyr   zipranger   r  r"   r   r   )	rc   r   r  r	   on_hullrA  normaloriginr   s	            re   facets_on_hullzTrimesh.facets_on_hull	  s     t{q  8Bd++++ $$ !*//
;;@@BB (3t{++4888!$U3w<<%8%8'7!K!K 	1 	1Avv &&6/!455C	/..00GAJJrg   	multibodyc                 L    || j         dk    }t          j        | |           dS )a  
        Find and fix problems with self.face_normals and self.faces
        winding direction.

        For face normals ensure that vectors are consistently pointed
        outwards, and that self.faces is wound in the correct direction
        for all connected components.

        Parameters
        -------------
        multibody : None or bool
          Fix normals across multiple bodies
          if None automatically pick from body_count
        Nr   )r  )r*  r   rp   )rc   r  s     re   rp   zTrimesh.fix_normals*  s2     !+I49555555rg   c                 *    t          j        |           S )z
        Fill single triangle and single quad holes in the current mesh.

        Returns
        ----------
        watertight : bool
          Is the mesh watertight after the function completes
        )r   
fill_holesrx   s    re   r  zTrimesh.fill_holes=  s      &&&rg   otherc                 8    t          j        d| |d|\  }}||fS )a  
        Align a mesh with another mesh or a PointCloud using
        the principal axes of inertia as a starting point which
        is refined by iterative closest point.

        Parameters
        ------------
        other : trimesh.Trimesh or (n, 3) float
          Mesh or points in space
        samples : int
          Number of samples from mesh surface to align
        icp_first : int
          How many ICP iterations for the 9 possible
          combinations of
        icp_final : int
          How many ICP itertations for the closest
          candidate from the wider search

        Returns
        -----------
        mesh_to_other : (4, 4) float
          Transform to align mesh to the other object
        cost : float
          Average square distance per point
        )rT   r  r  )r   
mesh_other)rc   r  rd   mesh_to_othercosts        re   registerzTrimesh.registerH  s2    4 +5W4uWWPVWWtd""rg   r  r   r   sigma	n_samples	thresholdc                 4    t          j        | ||||          S )a  
        Computes stable orientations of a mesh and their quasi-static probabilities.

        This method samples the location of the center of mass from a multivariate
        gaussian (mean at com, cov equal to identity times sigma) over n_samples.
        For each sample, it computes the stable resting poses of the mesh on a
        a planar workspace and evaluates the probabilities of landing in
        each pose if the object is dropped onto the table randomly.

        This method returns the 4x4 homogeneous transform matrices that place
        the shape against the planar surface with the z-axis pointing upwards
        and a list of the probabilities for each pose.
        The transforms and probabilities that are returned are sorted, with the
        most probable pose first.

        Parameters
        ------------
        center_mass : (3, ) float
          The object center of mass (if None, this method
          assumes uniform density and watertightness and
          computes a center of mass explicitly)
        sigma : float
          The covariance for the multivariate gaussian used
          to sample center of mass locations
        n_samples : int
          The number of samples of the center of mass location
        threshold : float
          The probability value at which to threshold
          returned stable poses

        Returns
        -------
        transforms : (n, 4, 4) float
          The homogeneous matrices that transform the
          object to rest in a stable pose, with the
          new z-axis pointing upwards from the table
          and the object just touching the table.

        probs : (n, ) float
          A probability ranging from 0.0 to 1.0 for each pose
        )rT   r   r  r  r  )r   compute_stable_poses)rc   r   r  r  r  s        re   r  zTrimesh.compute_stable_posese  s.    ` )#
 
 
 	
rg   
face_indexc                 (   d}t          | j        d          rt          j        | j        j                  t          | j                  dfk    rt          j        t          j	        | j        | j        j        f          | j
        || j                  \  }}}| j                                        }|ddddf         |ddddf         c}|_        n+t          j        | j        | j
        || j                  \  }}}t          ||||d          }|S )a  
        Subdivide a mesh with each subdivided face replaced
        with four smaller faces. Will return a copy of current
        mesh with subdivided faces.

        Parameters
        ------------
        face_index : (m, ) int or None
          If None all faces of mesh will be subdivided
          If (m, ) int array of indices: only specified faces will be
          subdivided. Note that in this case the mesh will generally
          no longer be manifold, as the additional vertex on the midpoint
          will not be used by the adjacent faces to the faces specified,
          and an additional postprocessing step will be required to
          make resulting mesh watertight
        Nuvr   )r@   rA   r  rG   r   F)r@   rA   rO   rG   rI   )r   rO   r   r   r  r   r@   r   	subdividehstackrA   rG   r  r?   )rc   r  rO   r@   rA   attrr-  s          re   r  zTrimesh.subdivide  s9   " 4;%% 	"(4;>*B*BG
 +
 +

 %+$4DM4;>#BCCj%"&"8	% % %!HeT [%%''F #+111bqb5/8AAAqrrE?Hfii %+$4j%"&"8	% % %!HeT "
 
 
 rg   
   c                 J   d}t          | j        d          rt          j        | j        j                  t          | j                  dfk    rt          j        t          j	        | j        | j        j        f          | j
        |||          }|r|\  }}}n|\  }}| j                                        }|ddddf         |ddddf         c}|_        n1t          j        | j        | j
        |||          }|r|\  }}}n|\  }}t          |||d          }	|r|	|fS |	S )a  
        Subdivide a mesh until every edge is shorter than a
        specified length.

        Will return a triangle soup, not a nicely structured mesh.

        Parameters
        ------------
        max_edge : float
            Maximum length of any edge in the result
        max_iter : int
            The maximum number of times to run subdivision
        return_index : bool
            If True, return index of original face for new faces
        Nr  r   )r@   rA   max_edgemax_iterr  r   Fr@   rA   rO   rI   )r   rO   r   r   r  r   r@   r   subdivide_to_sizer  rA   r  r?   )
rc   r  r  r  rO   vertices_facesr@   rA   final_indexr-  s
             re   r  zTrimesh.subdivide_to_size  sr   " 4;%% %	1"(4;>*B*BG
 +
 +

 $5DM4;>#BCCj!!)  N  1/=,%"0% [%%''F #+111bqb5/8AAAqrrE?Hfii $5j!!)  N  1/=,%"0% (%PUVVV 	';&&rg   c                 r    t          j        | j        | j        |          \  }}t	          ||d          }|S )a  
        Subdivide a mesh by dividing each triangle into four
        triangles and approximating their smoothed surface
        using loop subdivision. Loop subdivision often looks
        better on triangular meshes than catmul-clark, which
        operates primarily on quads.

        Parameters
        ------------
        iterations : int
          Number of iterations to run subdivision.
        multibody : bool
          If True will try to subdivide for each submesh
        )r@   rA   
iterationsF)r@   rA   rI   )r   subdivide_loopr@   rA   r?   )rc   r  new_vertices	new_facesr-  s        re   r  zTrimesh.subdivide_loop  sF      #)"7]$*#
 #
 #
i ,iOOOrg   c                 H    t          j        dt          d           | j        S )z\
        DEPRECATED: use `mesh.smooth_shaded` or `trimesh.graph.smooth_shade(mesh)`
        z`mesh.smoothed()` is deprecated and will be removed in March 2024: use `mesh.smooth_shaded` or `trimesh.graph.smooth_shade(mesh)`r   rQ  )rT  rU  rV  smooth_shadedr^  s     re   smoothedzTrimesh.smoothed,  s4     	O'		
 	
 	
 	
 !!rg   c                     | j                                          | j         j        }dt          | j                    dt          |            }||v r||         S t	          j        |           }|||<   |S )a  
        Smooth shading in OpenGL relies on which vertices are shared,
        this function will disconnect regions above an angle threshold
        and return a non-watertight version which will look better
        in an OpenGL rendering context.

        If you would like to use non-default arguments see `graph.smooth_shade`.

        Returns
        ---------
        smooth_shaded : trimesh.Trimesh
          Non watertight version of current mesh.
        smooth_shaded_r   )rO   _verify_hashrW   hashr   smooth_shade)rc   cacherJ  smooths       re   r  zTrimesh.smooth_shaded9  sz    " 	  """"?tDK00??4::??%<<:#D)) c
rg   c                 4    t          | d          r| j        S dS )z
        Get the stored visuals for the current mesh.

        Returns
        -------------
        visual : ColorVisuals or TextureVisuals
          Contains visual information about the mesh
        _visualN)r   r  rx   s    re   rO   zTrimesh.visualW  s#     4## 	 <trg   c                 "    | |_         || _        dS )a  
        When setting a visual object, always make sure
        that `visual.mesh` points back to the source mesh.

        Parameters
        --------------
        visual : ColorVisuals or TextureVisuals
          Contains visual information about the mesh
        N)rT   r  r{   s     re   rO   zTrimesh.visuale  s     
rg   plane_normalplane_originc                     ddl m} t          j        d| ||dd|\  }}t	          |          dk    rdS  ||          }||j        d<   |S )	a  
        Returns a 3D cross section of the current mesh and a plane
        defined by origin and normal.

        Parameters
        ------------
        plane_normal : (3,) float
          Normal vector of section plane.
        plane_origin : (3, ) float
          Point on the cross section plane.

        Returns
        ---------
        intersections
          Curve of intersection or None if it was not hit by plane.
        r   	load_pathT)rT   r  r  return_facesr   Nr  r  )exchange.loadr  r   
mesh_planer   rH   )rc   r  r  rd   r  linesr  paths           re   r   zTrimesh.sections  s    ( 	-,,,,, *4 
%%	
 

 
 
z u::??4 y '1l#rg   heightsc                 $   ddl m} t          j        | |||          \  }}}dgt	          |          z  }t          t          t	          |                    |||          D ]-\  }	}
}}t	          |          dk    r ||||
d          ||	<   .|S )ai  
        Return multiple parallel cross sections of the current
        mesh in 2D.

        Parameters
        ------------
        plane_origin : (3, ) float
          Point on the cross section plane
        plane_normal : (3) float
          Normal vector of section plane
        heights : (n, ) float
          Each section is offset by height along
          the plane normal.

        Returns
        ---------
        paths : (n, ) Path2D or None
          2D cross sections at specified heights.
          path.metadata['to_3D'] contains transform
          to return 2D section back into 3D space.
        r   r  )rT   r  r  r  Nr   )to_3Dr  )rH   )r  r  r   mesh_multiplaner   r  r  )rc   r  r  r  r  r  
transformsrA   pathsrA  fsegmentsr  s                re   section_multiplanezTrimesh.section_multiplane  s    8 	-,,,,, $1#@%%	$
 $
 $
 z5 U#!$U3u::%6%6uj!Q!Q 	W 	WAq(A8}}q  $9X!ST8U8UVVVarg   c           
      6    t          j        d| |||||d|}|S )a  
        Slice the mesh with a plane, returning a new mesh that is the
        portion of the original mesh to the positive normal side of the plane

        plane_origin :  (3,) float
          Point on plane to intersect with mesh
        plane_normal : (3,) float
          Normal vector of 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

        Returns
        ---------
        new_mesh: trimesh.Trimesh or None
          Subset of current mesh that intersects the half plane
          to the positive normal side of the plane
        )rT   r  r  capr  cached_dotsr  )r   slice_mesh_plane)rc   r  r  r  r  r  rd   new_meshs           re   slice_planezTrimesh.slice_plane  sD    D !1 
%%!#
 
 
 
 rg   c                 $   ddl }|                    | j        | j                  \  }}}t	          | j        |         |t          ||          d          }t          j        r-t          j	        |j
        j        |          sJ t          j	        |j        |          sJ t          j	        |j        | j        |                   sJ |                    d          }t          j        d t                              |          D             t           	          }t          j	        ||          sJ t          j        d
 t                              |          D             t           	          }	t          j	        |	| j        |                   sJ |S )a)  
        Returns a Trimesh object equivalent to the current mesh where
        the vertices have been assigned uv texture coordinates. Vertices
        may be split into as many as necessary by the unwrapping
        algorithm, depending on how many uv maps they appear in.

        Requires `pip install xatlas`

        Parameters
        ------------
        image : None or PIL.Image
          Image to assign to the material

        Returns
        --------
        unwrapped : trimesh.Trimesh
          Mesh with unwrapped uv coordinates
        r   N)r  imageFr  obj)	file_typec                 p    g | ]3}|                     d           |dd                                         4S )zvt r   N
startswithr]  r  Ls     re   r  z"Trimesh.unwrap.<locals>.<listcomp>"	  s9    VVV1!,,uBUBUV122VVVrg   r   c                 p    g | ]3}|                     d           |dd                                         4S )zv r   Nr  r  s     re   r  z"Trimesh.unwrap.<locals>.<listcomp>'	  s9    UUU1!,,tBTBTU122UUUrg   )xatlasparametrizer@   rA   r?   r6   r"   strictr   r   rO   r  exportr   str
splitlinesr   )
rc   r  r  vmaprA   r  r-  r  uv_reconv_recons
             re   unwrapzTrimesh.unwrap  s   & 	 ,,T]DJGGeR]4(!Ru555	
 
 
 : 	= ;v}/44444;v|U33333;vd0CDDDDD ]]U]33FxVVv(>(>VVV  H ;x,,,,,hUUv(>(>UUU  G ;wd(;<<<<<rg   c                 *    t          j        |           S )z
        Returns a Trimesh object representing the convex hull of
        the current mesh.

        Returns
        --------
        convex : trimesh.Trimesh
          Mesh of convex hull of current mesh
        )r	   r  rx   s    re   r  zTrimesh.convex_hull.	  s     !$'''rg   r  r  face_weightc                 F    t          j        | ||          \  }}|r||fS |S )a  
        Return random samples distributed across the
        surface of the mesh

        Parameters
        ------------
        count : int
          Number of points to sample
        return_index : bool
          If True will also return the index of which face each
          sample was taken from.
        face_weight : None or len(mesh.faces) float
          Weight faces by a factor other than face area.
          If None will be the same as face_weight=mesh.area

        Returns
        ---------
        samples : (count, 3) float
          Points on surface of mesh
        face_index : (count, ) int
          Index of self.faces
        )rT   r  r  )r   sample_surface)rc   r  r  r  samplesr  s         re   r   zTrimesh.sample;	  s?    8  .U
 
 
  	"E>!rg   c                 N   t          j        t          | j                  t                    }d|| j        <   t          j        t          | j                  t                    }t          j        |                                          ||<   | 	                    ||           dS )ze
        Remove all vertices in the current mesh which are not
        referenced by a face.
        r   T)rt   r  N)
r   r   r   r@   r4  rA   r   rD  r1  rF  )rc   r5  r  s      re   remove_unreferenced_verticesz$Trimesh.remove_unreferenced_vertices^	  s    
 Xc$-00===
!%
4:(3t}--U;;; i
(8(899
*g>>>>>rg   c                 ,   t          j        t          | j                  dz  t                                        d          }|                     | j                            d                     || _        | j                            dg           dS )z
        Removes all face references so that every face contains
        three unique vertex indices and no faces are adjacent.
        r   r   r,  r   rB   ri   N)	r   rD  r   rA   r   r   rF  rW   rs   )rc   rA   s     re   unmerge_verticeszTrimesh.unmerge_verticesk	  s     	#dj//A-U;;;CCGLL 	TZ//33444
>"233333rg   r   c                    t          j        |dt                    }|j        dk    rt	          d          t          j        |t          j        d          d          r| S t          j	        | j
        |          }t          j        |dd	dd	f         t          j        d	          d
           }d| j        v r.| j        d         g}t          j	        ||          d         | _        |rDd| j        v r;t          j        t          j	        | j        |d                    | j        j        d<   |rDd| j        v r;t          j        t          j	        | j        |d                    | j        j        d<   |rXt          j        |          rDt'          j        d           t          j        t          j        | j                            | _        || _
        | j                            h d           | j                                         | S )a_  
        Transform mesh by a homogeneous transformation matrix.

        Does the bookkeeping to avoid recomputing things so this function
        should be used rather than directly modifying self.vertices
        if possible.

        Parameters
        ------------
        matrix : (4, 4) float
          Homogeneous transformation matrix
        r   r   )r   r   z%Transformation matrix must be (4, 4)!r   g:0yE>)r   Nr   gư>)atolr   r   rB   F)r   	translaterC   ztransform flips winding>   r  r*  r  r  r"  r  r2  rB   rb  rC   r  r.  r  ra  ru  ri   )r   r   r   r   rb   r   r   r   r   transform_pointsr@   rU   r   rW   unitizerB   r  rC   flips_windingr!   r   ascontiguousarrayfliplrrA   rs   id_set)rc   r   r  has_rotationr   s        re   apply_transformzTrimesh.apply_transform{	  s1    vS@@@ <6!!DEEE ]626!99d33 	K '7fUUU  =BQBNNNN DJ&&:m45K.?     D  	Ndk99040%f  1 1DKn-  	,;;26,0'%  3 3DK./  	EO9&AA 	EI/000 -bi
.C.CDDDJ % 	   	 	
 	
 	
( 	rg   r  c                 0    ddl m}  |j        d| ||d|S )a  
        Return a VoxelGrid object representing the current mesh
        discretized into voxels at the specified pitch

        Parameters
        ------------
        pitch : float
          The edge length of a single voxel
        method: implementation key. See `trimesh.voxel.creation.voxelizers`
        **kwargs: additional kwargs passed to the specified implementation.

        Returns
        ----------
        voxelized : VoxelGrid object
          Representing the current mesh
        r   )creation)rT   pitchmethodr  )voxelr/  voxelize)rc   r0  r1  rd   r/  s        re   	voxelizedzTrimesh.voxelized	  s8    " 	$##### x Qd%QQ&QQQrg   percent
face_count
aggressionc                    ddl m} |||d} |d| j                            t          j                  | j                            t          j                  dd |                                D             \  }}t          ||          S )a  
        A thin wrapper around `pip install fast-simplification`.

        Parameters
        -----------
        percent
          A number between 0.0 and 1.0 for how much
        face_count
          Target number of faces desired in the resulting mesh.
        agression
          An integer between `0` and `10`, the scale being roughly
          `0` is "slow and good" and `10` being "fast and bad."

        Returns
        ---------
        simple : trimesh.Trimesh
          Simplified version of mesh.
        r   )simplify)target_counttarget_reductionagg)pointsr   c                     i | ]
\  }}|||S Nr  )r  kvs      re   
<dictcomp>z7Trimesh.simplify_quadric_decimation.<locals>.<dictcomp>
  s    @@@1!-q!---rg   )r@   rA   r  )	fast_simplificationr9  r@   r   r   r   rA   rG  r?   )rc   r5  r6  r7  r9  rd   r@   rA   s           re   simplify_quadric_decimationz#Trimesh.simplify_quadric_decimation	  s    0 	100000 ' '
 
 #( 
=%%bj11joobj11
 
 A@@@@
 
% 6666rg   face_idsc           	      6    ddl m} t          di  || |fi |S )a  
        Given a list of face indexes find the outline of those
        faces and return it as a Path3D.

        The outline is defined here as every edge which is only
        included by a single triangle.

        Note that this implies a non-watertight mesh as the
        outline of a watertight mesh is an empty path.

        Parameters
        ------------
        face_ids : (n, ) int
          Indices to compute the outline of.
          If None, outline of full mesh will be computed.
        **kwargs: passed to Path3D constructor

        Returns
        ----------
        path : Path3D
          Curve in 3D of the outline
        r   )faces_to_pathr  )path.exchange.miscrG  r=   )rc   rE  rd   rG  s       re   outlinezTrimesh.outline
  s>    . 	655555@@dH????@@@rg   c                 j    ddl m} ddlm} ddlm}  |d| |d|}|
 |            S  ||          S )a  
        Project a mesh onto a plane and then extract the
        polygon that outlines the mesh projection on that
        plane.

        Parameters
        ----------
        mesh : trimesh.Trimesh
          Source geometry
        check : bool
          If True make sure is flat
        normal : (3,) float
          Normal to extract flat pattern along
        origin : None or (3,) float
          Origin of plane to project mesh onto
        pad : float
          Proportion to pad polygons by before unioning
          and then de-padding result by to avoid zero-width gaps.
        tol_dot : float
          Tolerance for discarding on-edge triangles.
        max_regions : int
          Raise an exception if the mesh has more than this
          number of disconnected regions to fail quickly before unioning.

        Returns
        ----------
        projected : trimesh.path.Path2D
          Outline of source mesh
        r   r  )r<   )	projected)rT   r  Nr  )r  r  r  r<   path.polygonsrK  )rc   r  rd   r  r<   rK  
projections          re   rK  zTrimesh.projected5
  sw    < 	-,,,,,      ,,,,,,YBDBB6BB
688Oy$$$rg   c                 8    | j                                         }|S )z
        Summed area of all triangles in the current mesh.

        Returns
        ---------
        area : float
          Surface area of mesh
        )r   r1  )rc   areas     re   rO  zTrimesh.area\
  s     ""$$rg   c                 6    t          j        | j                  S )z
        The area of each face in the mesh.

        Returns
        ---------
        area_faces : (n, ) float
          Area of each face
        )r   )r   rO  r   rx   s    re   r   zTrimesh.area_facesi
  s     ~d&:;;;;rg   c                     | j         j                            dd          }| j         j                            dd          }t          j        | j        | j        ||d          S )an  
        Returns the mass properties of the current mesh.

        Assumes uniform density, and result is probably garbage if mesh
        isn't watertight.

        Returns
        ----------
        properties : dict
          With keys:
          'volume'      : in global units^3
          'mass'        : From specified density
          'density'     : Included again for convenience (same as kwarg density)
          'inertia'     : Taken at the center of mass and aligned with global
                         coordinate system
          'center_mass' : Center of mass location, in global coordinate system
        r   Nr   F)r   r   r   r   skip_inertia)rU   r   getr   r   r   )rc   r   r   s      re   r   zTrimesh.mass_propertiesu
  sd    ( */%%i66jo))->>(n(#
 
 
 	
rg   c                 V   | j         5  d| j         v r| j         d         dz  | _        d| j         v r| j         d         dz  | _        t          j        t          j        | j                            | _        ddd           n# 1 swxY w Y   | j                             ddg           dS )a   
        Invert the mesh in-place by reversing the winding of every
        face and negating normals without dumping the cache.

        Alters `self.faces` by reversing columns, and negating
        `self.face_normals` and `self.vertex_normals`.
        rB   rY  rC   Nri   )rW   rB   rC   r   r)  r*  rA   rs   rx   s    re   invertzTrimesh.invert
  s     [ 	E 	E,,$(K$?$$F!4;..&*k2B&Cd&J#-bi
.C.CDDDJ	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	E 	>3C"DEEEEEs   A-BBBc                     t          | fi |S )z
        Returns a Scene object containing the current mesh.

        Returns
        ---------
        scene : trimesh.scene.scene.Scene
          Contains just the current mesh
        r'   r^  s     re   scenezTrimesh.scene
  s     T$$V$$$rg   c                 D    |                                  } |j        di |S )aH  
        Render the mesh in an opengl window. Requires pyglet.

        Parameters
        ------------
        smooth : bool
          Run smooth shading on mesh or not,
          large meshes will be slow

        Returns
        -----------
        scene : trimesh.scene.Scene
          Scene with current mesh in it
        r  )rW  show)rc   rd   rW  s      re   rY  zTrimesh.show
  s)     

uz##F###rg   faces_sequencec                 *    t          j        d| |d|S )a  
        Return a subset of the mesh.

        Parameters
        ------------
        faces_sequence : sequence (m, ) int
          Face indices of mesh
        only_watertight : bool
          Only return submeshes which are watertight
        append : bool
          Return a single mesh which has the faces appended.
          if this flag is set, only_watertight is ignored

        Returns
        ---------
        submesh : Trimesh or (n,) Trimesh
          Single mesh if `append` or list of submeshes
        )rT   rZ  r  )r   submesh)rc   rZ  rd   s      re   r\  zTrimesh.submesh
  s!    * |OnOOOOOrg   c                 *    t          j        |           S )z
        Return a float vector which is unique to the mesh
        and is robust to rotation and translation.

        Returns
        -----------
        identifier : (7,) float
          Identifying properties of the current mesh
        )r   identifier_simplerx   s    re   
identifierzTrimesh.identifier
  s     +D111rg   c                 4    t          j        | j                  S )z
        A hash of the rotation invariant identifier vector.

        Returns
        ---------
        hashed : str
          Hex string of the SHA256 hash from
          the identifier vector at hand-tuned sigfigs.
        )r   identifier_hashr_  rx   s    re   ra  zTrimesh.identifier_hash
  s     )$/:::rg   r	  c                 "    t          d| ||d|S )a  
        Export the current mesh to a file object.
        If file_obj is a filename, file will be written there.

        Supported formats are stl, off, ply, collada, json,
        dict, glb, dict64, msgpack.

        Parameters
        ------------
        file_obj : open writeable file object
          str, file name where to save the mesh
          None, return the export blob
        file_type : str
          Which file type to export as, if `file_name`
          is passed this is not required.
        )rT   file_objr	  r  r$   )rc   rc  r	  rd   s       re   r  zTrimesh.export
  s"    , Wx9WWPVWWWrg   c                 j    d| j                                         | j                                        dS )ae  
        Return a dictionary representation of the current mesh
        with keys that can be used as the kwargs for the
        Trimesh constructor and matches the schema in:
        `trimesh/resources/schema/primitive/trimesh.schema.json`

        Returns
        ----------
        result : dict
          Matches schema and Trimesh constructor.
        trimesh)rC  r@   rA   )r@   tolistrA   rx   s    re   to_dictzTrimesh.to_dict  s8     ,,..Z&&((
 
 	
rg   c                 :    d t          j        | fi |D             S )a  
        Compute an approximate convex decomposition of a mesh
        using `pip install pyVHACD`.

        Returns
        -------
        meshes
          List of convex meshes that approximate the original
        **kwargs : VHACD keyword arguments
        c                 &    g | ]}t          d i |S )r  )r?   )r  rd   s     re   r  z0Trimesh.convex_decomposition.<locals>.<listcomp>(  s6     
 
 
 f
 
 
rg   )r   convex_decompositionr^  s     re   rj  zTrimesh.convex_decomposition  s6    
 
'<TLLVLL
 
 
 	
rg   enginecheck_volumec                 0    t          j        d| |g||d|S )a  
        Boolean union between this mesh and other meshes.

        Parameters
        ------------
        other : Trimesh or (n, ) Trimesh
          Other meshes to union
        engine
          Which backend to use, the default
          recommendation is: `pip install manifold3d`.
        check_volume
          Raise an error if not all meshes are watertight
          positive volumes. Advanced users may want to ignore
          this check as it is expensive.
        kwargs
          Passed through to the `engine`.

        Returns
        ---------
        union : trimesh.Trimesh
          Union of self and other Trimesh objects
        meshesrk  rl  r  )r   unionrc   r  rk  rl  rd   s        re   rp  zTrimesh.union-  s9    < } 
%=%
 
 	
 
 	
rg   c                 0    t          j        d| |g||d|S )a  
         Boolean difference between this mesh and n other meshes

         Parameters
         ------------
         other : trimesh.Trimesh, or list of trimesh.Trimesh objects
           Meshes to difference
         engine
           Which backend to use, the default
           recommendation is: `pip install manifold3d`.
        check_volume
           Raise an error if not all meshes are watertight
           positive volumes. Advanced users may want to ignore
           this check as it is expensive.
         kwargs
           Passed through to the `engine`.

         Returns
         ---------
         difference : trimesh.Trimesh
           Difference between self and other Trimesh objects
        rn  r  )r   
differencerq  s        re   rs  zTrimesh.differenceR  s6    : ! 
%=l
 
NT
 
 	
rg   c                 0    t          j        d| |g||d|S )a  
         Boolean intersection between this mesh and other meshes.

         Parameters
         ------------
         other : trimesh.Trimesh, or list of trimesh.Trimesh objects
           Meshes to calculate intersections with
         engine
           Which backend to use, the default
           recommendation is: `pip install manifold3d`.
        check_volume
           Raise an error if not all meshes are watertight
           positive volumes. Advanced users may want to ignore
           this check as it is expensive.
         kwargs
           Passed through to the `engine`.

         Returns
         ---------
         intersection : trimesh.Trimesh
           Mesh of the volume contained by all passed meshes
        rn  r  )r   intersectionrq  s        re   ru  zTrimesh.intersections  s:    : # 
%=%
 
 	
 
 	
rg   r=  c                 6    | j                             |          S )a  
        Given an array of points determine whether or not they
        are inside the mesh. This raises an error if called on a
        non-watertight mesh.

        Parameters
        ------------
        points : (n, 3) float
          Points in cartesian space

        Returns
        ---------
        contains : (n, ) bool
          Whether or not each point is inside the mesh
        )r   contains_points)rc   r=  s     re   containszTrimesh.contains  s      x''///rg   c                 4    t          j        | j                   S )z
        Returns the angle at each vertex of a face.

        Returns
        --------
        angles : (len(self.faces), 3) float
          Angle at each vertex of a face
        )r   rl  rx   s    re   r   zTrimesh.face_angles  s     ///rg   c                 .    t          j        |           }|S )z
        A sparse matrix representation of the face angles.

        Returns
        ----------
        sparse : scipy.sparse.coo_matrix
          Float sparse matrix with with shape:
          (len(self.vertices), len(self.faces))
        )r
   face_angles_sparse)rc   rl  s     re   r{  zTrimesh.face_angles_sparse  s     -d33rg   c                 .    t          j        |           }|S )a  
        Return the vertex defects, or (2*pi) minus the sum of the angles
        of every face that includes that vertex.

        If a vertex is only included by coplanar triangles, this
        will be zero. For convex regions this is positive, and
        concave negative.

        Returns
        --------
        vertex_defect : (len(self.vertices), ) float
          Vertex defect at the every vertex
        )r
   vertex_defects)rc   defectss     re   r}  zTrimesh.vertex_defects  s     *400rg   c                     t          j        | j                            d                                                    }|S )z
        Return the number of faces each vertex is included in.

        Returns
        ----------
        degree : (len(self.vertices), ) int
          Number of faces each vertex is included in
        r   r   )r   r   r   r1  flatten)rc   degrees     re   vertex_degreezTrimesh.vertex_degree  s8     $+//Q/7788@@BBrg   c                     t          j        t          j        | j        | j                                     d          | j        | j                                     d          f                    S )z
        An R-tree of face adjacencies.

        Returns
        --------
        tree
          Where each edge in self.face_adjacency has a
          rectangular cell
        r   r   )r   r   r   column_stackr@   ra  r   r   rx   s    re   face_adjacency_treezTrimesh.face_adjacency_tree  si     OM$";<@@a@HHM$";<@@a@HH 
 
 	
rg   include_cacheinclude_visualc                 v   t                      }t          j        | j        j                  |j        _        |r| j                                        |_        t          j        | j                  |_        |j                                         |r)|j        j	        
                    | j        j	                   |S )a  
        Safely return a copy of the current mesh.

        By default, copied meshes will have emptied cache
        to avoid memory issues and so may be slow on initial
        operations until caches are regenerated.

        Current object will *never* have its cache cleared.

        Parameters
        ------------
        include_cache : bool
          If True, will shallow copy cached data to new mesh

        Returns
        ---------
        copied : trimesh.Trimesh
          Copy of current mesh
        )r?   r  deepcopyrU   r   rO   rH   rW   verifyr  rX   )rc   r  r  copieds       re   r  zTrimesh.copy  s    *  M$*/:: 	/ K,,..FM -66 	 	: M&&t{'8999rg   c                 .    |                      d          S )NFr  r  rc   argss     re   __deepcopy__zTrimesh.__deepcopy__%  s    yyuy---rg   c                 .    |                      d          S )NTr  r  r  s     re   __copy__zTrimesh.__copy__)  s    yyty,,,rg   	statementc                     t          |          g}|                    d |D                        dt          t          |                     }|| j        v r| j        |         S t	          |          }|| j        |<   |S )a  
        Evaluate a statement and cache the result before returning.

        Statements are evaluated inside the Trimesh object, and

        Parameters
        ------------
        statement : str
          Statement of valid python code
        *args : list
          Available inside statement as args[0], etc

        Returns
        -----------
        result : result of running eval on statement with args

        Examples
        -----------
        r = mesh.eval_cached('np.dot(self.vertices, args[0])', [0, 0, 1])
        c              3   4   K   | ]}t          |          V  d S r?  )r  )r  as     re   	<genexpr>z&Trimesh.eval_cached.<locals>.<genexpr>E  s(      ..AQ......rg   eval_cached_)r  extendtuplerW   eval)rc   r  r  hashablerJ  r-  s         re   eval_cachedzTrimesh.eval_cached-  s    . OO$........4T%//2244$+;s##i!Crg   c                 0    t          j        | |          }|S )a#  
        Concatenate the mesh with another mesh.

        Parameters
        ------------
        other : trimesh.Trimesh object
          Mesh to be concatenated with self

        Returns
        ----------
        concat : trimesh.Trimesh
          Mesh object of combined result
        )r   concatenate)rc   r  concats      re   __add__zTrimesh.__add__P  s     !$..rg   )NNNNNNNNNTFNNTNN)FNN)F)NNNNNr?  )rP   N)Nr  r   r  )r  F)rP   r?   )FN)r  )NNN)NN)NT)FT)r  r?   rP   r?   )__name__
__module____qualname__r2   r+   r,   r  r*   r4  r   r4   r5   r6   rf   rI   propertyrw   setterr   rA   r    r8   r   r0   r   rB   r@   rC   r   r   r   r   r   r   r   r   r1   r   r   r   r   r   r   r   r   r   r   r   r;   r   r   r   r  r  r  r  r  r  r9   r  r"  r0  r*  r.  r2  r   bool_r   r:  r.   rr   rF  ro   rq   rm   rW  r[  r/   r]  rb  re  ra  rh  rm  rq  rs  ru  ry  rx  r  r:   r  r  r  r  r  rl   r  r  r"   r   r  rn   r  r  r  r  r  r  rp   r  r&   r  r  r  r  r  r  r  rO   r=   r   r<   r  r  r  r  r   r   r"  r-  r4  r-   rD  rI  rK  rO  r   r)   r   rU  r(   rW  rY  r3   r\  r_  ra  r  rg  rj  rp  rs  ru  rx  r   r{  r}  r  r  r  r  r  r  r  r  rg   re   r?   r?   S   s        )-%),0.2+/-1:><@-1$(%)6:@D#FX FX9%FX 	"FX y)	FX
 !+FX i(FX  	*FX "$sI~"67FX $Di$89FX 4S>*FX FX FX D>FX TNFX FX   S'\ 23!FX" |^;<=#FX& 
'FX FX FX FXT $(%)	5 55 D>5 TN	5
 
5 5 5 5n 	" 	" 	" 	" X	" ^	#T 	#d 	# 	# 	# ^	# #| # # # X#  \%HY/ %D % % % \%, Uj U U U _U 1gg. 1 1 1 X1f %-8I#6 %-4 %- %- %- %-N &, & & & X&" _Qx	2 Q Q Q _Q 
 0 
 
 
 _
0 7Y 74 7 7 7 7" gen    _$ D!12 D D D _D$ ''"23    _$ ''*    _. 	0WW- 	0 	0 	0 X	0 . .t . . . . 	3 	3 	3 	3 X	3 ^.V . . . . ^. + + + + X+ 
)g 
) 
) 
) X
) , 0 , , , X,"$
i $
GG<L $
 $
 $
 $
L gg.>    _$ 877+; 8 8 8 X8 WW-=    _0 (3-    _ ,x(89 , , , X, /(77+;"< / / / X/ :77+ : : : _: 	5 	5 	5 	5 _	5 	+''"2 	+ 	+ 	+ _	+ 
!1 
 
 
 _
 wu~    _ 
)GEN 
) 
) 
) _
) gen    _" WW%5    _ 3gen 3 3 3 _3  
gen 
 
 
 _
 
*7 
* 
* 
* _
* j    _ C    _$ GEN    _B 
c 
 
 
 _
 WRX%6    _ S  )    " %)%)+/)-'+$
 $
D>$
 TN$
  (	$

 g&$
 G$$
 
$
 $
 $
 $
R (,B BB )$B 
	B B B BH25 25t 25 25 25 25h. . . ."gbh/    / / / /6 6 6 6+i + + + +& % % % % _%N 	-75> 	- 	- 	- _	- 3gen 3 3 3 _3 
27 
2 
2 
2 _
2 ww'7    _  GG,<    _ ;wrx'8 ; ; ; _; 
3 
3 
3 
3 _
3 
ww'7 
 
 
 _
 2WW%5 2 2 2 _2 G G G G _G 7 7 7 7 _70 V$tE{"3 V V V _V, 4t 4 4 4 _4" t    _$ 4    _* 	%$ 	% 	% 	% X	% 4    _ 
7 
7 
7 
7 _
7 7:i C Ce CD C C C C 36) 
 
% 
@Q 
 
 
 
8 
WU^, 
 
 
 _
 WW-    _$ ww/    _2 
,ww/ 
, 
, 
, _
, gen!5    _   1    _@6 6Xd^ 6t 6 6 6 6&	'D 	' 	' 	' 	'#eJ$78 # # # #> 376
 6
gg./6
 6
 	6

 6
 6
 6
 6
p5 5HY$7 59 5 5 5 5n? ? ? ?B   ." " "   X:   X ]  ])%)5>)	&	) ) ) )V++  + 	+
 
hv	+ + + +b , , , ,\3 3 3 3j 
( 
( 
( _
( #26	! !! ! gg./	! ! ! !F? ? ? ?4 4 4 4 [i [I [ [ [ [zR R R R. '+(,(,	+7 +7(#+7 W%+7 W%	+7
 
+7 +7 +7 +7ZA A 8 Af A A A A6%%V %% %% %% %%N 
g 
 
 
 _
 	<GG, 	< 	< 	< _	< 
 
 
 
 _
:F F F F$	% 	% 	% 	% 	%$ $ $$P&y1P	y$y/)	*P P P P. 
2GG, 
2 
2 
2 _
2 
; 
; 
; 
; _
; #'X X C=X X X X0
c5d4;.?d3i)P#QQR 
 
 
 
$
Y 
 
 
 
& !%!	#
 #
#
 #
 	#
 
#
 #
 #
 #
P !%!	
 

 
 	
 

 
 
 
H !%!	"
 "
"
 "
 	"
 
"
 "
 "
 "
H0y 0WRX-> 0 0 0 0$ 	0WW- 	0 	0 	0 _	0 J    _  0    _" wu~    _ 
U 
 
 
 _
(+ +$ + +PY + + + +Z. . . .- - - -!S ! ! ! !F     rg   r?   )N__doc__r  rT  numpyr   r   r   r    r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   cachingr   r   r   r    	constantsr!   r"   
exceptionsr#   exchange.exportr%   parentr&   rW  r(   r)   typedr*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   rO   r5   r6   r7   scipy.sparser8   scipy.spatialr9   r   Enetworkxr:   rtree.indexr;   r  r<   r=   r?   r  rg   re   <module>r     s;          ) ) ) ) ) ) ) ) ) )                                               0 E D D D D D D D D D D D         ( ( ( ( ( ( ( ( ( ( ( (             % % % % % %                          @ ? ? ? ? ? ? ? ? ?%''''''%%%%%%% % % %q!!G!!!$$JJJJJJ%       QEEEEEE  !!!!!!!      QEEEEEE !$$$$$$$$$ ! ! !a  Fa  FFFFFF!
L0 L0 L0 L0 L0j L0 L0 L0 L0 L0s`    B- -C2CCC C7"C22C7;D DDD D) )E.E		E