
    j3{                        d Z ddlZddlZddlmZmZmZ ddlm	Z	m
Z
 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 	 ddlmZmZ dd	lmZ 	 ddl!Z"d+d
Z#dee   fdZ$d Z%d Z&d Z'd Z(	 d,dedee   fdZ)	 	 	 	 d-de*de*dee   dedef
dZ+	 d.dedefdZ,d/dZ-dedee   fdZ.dededeeef   fdZ/d0d Z0d,d!Z1d1d"Z2	 d2d#ee   d$ee   fd%Z3	 d/ded&ee   dee*e*f   fd'Z4d( Z5d/d)Z6d/d*Z7y# e$ r@Z ej@                  e      Z ej@                  e      Z ej@                  e      ZY dZ[dZ[ww xY w# e$ rZ ej@                  e      Z"Y dZ[dZ[ww xY w)3z
graph.py
-------------

Deal with graph operations. Primarily deal with graphs in (n, 2)
edge list form, and abstract the backend graph library being used.

Currently uses networkx or scipy.sparse.csgraph backend.
    N   )
exceptionsgroupingutil)logtol)faces_to_edges)	ArrayLikeGraphEngineTypeIntegerListNDArrayNumberOptionalSequenceTupleUnionint64)
coo_matrixcsgraph)cKDTreec                    |#t        | d      \  }}|j                  d       n|j                  }|j                  }t	        j
                  |d      }t        |      dk(  rt        j                  d	       ||   }|dddf   |dddf   k7  }||   }|j                  d       |r,||dddf   |      }t        |      t        |      k(  sJ ||fS |S )
a  
    Returns an (n, 2) list of face indices.
    Each pair of faces in the list shares an edge, making them adjacent.


    Parameters
    -----------
    faces : (n, 3) int, or None
        Vertex indices representing triangles
    mesh : Trimesh object
        If passed will used cached edges
        instead of generating from faces
    return_edges : bool
        Return the edges shared by adjacent faces

    Returns
    ----------
    adjacency : (m, 2) int
        Indexes of faces that are adjacent
    edges: (m, 2) int
        Only returned if return_edges is True
        Indexes of vertices which make up the
        edges shared by the adjacent faces

    Examples
    ----------
    This is useful for lots of things such as finding
    face- connected components:
    ```python
    >>> graph = nx.Graph()
    >>> graph.add_edges_from(mesh.face_adjacency)
    >>> groups = nx.connected_components(graph_connected)
    ```
    NT)return_indexr   axis   require_countr   z3No adjacent faces detected! Did you merge vertices?)	r	   sortedges_sorted
edges_facer   
group_rowslenr   debug)	facesmeshreturn_edgesedgesr!   edge_groups	adjacencynondegenerateadjacency_edgess	            :/DATA/.local/lib/python3.12/site-packages/trimesh/graph.pyface_adjacencyr.   1   s    H | +5tDz


 !!__
 %%e1=K
;1		GH
 ;'I adOyA6M-(I NNNAqD 1- @A?#s9~555/))    returnc                 2   | j                   }|j                  |z  }|j                  d       |j                          |j	                         }t        j                  |j                  dddf   |j                  dddf   fdt
        j                        }|S )a  
    Find faces that share a vertex i.e. 'neighbors' faces.
    Relies on the fact that an adjacency matrix at a power p
    contains the number of paths of length p connecting two nodes.
    Here we take the bipartite graph from mesh.faces_sparse to the power 2.
    The non-zeros are the faces connected by one vertex.

    Returns
    ----------
    neighborhood : (n, 2) int
        Pairs of faces which share a vertex
    r   N)r   dtype)
faces_sparseTsetdiageliminate_zerostocoonpconcatenaterowcolr   )r&   VTTTneighborhoods       r-   face_neighborhoodr@      s|     
		B	BJJqM	B>>	4"&&D/*288L r/   c           
         t        j                  | j                  t         j                        dz
  }| j                  }t        | j                  j                        D ]  \  }}| j                  |   }t        j                  t        j                  ||dddf   j                  d      k(  ||dddf   j                  d      k(              }|j                  d      dk(  }d|| ddf<   ||   |||f<    |S )a  
    Return the vertex index of the two vertices not in the shared
    edge between two adjacent faces

    Parameters
    ----------
    mesh : Trimesh object
      Input mesh

    Returns
    -----------
    vid_unshared : (len(mesh.face_adjacency), 2) int
      Indexes of mesh.vertices
      for degenerate faces without exactly
      one unshared vertex per face it will be -1
    r3   r   Nr   r2   r   r   F)r9   
zeros_liker.   r   face_adjacency_edges	enumerater5   r%   logical_not
logical_orreshapesum)r&   vid_unsharedr(   ifidr%   unsharedrow_oks           r-   face_adjacency_unsharedrP      s    ( ==!4!4BHHEIL%%E D//1123

3 >>MMq!t,,W55q!t,,W55
 1%*$&!"'/VQY! 3$ r/   c                 
   | j                   t        j                  d      kD  }t        j                  dt        j                  | j                   |         z        }| j
                  | j                     }t        j                  |d      j                  d      }| j                  }t        j                  t        j                  | j
                  |   d      j                  d            }t        j                  |t        j                  ||      j                  d      |z        }t        j                  |      }t        j                  t!        | j"                              t        j$                  z  }	||   |z  |	|<   |	|fS )a  
    Compute an approximate radius between adjacent faces.

    Parameters
    --------------
    mesh : trimesh.Trimesh

    Returns
    -------------
    radii : (len(self.face_adjacency),) float
      Approximate radius between faces
      Parallel faces will have a value of np.inf
    span :  (len(self.face_adjacency),) float
      Perpendicular projection distance of two
      unshared vertices onto the shared edge
    g{Gz?g       @r   r   )r2      rC   )face_adjacency_anglesr9   radiansabssinverticesrP   diffrI   rE   r   unitizesubtractdiagonal_dotrow_normonesr#   r.   inf)
r&   nonzerodenominatorpoint_pairsvectorsr(   	edges_vecperpspanradiis
             r-   face_adjacency_radiusrg      s1   , ((2::d+;;G&&rvvd&@&@&IJJKK -- < <=Kggk*227;G %%ERWWT]]5%9BJJ7STI ;;$##GY7??H9TD ==D GGC++,-6E'][0E'N$;r/   c                 d    t        j                         }|j                  | j                         |S )a/  
    Returns a networkx graph representing the vertices and
    their connections in the mesh.

    Parameters
    ----------
    mesh : Trimesh object

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

    Examples
    ----------
    This is useful for getting nearby vertices for a given vertex,
    potentially for some simple smoothing techniques.
    >>> graph = mesh.vertex_adjacency_graph
    >>> graph.neighbors(0)
    > [1, 3, 4]
    )nxGraphadd_edges_fromedges_unique)r&   gs     r-   vertex_adjacency_graphrn      s(    . 	
AT&&'Hr/   c                     t        j                  t        |       d      }t        j                  t        |      d      }t        j                  ||t         j
                        }|S )a  
    Given two sets of faces, find the edges which are in both sets.

    Parameters
    ---------
    faces_a : (n, 3) int
      Array of faces
    faces_b : (m, 3) int
      Array of faces

    Returns
    ---------
    shared : (p, 2) int
      Edges shared between faces
    r   r   	operation)r9   r   r	   r   boolean_rowsintersect1d)faces_afaces_be_ae_bshareds        r-   shared_edgesry     sK      ''.)
2C
''.)
2C""3r~~FFMr/   enginefacet_thresholdc                    |t         j                  }| j                  }| j                  }t	        j
                  t        |      t              }t	        j                  |      t         j                  kD  }||   ||   z  dz  |kD  ||<   t        | j                  |   t	        j                  t        | j                              d|      }|S )an  
    Find the list of parallel adjacent faces.

    Parameters
    -----------
    mesh : trimesh.Trimesh
    engine
      Which graph engine to use
    facet_threshold : float
      Threshold for two facets to be considered coplanar

    Returns
    ---------
    facets : sequence of (n,) int
        Groups of face indexes of
        parallel adjacent faces.
    rB   r   )nodesmin_lenrz   )r   r{   rg   face_adjacency_spanr9   r]   r#   boolrU   zeroconnected_componentsr.   aranger%   )r&   rz   r{   rf   re   parallelr_   
componentss           r-   facetsr   )  s    ( -- &&E##D wws5z.HffTlSXX%Gw$w-7A=OHW &H%iiDJJ(	J r/   only_watertightrepairr*   c                     || j                   }|rd}nd}t        |t        j                  t	        | j
                              ||      } | j                  |f||d|S )a3  
    Split a mesh into multiple meshes from face
    connectivity.

    If only_watertight is true it will only return
    watertight meshes and will attempt to repair
    single triangle or quad holes.

    Parameters
    ----------
    mesh : trimesh.Trimesh
      The source multibody mesh to split
    only_watertight
      Only return watertight components and discard
      any connected component that isn't fully watertight.
    repair
      If set try to fill small holes in a mesh, before the
      discard step in `only_watertight.
    adjacency : (n, 2) int
      If passed will be used instead of `mesh.face_adjacency`
    engine
      Which graph engine to use for the connected components.

    Returns
    ----------
    meshes : (m,) trimesh.Trimesh
      Results of splitting based on parameters.
       r   )r(   r}   r~   rz   )r   r   )r.   r   r9   r   r#   r%   submesh)r&   r   r   r*   rz   kwargsr~   r   s           r-   splitr   \  st    H ''	 %ryyTZZ97SYJ 4<<$3FFL r/   r~   c                      fd} fd}t        j                   t         j                         t        j                         t	              dk(  rg S t	               dk(  r+dk  r$t        j
                  d      j                         S g S t        j                   d      st        d      dg}t	               dkD  r|j                   j                                t	              dkD  r|j                  j                                t        j                  |      dz   t        j                  t              }d	|<   |    j                  d
      } |    t        j                   d|fd|ff      }	||	v r
 |	|          S |	j#                         D ]  }
	  |
       c S  t'        d      # t$        $ r Y $w xY w)a  
    Find groups of connected nodes from an edge list.

    Parameters
    -----------
    edges : (n, 2) int
      Edges between nodes
    nodes : (m, ) int or None
      List of nodes that exist
    min_len : int
      Minimum length of a component group to return
    engine :  str or None
      Which graph engine to use (None for automatic):
      (None, 'networkx', 'scipy')


    Returns
    -----------
    components : (n,) sequence of (*,) int
      Nodes which are connected
    c                      t        j                        } dk  r| j                         t        j                  |       D cg c]  }t	        |       c}S c c}w )z:
        Find connected components using networkx
        r   )ri   from_edgelistadd_nodes_fromr   list)graphrL   r(   r~   r}   s     r-   components_networkxz1connected_components.<locals>.components_networkx  sU       ' a<  '!#!8!8!?@!?AQ!?@@@s   Ac                     t              } t        j                  t              }d|<   t        j                  t        j
                        |   }t        j                  | |         }|D cg c]  }||   	 c}S c c}w )zF
        Find connected components using scipy.sparse.csgraph
        )
node_countrB   T)r~   )connected_component_labelsr9   zerosr   r   r   r   group)	labels	containedindexr   cr(   r~   r   r}   s	        r-   components_csgraphz0connected_components.<locals>.components_csgraph  sw    
 ,EjI HHZt4		%		*BHH5i@^^F9$5wG
",-*Qa*---s   5BrB   r   r   rC   r2   r   edges must be (n, 2)!Tr   scipynetworkxzno graph engines available!)r9   
asanyarrayr   uniquer#   rI   tolistr   is_shape
ValueErrorappendmaxr   r   allcollectionsOrderedDictvaluesBaseExceptionImportError)r(   r~   r}   rz   r   r   countsmaskedges_okenginesfunctionr   s   ```        @r-   r   r     s   2	A$ MM%rxx0E}		%  5zQ		Uqa<::eW-4466I==(011 SF
5zA~eiik"
5zA~eiik"!#J 88Jd+DDKE{A&H(OE %%
%	&5H(IJG
 wv   NN$	: % 3
44  		s   &F;;	GGc                 v    t        | |      }t        j                  |d      \  }}|t        |      |k(  sJ |S )a?  
    Label graph nodes from an edge list, using scipy.sparse.csgraph

    Parameters
    -----------
    edges : (n, 2) int
       Edges of a graph
    node_count : int, or None
        The largest node in the graph.

    Returns
    ----------
    labels : (node_count,) int
        Component labels for each node
    F)directed)edges_to_coor   r   r#   )r(   r   matrix_body_countr   s        r-   r   r     sD      %,F!66vNK6{j(((Mr/   	traversalc                    t        j                  | dd | dd f      }|j                  t        j                  |d            d   dk  }|j	                         r| g}nOt        j                  |dd      }|D cg c],  }t        j                  |dddf   |   ||d      dd g      . }}t        j                  |D cg c]G  }t        |      d	kD  xr5 |d   |d   k7  xr( |j                  t        |d   |d   g            d   dk  I c}      }|j                         r@t        j                  |      d   D ]%  }	t        j                  ||	   ||	   dd g      ||	<   ' t        j                  r`|D ][  }t        j                  t        j                  |dd |dd f      d      }
|j                  |
      d   dk  j	                         r[J  |S c c}w c c}w )
a  
    Given a traversal as a list of nodes split the traversal
    if a sequential index pair is not in the given edges.
    Useful since the implementation of DFS we're using will
    happily return disconnected values in a flat traversal.

    Parameters
    --------------
    traversal : (m,) int
       Traversal through edges
    edges_tree : cKDTree
      A way to reconstruct original edge indices from
      sorted (n, 2) edge values. This is a slight misuse of a
      kdtree since one could just hash the tuples of the integer
      edges, but that isn't possible with numpy arrays easily
      and this allows a vectorized reconstruction.

    Returns
    ---------------
    split : sequence of (p,) int
      Traversals split into only connected paths.
    Nr2   r   r   r   g|=T)r~   only_nonzeror   )r9   column_stackqueryr   r   r   blocksr:   arrayr#   sortedanyr_   r   strict)r   
edges_tree	trav_edgeexistsr   r   bsneeds_closerL   
check_edges              r-   _split_traversalr     s   2 3B12 ?@I bggia89!<uDFzz| FPV
PV1BNNIadOA.	!B%0@0DEFPV 	 
 ((
 		
  FQJ C!"C  1qu!67:UBC 		
K K(+A~~uQxq"1&>?E!H , zzA!CR&!AB%!AJJ$$Z03e;@@BBB  L1
	
s   :1G AG
traversalsr(   c                 $   t        j                  |d      }t        |      }t        |       dk(  r|j	                         S g }| D ]  }|j                  t        ||               t        j                  |D cg c]  }t        j                  |dd |dd f      ! c}      }t        |      dkD  rI|j                  d       |j                  t        j                  ||t         j                               |S |j	                         }|S c c}w )a  
    Convert a traversal of a list of edges into a sequence of
    traversals where every pair of consecutive node indexes
    is an edge in a passed edge list

    Parameters
    -------------
    traversals : sequence of (m,) int
       Node indexes of traversals of a graph
    edges : (n, 2) int
       Pairs of connected node indexes

    Returns
    --------------
    splits : sequence of (p,) int
       Node indexes of connected traversals
    r   r   r   )r   r   Nr2   rp   )r9   r   r   r#   copyextendr   r   vstack_emptyr   r   rr   	setdiff1d)r   r(   r   splitsr}   rL   includeds          r-   fill_traversalsr   S  s    & GGE"EJ :!zz|F&:NO 
   F!SFq"//1Sb61QR5/"BF!STH
8}q1 	h++E8r||TU M M "Ts   9$Dc                    t        j                  | t         j                        } t        |       dk(  rg S t	        j
                  | d      st        d      t        |      j                         j                         }|dk(  rt        j                  }n!|dk(  rt        j                  }nt        d      | j                  d	       t        |       }t        j                  | j!                               }t        j"                  |dk(        d   }t        j"                  |dkD        d   }g }t        j$                  t        |      dz   t         j&                        }t        j(                  ||f      D ]G  }	||	   r	 |||	d
d
      j+                  t         j                        }
|j-                  |
       d||
<   I |S )a  
    Given an edge list generate a sequence of ordered depth
    first search traversals using scipy.csgraph routines.

    Parameters
    ------------
    edges : (n, 2) int
      Undirected edges of a graph
    mode :  str
      Traversal type, 'bfs' or 'dfs'

    Returns
    -----------
    traversals : (m,) sequence of (p,) int
      Ordered DFS or BFS traversals of the graph.
    rB   r   r   zedges are not (n, 2)!bfsdfsz(traversal mode must be either dfs or bfsr   r   F)i_startreturn_predecessorsr   T)r9   r   r   r#   r   r   r   strlowerstripr   breadth_first_orderdepth_first_orderr   r   bincountravelr_   r   bool_r:   astyper   )r(   modefuncr   r   
nodes_leafr}   r   visitedstartordereds              r-   r   r     s}   " HHU"((+E
5zQ	]]5'*011 t9??""$Du}**	((CDD 
JJAJE {{5;;=)H HM*1-JJJx!|$Q'E Jhhs8}q(9G U 345> 5ee

&
 	
 	'" 5 r/   c                    t        j                  | t         j                        } t        |       dk(  s!t	        j
                  | d      st        d      || j                         dz   }t        |      }|$t        j                  t        |       t              }t        || j                  f|j                  ||f      S )a  
    Given an edge list, return a boolean scipy.sparse.coo_matrix
    representing the edges in matrix form.

    Parameters
    ------------
    edges : (n, 2) int
      Edges of a graph
    count : int
      The total number of nodes in the graph
      if None: count = edges.max() + 1
    data : (n,) any
      Assign data to each edge, if None will
      be bool True for each specified edge

    Returns
    ------------
    matrix: (count, count) scipy.sparse.coo_matrix
      Sparse COO
    rB   r   r   r   r   )r3   shape)r9   r   r   r#   r   r   r   r   intr]   r   r   r5   r3   )r(   countdatas      r-   r   r     s    * MM%rxx0EJ!Ot}}UG<011 }		aJE |wws5z.tUWWoTZZu~NNr/   c                    t        j                  t              }|r)| D cg c]  }||d      j                  |d          c} nB| D cg c]6  }||d      j                  |d         ||d      j                  |d         f8 c} || j	                         dz   }t        |      D cg c]  }t        ||          }}|S c c}w c c}w c c}w )a  
    Find the neighbors for each node in an edgelist graph.

    TODO : re-write this with sparse matrix operations

    Parameters
    ------------
    edges : (n, 2) int
      Connected nodes
    directed : bool
      If True, only connect edges in one direction

    Returns
    ---------
    neighbors : sequence
      Vertex index corresponds to set of other vertex indices
    r   r   )r   defaultdictsetaddr   ranger   )r(   	max_indexr   	neighborsedgerL   r   s          r-   r   r     s    $ '',I5:;UT47			Q	(U; 	
 tAw##DG,iQ.@.D.DT!W.MN	

 IIK!O	).y)9:)9AT)A,)9E:L 	<	
 ;s   !C	;C)Canglefacet_minareac                 d   |t        j                  d      }t        | j                        dk(  r| j	                         S | j
                  |k  }| j                  |   }g }d}|| j                  }| j                  |z  }	 | j                  D 	cg c]  }	||	   j                         |kD  s|	 }}	t        |      dkD  rst        j                  t        | j                        t              }
d|
t        j                  |      <   ||
|   j                  d         }t        j                  |      }t'        |d|      }t        |      dkD  r|j)                  |       t        |      dk(  r| j	                         S t        j                  t        j                  |            }t        |      t        | j                        k7  r\t        j*                  t        j,                  t        | j                              |      }|j)                  |j/                  d             | j1                  |dd	      }||j2                  d<   t        |j                        t        | j                        k7  rt#        j$                  d       |S c c}	w # t         $ r t#        j$                  dd	
       Y }w xY w)az  
    Return a non-watertight version of the mesh which
    will render nicely with smooth shading by
    disconnecting faces at sharp angles to each other.

    Parameters
    -----------
    mesh : trimesh.Trimesh
      Source geometry
    angle : float or None
      Angle in radians face pairs with angles
      smaller than this will appear smoothed
    facet_minarea : float or None
      Minimum area fraction to consider
      IE for `facets_minarea=25` only facets larger
      than `mesh.area / 25` will be considered.

    Returns
    ---------
    smooth : trimesh.Trimesh
      Geometry with disconnected face patches
    N   r   rB   Fr   r   zfailed to calculate facetsT)exc_infor   )r~   r}   rC   )r   r   original_componentszface count in smooth wrong!)r9   rT   r#   r.   r   rS   
area_facesarear   rJ   r]   r%   r   hstackr   r   r   r   warningr   r   r   r   rI   r   metadata)r&   r   r   angle_okr*   r   r}   areasmin_areafr   r   r   brokesmooths                  r-   smooth_shader    s=   2 }

2 41$yy{ ))E1H##H-I FE 99},	E "&JAa0IaFJ6{Q wws4::d;*/RYYv&'%d9o&9&9q&9&AB			), &i%HJ 6{Q&!
:! yy{ YYryy,-F
6{c$**o% RYYs4::7@%--01 \\*eD\IF-7FOO)*
6<<C

O+12MO K  	EKK4tDD	Es+    J J*J.BJ J  J/.J/r    c                 P   |t        j                  | d      }t        j                  |d      }t	        t        |      dz  t        |       k(        }| |   j                  d      ddddf   j                  }t	        t        j                  | j                               }||fS )ah  
    Parameters
    -----------
    edges : (n, 2) int
      List of vertex indices
    edges_sorted : (n, 2) int
      Pass vertex indices sorted on axis 1 as a speedup

    Returns
    ---------
    watertight : boolean
      Whether every edge is shared by an even
      number of faces
    winding : boolean
      Whether every shared edge is reversed
    Nr   r   r   r   )r2   r   rR   )
r9   r   r   r"   r   r#   rI   r5   equalr   )r(   r    groups
watertightopposingwindings         r-   is_watertightr  k  s    ( wwu1-   Q?F s6{Q3u:56J V}$$W-a1f577H288X&**,-Gwr/   c                    ddl }ddl}|j                         5 }t        j                  j
                  j                  | |j                         |j                  d|j                  dg      }ddd       |S # 1 sw Y   S xY w)z
    Turn a networkx graph into an SVG string
    using graphviz `dot`.

    Parameters
    ----------
    graph: networkx graph

    Returns
    ---------
    svg: string, pictoral layout in SVG format
    r   Ndotz-Tsvg)	
subprocesstempfileNamedTemporaryFileri   drawing	nx_agraph	write_dotnamecheck_output)r   r  r  dot_filesvgs        r-   graph_to_svgr    sj     		$	$	&(


&&uhmm<%%uhmmW&EF 
' J 
' Js   AA66B c                    |6t        | j                               t        | j                               z  dz   }|dfg}g }g }t        |      D ]  }|d   d   }| |   }t        |      dk(  r3|j	                  |       t        |      dk(  r |S |j                         }Qd}	|j                         D ]L  }
||
   j                         D ]4  }|	r|j	                  |
|f       d}	|j	                  |dd |
|fgz          6 N  |S )a*  
    For a networkx MultiDiGraph, find all paths from a source node
    to leaf nodes. This function returns edge instance numbers
    in addition to nodes, unlike networkx.all_simple_paths.

    Parameters
    ---------------
    G : networkx.MultiDiGraph
      Graph to evaluate
    source : hashable
      Node to start traversal at
    cutoff : int
      Number of nodes to visit
      If None will visit all nodes

    Returns
    ----------
    traversals : (n,) list of [(node, edge instance index), ] paths
      Traversals of the multigraph
    Nr   r   r2   TF)r#   r(   r}   r   r   popkeys)Gsourcecutoffcurrentqueuer   _current_nodechildr   nodeinstances               r-   multigraph_pathsr)    s   * ~aggi.3qwwy>1Q6 {mGEJ6] r{1~,u:? g&5zQ* % iikG E

 %d 0 0 2H  h'78 % WSb\dH5E4F%FG !3 %+ D r/   c                     g }t        j                  |      D ]A  \  }}| |d      |d      |d      }||j                  |       .|j                  ||          C |S )a\  
    Given a MultiDiGraph traversal, collect attributes along it.

    Parameters
    -------------
    G:          networkx.MultiDiGraph
    traversal:  (n) list of (node, instance) tuples
    attrib:     dict key, name to collect. If None, will return all

    Returns
    -------------
    collected: (len(traversal) - 1) list of attributes
    r   r   )r   pairwiser   )r  r   attrib	collecteduvattribss          r-   multigraph_collectr1    sk     Ii(1AaD'!A$-!%>W%WV_- ) r/   )NNF)NN)TTNN)r   NN)N)r   )NF)Ng      $@)8__doc__r   numpyr9    r   r   r   	constantsr   r   geometryr	   typedr
   r   r   r   r   r   r   r   r   r   r   scipy.sparser   r   scipy.spatialr   r   EExceptionWrapperr   ri   r.   r@   rP   rg   rn   ry   r   r   r   r   r   r   r   r   r   r   r  r  r  r)  r1   r/   r-   <module>r=     s-     ( (  $   00%(K\wu~ 2+\.b8. OS0!0;CF;K0j !%)"33 3 	"	3
 3 
3n HLf5f55Df5R2< <W <~, , ,uXwEV?W ,^DN$ONF MQV&!V9A&9IVt ;?""$,Y$7"
4:"J.AHQ  0)j))!,G)j))!,G,,,Q/J	0  ( 
%	$	$Q	'B(s/   C1 D9 1D666D11D69E>EE