
    j                     X   d dl Z d dlZd dlZd dlmZ d dlmZ d dlZddl	m
Z
mZmZmZmZmZmZ ddlmZ ddlmZ ddlmZmZ dd	l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( ddlm)Z) ddl	m*Z*m+Z+ ddl,m-Z- e%eee   ee.ef   ef   Z/ G d de      Z0d Z1ddZ2dde0dede0fdZ3y)    N)deepcopy)sha256   )cachingconvexgroupinginertiatransformationsunitsutil)log)export)Geometry
Geometry3D)
procrustes)	ArrayLikeDictFloatingIntegerIterableListNDArrayOptionalSequenceTupleUnion
ViewerTypefloat64int64)unique_name   )cameraslighting)
SceneGraphc                      e Zd ZdZ	 	 	 	 	 	 	 dNdee   dedee   dee   dee	j                     deeej                        d	ee   fd
Zd Z	 	 	 	 	 dOdedee   dee   dee   dee   dee   fdZdeeeef   ddfdZdPdZ	 	 	 dQdee   dee   dee   ddfdZdefdZedefd       Zedefd       Zej@                  deeee!   f   fd       Z"ej@                  deee!      fd       Z#ej@                  deee!      fd       Z$ej@                  de%fd       Z&ej@                  deee!      fd        Z'ej@                  defd!       Z(ej@                  d"        Z)d# Z*ej@                  de%fd$       Z+ej@                  de!fd%       Z,ej@                  dee!   fd&       Z-ej@                  d'        Z.ej@                  deeef   fd(       Z/ej@                  defd)       Z0ej@                  de1e1e      fd*       Z2dRd+edd fd,Z3	 dOde	j                  fd-Z4ed.        Z5e5jl                  d/e7fd0       Z5de8ee!   ee!   ee9   f   fd1Z:ede	j                  fd2       Z;e;jl                  dee	j                     fd3       Z;edefd4       Z<ede1ej                     fd5       Z=e=jl                  deej                     fd6       Z=dPd7Z>dSd8ede1e?   fd9Z@dTd:ZAde?fd;ZBd<edd fd=ZCej@                  d>        ZDdUd?ZEdVdeFfd@ZGedee   fdA       ZHeHjl                  dBefdC       ZHdSdDedEedd fdFZIdUdPdGZJdHeee7f   dd fdIZKdWdJZL	 dVdKeMfdLZNdM ZOy)XScenez
    A simple scene graph which can be rendered directly via
    pyglet/openGL or through other endpoints such as a
    raytracer. Meshes are added by name, which can then be
    moved by updating transform in the transform tree.
    Ngeometry
base_framemetadatagraphcameralightscamera_transformc                 x   t        j                         | _        t        |      | _        t        j                  | j                        | _        || j                  |       i | _
        t        |t              r| j                  j                  |       ||| _        ||| _        ||| _        ||| _        yyy)aX  
        Create a new Scene object.

        Parameters
        -------------
        geometry : Trimesh, Path2D, Path3D PointCloud or list
          Geometry to initially add to the scene
        base_frame
          Name of base frame
        metadata
          Any metadata about the scene
        graph
          A passed transform graph to use
        camera : Camera or None
          A passed camera to use
        lights : [trimesh.scene.lighting.Light] or None
          A passed lights to use
        camera_transform
          Homogeneous (4, 4) camera transform in the base frame
        r(   )id_functionN)collectionsOrderedDictr'   r$   r*   r   Cache__hash___cacheadd_geometryr)   
isinstancedictupdater,   r+   r-   )selfr'   r(   r)   r*   r+   r,   r-   s           @/DATA/.local/lib/python3.12/site-packages/trimesh/scene/scene.py__init__zScene.__init__/   s    > $//1  :6
 mm>h' h%MM  *DJ DK DK+(8% ,     c                 
   | j                   j                  }| j                   j                  j                  |   D ]F  }t	        j
                  || j                   |   d         }| j                   j                  |||       H | S )z
        Apply a transform to all children of the base frame
        without modifying any geometry.

        Parameters
        --------------
        transform : (4, 4)
          Homogeneous transformation matrix.
        r   
frame_fromframe_tomatrix)r*   r(   
transformschildrennpdotr9   )r:   	transformbasechildcombineds        r;   apply_transformzScene.apply_transformj   sp     zz$$ZZ**33D9EvviE):1)=>HJJhO : r=   	node_name	geom_nameparent_node_namerG   c                 X   |yt        j                  |      r%|D cg c]  }| j                  ||||||       c}S t        |t              r6|j                         D 	ci c]  \  }}	|| j                  |	||       c}	}S t        |t              rj| |z   }
| j                  j                          | j                  j                  |
j                         |
j                  j                  | j                  _        y||}nld|j                  v r|j                  d   }nN|j                  j                  |j                  j                  }n!dt        t!        | j                              z   }t#        || j                  j%                               }|| j                  |<   |@| j                  j                  j&                  j%                         }t#        ||      }||vsJ |t)        j*                  d      }| j                  j                  ||||dd	i|
       |S c c}w c c}	}w )a  
        Add a geometry to the scene.

        If the mesh has multiple transforms defined in its
        metadata, they will all be copied into the
        TransformForest of the current scene automatically.

        Parameters
        ----------
        geometry : Trimesh, Path2D, Path3D PointCloud or list
          Geometry to initially add to the scene
        node_name : None or str
          Name of the added node.
        geom_name : None or str
          Name of the added geometry.
        parent_node_name : None or str
          Name of the parent node in the graph.
        transform : None or (4, 4) float
          Transform that applies to the added node.
        metadata : None or dict
          Optional metadata for the node.

        Returns
        ----------
        node_name : str
          Name of single node in self.graph (passed in) or None if
          node was not added (eg. geometry was null or a Scene).
        N)r'   rL   rM   rN   rG   r)   )r'   rM   r)   name	geometry_startcontains   visibleT)rA   r@   rB   r'   geometry_flagsr)   )r   is_sequencer6   r7   r8   itemsr&   r'   clearr9   r*   rC   r)   source	file_namestrlenr    keys	node_datarE   eye)r:   r'   rL   rM   rN   rG   r)   valuekvconcatrP   existings                r;   r6   zScene.add_geometryz   s-   L h' &
 &E !!"''%5'% "  &
 
 $' %NN,,DAq 4$$a1x$PP, 
 %(H_FMM!MM  1$*LL$;$;DJJ!  Dx((($$V,D__&&2??,,D S%7!88D 0B0B0DE&d  zz,,66;;=H $D(3IH,,,q	I

'%t, 	 	
 K
s   H!!H&namesreturnc                     t        |t              r|g}t        |      }| j                  j	                  |       |D cg c]  }| j
                  j                  |d        c} yc c}w )a  
        Delete one more multiple geometries from the scene and also
        remove any node in the transform graph which references it.

        Parameters
        --------------
        name : hashable
          Name that references self.geometry
        N)r7   r]   setr*   remove_geometriesr'   pop)r:   rg   rP   s      r;   delete_geometryzScene.delete_geometry   sX     eS!GEE
 	

$$U+38954		4	&599s   #A%c                     ddl m} | j                  j                         D ]'  }t	        j
                  |d      s ||      |_        ) y)zl
        Strip visuals from every Trimesh geometry
        and set them to an empty `ColorVisuals`.
        r   )ColorVisualsTrimesh)meshN)visual.colorro   r'   valuesr   is_instance_namedvisual)r:   ro   r'   s      r;   strip_visualszScene.strip_visuals   s:    
 	0,,.H%%h	:".H"= /r=   percent
face_count
aggressionc                     i }| j                   j                         D ])  \  }}t        |d      s|j                  |||      ||<   + | j                   j	                  |       y)a  
        Apply in-place `mesh.simplify_quadric_decimation` to any meshes
        in the scene.

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

        simplify_quadric_decimation)rw   rx   ry   N)r'   rY   hasattrr{   r9   )r:   rw   rx   ry   updatesrc   rd   s          r;   r{   z!Scene.simplify_quadric_decimation  sc    , MM'')DAqq78::#
z ; 
 *
 	W%r=   c                 .   | j                   t        | j                  j                  j	                               g}|j                  fdj                         D               t        j                  dj                  |      j                  d            S )z
        Return information about scene which is hashable.

        Returns
        ---------
        hashed
          String hashing scene.
        c              3   V   K   | ]   }t        |   j                                " y wN)hexr4   ).0rc   r'   s     r;   	<genexpr>z!Scene.__hash__.<locals>.<genexpr>8  s$     M_HQK0023_s   &) zutf-8)r'   r   r*   rC   r4   extendr_   r   	hash_fastjoinencode)r:   hashabler'   s     @r;   r4   zScene.__hash__)  sm     == 

--6689:MX]]_MM  !2!9!9'!BCCr=   c                 2    t        | j                        dk(  S )z
        Does the scene have anything in it.

        Returns
        ----------
        is_empty
          True if nothing is in the scene
        r   )r^   r'   r:   s    r;   is_emptyzScene.is_empty;  s     4==!Q&&r=   c                    t        | j                        dk(  ry	 | j                  j                  D ch c]  }| j                  |   d    }}|t        | j                  j                               k(  S c c}w # t        $ r Y yw xY w)z
        Is every geometry connected to the root node.

        Returns
        -----------
        is_valid : bool
          Does every geometry have a transform
        r   Tr!   F)r^   r'   r*   nodes_geometryBaseExceptionrj   r_   )r:   i
referenceds      r;   is_validzScene.is_validH  s     t}}"	48JJ4M4MN4Mq$**Q-*4MJN S!3!3!5666 O 		s"   A9 A4A9 4A9 9	BBc                 P   i }| j                   j                         D ci c]B  \  }}|t        |d      r$t        |j                        dkD  r|j                  n|j
                  D }}}|j                  |j                         D ci c]M  \  }}|F|j                  d   dk(  r4|t        j                  |t        j                  t        |            f      O c}}       | j                  j                  D ]  }| j                  |   \  }}|j                  |      }	|	)t        j                  |ddddf   |	j                        }
t        j                   |
j#                  d      |dddf   z   |
j%                  d      |dddf   z   g      ||<    |S c c}}w c c}}w )z
        Get the post-transform AABB for each node
        which has geometry defined.

        Returns
        -----------
        corners
          Bounds for each node with vertices:
           {node_name : (2, 3) float}
        verticesr   Nr!   r      axis)r'   rY   r|   r^   r   boundsr9   shaperE   column_stackzerosr*   r   getrF   Tarrayminmax)r:   cornersrc   mr   rd   rL   rG   geometry_namepointsrF   s              r;   bounds_cornerszScene.bounds_corners^  s     ++-
-1 WQ
3AJJ!8KqzzQRQYQYY- 	 

 	 %NN,,DAq=QWWQZ1_ 2??ArxxA'7#899,	
 22I'+zz)'<$I}\\-0F~&&2A2rr6*FHH5C!#a9RaRU#33SWW!W_yQSRSQSUVQVGW5WX"GI 3 9
s   AFAF"
c                 2   | j                   }t        |      dk(  ryt        j                  t	        | j                   j                                     }t        j                  |j                  d      |j                  d      gt        j                        S )z
        Return the overall bounding box of the scene.

        Returns
        --------
        bounds : (2, 3) float or None
          Position of [min, max] bounding box
          Returns None if no valid bounds exist
        r   Nr   dtype)
r   r^   rE   vstacklistrs   r   r   r   r   )r:   r   r   s      r;   r   zScene.bounds  sq     ,,~!#))D!4!4!;!;!=>?xx!,gkkqk.AB"**UUr=   c                 l    | j                   }|yt        j                  |d      j                  d      S )z
        Return the axis aligned box size of the current scene
        or None if the scene is empty.

        Returns
        ----------
        extents
          Bounding box sides length or None for empty scene.
        Nr   r   )r   rE   diffreshape)r:   r   s     r;   extentszScene.extents  s1     >wwvA&..r22r=   c                 ^    | j                   }|yt        |dz  j                         dz        S )z
        The approximate scale of the mesh

        Returns
        -----------
        scale : float
          The mean of the bounding box edge lengths
              ?r   g      ?)r   floatsum)r:   r   s     r;   scalezScene.scale  s2     ,,?gqj%%'3.//r=   c                 f    | j                   }|yt        j                  | j                   d      }|S )z
        Return the center of the bounding box for the scene.

        Returns
        --------
        centroid : (3) float
          Point for center of bounding box
        Nr   r   )r   rE   mean)r:   r   centroids      r;   r   zScene.centroid  s.     >774;;Q/r=   c                 R   | j                   j                         D ci c]  \  }}t        |d      r||j                    }}}| j                   j                         D ci c]  \  }}t        |d      s||j                  ! }}}| j
                  }|j                  D cg c]  }||   	 }}t        j                  |D 	cg c]9  \  }}	|	|v r0t        j                  |t        j                  ||	   d            dd ; c}	}t        j                        }
t        j                  |D 	cg c]
  \  }}	||	    c}	}t        j                        }||j                         z  }|
|j                  d      z  j                  d	      S c c}}w c c}}w c c}w c c}	}w c c}	}w )
z
        Find the center of mass for every instance in the scene.

        Returns
        ------------
        center_mass : (3,) float
          The center of mass of the scene
        center_massmassr!   Nr   r   )r   r!   r   r   )r'   rY   r|   r   r   r*   r   rE   r   rF   appendr   r   r   )r:   rc   r   r   r   r*   ninstancematgtransformed_weightss                r;   r   zScene.center_mass  s    ++-
-1q-( q}}- 	 

 '+mm&9&9&;R&;dawq&?Q166	&;R 

&+&:&:;&:E!H&:; hh '&FC# sBIIk!na89"1=&
 **
 ((91DG9L7;;= goog66;;;CC/

 S < :s#   #F!F6F"F>F
.F#
c                 j    t        j                  | t        j                  | j                              S )a  
        Return the moment of inertia of the current scene with
        respect to the center of mass of the current scene.

        Returns
        ------------
        inertia : (3, 3) float
          Inertia with respect to cartesian axis at `scene.center_mass`
        scenerG   )r	   scene_inertiar
   translation_matrixr   r   s    r;   moment_inertiazScene.moment_inertia  s-     $$/"D"DTEUEU"V
 	
r=   c                 0    t        j                  | |      S )aM  
        Return the moment of inertia of the current scene relative
        to a transform from the base frame.

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

        Returns
        -------------
        inertia : (3, 3) float
          Inertia tensor at requested frame.
        r   )r	   r   )r:   rG   s     r;   moment_inertia_framezScene.moment_inertia_frame  s     $$49EEr=   c                       j                   j                         D ci c]  \  }}t        |d      s||j                  ! c}}t	         fd j
                  j                  D        d      S c c}}w )z
        What is the summed area of every geometry which
        has area.

        Returns
        ------------
        area : float
          Summed area of every instanced geometry
        areac              3   b   K   | ]&  }j                  j                  |   d    d       ( ywr!           Nr   r*   )r   r   areasr:   s     r;   r   zScene.area.<locals>.<genexpr>  s,     Q7P!UYYtzz!}Q'-7P   ,/r   )r'   rY   r|   r   r   r*   r   )r:   r   r   r   s   `  @r;   r   z
Scene.area  se     (,}}':':'<S'<tq!6@RAFF'<SQtzz7P7PQSV
 	
 T
   A2A2c                       j                   j                         D ci c]  \  }}t        |d      s||j                  ! c}}t	         fd j
                  j                  D        d      S c c}}w )z
        What is the summed volume of every geometry which
        has volume

        Returns
        ------------
        volume : float
          Summed area of every instanced geometry
        r   c              3   b   K   | ]&  }j                  j                  |   d    d       ( ywr   r   )r   r   r:   volumes     r;   r   zScene.volume.<locals>.<genexpr>0  s,     R8Q1VZZ

1a(#.8Qr   r   )r'   rY   r|   r   r   r*   r   )r:   r   r   r   s   `  @r;   r   zScene.volume!  se     +/--*=*=*?V*?$!Q71fCU!QXX+*?VR

8Q8QRTW
 	
 Wr   c           	      2   g }g }| j                   j                  D ]  }| j                   |   \  }}| j                  |   }t        |d      s1|j	                  t        j                  |j                  j                         j                  d      |             |j	                  t        j                  |t        |j                                      t        j                  |      | j                  d<   t        j                  |      j                  d      S )z
        Return a correctly transformed polygon soup of the
        current scene.

        Returns
        ----------
        triangles : (n, 3, 3) float
          Triangles in space
        	triangles)r   r   )rB   triangles_node)r   r   r   )r*   r   r'   r|   r   r
   transform_pointsr   copyr   rE   tiler^   hstackr5   r   )r:   r   r   rL   rG   r   r'   s          r;   r   zScene.triangles3  s     	22I'+zz)'<$I} }}]3H8[100&&++-55g>y !!"'')S9K9K5L"MN 3" )+		.(A$%yy#++J77r=   c                 8    | j                   }| j                  d   S )z
        Which node of self.graph does each triangle come from.

        Returns
        ---------
        triangles_index : (len(self.triangles),)
          Node name for each triangle
        r   )r   r5   )r:   populates     r;   r   zScene.triangles_nodeT  s     >>{{+,,r=   c                 ~    | j                   j                         D ci c]  \  }}|j                  | c}}S c c}}w )z
        Look up geometries by identifier hash.

        Returns
        ---------
        identifiers
          {Identifier hash: key in self.geometry}
        )r'   rY   identifier_hash)r:   rP   rq   s      r;   geometry_identifierszScene.geometry_identifiersa  s;     >B]]=P=P=RS=RztT$$d*=RSSSs   9c                     dj                  d | j                  j                         D              t        t	        | j
                              z   }t        |j                               j                         S )z8
        Get a unique identifier for the scene.
        r   c              3   4   K   | ]  }|j                     y wr   )r   r   r   s     r;   r   z(Scene.identifier_hash.<locals>.<genexpr>r  s     I2HQq((2Hs   )	r   r'   rs   r]   hashr*   r   r   	hexdigest)r:   dumps     r;   r   zScene.identifier_hashm  sZ    
 wwI$--2F2F2HIICM
 
 dkkm$..00r=   c           	      :   t        | j                        dk(  rg S | j                  j                         D ci c](  \  }}t        |d      r|t	        |j
                  d      * }}}| j                  }|j                  D ci c]  }||j                  ||   d          }}t        j                  t              }|j                         D cg c]  \  }}|||   j                  |       c}} t        |j                               S c c}}w c c}w c c}}w )a@  
        Return a sequence of node keys of identical meshes.

        Will include meshes with different geometry but identical
        spatial hashes as well as meshes repeated by self.nodes.

        Returns
        -----------
        duplicates
          Keys of self.graph that represent identical geometry
        r   r      r!   )r^   r'   rY   r|   intr   r*   r   r   r1   defaultdictr   r   rs   )	r:   rc   r   hashesr*   node	node_hash
duplicateshasheds	            r;   duplicate_nodeszScene.duplicate_nodesw  s!    t}}"I
 ++-
-1q+, s1$$b))- 	 
 

 CHBVBVWBV$T6::eDk!n55BV	W !,,T2

 !* 1	
 1f! v%%d+ 1	
 J%%'((/
 X	
s   -DD Dcost_thresholdc                     t        | |      S )a  
        If a scene has been "baked" with meshes it means that
        the duplicate nodes have *corresponding vertices* but are
        rigidly transformed to different places.

        This means the problem of finding ab instance transform can
        use the `procrustes` analysis which is *very* fast relative
        to more complicated registration problems that require ICP
        and nearest-point-on-surface calculations.

        TODO : construct a parent non-geometry node for containing every group.

        Parameters
        ----------
        scene
        The scene to handle.
        cost_threshold
        The maximum value for `procrustes` cost which is "squared mean
        vertex distance between pair". If the fit is above this value
        the instance will be left even if it is a duplicate.

        Returns
        ---------
        dedupe
        A copy of the scene de-duplicated as much as possible.
        )r   )reconstruct_instances)r:   r   s     r;   r   zScene.reconstruct_instances  s    6 %T.IIr=   c                    |t        j                  ddg      }t        | j                        dk(  r]t	        j
                  |      | _        t        j                  d      | j                  | j                  j                  <   | j                  S |t        j                  d      }t        j                  | }t	        j                  | j                  ||||      }t        | d      r1| j                  %|| j                  _        |.|| j                  _        nt	        j
                  ||	      | _        || j                  | j                  j                  <   | j                  S )
a  
        Create a camera object for self.camera, and add
        a transform to self.graph for it.

        If arguments are not passed sane defaults will be figured
        out which show the mesh roughly centered.

        Parameters
        -----------
        angles : (3,) float
          Initial euler angles in radians
        distance : float
          Distance from centroid
        center : (3,) float
          Point camera should be center on
        camera : Camera object
          Object that stores camera parameters
        <   -   r   )fovrU   r   )r   rotationdistancecenter_camera)r   
resolution)rE   r   r^   r'   r"   Camerar   ra   r*   rP   r   r
   euler_matrixlook_atr   r|   r   r   )r:   anglesr   r   r   r   r   rG   s           r;   
set_camerazScene.set_camera  s   , ;((B8$C t}}"">>c2DL,.FF1IDJJt||(()<<>XXa[F"//8OOKKS8hv
	 4#(@"DLL%*4' #>>cjIDL(1

4<<$$%||r=   c                 N    | j                   | j                  j                     d   S )z
        Get camera transform in the base frame.

        Returns
        -------
        camera_transform : (4, 4) float
          Camera transform in the base frame
        r   r*   r+   rP   r   s    r;   r-   zScene.camera_transform  s"     zz$++**+A..r=   rB   c                 J    || j                   | j                  j                  <   y)z
        Set the camera transform in the base frame

        Parameters
        ----------
        camera_transform : (4, 4) float
          Camera transform in the base frame
        Nr  )r:   rB   s     r;   r-   zScene.camera_transform  s     (.

4;;##$r=   c                     | j                   j                         \  }}| j                  }t        j                  ||d      }t        j                  |      t        j                  |      z  }|||fS )a  
        Calculate the trimesh.scene.Camera origin and ray
        direction vectors. Returns one ray per pixel as set
        in camera.resolution

        Returns
        --------------
        origin: (n, 3) float
          Ray origins in space
        vectors: (n, 3) float
          Ray direction unit vectors in world coordinates
        pixels : (n, 2) int
          Which pixel does each ray correspond to in an image
        F)	translate)r+   to_raysr-   r
   r   rE   	ones_liketranslation_from_matrix)r:   vectorspixelsrG   originss        r;   camera_rayszScene.camera_rays
  sl      ++--/))	!227IQVW,,w'/*Q*Q+
 
 ''r=   c                 n    | j                   s| j                         S | j                  J | j                  S )z
        Get the single camera for the scene. If not manually
        set one will abe automatically generated.

        Returns
        ----------
        camera : trimesh.scene.Camera
          Camera object defined for the scene
        )
has_camerar  r   r   s    r;   r+   zScene.camera%  s2     ??$$||'''||r=   c                     |y|| _         y)z
        Set a camera object for the Scene.

        Parameters
        -----------
        camera : trimesh.scene.Camera
          Camera object for the scene
        N)r   )r:   r+   s     r;   r+   zScene.camera8  s     >r=   c                 :    t        | d      xr | j                  d uS )Nr   )r|   r   r   s    r;   r  zScene.has_cameraF  s    tY'DDLL,DDr=   c                     t        | d      r| j                  Lt        j                  |       \  }}t	        ||      D ]  \  }}|| j
                  |j                  <     || _        | j                  S )z
        Get a list of the lights in the scene. If nothing is
        set it will generate some automatically.

        Returns
        -------------
        lights : [trimesh.scene.lighting.Light]
          Lights in the scene.
        _lights)r|   r  r#   	autolightzipr*   rP   )r:   r,   rC   Lr   s        r;   r,   zScene.lightsJ  sf     tY'4<<+?!)!3!3D!9FJFJ/1%&

166" 0 "DL||r=   c                     || _         y)z
        Assign a list of light objects to the scene

        Parameters
        --------------
        lights : [trimesh.scene.lighting.Light]
          Lights in the scene.
        N)r  )r:   r,   s     r;   r,   zScene.lights_  s     r=   c                 z   | j                   s t        j                  | j                  d      ryt        j                  d      }| j                   |dddf<   t        | j                  j                        dz   }| j                  j                  || j                  j                  |       || j                  _        y)z
        Move the current scene so that the AABB of the whole
        scene is centered at the origin.

        Does this by changing the base frame to a new, offset
        base frame.
        r   NrU   r   _Ir?   )	r   rE   allcloser   ra   r]   r*   r(   r9   )r:   rB   new_bases      r;   rezerozScene.rezerok  s     ==BKKs; rr1u tzz,,-4

$***?*? 	 	
 !)

r=   concatenatec                 V   g }| j                   j                  D ]  }| j                   |   \  }}| j                  |   j                         }t	        |d      r]t        j                  |t
        j                  d      }d|ddddf<   |j                         s|j                         }n|ddddf   }|j                  |       ||j                  d<   ||j                  d	<   |j                  |        |r1t        j                  d
t        d       t        j                   |      S |S )a  
        Get a list of every geometry moved to its instance position,
        i.e. freezing or "baking" transforms.

        Parameters
        ------------
        concatenate
          KWARG IS DEPRECATED FOR REMOVAL APRIL 2025
          Concatenate results into single geometry.
          This keyword argument will make the type hint incorrect and
          you should replace `Scene.dump(concatenate=True)` with:
            - `Scene.to_geometry()` for a Trimesh, Path2D or Path3D
            - `Scene.to_mesh()` for only `Trimesh` components.

        Returns
        ----------
        dumped
          Copies of `Scene.geometry` transformed to their instance position.
        to_3Dg:0yE>)atolTNr   r   rP   r   zd`Scene.dump(concatenate=True)` DEPRECATED FOR REMOVAL APRIL 2025: replace with `Scene.to_geometry()`)category
stacklevel)r*   r   r'   r   r|   r   isclose	_IDENTITYallr!  rK   r)   r   warningswarnDeprecationWarningr  )r:   r  resultrL   rG   r   currentchecks           r;   r   z
Scene.dump  s   * 22I'+zz)'<$I}mmM2779G w(YTJ $bqb"1"fyy{%mmoG !*"1"bqb& 1I ##I.'4GV$'0GV$ MM'"/ 32 MMv+ ##F++r=   c           	          ddl m} t        j                  | j	                         D cg c]  }t        ||      s| c}      S c c}w )a>  
        Concatenate every mesh instances in the scene into a single mesh,
        applying transforms and "baking" the result. Will drop any geometry
        in the scene that is not a `Trimesh` object.

        Returns
        ----------
        mesh
          All meshes in the scene concatenated into one.
        r   )rp   )rH   rp   r   r  r   r7   )r:   rp   ds      r;   to_meshzScene.to_mesh  s;     	# DIIK RKq:a;QK RSS Rs
   AAc                 H    t        j                  | j                               S )aM  
        Concatenate geometry in the scene into a single like-typed geometry,
        applying the transforms and "baking" the result. May drop geometry
        if the scene has mixed geometry.

        Returns
        ---------
        concat
          Either a Trimesh, Path2D, or Path3D depending on what is in the scene.
        )r   r  r   r   s    r;   to_geometryzScene.to_geometry  s     		,,r=   r   c                    | j                   }|j                  j                  |      }|j                         D cg c]  }|d   |v s| }}t	        |      }|j                  |       |D ch c]  }d|d   v s|d   d    }}|D ci c]  }|| j                  |    }}t        ||      }	|	S c c}w c c}w c c}w )a	  
        Get part of a scene that succeeds a specified node.

        Parameters
        ------------
        node
          Hashable key in `scene.graph`

        Returns
        -----------
        subscene
          Partial scene generated from current.
        r   r/   r'   r   r'   r*   )r*   rC   
successorsto_edgelistr$   from_edgelistr'   r&   )
r:   r   r*   nodeseedgesgeometry_namesrc   r'   r+  s
             r;   subscenezScene.subscene  s      

  ++D1!--/A/q1Q45=/A d+E"49PEqZ1Q4=O!A$z*EP1?@AAt}}Q''@6 B Q@s   B3B3.B8;
B8B=c                     t        j                  | j                         D cg c]  }|j                   c}      }t	        j
                  |      S c c}w )z
        The convex hull of the whole scene.

        Returns
        ---------
        hull : trimesh.Trimesh
          Trimesh object which is a convex hull of all meshes in scene
        )r   vstack_emptyr   r   r   convex_hull)r:   r   r   s      r;   r?  zScene.convex_hull  sD     ""		#D1AJJ#DE!!&)) $Es   Ac                 4    t        j                  d| ||d|S )a  
        Export a snapshot of the current scene.

        Parameters
        ----------
        file_obj : str, file-like, or None
          File object to export to
        file_type : str or None
          What encoding to use for meshes
          IE: dict, dict64, stl

        Returns
        ----------
        export : bytes
          Only returned if file_obj is None
        )r   file_obj	file_type )r   export_scene)r:   rA  rB  kwargss       r;   r   zScene.export  s+    " "" 
Y
BH
 	
r=   c                 (    ddl m}  |d| |ddd|S )a1  
        Get a PNG image of a scene.

        Parameters
        -----------
        resolution : (2,) int
          Resolution to render image
        **kwargs
          Passed to SceneViewer constructor

        Returns
        -----------
        png : bytes
          Render of scene as a PNG
        r   )render_sceneF)r   r   
fullscreen	resizablerC  )viewer.windowedrG  )r:   r   rE  rG  s       r;   
save_imagezScene.save_image  s*      	3 
:%5
TZ
 	
r=   c                     | j                   j                         D ch c]  }|j                   }}t        |      dk(  r|j	                         S t        |      dkD  rt        j                  d| d       yc c}w )a  
        Get the units for every model in the scene. If the scene has
        mixed units or no units this will return None.

        Returns
        -----------
        units
          Units for every model in the scene or None
          if there are no units or mixed units
        r!   zMixed units `z` returning NoneN)r'   rs   r   r^   rl   r   warning)r:   r   rf   s      r;   r   zScene.units0  sm     &*]]%9%9%;<%;AGG%;<x=A<<>!]QKK-z1ABC =s   A8rb   c                     |j                         j                         }| j                  j                         D ]	  }||_         y)z
        Set the units for every model in the scene without
        converting any units just setting the tag.

        Parameters
        ------------
        value : str
          Value to set every geometry unit value to
        N)striplowerr'   rs   r   )r:   rb   r   s      r;   r   zScene.unitsD  s6     ##%%%'AAG (r=   desiredguessc                     t        | j                        dk(  r| j                         S | j                  }|t        j                  | |      }t        j
                  ||      }| j                  |      }||_        |S )a%  
        If geometry has units defined convert them to new units.

        Returns a new scene with geometries and transforms scaled.

        Parameters
        ----------
        desired : str
          Desired final unit system: 'inches', 'mm', etc.
        guess : bool
          Is the converter allowed to guess scale when models
          don't have it specified in their metadata.

        Returns
        ----------
        scaled : trimesh.Scene
          Copy of scene with scaling applied and units set
          for every model
        r   )rR  )r,  rQ  )r   )r^   r'   r   r   units_from_metadataunit_conversionscaled)r:   rQ  rR  r,  r   r+  s         r;   convert_unitszScene.convert_unitsS  sw    * t}}"99;**? //EBG %%gwG 5) r=   c                    || j                   }|| j                  dz  }t        j                  |t        j                        }t        j                  |t        j                        }| j
                  j                  D ]  }| j
                  |   \  }}| j                  |   j                   }t        j                  |t        j                  |d            dd }|j                  dk(  r	||z
  |z  }nBt        j                  |      dk(  rt        j                  |||z
        }||z  }nt        d      |j                         }	|	dddfxx   |z  cc<   |	| j
                  |<    y)	a  
        Explode the current scene in-place around a point and vector.

        Parameters
        -----------
        vector : (3,) float or float
           Explode radially around a direction vector or spherically
        origin : (3,) float
          Point to explode around
        Ng      9@r   r!   r   rC  )r   zexplode vector wrong shape!)r   r   rE   
asanyarrayr   r*   r   r'   rF   r   r   
ValueErrorr   )
r:   vectororiginrL   rG   r   r   offset	projectedT_news
             r;   explodezScene.explode|  s3    >]]F>ZZ$&FvRZZ8vRZZ822I'+zz)'<$I}}}]3<<Hvvi8Q)?@!DH||r!"V+v5&!T)FF6Hv,=?	)+ !>?? NN$E"1"a%LF"L$)DJJy!% 3r=   r   c                    | j                         }t        j                  |d      r|S t        |t        t
        t        j                  f      xr t        |      dk(  }|r?t        j                  t        j                  |      |d   k(        rt        |d         }d}n|st        |      }|r&|j                  j                  D ]   }|j                  j                  |   }t        |      dkD  s,|j                  |   }|D ]  }|j                  j                  j                  |   }|j!                  |j                         ||||j                  j                  j"                  ||f   j%                  dd      |j                  j                  j"                  ||f   j%                  dd      	        |j'                  |        |j                  D ]V  }|j                  |   j(                  j*                  d   d
k(  s-|j                  |   j-                         |j                  |<   X |j                  j.                  D ]  }	|j                  j%                  |	      \  }
}|
j                         }
d|
dddf<   |j                  |   j1                  |
      j3                  |      j1                  t        j4                  j7                  |
              |j                  j                  j"                  }|D ]`  }d||   v s||   }||   d   j                         }
|
dddfxx   |z  cc<   |
|d<    |j                  j8                  d|d   |d   d| b i |j                  j                  _        t=        t?        j@                               |j                  j                  _!        |j                  j:                  jE                          nt        jF                  d      |z  }t        jF                  d      |z  }t        jH                  | j                  j.                        }t        jJ                  t        |      ddf      }dgt        |      z  }tM        |      D ]  \  }}| j                  |   \  ||<   ||<    |j                  jE                          tO        jP                  |      D ]  }||d      }||d      }t        jR                  ||      }|j                  |   j(                  j*                  d   d
k(  r|j                  |   j1                  |       n|j                  |   j1                  |       tU        ||   ||         D ]i  \  }}
tW        jX                  ||
t        j4                  j7                  |      g      }|dddfxx   |z  cc<   |j                  j9                  |||       k  d|_-        |S )ao  
        Return a copy of the current scene, with meshes and scene
        transforms scaled to the requested factor.

        Parameters
        -----------
        scale : float or (3,) float
          Factor to scale meshes and transforms

        Returns
        -----------
        scaled : trimesh.Scene
          A copy of the current scene but scaled
        r   r   r   Fr!   rB   Nr)   )r'   rM   rL   rN   rG   r)   r   r   )r@   rA   rU   )rA   rB   r'   rC  ).r   rE   r  r7   r   tuplendarrayr^   r'  asarrayr   r*   geometry_nodesr'   rC   parentsr6   	edge_datar   rm   r   r   r!  r   rK   apply_scalelinalginvr9   r5   r]   uuiduuid4	_modifiedrZ   ra   r   r   	enumerater   grouprF   r  r   	multi_dotr   )r:   r   r+  scale_is_3DrM   nodes_with_geomgeomr   pkeyr   rg  uvpropsscale_2Dscale_3Dr8  rC   
geometriesr   r   ro  r'   originalnew_geomrG   s                             r;   rV  zScene.scaled  s     ;;uc"M !ubjj(ABVs5zUV266"**U"3uQx"?@%(OEK%LE  $\\88	"(,,"="=i"H'!+!??95D,"LL33;;A>++%)YY[&/&'-.&,ll&=&=&G&GA&O&S&S ($' &,\\%<%<%F%F1v%N%R%R *D& ,  - **95% 9* $__	??9-66<<Q?1D171K1Q1Q1SFOOI. - ||22%||//49FFH"1"a% 	*::1=II!/"))--"23 3 //99Iy},%bME!"h/446Abqb!eH%H&'E(O'FLL''R2a52a5RER   .0FLL##*03DJJL0AFLL##-LL%%' vvay5(Hvvay5(H HHTZZ667E3u:q!"45J#e*,J %U+4/3zz$/?,
1z!} , LL !
3%eAh/%eAh/66(H5??8,55;;A>!COOH-==hG OOH-==hG"5<E1BCGD! $!RYY]]8=T/U VIbqb!e$-$LL''!%i( (   D 44 r=   c                 p   | j                   j                         D ci c]  \  }}||j                          }}}t        | d      r| j                  d}n| j
                  j                         }t        || j                  j                         | j                  j                         |      }|S c c}}w )z
        Return a deep copy of the current scene

        Returns
        ----------
        copied : trimesh.Scene
          Copy of the current scene
        r   N)r'   r*   r)   r+   )	r'   rY   r   r|   r   r+   r&   r*   r)   )r:   r   r   r'   r+   copieds         r;   r   z
Scene.copy+  s     -1MM,?,?,AB,ADAqAqvvxK,ABtY'4<<+?F [[%%'F**//#]]'')	
  Cs   B2viewerc                     |ddl m}  |       }|sd}|dk(  rddl m}  || fi |S |dk(  rddl m}  || fi |S |dk(  rddl m}  || fi |S t        |      r	 || fi |S t        d	      )
a  
        Display the current scene.

        Parameters
        -----------
        viewer
          What kind of viewer to use, such as
          `gl` to open a pyglet window
          `jupyter` for a jupyter notebook
          `marimo'` for a marimo notebook
          None for a "best guess"
        kwargs
          Passed to viewer, such as `smooth=False` which will turn
          off automatic smooth shading
        r   )in_notebookgl)SceneViewerjupyter)scene_to_notebookmarimo)scene_to_mo_notebookzJInvalid value for viewer: not 'gl', 'jupyter', 'marimo', callable, or None)r  r  r  r  r  callablerZ  )r:   r  rE  r  r  r  r  s          r;   showz
Scene.showG  s    * >, !]FT> -t.v..y 2$T4V44x5'777f $)&))\ r=   c                 N    t        | |g| j                  j                  g      }|S )a`  
        Concatenate the current scene with another scene or mesh.

        Parameters
        ------------
        other : trimesh.Scene, trimesh.Trimesh, trimesh.Path
           Other object to append into the result scene

        Returns
        ------------
        appended : trimesh.Scene
           Scene with geometry from both scenes
        )common)append_scenesr*   r(   )r:   otherr+  s      r;   __add__zScene.__add__|  s&     e}djj6K6K5LMr=   )NworldNNNNN)NNNNN)rh   N)NNN)gh㈵>)F)rh   ztrimesh.Trimesh)NNr   )rh   r&   )P__name__
__module____qualname____doc__r   GeometryInputr]   r   r$   r"   r   r   r#   Lightr   r<   rK   r6   r   rj   rm   rv   r   r   r{   r   r4   propertyboolr   r   r   cache_decoratorr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r-   setterr   r   r   r  r+   r  r,   r  r   r   r0  r2  r<  r?  r   bytesrK  r   rW  r`  rV  r   r   r  r  rC  r=   r;   r&   r&   '   s    -1!#'&*+/59.299=)99 99 4.	99
 
#99 (99 (..1299 #7+99v& $(#'*.'+#'pp C=p C=	p
 #3-p G$p 4.pd:U3X+=%> :4 :(	> '+(,(,	&(#& W%& W%	&
 
&<D# D$ 
'$ 
' 
' 7$ 7 7* *S''*:%: ; * *X V!12 V V" 3''"23 3 3 0u 0 0 (77#34   !DW !D !DF 
 
F  
e 
 
" 
 
 
" 877+ 8 8@ 
- 
- 	Td38n 	T 	T 1 1 1 ()d3i () ()TJH J J< MQ1	1f 	/ 	/ 	.y 	. 	.(U77#3WW5Ewu~#UV (6   $ ]]Xgnn5   ED E E X^^,  ( ]]	Xhnn5 	 	).8 8h 8tT -X -S W < 
* 
*
*
u 
, x}  & \\3  'S ' '' 'R%*NFE(I"56 F7 FP< "33jr=   r&   c           
         t        | t              r| S i }t        j                  |       rQ| D cg c]  }|j	                  t        |di               c} t        | |      }t        d | D        d      |_        |S t         | j                  di |t        | j                              }t        | j                        |_        |S c c}w )z
    Given a geometry, list of geometries, or a Scene
    return them as a single Scene object.

    Parameters
    ----------
    geometry : splittable

    Returns
    ---------
    scene: trimesh.Scene
    r)   )r)   c              3   N   K   | ]  }|j                   |j                     y wr   )r[   r   s     r;   r   zsplit_scene.<locals>.<genexpr>  s     Q1AHH<Pahhs   %%NrC  )r7   r&   r   rX   r9   getattrnext_sourcesplitr   r)   r[   )r'   rE  r)   r   r   s        r;   split_scener    s     (E" H !>FGhJ3	4hGh2QQSWX L HNN$V$h//0
 !1L 	Hs   #Cc                 4   t        | t              r| S |gi }g }t              t               fd}| D ]  }t        |d      r|j	                         }t        |t              s!t        t        |      j                   d      i }|j                  j                         D ]*  \  }}	t        ||j                               }
|
||<   |	||
<   , i t               |j                  j                         D ]@  \  }}} ||       ||      }}d|v r|d   |v r||d      |d<   |j                  |||f       B j                          t        |      }|j                  j!                  |       |j                  j                  |       |S )a  
    Concatenate multiple scene objects into one scene.

    Parameters
    -------------
    iterable : (n,) Trimesh or Scene
       Geometries that should be appended
    common : (n,) str
       Nodes that shouldn't be remapped
    base_frame : str
       Base frame of the resulting scene

    Returns
    ------------
    result : trimesh.Scene
       Scene containing all geometry
    c                     | v r|    S | vr"| v r| t        j                         z   }|| <   |} j                  |        | S )a  
        Remap node to new name if necessary

        Parameters
        -------------
        node : hashable
           Node name in original scene

        Returns
        -------------
        name : hashable
           Node name in concatenated scene
        )r   	unique_idadd)r   rP   r  consumedr,  map_nodes     r;   
node_remapz!append_scenes.<locals>.node_remap  sZ      8D>! v$("2$..**D!HTND 	Dr=   r   z is not a scene!rR   r'   r/   )r7   r&   rj   r|   r   rZ  typer  r'   rY   r    r_   r*   r6  r   r9   r7  )iterabler  r(   r'   r:  r  smap_geomrc   rd   rP   abattrr+  r  r,  r  s    `             @@@r;   r  r    s   $ (E"~ HE [FuHB 1g	A!U#Q 0 011ABCC JJ$$&DAqQADHQKHTN ' %''--/JAq$a=*Q-qA T!d:&6(&B#+D,<#=Z LL!Q& 0 	 I N j)F
LLu%
OO8$Mr=   r   r   rh   c           	      Z   | j                   j                         }| j                  D ]  }t        |      dk  r|d   }| j                   |   \  }}| j                  |   j
                  j                  t        j                        }|dd D ]  }| j                   |   \  }	}
| j                  |
   j
                  j                  t        j                        }|j                  |j                  k7  ret        ||ddd      \  }}}||k  s|j                  |t        j                  |	|      |         t        |j                  j                               }t!        | j                  j#                         D ci c]  \  }}||v s||j                          c}}|	      S c c}}w )
ad  
    If a scene has been "baked" with meshes it means that
    the duplicate nodes have *corresponding vertices* but are
    rigidly transformed to different places.

    This means the problem of finding ab instance transform can
    use the `procrustes` analysis which is *very* fast relative
    to more complicated registration problems that require ICP
    and nearest-point-on-surface calculations.

    TODO : construct a parent non-geometry node for containing every group.

    Parameters
    ----------
    scene
      The scene to handle.
    cost_threshold
      The maximum value for `procrustes` cost which is "squared mean
      vertex distance between pair". If the fit is above this value
      the instance will be left even if it is a duplicate.

    Returns
    ---------
    dedupe
      A copy of the scene de-duplicated as much as possible.
    r   r   r!   NTF)translationr   
reflection)rB   r'   r4  )r*   r   r   r^   r'   r   viewrE   rc  r   r   r9   rF   rj   re  r_   r&   rY   )r   r   r*   ro  	node_baser   	geom_baserH   r   node_mat	node_geomnode_verticesrB   _pcostr   rc   rd   s                     r;   r   r   $  s~   8 KKE&&u:> !H	{{9-9y1::??

K!"ID"'++d"3Hi "NN95>>CCBJJOM ""djj0  *mUu FB n$T"&&6*BYW#  '@ U))..01J */..*>*>*@T*@$!QAO!QVVX+*@T Ts   =F'

F'
)Nr  )gư>)4r1   rk  r(  r   r   hashlibr   numpyrE   r   r   r   r   r	   r
   r   r   	constantsr   exchanger   parentr   r   registrationr   typedr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r"   r#   rC   r$   r]   r  r&   r  r  r   rC  r=   r;   <module>r     s          O O O   ) %       " h 2Dh4GRSdJ dN+"JnbD D DE Dr=   