
    Ti[f                     2   d Z ddlZddlmZmZ ddlmZmZm	Z	m
Z
mZmZ ddlmZmZ dZ G d d	          Zd
 Zd"dZd Zd Z	 	 	 	 	 	 	 d#dZ	 	 	 	 	 	 d$dededee         dee         dee
         dee         fdZd Zd Zdedede	e         fdZd%d!ZdS )&zT
packing.py
------------

Pack rectangular regions onto larger rectangular regions.
    N   )logtol)	ArrayLikeIntegerNDArrayNumberOptionalfloat64)allclosebounds_treeg-q=c                   6    e Zd ZdZd Zed             ZddZdS )RectangleBina  
    An N-dimensional binary space partition tree for packing
    hyper-rectangles. Split logic is pure `numpy` but behaves
    similarly to `scipy.spatial.Rectangle`.

    Mostly useful for packing 2D textures and 3D boxes and
    has not been tested outside of 2 and 3 dimensions.

    Original article about using this for packing textures:
    http://www.blackpawn.com/texts/lightmaps/
    c                 l    g | _         d| _        t          j        |t          j                  | _        dS )z
        Create a rectangular bin.

        Parameters
        ------------
        bounds : (2, dimension *) float
          Bounds array are `[mins, maxes]`
        FdtypeN)childoccupiednparrayr   boundsselfr   s     N/DATA/AppData/hermes/venv/lib/python3.11/site-packages/trimesh/path/packing.py__init__zRectangleBin.__init__   s.     
hvRZ888    c                 2    | j         }|d         |d         z
  S )z
        Bounding box size.

        Returns
        ----------
        extents : (dimension,) float
          Edge lengths of bounding box
           r   r   r   s     r   extentszRectangleBin.extents0   s     ay6!9$$r   Tc                 f   | j         D ]}|                    ||          }||c S  | j        rdS | j                                        }|d         |d         z
  }|rit          t          |                    D ]G}|t          ||          z
  }|t           k    	                                }	|	rt          ||          } nH|	sdS n%||z
  }|t           k     
                                rdS d| _        |t          k     	                                r|S |                                }
t          j        ||f          }|d         |
         ||
         z   |dd|
f<   t          |dd                   t          |dd                   f| j         dd<   | j         d                             ||          S )	aP  
        Insert a rectangle into the bin.

        Parameters
        -------------
        size : (dimension,) float
          Size of rectangle to insert/

        Returns
        ----------
        inserted : (2,) float or None
          Position of insertion in the tree or None
          if the insertion was unsuccessful.
        )sizerotateNr   r   T   r   r#   )r   insertr   r   copyrangelen_roll	_TOL_ZEROallanyargmaxr   vstackr   )r   r"   r#   r   attemptr   r    roll	size_testfitsaxissplitss               r   r&   zRectangleBin.insert=   s    Z 	 	EllVl<<G" # = 	4 !!##)fQi' 	c$ii((  #eD$&7&77	!YJ.3355  t,,DE  t
  $IYJ&++-- t
 
 	!&&(( 	M !! FF+,,"1IdOd4j8qsDy %VBQBZ00,vabbz2J2JJ
111 z!}##D#888r   N)T)__name__
__module____qualname____doc__r   propertyr    r&    r   r   r   r      sb        
 
9 9 9" 
% 
% X
%F9 F9 F9 F9 F9 F9r   r   c                     ddgddggg dg dg dgg}	 | |t          |           dz
           |                  S # t          $ r+ t          j        | | d         | d|          g          cY S w xY w)al  
    A speedup for `numpy.roll` that only works
    on flat arrays and is fast on 2D and 3D and
    reverts to `numpy.roll` for other cases.

    Parameters
    -----------
    a : (n,) any
      Array to roll
    count : int
      Number of places to shift array

    Returns
    ---------
    rolled : (n,) any
      Input array shifted by requested amount

    r   r   )r   r   r   )r   r   r   )r   r   r   r   N)r)   
IndexErrorr   concatenate)acountlookups      r   r*   r*      s    ( 1v1vIIIyyy ABF8A
#E*++ 8 8 8~q%z1WufW:6777778s   #9 2A.-A.FTc           	         t          j        | t           j                  } | j        d         }t          j        t          |           d|f          }t          j        t          |           t                    }t          j        |                     d                    ddd         }|r7||	                    |          }nt           j
        	                    |          }|5dg|z  | t          j        | d                                                   g}	ndg|z  |g}	t          |	          }
|D ]}| |         }|
                    ||	          }|||
j        }t          j        |d
          }t           j        }t#          t          |                    D ]}t          j        |t'          ||          g          }t          j        |                    d
          t          |          df          }t          j        ||                    d
                     t          j        |d          }|                                |k     r|}|                                }||         }|s n|d
         ||         z   }|d
                                         }||xx         ||         z  cc<   t          j        |d         |f                              d
          }|d         |         ||<   ||d         k                                    sJ t          j        |d
         |g          }t          j        ||g          }t          |d
         |g          }d|_        t          |          t          |          g|_        |j        d
                             t          j        |d
          |	          }|J t?          |d
         d
         d          s||xx         |d
         d
         z  cc<   |j        d                             ||	          }|J |||<   d||<   |}
 |
|||<   d||<   t@          j!        rtE          ||                   rJ ||         |fS )a  
    Execute a single insertion order of smaller rectangles onto
    a larger rectangle using a binary space partition tree.

    Parameters
    ----------
    extents : (n, dimension) float
      The size of the hyper-rectangles to pack.
    size : None or (dim,) float
      Maximum size of container to pack onto.
      If not passed it will re-root the tree when items
      larger than any available node are inserted.
    shuffle : bool
      Whether or not to shuffle the insert order of the
      smaller rectangles, as the final packing density depends
      on insertion order.
    rotate : bool
      If True, allow integer-roll rotation.

    Returns
    ---------
    bounds : (m, 2, dim) float
      Axis aligned resulting bounds in space
    transforms : (m, dim + 1, dim + 1) float
      Homogeneous transformation including rotation.
    consume : (n,) bool
      Which of the original rectangles were packed,
      i.e. `consume.sum() == m`
    r   r   r   r4   N        r   r%   r   T)#r   
asanyarrayr   shapezerosr)   boolargsortmaxpermutationrandomptpr.   r   r&   r   infr(   r   r*   tilefill_diagonalsumprodminargminr'   r/   r,   r   r   r   r   strictbounds_overlap)r    r"   shuffler#   rM   	dimensionoffsetconsumeorderroot_boundsrootindex	rectangleinsertedr   currentbestr1   stackchchoice_prodchoiceschoices_idxnew_maxnew_minnew_ori_max
bounds_ori
bounds_insnew_rootroot_offsetr   s                                  r   rectangles_singlerp      s   > mG2:666Ga IXs7||Q	233Fhs7||4000GJw{{{**++DDbD1E 1&&u--EE I))%00E| uy('"&q2I2I2I2P2P2R2R*ST uy($/ {+++D S" S"EN	;;y;88 [FfV!,,,G 6Dc'll++  '5D+A+A!BCC WUYYAY..Wq0ABB UYYAY%6%6777 !gbq111??$$t++ G"-"4"4"6"6K&{3D E Qi'+"66G Qinn&&GK   GK$88    )VAY$899==1=EEK'-ay'=K$6!9,1133333 6!9k":;;J 7G"455J $VAY$899H $H*:66Z8P8PQHN #.+2226&q3I3I3IRX2YYK*** KN1-s33 5w;q>!#44 N1%,,Yv,FFE$$$!F5M!GENDD!$F5M!GEN
z 3!&/22222'?G##r   c                 <   ddl m} g }g }t          |           D ]h\  }}|j                            dd          }|                    |g|z             |                    |j        |j        d                  g|z             it          dd|i|\  }}	g }
t          t          j        |	          d         |          D ]O\  }}| ||                                                  }|                    |           |
                    |           P ||
          }|||	fS )a  
    Pack a list of Path2D objects into a rectangle.

    Parameters
    ------------
    paths: (n,) Path2D
      Geometry to be packed

    Returns
    ------------
    packed : trimesh.path.Path2D
      All paths packed into a single path object.
    transforms : (m, 3, 3) float
      Homogeneous transforms to move paths from their
      original position to the new one.
    consume : (n,) bool
      Which of the original paths were inserted,
      i.e. `consume.sum() == m`
    r   )r>   quantityr   polygonsr;   )utilr>   	enumeratemetadatagetextendpolygons_closedr^   rs   zipr   nonzeror'   apply_transformappend)pathskwargsr>   packableoriginalr_   pathrr   
transformsr[   
positionedmatrixrb   packeds                 r   r~   r~   9  sM   ( "!!!!! HH '' I It=$$Z33(*+++-dil;<xGHHHH #??H???JJRZ003Z@@ # #v(--//''''"""" [$$F:w&&r   c                 B   
 ddl m
m}  |           \  }}t          d	d|i|\  }}t	          j        d|                                t                                t          |||                   }t          j
        d t          ||         |          D                       }t          j        rit          |          rJ t          j
        
 fdt          t          j        |          d         |          D                       }	t          |	          rJ ||fS )
a  
    Pack polygons into a rectangle by taking each Polygon's OBB
    and then packing that as a rectangle.

    Parameters
    ------------
    polygons : (n,) shapely.geometry.Polygon
      Source geometry
    **kwargs : dict
      Passed through to `packing.rectangles`.

    Returns
    -------------
    transforms : (m, 3, 3) float
      Homogeonous transforms from original frame to
      packed frame.
    consume : (n,) bool
      Which of the original polygons was packed,
      i.e. `consume.sum() == m`
    r   )polygon_boundspolygons_obbr    z$%i/%i parts were packed successfullyr   r    c                 >    g | ]\  }}t          j        ||          S r;   r   dot).0r?   bs      r   
<listcomp>zpolygons.<locals>.<listcomp>  s&    LLLDAq26!Q<<LLLr   c                 <    g | ]\  }} |         |           S ))r   r;   )r   r_   mr   rs   s      r   r   zpolygons.<locals>.<listcomp>  s@       E1 xq999  r   r   r;   )rs   r   r   
rectanglesr   debugrR   r)   roll_transformr   r   rz   r   rV   rW   r{   )rs   r   r   obbr    r   r[   r1   r   check_boundr   s   `         @r   rs   rs   g  sM   , 76666666  <))LC !;;;F;;OFGI4gkkmmS]]SSS 1ABBBDLLCGd4K4KLLLMMJ
z 
/!&)))))h     #BJw$7$7$:J G G  
 
 "+.....wr   Gz?2   c                 $   t          j        | t           j                  } | j        d         }|| |dz  z  } t          j        | d          }	d}
d}|d}n t           j                            |          }t          |          D ]}t          | ||dk    ||	          \  }}|	                                }t          j
        |                    d
|f          d          }|t          j        ||z            |z  } |	|         	                                t          j        |          z  }||
k    s||k    r$|}
|}||g}||k    r|                                r n||dxx         |g| gggz  cc<   t          j        | d|
d           |S )a  
    Run multiple iterations of rectangle packing, this is the
    core function for all rectangular packing.

    Parameters
    ------------
    extents : (n, dimension) float
      Size of hyper-rectangle to be packed
    size : None or (dimension,) float
      Size of sheet to pack onto. If not passed tree will be allowed
      to create new volume-minimizing parent nodes.
    density_escape : float
      Exit early if rectangular density is above this threshold.
    spacing : float
      Distance to allow between rectangles
    iterations : int
      Number of iterations to run
    rotate : bool
      Allow right angle rotations or not.
    quanta : None or float
      Discrete "snap" interval.
    seed
      If deterministic results are needed seed the RNG here.

    Returns
    ---------
    bounds :  (m, 2, dimension) float
      Axis aligned bounding boxes of inserted hyper-rectangle.
    inserted : (n,) bool
      Which of the original rect were packed.
    r   r   N       @rC   rE   r   )seed)r    r"   rX   r#   rM   rD   z  iterations packed with density z0.3f)r   r   r   rG   rS   rM   default_rngr(   rp   rR   rN   reshapeceilr,   r   r   )r    r"   density_escapespacing
iterationsr#   quantar   dimareabest_density
best_countrM   ir   r&   r@   extents_alldensityresults                       r   r   r     s   T hwbj111G
-
C7S=  77###DLJ|&&D&11:   +$aPV
 
 
 

fV^^RI66Q???gkF233f<G v,""$$rw{';';; \!!UZ%7%7"LJf%F ''FJJLL'q			yG8*-..			IPP\PPPQQQMr   power_resizededuplicater   r   r   modec                     ddl m} |rt          j        d  D             dd          \  }}	}
t	           fd|	D             d|||          \  }}|                                sJ ||
         }t          j        t          j        |d	
          d  D                       sJ n7t	          d  D             d|||          \  }}|                                sJ |d}nt          |          }|dddf         	                                
                    t                    }t          j        |                    d          d
          |dz  z   }|	                                
                    t                    }|rFdt          j        t          j        |                    z  
                    t          j                  }|=t          d  D                       }|t          j        d |D                                }|                    |t%          |                    }t'                      }t)           |          D ]w\  }}t%          |          |vr?|d         |d	         |j        d	         z
  |d	         z
  f}|                    ||           U|                    t%          |                     x||fS )a  
    Pack a list of images and return result and offsets.

    Parameters
    ------------
    images : (n,) PIL.Image
      Images to be packed
    power_resize : bool
      Should the result image be upsized to the nearest
      power of two? Not every GPU supports materials that
      aren't a power of two size.
    deduplicate
      Should images that have identical hashes be inserted
      more than once?
    mode
      If passed return an output image with the
      requested mode, otherwise will be picked
      from the input images.

    Returns
    -----------
    packed : PIL.Image
      Multiple images packed into result
    offsets : (n, 2) int
       Offsets for original image to pack
    r   )Imagec                 P    g | ]#}t          |                                          $S r;   )hashtobytesr   r   s     r   r   zimages.<locals>.<listcomp>%  s(    ///1T!))++///r   T)return_indexreturn_inversec                 *    g | ]}|         j         S r;   r"   )r   r   imagess     r   r   zimages.<locals>.<listcomp>)  s    333VAY^333r   F)r    r#   r   r   r   r   rC   c                     g | ]	}|j         
S r;   r   r   s     r   r   zimages.<locals>.<listcomp>3  s    3K3K3KqAF3K3K3Kr   c                     g | ]	}|j         
S r;   r   r   s     r   r   zimages.<locals>.<listcomp>7  s    ,,,QV,,,r   N)rD   r   r   c                     h | ]	}|j         
S r;   )r   r   s     r   	<setcomp>zimages.<locals>.<setcomp>O  s    ---af---r   c                 ,    g | ]}t          |          S r;   )r)   )r   r   s     r   r   zimages.<locals>.<listcomp>R  s    6661A666r   box)PILr   r   uniquer   r,   r   rN   introundastyper   r   log2int64listr.   newtuplesetrz   r"   pasteadd)r   r   r   r   r   r   r   r   _r_   inverser   r&   rZ   r    r"   modesr   doneimgoffcorners   `                     r   r   r     s   F  I/////dSW
 
 
5' $3333U333!
 
 
 zz|||{26&q1113K3KF3K3K3KLLLLLL $,,V,,,!
 
 
 zz|||g,, AAAqD\!!((--FfV^^G,,15551EG==??!!#&&D >RWRWT]]+++33BH==|--f---.. RY66666778 YYtU4[[))F55D'' ! !S::T!!!fd1g3c!f<=FLL&L))))HHU3ZZ    6>r   c                     d  D             }t          j        d |D                       }t          j        d |D                       }t          |fi |\  }}t          j        d t          ||         t	          |||                             D             t           j                  } fdt          t          j        |          d         |          D             }|||fS )	aG  
    Pack 3D meshes into a rectangular volume using box packing.

    Parameters
    ------------
    meshes : (n,) trimesh.Trimesh
      Input geometry to pack
    **kwargs : dict
      Passed to `packing.rectangles`

    Returns
    ------------
    placed : (m,) trimesh.Trimesh
      Meshes moved into the rectangular volume.
    transforms : (m, 4, 4) float
      Homogeneous transform moving mesh from original
      position to being packed in a rectangular volume.
    consume : (n,) bool
      Which of the original meshes were inserted,
      i.e. `consume.sum() == m`
    c                     g | ]	}|j         
S r;   )bounding_box_orientedr   s     r   r   zmeshes.<locals>.<listcomp>{  s    444A#444r   c                 &    g | ]}|j         j        S r;   )	primitiver    r   s     r   r   zmeshes.<locals>.<listcomp>|  s    ===11;.===r   c                 &    g | ]}|j         j        S r;   )r   	transform)r   os     r   r   zmeshes.<locals>.<listcomp>}  s    BBBak3BBBr   c                 x    g | ]7\  }}t          j        |t           j                            |                    8S r;   )r   r   linalginv)r   r   rs      r   r   zmeshes.<locals>.<listcomp>  sF     	
 	
 	
1 F1bimmA&&''	
 	
 	
r   r   r   c                 p    g | ]2\  }}|                                                              |          3S r;   )r'   r|   )r   r_   Tmeshess      r   r   zmeshes.<locals>.<listcomp>  sK       E1 	u,,Q//  r   r   )r   r   r   rz   r   r   r{   )	r   r   obbs
obb_extentobb_transformr   r[   r   placeds	   `        r   r   r   d  s!   . 54V444D=====>>JHBBTBBBCCM !66v66OFG 	
 	
g&fj6IJJJ 	
 	
 	
 j	 	 	J   BJw//2J??  F
 :w&&r   c                 6  	 ddl m	 ddlm} ddlm} t          ||           }	fd| D             }t          |||          D ]K\  }}}|                    |           t          j
        |j        |          sJ  |            |j        _        L ||          S )a(  
    Visualize a 3D box packing.

    Parameters
    ------------
    extents : (n, 3) float
      AABB size before packing.
    bounds : (n, 2, 3) float
      AABB location after packing.

    Returns
    ------------
    scene : trimesh.Scene
      Scene with boxes at requested locations.
    r   r   )Scene)random_colorr   c                 (    g | ]} |           S )r    r;   )r   er   s     r   r   zvisualize.<locals>.<listcomp>  s#    ...cc!nnn...r   )creationr   scener   visualr   r   rz   r|   r   r   r   face_colors)
r    r   r   r   r   r   r   r   checkr   s
            @r   	visualizer     s      %%%%%%  vw???J....g...F
F;; . .65	&!!!{18U++++++|~~5==r   r   r    returnc           
      X  
 t          |           t          |          k    rt          d          t          |          dk    rg S t          j        | d          }|j        d         }t          j        t          j        |dz             t          |           ddf          }t          j        t          j        d          t          j        g dg dg dg          g          t          j        t          j        d	          g d
g dg dg dgg dg dg dg dgg          g}t          |j        d                   D ]}t          j	        ||d          }t          j        ||z
  d          t          k     }|                                sP||dz
           |         t          j        t          j        |dz             |                                ddf          }	| dddf         |         ||         dz  z   |	ddd||f<   fd|	D             ||<   t          j        r|dk    r3ddlm
 t#          
fdt%          | ||          D                       sJ nH|dk    r3ddlm t#          fdt%          | ||          D                       sJ nt          d          |S )aw  
    Packing returns rotations with integer "roll" which
    needs to be converted into a homogeneous rotation matrix.

    Currently supports `dimension=2` and `dimension=3`.

    Parameters
    --------------
    bounds : (n, 2, dimension) float
      Axis aligned bounding boxes of packed position
    extents : (n, dimension) float
      Original pre-rolled extents will be used
      to determine rotation to move to `bounds`.

    Returns
    ----------
    transforms : (n, dimension + 1, dimension + 1) float
      Homogeneous transformation to move cuboid at the origin
      into the position determined by `bounds`.
    z`bounds` must match `extents`r   r   rC   r$   )rE         rE   )      ?rE   rE   )rE   rE   r      )       r   r   r   )r   r   r   r   )rE   r   rE   rE   )rE   rE   rE   r   )r   r   r   r   )rE   rE   r   rE   r   Nr   c                 :    g | ]}t          j        |          S r;   r   )r   r   mats     r   r   z"roll_transform.<locals>.<listcomp>  s#    555bfQnn555r   r   c              3      K   | ]:\  }}}t           |                               |          j        |          V  ;dS )r   Nr   r|   r   )r   r   r   r   r   s       r   	<genexpr>z!roll_transform.<locals>.<genexpr>
  sb        Aq! Q77::A1EE     r   )r`   c              3      K   | ]C\  }}}t           | d z  |d z  g                              |          j        |          V  DdS )r   r   Nr   )r   r   r   r   r`   s       r   r   z!roll_transform.<locals>.<genexpr>  st        Aq! A261q5/:::JJ1MMTVWXX     r   zunsupported dimension)r)   
ValueErrorr   rN   rG   rP   eyer   r(   r1   r+   r-   rR   r   rV   r   r   r,   rz   r`   )r   r    passedrY   r   rA   r1   rolledokrZ   r   r   r`   s             @@@r   r   r     sQ   * 6{{c'll""8999
7||q	 VF###FQI WRVIM**S[[!Q,?@@F 	VAYY"2"2"2OOO___!UVVW	
 	
 	q		,,,,,,((((((	 -,,(((,,,(((		
 	
	F0 gmA&'' 6 6 $Q/// VVf_A...:vvxx 	 Y]#D)	A..1a0@AA+1!!!Q$<+;fRj3>N+Nqqq*9*i'(5555f555r


z 6>>&&&&&&    "67F;;         !^^++++++    "67F;;        
 4555Mr   :0yE>c                     t          j        |           t          j        || gd          z   }t          |          t	          fdt          |           D                       S )a  
    Check to see if multiple axis-aligned bounding boxes
    contains overlaps using `rtree`.

    Parameters
    ------------
    bounds : (n, 2, dimension) float
      Axis aligned bounding boxes
    epsilon : float
      Amount to shrink AABB to avoid spurious floating
      point hits.

    Returns
    --------------
    overlap : bool
      True if any bound intersects any other bound.
    )r   r   r   c              3      K   | ]@\  }}t                              |                                                    |hk    V  Ad S )N)r   intersectionravel)r   r   rb   trees      r   r   z!bounds_overlap.<locals>.<genexpr>2  s]        ;E1gDgmmoo..//A36     r   )r   r   r   r   r-   ru   )r   epsilonpaddedr
  s      @r   rW   rW     sz    & Xf
GgX+>	 J JJFvD    IRSYIZIZ     r   )NFTN)Nr   Nr   TNN)FFr   NNN)r  )r9   numpyr   	constantsr   r   typedr   r   r   r	   r
   r   rt   r   r   r+   r   r*   rp   r~   rs   r   rI   strr   r   r   r   rW   r;   r   r   <module>r     s&                        J J J J J J J J J J J J J J J J ( ( ( ( ( ( ( ( 	q9 q9 q9 q9 q9 q9 q9 q9h8 8 8:S$ S$ S$ S$l+' +' +'\1 1 1l 
	_ _ _ _H $&" $d dd d !	d
 7
d fd 3-d d d dN1' 1' 1'h  >b9 by bWW=M b b b bJ     r   