
    Miѻ                     2   S r SSKrSSKrSSKJr  SSKJr  SSKrSSK	J
r
JrJrJrJrJrJrJrJr  SSK	Jr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJrJ r J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(  SSK)J*r*  SSK	J+r+J,r,J-r-J.r.J/r/  SSK0J1r1  SSK2J3r3  SSKJ4r4   SSK	J5r5   SSK	J9r9   SSK:J;r;   SSK<J=r=   SSK>r? " S S\R                  5      rA " S S\A5      rB " S S\A5      rCg! \6 a  r7\Rp                  " \75      r5 Sr7C7NcSr7C7ff = f! \6 a  r7\Rp                  " \75      r9 Sr7C7NSr7C7ff = f! \6 a  r7\Rp                  " \75      r; Sr7C7NSr7C7ff = f! \6 a  r7\Rp                  " \75      r= Sr7C7NSr7C7ff = f! \6 a  r7\Rp                  " \75      r? Sr7C7NSr7C7ff = f)zm
path.py
-----------

A module designed to work with vector paths such as
those stored in a DXF or SVG file.
    N)deepcopy)sha256   )	boundscaching
comparisonconvex
exceptionsgroupingparentunitsutil)transformations)cache_decorator)log)tol_path)plane_transform)	plane_fit)
	ArrayLikeIterableListMappingNDArrayOptionalSelfTupleUnionfloat64)to_rgba   )creationrastersegmentssimplify	traversal)Entityexport_pathconcatenate)repair)polygons)cKDTree)Polygonc                   L   \ rS rSrSr      S<S\\\\   S4   S\	\   S\	\
   S\S\	\   S	\	\
   4S
 jjrS rS\4S jr\S\	\   4S j5       r\R&                  S\	\   4S j5       r\S\\   4S j5       r\R&                  S\	\   4S j5       r\S 5       r\R&                  S 5       r\S 5       rS r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S\\   4S j5       r \S\\   4S j5       r!S=S\"S \4S! jjr#S" r$S>S# jr%\S$ 5       r&\S% 5       r'\S& 5       r(\S' 5       r)S(\S\4S) jr*S*\"SS4S+ jr+S, r,S?S- jr-S. r.S/ r/S0 r0S1 r1\S2 5       r2S3 r3\S\4\\      4S4 j5       r5S@S5 jr6S\74S6 jr8S?S7\\"S\\\"S4      4   4S8 jjr9S9 r:S: r;S;r<g)APathS   aU  
A Path object consists of vertices and entities. Vertices
are a simple (n, dimension) float array of points in space.

Entities are a list of objects representing geometric
primitives, such as Lines, Arcs, BSpline, etc. All entities
reference vertices by index, so any transform applied to the
simple vertex array is applied to the entity.
Nentitiesverticesmetadataprocesscolorsvertex_attributesc                 V   Xl         X l        XPl        0 U l        [	        U[
        5      (       a  U R                  R                  U5        0 U l        Ub  U R                  R                  U5        [        R                  " U R                  S9U l        U(       a  U R                  5         gg)av  
Instantiate a path object.

Parameters
-----------
entities : (m,) trimesh.path.entities.Entity
  Contains geometric entities
vertices : (n, dimension) float
  The vertices referenced by entities
metadata : dict
  Any metadata about the path
process :  bool
  Run simple cleanup or not
colors
  Set any per-entity colors.
vertex_attributes
  Set any per-vertex array data.
N)id_function)r2   r3   r6   r4   
isinstancedictupdater7   r   Cache__hash___cachemerge_vertices)selfr2   r3   r4   r5   r6   r7   kwargss           k/var/www/eduai.edurigo.com/storigo/production/storigo_env/lib/python3.13/site-packages/trimesh/path/path.py__init__Path.__init__^   s    : !  h%%MM  *!#(""))*;< mm> !     c                     S[        U 5      R                   SU R                  R                   S[	        U R
                  5       S3$ )z?
Print a quick summary of the number of vertices and entities.
z	<trimesh.z(vertices.shape=z, len(entities)=z)>)type__name__r3   shapelenr2   rA   s    rC   __repr__Path.__repr__   sF     4:..//?@S@S?TTdehimivivewdxxz{{rF   returnc                     U R                      U R                  5         U R                  5         U R                  5         SSS5        U $ ! , (       d  f       U $ = f)z=
Apply basic cleaning functions to the Path object in-place.
N)r?   r@   remove_duplicate_entitiesremove_unreferenced_verticesrL   s    rC   r5   Path.process   sJ     [[!**,--/  	 [ s   1A
Ac                    U R                    Vs/ s H  oR                  PM     nn[        S U 5       5      (       d  g[        R                  " U Vs/ s H  n[        U5      PM     sn5      nSUR                  S'   U$ s  snf s  snf )zu
Colors are stored per-entity.

Returns
------------
colors : (len(entities), 4) uint8
  RGBA colors for each entity
c              3   (   #    U  H  oS Lv   M
     g 7fN ).0cs     rC   	<genexpr>Path.colors.<locals>.<genexpr>   s     .#QD=#s   NF	WRITEABLE)r2   coloranynparrayr   flags)rA   erawrY   r6   s        rC   r6   Path.colors   sp     !%.1ww..#...s3s!71:s34$)[! / 4s   A?Bvaluesc                     Uc  g[        U5      n[        U5      [        U R                  5      :w  a  [        S5      e[	        X R                  5       H  u  p4X4l        M     g)z
Set the color for every entity in the Path.

Parameters
------------
values : (len(entities), 4) uint8
  Color of each entity
Nzcolors must be per-entity!)r   rK   r2   
ValueErrorzipr]   )rA   re   r6   rY   rb   s        rC   r6   rd      sP     >v;#dmm,,9::.DAG /rF   c                     U R                   $ rV   )	_verticesrL   s    rC   r3   Path.vertices   s    ~~rF   c                     Uc)  [         R                  " / [        R                  S9U l        g [         R                  " U[        R                  S9U l        g )Ndtype)r   tracked_arrayr_   r   rj   rA   re   s     rC   r3   rk      s7    >$222RZZHDN$226LDNrF   c                     U R                   $ )z
The actual entities making up the path.

Returns
-----------
entities : (n,) trimesh.path.entities.Entity
  Entities such as Line, Arc, or BSpline curves
)	_entitiesrL   s    rC   r2   Path.entities   s     ~~rF   c                 x    Uc  [         R                  " / 5      U l        g [         R                  " U5      U l        g rV   )r_   r`   rr   
asanyarrayrp   s     rC   r2   rs      s&    >XXb\DN]]62DNrF   c                 X    U R                    Vs/ s H  oR                  PM     sn$ s  snf )z
Get a list of the layer for every entity.

Returns
---------
layers : (len(entities), ) any
  Whatever is stored in each `entity.layer`
r2   layerrA   rb   s     rC   layersPath.layers   s"     "&/A///s   'c                     [        U R                  R                  5       5      R                  S5      /nUR	                  S U R
                   5       5        [        R                  " SR                  U5      5      $ )zf
A hash of the current vertices and entities.

Returns
------------
hash : long int
  Appended hashes
zutf-8c              3   @   #    U  H  oR                  5       v   M     g 7frV   )_bytes)rX   rb   s     rC   rZ    Path.__hash__.<locals>.<genexpr>  s     :Mq

Ms   rF   )	hexr3   r>   encodeextendr2   r   	hash_fastjoin)rA   hashables     rC   r>   Path.__hash__   sY     ..0188AB:DMM::  (!344rF   c                     U R                   S-  R                  [        R                  5      n[	        UR                  SS95      R                  5       $ )zq
Return a hash of the identifier.

Returns
----------
hashed : (64,) str
  SHA256 hash of the identifier vector.
g     @C)order)
identifierastyper_   int64r   tobytes	hexdigest)rA   as_ints     rC   identifier_hashPath.identifier_hash  s@     //C'//9fnn3n/0::<<rF   c                 \    [         R                  " U R                  U R                  5      nU$ )z
Sequence of closed paths, encoded by entity index.

Returns
---------
paths : (n,) sequence of (*,) int
  Referencing self.entities
)r%   closed_pathsr2   r3   )rA   pathss     rC   r   
Path.paths  s#     &&t}}dmmDrF   c                 >   [        U R                  5      S:X  a)  [        R                  " [        U R                  5      5      $ [        R
                  " [        R                  " [        U R                  5      5      [        R                  " U R                  5      5      $ )zy
List of entities that aren't included in a closed path

Returns
----------
dangling : (n,) int
  Index of self.entities
r   )rK   r   r_   aranger2   	setdiff1dhstackrL   s    rC   danglingPath.dangling  s\     tzz?a99S/00||BIIc$--&89299TZZ;PQQrF   c                 j    [        U R                  R                  [        R                  5      5      nU$ )z
A KDTree object holding the vertices of the path.

Returns
----------
kdtree : scipy.spatial.cKDTree
  Object holding self.vertices
)r-   r3   viewr_   ndarray)rA   kdtrees     rC   r   Path.kdtree.  s&     ++BJJ78rF   c                 X   ^  [        [        U 4S jT R                   5       5      5      nU$ )zp
The total discretized length of every entity.

Returns
--------
length : float
  Summed length of every entity
c              3   X   >#    U  H  oR                  TR                  5      v   M!     g 7frV   )lengthr3   )rX   irA   s     rC   rZ   Path.length.<locals>.<genexpr>E  s     JMq88DMM22Ms   '*)floatsumr2   )rA   r   s   ` rC   r   Path.length;  s#     sJDMMJJKrF   c                    [         R                  " U R                   Vs/ s H  oR                  U R                  5      PM     sn[         R
                  S9nUR                  SU R                  R                  S   45      n[         R                  " UR                  SS9UR                  SS9/[         R
                  S9$ s  snf )z
Return the axis aligned bounding box of the current path.

Returns
----------
bounds : (2, dimension) float
  AABB with (min, max) coordinates
rm   r    r   axis)
r_   r`   r2   r   r3   r   reshaperJ   minmax)rA   rb   pointss      rC   r   Path.boundsH  s     .2mm<mXXdmm$m<BJJ

 T]]%8%8%; <=xx+VZZQZ-?@

SS =s   $C c                 4    U R                   R                  SS9$ )z
Return the centroid of axis aligned bounding box enclosing
all entities of the path object.

Returns
-----------
centroid : (d,) float
  Approximate centroid of the path
r   r   )r   meanrL   s    rC   centroidPath.centroid_  s     {{Q''rF   c                 @    [         R                  " U R                  SS9$ )zr
The size of the axis aligned bounding box.

Returns
---------
extents : (dimension,) float
  Edge length of AABB
r   r   )r_   ptpr   rL   s    rC   extentsPath.extentsl  s     vvdkk**rF   desiredguessc                 .    [         R                  " XUS9  g)z
Convert the units of the current drawing in place.

Parameters
-----------
desired : str
  Unit system to convert to
guess : bool
  If True will attempt to guess units
)r   r   N)r   _convert_units)rA   r   r   s      rC   convert_unitsPath.convert_unitsx  s     	T%@rF   c                     / nU R                    H"  nUR                  UR                  5       5        M$     [        R                  " U5      U l        U R                  R                  5         g)zJ
Turn every multi- segment entity into single segment
entities in- place.
N)r2   r   exploder_   r`   rr   r?   clear)rA   new_entitiesentitys      rC   r   Path.explode  sN    
 mmF 01 $ ,/rF   c                 ,    [         R                  " XS9  g)z
Find vertices without degree 2 and try to connect to
other vertices. Operations are done in-place.

Parameters
----------
distance : float
  Connect vertices up to this distance
)distanceN)r+   	fill_gaps)rA   r   s     rC   r   Path.fill_gaps  s     	1rF   c                     [        S [        U R                  R                  5       5      R	                  5        5       5      nU$ )zz
Are all entities connected to other entities.

Returns
-----------
closed : bool
  Every entity is connected at its ends
c              3   *   #    U  H	  oS :H  v   M     g7f)r   NrW   rX   r   s     rC   rZ   !Path.is_closed.<locals>.<genexpr>  s     O%N!V%Ns   )allr;   vertex_graphdegreere   )rA   closeds     rC   	is_closedPath.is_closed  s6     OT$*;*;*B*B*D%E%L%L%NOOrF   c                 2    [        U R                  5      S:H  $ )zs
Are any entities defined for the current path.

Returns
----------
empty : bool
  True if no entities are defined
r   )rK   r2   rL   s    rC   is_emptyPath.is_empty  s     4==!Q&&rF   c                 J    [         R                  " U R                  5      u  pU$ )zk
Return a networkx.Graph object for the entity connectivity

graph : networkx.Graph
  Holds vertex indexes
)r%   r   r2   )rA   graph_closeds      rC   r   Path.vertex_graph  s     #//>rF   c                     [         R                  " U R                   Vs/ s H  oR                  PM     sn5      nU$ s  snf )z
Get a list of which vertex indices are nodes,
which are either endpoints or points where the
entity makes a direction change.

Returns
--------------
nodes : (n, 2) int
  Indexes of self.vertices which are nodes
)r_   vstackr2   nodes)rA   rb   r   s      rC   vertex_nodesPath.vertex_nodes  s1     		DMM:Mq77M:; ;s   =	transformc                    U R                   R                  S   n[        R                  " U[        R                  S9nUR                  US-   US-   4:w  a  [        S5      e[        R                  " U[        R                  " US-   5      -
  5      R                  5       S:  a  U $ U R                  R                  5         0 nSU R                  R                  ;   a2  U R                   Vs/ s H  n[        R                  " XAS9PM     snUS'   S H9  nXPR                  R                  ;   d  M  U R                  R                  U   X5'   M;     [        R                  " U R                   US9U l         U R                  R                  5         U R                  R!                  5         U R                  R                  R#                  U5        U $ s  snf )z
Apply a transformation matrix to the current path in- place

Parameters
-----------
transform : (d+1, d+1) float
  Homogeneous transformations for vertices
r    rm   ztransform is incorrect shape!g:0yE>discrete)matrix)rootr   
path_validr   r   	enclosureenclosure_shellenclosure_directed)r3   rJ   r_   ru   r   rg   abseyer   r?   verifycacher   tftransform_pointsr   id_setr<   )rA   r   	dimensionr   dkeys         rC   apply_transformPath.apply_transform  sj    MM''*	MM)2::>	??y1}i!m<<<==VVIy1} 556::<tCK 	***BF--!BOQ##A8-!E*	
C kk'''![[..s3
	
 ++DMM)L 	  '9!s   (G
namec                 6    U R                    H	  nXl        M     g)zx
Apply a layer name to every entity in the path.

Parameters
------------
name : str
  Apply layer name to every entity
Nrw   )rA   r   rb   s      rC   apply_layerPath.apply_layer	  s     AG rF   c                 p    [         R                  " U R                  S   * 5      nU R                  U5        U$ )z
Translate so that every vertex is positive in the current
mesh is positive.

Returns
-----------
matrix : (dimension + 1, dimension + 1) float
  Homogeneous transformations that was applied
  to the current Path object.
r   )r   translation_matrixr   r   rA   r   s     rC   rezeroPath.rezero  s1     &&A7V$rF   c                    [        U R                  5      S:X  a  gUc0  [        R                  " [        R
                  U R                  -  SS9n[        R                  " U R                  US9u  p#U R                  U   U l        U R                  R                  5        VVs0 s H  u  pEU[        R                  " U5      U   _M!     snnU l	        [        R                  " [        U R                  5      [        S9n[!        U R                  5       H  u  px[#        U5      R$                  n	U	S;   a  X8R&                     Ul        M5  [        R(                  " X8R&                     5      n
U	S:X  a5  [        U
5      S	:X  a  U
S   U
S
   :X  a  U
SS n
O-[        U
5      S:  a  SXg'   OU	S:X  a  [        U
5      S	:w  a  SXg'   Xl        M     U R                  U   U l        gs  snnf )z
Merges vertices which are identical and replace references
by altering `self.entities` and `self.vertices`

Parameters
--------------
digits : None, or int
  How many digits to consider when merging vertices
r   Nr    )
min_digits)digitsrm   zBSpline Bezier TextLine   r   r   FArc)rK   r3   r   decimal_to_digitstolmergescaler   unique_rowsr7   itemsr_   r`   onesr2   bool	enumeraterH   rI   r   
merge_runs)rA   r   uniqueinverser   valueentities_okindexr   kindr   s              rC   r@   Path.merge_vertices'  s    t}}">++CII

,BqQF"..t}}VLf-;?;Q;Q;W;W;Y"
;YZSC%((;Y"
 ggc$--0=&t}}5ME<((D ,, ' 6 (()?@Fv~v;!#q	VBZ(?#BQZF[1_).K&3v;!#3%*" #M1 66 k2C"
s    &Gc                 P    U R                    H  nXR                     Ul        M     g)z
Replace the vertex index references in every entity.

Parameters
------------
mask : (len(self.vertices), ) int
  Contains new vertex indexes

Notes
------------
entity.points in self.entities
  Replaced by mask[entity.points]
N)r2   r   )rA   maskr   s      rC   replace_vertex_referencesPath.replace_vertex_references[  s      mmF /FM $rF   c                     [        U5      S:X  a  g[        R                  " [        U R                  5      [        S9nSX!'   U R                  U   U l        g)zn
Remove entities by index.

Parameters
-----------
entity_ids : (n,) int
  Indexes of self.entities to remove
r   Nrm   F)rK   r_   r
  r2   r  )rA   
entity_idskeeps      rC   remove_entitiesPath.remove_entitiesl  sD     z?awws4==)6 d+rF   c                     [         R                  " U R                   Vs/ s H  oR                  PM     sn[        S9nU R                  U   U l        gs  snf )z]
Remove entities which declare themselves invalid

Notes
----------
self.entities: shortened
rm   N)r_   r`   r2   is_validr  )rA   r   valids      rC   remove_invalidPath.remove_invalid{  s>     dmm<m**m<DIe, =s   Ac                     [         R                  " U R                   Vs/ s H  n[        U5      PM     sn5      n[        R
                  " U5      u  p4[        U5      [        U R                  5      :w  a  U R                  U   U l        ggs  snf )zZ
Remove entities that are duplicated

Notes
-------
self.entities: length same or shorter
N)r_   r`   r2   hashr   r  rK   )rA   r   entity_hashesr  _inverses        rC   rQ   Path.remove_duplicate_entities  sl     4==!A=a$q'=!AB#//>v;#dmm,, MM&1DM - "Bs   Bc                 Z   [        U R                  5      S:X  a#  [        R                  " / [        R                  S9$ [        R
                  " [        R                  " U R                   Vs/ s H  oR                  PM     sn5      R                  [        R                  5      5      $ s  snf )zz
Which vertices are referenced by an entity.

Returns
-----------
referenced_vertices: (n,) int, indexes of self.vertices
r   rm   )	rK   r2   r_   r`   r   r  r*   r   r   ry   s     rC   referenced_verticesPath.referenced_vertices  sn     t}}"88Bbhh//yyNNdmm<mHHm<=DDRXXN
 	
<s   +B(c                 0   U R                   n[        R                  " [        U R                  5      [        R
                  S9S-  n[        R                  " [        U5      [        R
                  S9X!'   U R                  US9  U R                  U   U l        g)z
Removes all vertices which aren't used by an entity.

Notes
---------
self.vertices : reordered and shortened
self.entities : entity.points references updated
rm   r   )r  N)r)  r_   r
  rK   r3   r   r   r  )rA   r  r  s      rC   rR   !Path.remove_unreferenced_vertices  sl     ))wws4==):R?yyVBHH=&&D&1f-rF   c           
          U R                   nU R                  nU R                  nU R                   Vs/ s H  n[        R
                  " X#XAS9PM     sn$ s  snf )z
A sequence of connected vertices in space, corresponding to
self.paths.

Returns
---------
discrete : (len(self.paths),)
    A sequence of (m*, dimension) float
)r2   r3   pathr  )r  r2   r3   r   r%   discretize_path)rA   r  r2   r3   r.  s        rC   r   Path.discrete  s^     

==== 

	
 # %%!4 #	
 	
 
s   Ac                     [        U 4X!S.UD6$ )a  
Export the path to a file object or return data.

Parameters
---------------
file_obj : None, str, or file object
  File object or string to export to
file_type : None or str
  Type of file: dxf, dict, svg

Returns
---------------
exported : bytes or str
  Exported as specified type
)	file_typefile_objr'   )rA   r3  r2  rB   s       rC   exportPath.export  s      4R9R6RRrF   c                      U R                  SS9$ )Nr;   )r2  )r4  rL   s    rC   to_dictPath.to_dict  s    {{V{,,rF   rz   c                    0 n[        U R                  R                  5       5       H  n [        U R                  U   5      X#'   M      UbR  [        U[        5      (       a  U1nO[        U5      nU R                   Vs/ s H  oDR                  U;   d  M  UPM     nnOU R                  n[        U 5      " [        U5      [        U R                  5      USS9nUb  U$ 0 n [        U R                  R                  R                  5       5      nU H'  n	[        U R                  R                  U	   5      Xy'   M)     XvR                  l        UR                  R'                  5         U$ ! [         a    [
        R                  " SU S35         GMg  f = fs  snf ! [         a    [
        R                   " S5         N["         a    [
        R$                  " SSS9   Nf = f)z
Get a copy of the current mesh

Parameters
------------
layers
  If passed an iterable of layer names which will
  only include those layers in the copy of the path.

Returns
---------
copied : Path object
  Copy of self
zkey z changed during copyFr2   r3   r4   r5   zunable to copy cacheTexc_info)listr4   keysr   RuntimeErrorr   warningr:   strsetr2   rx   rH   r3   r?   r   debugBaseExceptionerrorr   )
rA   rz   r4   r   rb   r2   copiedr   r>  ks
             rC   copy	Path.copy  s      **,-C> (s); < . &#&&  V#'==F=aGGv4E=HFH}}H dh'dmm,	
 M	=))..01D#DKK$5$5a$89  $]   >d3%';<==> G0  	.II,- 	=II,t<	=s6   E%=FFAF %$FF G8GGc                 "    SSK Jn  U" U 5      nU$ )z
Get a scene object containing the current Path3D object.

Returns
--------
scene: trimesh.scene.Scene object containing current path
r   )Scene)scenerK  )rA   rK  rL  s      rC   rL  
Path.scene(  s     	"drF   c                     [        X/5      nU$ )z
Concatenate two Path objects by appending vertices and
reindexing point references.

Parameters
-----------
other: Path object

Returns
-----------
concat: Path object, appended from self and other
r)   )rA   otherconcats      rC   __add__Path.__add__5  s     d]+rF   )r?   rr   rj   r6   r2   r4   r7   r3   )NNNTNNF)g?rV   NN)=rI   
__module____qualname____firstlineno____doc__r   r   r   r&   r   r   r  rD   rM   r   r5   propertyr   r6   setterr   r3   r2   rz   r>   r   r   r   r   r   r   r   r   r   rA  r   r   r   r   r   r   r   r   r   r   r@   r  r  r!  rQ   r)  rR   r   r   r4  r;   r7  rH  rL  rQ  __static_attributes__rW   rF   rC   r0   r0   S   sX    >B(,&*&*/31"	8F#3T9:1" 9%1" 7#	1"
 1" #1" $G,1"f|  )  & ]]Xi0  ( ''*   __Mx	2 M M 	 	 __3 3 
0 
05  
= 
= 
 
 R R 
 
 
 
 T T, 
(''* 
( 
( 	+) 	+ 	+AS A A
2   	' 	'    4 4t 4l
 
 
$23h0",	-2 
 
.$ 
$ww/0 
 
.S$- -D5dHU395E,F!FG DLrF   r0   c                       \ rS rSrSrS r   SS\\   S\\   S\S\	S	\
\   4   4S
 jjr\S\
\   4S j5       r\S 5       rS rSrg)Path3DiF  @
Hold multiple vector curves (lines, arcs, splines, etc) in 3D.
c                 Z    [         R                  " S[        SS9  U R                  " U0 UD6$ )zF
DEPRECATED: replace `path.to_planar`->`path.to_2D), removal 1/1/2026
zDDEPRECATED: replace `path.to_planar`->`path.to_2D), removal 1/1/2026r   )category
stacklevel)warningswarnDeprecationWarningto_2D)rA   argsrB   s      rC   	to_planarPath3D.to_planarK  s/     	R'	

 zz4*6**rF   Nre  normalcheckrO   Path2Dc                 R   U R                   n[        U5      S:X  a   [        5       [        R                  " S5      4$ U R
                  R                  S   nUS:X  a  [        R                  " S5      nOUS:w  a  [        SU S35      eUc  [        U R
                  U   5      u  pgUb_  [        R                  " U[        R                  S	9R                  S5      nU[        R                  " [        R                  " Xr5      5      -  n[        XgS
9n[        R                  " U[        R                  S	9nUR                  S:w  a  [        S5      eUS:X  az  [        R                   " U R
                  U5      nX   SS2S4   n	[        R"                  " U	5      [$        R&                  :  a  Sn
U(       a  [        S5      eO3U	R)                  5       n
O"US:X  a  U R
                  R+                  5       nSn
[        R,                  R/                  U5      n[        R0                  " W
5      [$        R&                  :  a/  [        R2                  " SSU
/5      n[        R                  " X5      n[5        U R6                  5      nXS'   [        [5        U R8                  5      WSS2SS24   USS9nX4$ )aR  
Check to see if current vectors are all coplanar.

If they are, return a Path2D and a transform which will
transform the 2D representation back into 3 dimensions

Parameters
-----------
to_2D : (4, 4) float
  Homogeneous transformation matrix to apply,
  if not passed a plane will be fitted to vertices.
normal : (3,) float or None
  Normal of direction of plane to use.
check
  Raise a ValueError if points aren't coplanar.

Returns
-----------
planar
  Current path transformed onto plane
to_3D : (4, 4) float
  Homeogenous transformations to move planar
  back into the original 3D frame.
r      r    r   r  zvertices are `zD != 2D | 3D`!Nrm   )originri  )rm  rm  zunable to create transform!g        zpoints are not flat!to_3DFr:  )r)  rK   rk  r_   r   r3   rJ   rg   r   r`   r   r   signdotr   r   r   r   r  planarr   rH  linalginvr   r   r   r4   r2   )rA   re  ri  rj  
referenceddimr   Nflatheightsheightro  adjustr4   rr  s                  rC   re  Path3D.to_2DV  s/   > --
z?a8RVVAY&& mm!!!$ !8FF1IEAX~cU.ABB =T]]:67DA!&

;CCAFRWWRVVA.//#17E bjj1;;& :;;!8&&t}}e<D&q!t,Gvvg+$%;<<  !AX==%%'DF 		e$ 66&>CJJ&**Aq&>:FFF5)E DMM*! dmm,!RaR%[	
 }rF   c                     [         R                  " [        R                  " U R                  5      U R
                  /45      $ )z-
Return a simple identifier for the 3D path.
)r_   r*   r   identifier_simpleconvex_hullr   rL   s    rC   r   Path3D.identifier  s4    
 ~~))$*:*:;dkk]K
 	
rF   c                 \    [         R                  " U R                  U R                     5      $ )z{
Return a convex hull of the 3D path.

Returns
--------
hull : trimesh.Trimesh
  A mesh of the convex hull of the 3D path.
)r	   r  r3   r)  rL   s    rC   r  Path3D.convex_hull  s$     !!$--0H0H"IJJrF   c                 F    U R                  5       nUR                  " S0 UD6$ )z!
Show the current Path3D object.
rW   )rL  show)rA   rB   rL  s      rC   r  Path3D.show  s!     

zz#F##rF   rW   )NNT)rI   rU  rV  rW  rX  rg  r   r   r  r   r   r   re  r   r   r  r  r[  rW   rF   rC   r]  r]  F  s    	+ &*&*	j	"j #j 	j
 
x))	*jX 
GG, 
 
 	K 	K$rF   r]  c                      \ rS rSrSrS!S jrS rS r\S 5       r	\S"S j5       r
 S#S
 jrS r\S 5       rS$S jr\S\4S j5       r\S\4S j5       r\S 5       rS rS rS%S jrS&S jrS rS'S jrS rS(S jrS)S jr\S 5       r\S 5       r\S\\ RB                     4S j5       r"\S 5       r#\S 5       r$\S 5       r%S r&g	)*rk  i  r^  c                 h    U R                   (       a  U R                  SUS9  gU R                  SUS9  g)z2
Plot the current Path2D object using matplotlib.
T)r  annotationsN)r   plot_discreteplot_entities)rA   r  s     rC   r  Path2D.show  s1     >>DkBDkBrF   c                 @    U R                   nU R                  U5        U$ )z
Transform the current path so that its OBB is axis aligned
and OBB center is at the origin.

Returns
-----------
obb : (3, 3) float
  Homogeneous transformation matrix
)obbr   r   s     rC   	apply_obbPath2D.apply_obb  s      V$rF   c                 v    [         R                  " S5      nUSS2SS24==   U-  ss'   U R                  U5      $ )zz
Apply a 2D scale to the current Path2D.

Parameters
-------------
scale : float or (2,) float
  Scale to apply in-place.
r  Nr   )r_   r   r   )rA   r  r   s      rC   apply_scalePath2D.apply_scale  s<     rr2A2v%##F++rF   c                 f    [         R                  " U R                  U R                     5      S   nU$ )z
Get a transform that centers and aligns the OBB of the
referenced vertices with the XY axis.

Returns
-----------
obb : (3, 3) float
  Homogeneous transformation matrix
r   )r   oriented_bounds_2Dr3   r)  r   s     rC   r  
Path2D.obb  s.     **4==9Q9Q+RSTUVrF   rO   c           	      z   SSK Jn  SSKJn  U R                  U R
                     /nUR                  U R                  5        [        R                  " U5      n[        U5      S:  a
  [        5       $  U" U5      n[        R                  " [        UR                   5      5      n[        R                  " [        UR                  5      5      XTR                  '   XTR"                     nUR                   UR                     n[        S
0 U" XgS	9D6$ ! [         a"    [        R                  " SSS9  [        5       s $ f = f)zr
Return a convex hull of the 2D path.

Returns
--------
hull
  A convex hull of included vertices from this path.
r   )
ConvexHullr    edges_to_pathr  zFailed to construct convex hullTr;  edgesr3   rW   )scipy.spatialr  exchange.miscr  r3   r)  r   r   r_   r   rK   rk  rD  r   rC  r   r   	simplices)rA   r  r  
candidateshullremapr  r3   s           rC   r  Path2D.convex_hull  s     	-0 mmD$<$<=>
 	$--(YYz*
 z?Q8O	j)D 		#dkk*+!yyT]]);<mm nn%;;t}}-FEEFF  	 II7$G8O		s   2D )D:9D:Nc           	      8    [         R                  " U UUUUUS9nU$ )a  
Rasterize a Path2D object into a boolean image ("mode 1").

Parameters
------------
pitch : float or (2,) float
  Length(s) in model space of pixel edges
origin : (2,) float
  Origin position in model space
resolution : (2,) int
  Resolution in pixel space
fill : bool
  If True will return closed regions as filled
width : int
  If not None will draw outline this wide (pixels)

Returns
------------
raster : PIL.Image object, mode 1
  Rasterized version of closed regions.
)pitchrn  
resolutionfillwidth)r"   	rasterize)rA   r  rn  r  r  r  rB   images           rC   r  Path2D.rasterizeD  s-    0   !
 rF   c           
      L   U R                   n[        U5      S:X  a  [        R                  " / 5      nU$ [        U5      S:X  a  [        R
                  " US   4SU0UD6nU$ [        R                  " U Vs/ s H  n[        R
                  " U4SU0UD6PM     sn5      nU$ s  snf )a  
Use rejection sampling to generate random points inside a
polygon.

Parameters
-----------
count : int
  Number of points to return
  If there are multiple bodies, there will
  be up to count * bodies points returned
factor : float
  How many points to test per loop
  IE, count * factor
max_iter : int,
  Maximum number of intersection loops
  to run, total points sampled is
  count * factor * max_iter

Returns
-----------
hit : (n, 2) float
  Random points inside polygon
r   r    count)polygons_fullrK   r_   r`   r,   sampler   vstack_empty)rA   r  rB   polysamplesr   s         rC   r  Path2D.samplef  s    2 !!t9>hhrlG  Y!^ood1gEUEfEG 	 ''DHIDq:%:6:DIG  Js   5#B!c                 ,    [        U R                  5      $ )z
Returns a count of the number of unconnected polygons that
may contain other curves but aren't contained themselves.

Returns
---------
body_count : int
  Number of unconnected independent polygons.
)rK   r   rL   s    rC   
body_countPath2D.body_count  s     499~rF   c                    Uc  SU R                   ;   a  U R                   S   n[        R                  " [        U R                  5      [        R
                  " [        U R                  5      5      45      nUb  [        R                  " X!5      n[        [        U R                  5      U[        U R                   5      S9nU$ )a  
Convert 2D path to 3D path on the XY plane.

Parameters
-------------
transform : (4, 4) float
  If passed, will transform vertices.
  If not passed and 'to_3D' is in self.metadata
  that transform will be used.

Returns
-----------
path_3D : Path3D
  3D version of current path
ro  )r2   r3   r4   )r4   r_   column_stackr   r3   zerosrK   r   r   r]  r2   )rA   r   r3   path_3Ds       rC   ro  Path2D.to_3D  s    " DMM!9g.I ??dmm$bhhs4==/A&BC
  **8?Hdmm,dmm,

 rF   c                 B    [         R                  " U R                  5      $ )a@  
Cycles in the vertex graph, as shapely.geometry.Polygons.
These are polygon objects for every closed circuit, with no notion
of whether a polygon is a hole or an area. Every polygon in this
list will have an exterior, but NO interiors.

Returns
---------
polygons_closed : (n,) list of shapely.geometry.Polygon objects
)r,   paths_to_polygonsr   rL   s    rC   polygons_closedPath2D.polygons_closed  s     ))$--88rF   c                    S/[        U R                  5      -  nU R                  nU R                  n[	        U R                  5       H  u  pEX%   R                  5        Vs/ s H  ocU   PM	     nnU Vs/ s H3  n[        R                  " UR                  R                  5      SSS2   PM5     n	nX5   R                  n
[        R                  " [        XS95      X'   M     U$ s  snf s  snf )z
A list of shapely.geometry.Polygon objects with interiors created
by checking which closed polygons enclose which other polygons.

Returns
---------
full : (len(self.root),) shapely.geometry.Polygon
    Polygons containing interiors
Nr   )shellholes)rK   r   r   r  r  r>  r_   r`   exteriorcoordsr,   repair_invalidr.   )rA   fullr   r   r   r   childchildrenpr  r  s              rC   r  Path2D.polygons_full  s     vDII&++	%% !+GA 4=?3G3G3IJ3I%u3IHJ@HI1RXXajj//026EIL))E--gE.OPDG ,  KIs    C#4:C(c                 P    [        [        S U R                   5       5      5      nU$ )zt
Return the area of the polygons interior.

Returns
---------
area : float
  Total area of polygons minus interiors
c              3   8   #    U  H  oR                   v   M     g 7frV   )arear   s     rC   rZ   Path2D.area.<locals>.<genexpr>  s     <);A);s   )r   r   r  )rA   r  s     rC   r  Path2D.area  s$     S<););<<=rF   c           	          SSK Jn  U R                   Vs/ s H  oC" SXAS.UD6PM     nn[        U5      S:X  a  US   $ U$ s  snf )a  
Extrude the current 2D path into a 3D mesh.

Parameters
----------
height: float, how far to extrude the profile
kwargs: passed directly to meshpy.triangle.build:
        triangle.build(mesh_info,
                       verbose=False,
                       refinement_func=None,
                       attributes=False,
                       volume_constraints=True,
                       max_volume=None,
                       allow_boundary_steiner=True,
                       allow_volume_steiner=True,
                       quality_meshing=True,
                       generate_edges=None,
                       generate_faces=False,
                       min_angle=None)
Returns
--------
mesh: trimesh object representing extruded polygon
r   )	Extrusion)polygonrz  r    r   rW   )
primitivesr  r  rK   )rA   rz  rB   r  r   results         rC   extrudePath2D.extrude  s]    0 	+ DHCUCU
CUaI9a9&9CU 	 
 v;!!9
s   A c                     SSK Jn  / n/ nU R                   H0  nU" U40 UD6u  pgUR                  U5        UR                  U5        M2     [        R
                  " X45      $ )a  
Create a region- aware triangulation of the 2D path.

Parameters
-------------
**kwargs : dict
  Passed to `trimesh.creation.triangulate_polygon`

Returns
-------------
vertices : (n, 2) float
  2D vertices of triangulation
faces : (n, 3) int
  Indexes of vertices for triangles
r   )triangulate_polygon)r!   r  r  appendr   append_faces)rA   rB   r  v_seqf_seqr  vfs           rC   triangulatePath2D.triangulate  s_      	3  ))G&w9&9DALLOLLO *
   ..rF   c                 
   Uc  U R                   S-  nSSKJn  U R                   Vs/ s H  n[        R
                  " XAU5      PM     nnU VVs/ s H  u  pg[        S0 U" XgS9D6PM     nnn[        U5      n	U	$ s  snf s  snnf )ae  
Find the approximate medial axis based
on a voronoi diagram of evenly spaced points on the
boundary of the polygon.

Parameters
----------
resolution : None or float
  Distance between each sample on the polygon boundary
clip : None, or (2,) float
  Min, max number of samples

Returns
----------
medial : Path2D object
  Contains only medial axis of Path
g     @@r    r  r  rW   )r  r  r  r  r,   medial_axisrk  r*   )
rA   r  clipr  r   	edge_vertrb   r  medialsmedials
             rC   r  Path2D.medial_axis6  s    $ f,J 	1 @D?Q?Q
?Q!H  5?Q 	 
 MVVIDA6?M>?IV W%
 Ws   !A:A?c                 D   [        U R                  5      S:X  a*  [        R                  " [        U R                  5      5      nO*[        [        R                  " U R                  U5      5      nU(       a  [        R                  " U5      $ [        R                  " X1/5      $ )a&  
Given an index of self.paths find other paths which
overlap with that path.

Parameters
-----------
path_id : int
  Index of self.paths
include_self : bool
  Should the result include path_id or not

Returns
-----------
path_ids :  (n, ) int
  Indexes of self.paths that overlap input path_id
r    )rK   r   r_   r   r  r=  nxnode_connected_componentr   r`   r   )rA   path_idinclude_selfpath_idss       rC   connected_pathsPath2D.connected_pathsZ  sk    " tyy>QyyT%9%9!:;HB77PQH88H%%||Hi00rF   c                 0    [         R                  " U 40 UD6$ )z
Return a version of the current path with colinear segments
merged, and circles entities replacing segmented circular paths.

Returns
---------
simplified : Path2D object
)r$   simplify_basicrA   rB   s     rC   r$   Path2D.simplifys  s     &&t6v66rF   c                 ,    [         R                  " XUS9$ )z
Convert paths into b-splines.

Parameters
-----------
smooth : float
  How much the spline should smooth the curve
verbose : bool
  Print detailed log messages

Returns
------------
simplified : Path2D
  Discrete curves replaced with splines
)smoothverbose)r$   simplify_spline)rA   r  r  s      rC   r  Path2D.simplify_spline~  s      ''WMMrF   c                 .    [         R                  " U 5      $ )z
If the current Path2D consists of n 'root' curves,
split them into a list of n Path2D objects

Returns
----------
split:  (n,) list of Path2D objects
  Each connected region and interiors
)r%   splitr  s     rC   r  Path2D.split  s     t$$rF   c                    SSK Jn  UR                  5       nUR                  SS5        [	        U R
                  5       H4  u  pVSS/XPR                  ;      nUR                  " UR                  SU06  M6     U(       aA  U R                   H1  n[        US5      (       d  M  UR                  U R                  5        M3     U(       a  UR                  5         U$ )	z%
Plot the closed curves of the path.
r   NequaldatalimgrG  r]   plot)matplotlib.pyplotpyplotgca
set_aspectr  r   r   r  Tr2   hasattrr3   r  )	rA   r  r  pltr   r   r   r]   rb   s	            rC   r  Path2D.plot_discrete  s     	(wwy+"4==1IA#JqII~.EIIvxx-u- 2 ]]q&))t}}% #
 HHJrF   c           
         SSK Jn  UR                  5       nUR                  SS5        SSS.SSS.S	SS.S
SS.SSS.SSS.SSS.SSS.S.nU R                   H  nU(       a.  [        US5      (       a  UR                  U R                  5        M8  UR                  U R                  5      nUR                  R                  [        [        UR                  5      5      -   n	Xi   R                  5       n
Ub  X:S'   O [        US5      (       a  UR                  U
S'   UR                  " UR                   0 U
D6  M     U(       a  UR#                  5         gg)a  
Plot the entities of the path with no notion of topology.

Parameters
------------
show : bool
  Open a window immediately or not
annotations : bool
  Call an entities custom plot function.
color : str
  Override entity colors and make them all this color.
r   Nr  r  r  r    )r]   	linewidthyrbrG  m)Line0Line1Arc0Arc1Bezier0Bezier1BSpline0BSpline1r  r]   )r   r  r  r  r2   r  r  r3   r   	__class__rI   rA  intr   rH  r]   r  r  )rA   r  r  r]   r  r   eformatr   r   e_keyfmts              rC   r  Path2D.plot_entities  s2    	( wwy+  #3"3!2!2!$15!$15"%A6"%A6	
 mmFwvv66DMM*t}}5H$$--C4F0GGE.%%'C $G))%||GIIxzz)S)# $$ HHJ rF   c                 ,   [         R                  nU R                  n[        U5      S:X  a  U" U R                  S   5      $ [        U5      S:X  a  [        R
                  " S5      $ [        R                  " U Vs/ s H
  o1" U5      PM     snSS9$ s  snf )zb
A unique identifier for the path.

Returns
---------
identifier : (5,) float
  Unique identifier
r    r      r   )r,   r   r  rK   r_   r  r   )rA   hashertargetr  s       rC   r   Path2D.identifier  s}     $$##v;!$,,Q/00[A88A;vv&1&Qvay&1::1s   :Bc                 v    [         R                  " U R                   Vs/ s H  oSLPM     sn[        S9$ s  snf )zt
Returns
----------
path_valid : (n,) bool
  Indexes of self.paths self.polygons_closed
  which are valid polygons.
Nrm   )r_   r`   r  r  )rA   r   s     rC   r   Path2D.path_valid  s1     xx0D0DE0D1$0DETRREs   6c                 8    U R                   nU R                  S   $ )z
Which indexes of self.paths/self.polygons_closed
are root curves, also known as 'shell' or 'exterior.

Returns
---------
root : (n,) int
  List of indexes
r   )r   r?   )rA   populates     rC   r   Path2D.root  s     **{{6""rF   c                     U R                      U R                  R                  5       nSSS5        U$ ! , (       d  f       W$ = f)z
Undirected graph object of polygon enclosure.

Returns
-----------
enclosure : networkx.Graph
  Enclosure graph of self.polygons by index.
N)r?   r   to_undirected)rA   
undirecteds     rC   r   Path2D.enclosure  s8     [[00>>@J  [s	   2
Ac                 f    [         R                  " U R                  5      u  pXR                  S'   U$ )z
Directed graph of polygon enclosure.

Returns
----------
enclosure_directed : networkx.DiGraph
  Directed graph: child nodes are fully
  contained by their parent node.
r   )r,   enclosure_treer  r?   )rA   r   r   s      rC   r   Path2D.enclosure_directed  s.     #11$2F2FG"FrF   c           	          U R                    Vs/ s H  oU R                  USS94PM     nn[        R                  " U5      $ s  snf )z
A dictionary of path indexes which are 'shell' paths, and values
of 'hole' paths.

Returns
----------
corresponding : dict
  {index of self.paths of shell : [indexes of holes]}
F)r  )r   r  collectionsOrderedDict)rA   r  pairss      rC   r   Path2D.enclosure_shell-  sH     LP99U9aT))!%)@A9U&&u-- Vs   ArW   )T)rO   rk  )NNNTNrV   rT  rS  )g-C6*?F)FT)FTN)'rI   rU  rV  rW  rX  r  r  r  r   r  r  r  r  rY  r  ro  r   r  r   r  r  r  r  r  r  r$   r  r  r  r  r   r   r_   r   r   r   r   r   r[  rW   rF   rC   rk  rk    st   C,   +G +G\ JN D#J 
 
 D 9 9 9 t  > 
 
B/<"H12	7N$
%.0d ; ;" S S #gbhh' # #     . .rF   rk  )DrX  r.  rb  rH  r   hashlibr   numpyr_    r   r   r   r	   r
   r   r   r   r   r   r   r   	constantsr   r   r  geometryr   r   r   typedr   r   r   r   r   r   r   r   r   r   visualr   r!   r"   r#   r$   r%   r2   r&   exchange.exportr(   r*   r+   rD  EExceptionWrapperr,   r  r-   shapely.geometryr.   networkxr  Geometryr0   r]  rk  rW   rF   rC   <module>r?     sf       
 
 
 % %  ' &       ( 
,.-%-((
p6?? pfV$T V$r[	.T [	.C  ,((+F,  .**1-H.  -))!,G-  -))!,G-
  (		$	$Q	'B(sx   C  D "D* )E 0E4  D&C==DD'D""D'*E0EEE1E,,E14F:FF