
    SOg_L                         S r SSKJr  SSKrSSKrSSKrSSKrSSKJr  SSK	J
r
  SrSrSrS	r " S
 S\5      rS r " S S\5      rSS jrSS jrSS jrSS jrg)zA Python implemntation of a kd-tree

This package provides a simple implementation of a kd-tree in Python.
https://en.wikipedia.org/wiki/K-d_tree
    )print_functionN)dequewrapsu    Stefan Kögl <stefan@skoegl.net>z0.16z%https://github.com/stefankoegl/kdtreezISC licensec                       \ rS rSrSrSS jr\S 5       rS rS r	S r
\S	 5       rS
 rS rS rS rS r\rS rS rSrg)Node   zbA Node in a kd-tree

A tree is represented by its root node, and every node represents
its subtreeNc                 (    Xl         X l        X0l        g Ndataleftright)selfr   r   r   s       K/Users/admin/workspace/ai/Jarvis/env/lib/python3.13/site-packages/kdtree.py__init__Node.__init__   s    		
    c                 j    U R                   (       + =(       d    [        S U R                   5       5      $ )zkReturns True if a Node has no subnodes

>>> Node().is_leaf
True

>>> Node( 1, left=Node(2) ).is_leaf
False
c              3   F   #    U  H  u  p[        U5      (       + v   M     g 7fr   )bool).0cps      r   	<genexpr>Node.is_leaf.<locals>.<genexpr>0   s     :MDAQKKM   !)r   allchildrenr   s    r   is_leafNode.is_leaf%   s)     II <:DMM::	<r   c              #      #    U (       d  gU v   U R                   (       a%  U R                   R                  5        H  nUv   M	     U R                  (       a&  U R                  R                  5        H  nUv   M	     gg7f)z&iterator for nodes: root, left, right N)r   preorderr   r   xs     r   r$   Node.preorder3   s_      
99YY'') * ::ZZ((* +    A;A=c              #      #    U (       d  gU R                   (       a%  U R                   R                  5        H  nUv   M	     U v   U R                  (       a&  U R                  R                  5        H  nUv   M	     gg7f)z&iterator for nodes: left, root, right N)r   inorderr   r%   s     r   r*   Node.inorderD   s_      99YY&&( ) 
::ZZ'') * r(   c              #      #    U (       d  gU R                   (       a%  U R                   R                  5        H  nUv   M	     U R                  (       a%  U R                  R                  5        H  nUv   M	     U v   g7f)z&iterator for nodes: left, right, root N)r   	postorderr   r%   s     r   r-   Node.postorderU   s\      99YY((* + ::ZZ))+ , 
s   A:A<c              #      #    U R                   (       a'  U R                   R                  b  U R                   S4v   U R                  (       a)  U R                  R                  b  U R                  S4v   ggg7f)aB  
Returns an iterator for the non-empty children of the Node

The children are returned as (Node, pos) tuples where pos is 0 for the
left subnode and 1 for the right.

>>> len(list(create(dimensions=2).children))
0

>>> len(list(create([ (1, 2) ]).children))
0

>>> len(list(create([ (2, 2), (2, 1), (2, 3) ]).children))
2
Nr      )r   r   r   r    s    r   r   Node.childrenf   sR     $ 993))Q,::$**//5**a- 6:s   A4A6c                 *    US:X  a  X l         gX l        g)zRSets one of the node's children

index 0 refers to the left, 1 to the right child r   N)r   r   )r   indexchilds      r   	set_childNode.set_child~   s    
 A:IJr   c           	          [        [        U 5      5      n[        U/U R                   VVs/ s H  u  p#UR	                  5       S-   PM     snn-   5      $ s  snnf )z
Returns height of the (sub)tree, without considering
empty leaf-nodes

>>> create(dimensions=2).height()
0

>>> create([ (1, 2) ]).height()
1

>>> create([ (1, 2), (2, 3) ]).height()
2
r0   )intr   maxr   height)r   
min_heightr   r   s       r   r:   Node.height   sE     d_
J<DMM"JMDA188:a<M"JJKK"Js   Ac                 @    U R                    H  u  p#X:X  d  M  Us  $    g)zReturns the position if the given child

If the given node is the left child, 0 is returned. If its the right
child, 1 is returned. Otherwise None N)r   )r   r4   r   poss       r   get_child_posNode.get_child_pos   s     mmFAz
 $r   c                 j    S[        U R                  R                  [        U R                  5      S9-  $ )Nz<%(cls)s - %(data)s>)clsr   )dict	__class____name__reprr   r    s    r   __repr__Node.__repr__   s-    %T^^,,4		?CD 	Dr   c                     U R                   S L$ r   r   r    s    r   __nonzero__Node.__nonzero__   s    yy$$r   c                 |    [        U[        5      (       a  U R                  U:H  $ U R                  UR                  :H  $ r   )
isinstancetupler   )r   others     r   __eq__Node.__eq__   s1    eU##99%%99

**r   c                     [        U 5      $ r   )idr    s    r   __hash__Node.__hash__   s    $xr   r   )NNN)rE   
__module____qualname____firstlineno____doc__r   propertyr!   r$   r*   r-   r   r5   r:   r?   rG   rK   __bool__rQ   rU   __static_attributes__ r   r   r   r      so    
 
< 
<"""    .L&D
% H+r   r   c                 0   ^  [        T 5      U 4S j5       nU$ )zBCheck if the object of the function has axis and sel_axis members c           	         > S U R                   U R                  4;   a)  [        S[        TR                  [        U 5      S9-  5      eT" U /UQ70 UD6$ )NzO%(func_name) requires the node %(node)s to have an axis and a sel_axis function)	func_namenode)axissel_axis
ValueErrorrC   rE   rF   )r   argskwargsfs      r   _wrapperrequire_axis.<locals>._wrapper   s[    DIIt}}-- >1::DJ?@ A A ''''r   r   )rh   ri   s   ` r   require_axisrk      s"     1X( ( Or   c                     ^  \ rS rSrSr  SU 4S jjr\S 5       r\S 5       r\S 5       r	S r
\SS j5       r\S	 5       r\S
 5       rS rS rS rSS jrS r\SS j5       rS r\SS j5       r\S 5       rS rSrU =r$ )KDNode   z7A Node that contains kd-tree specific data and methods c                 R   > [         [        U ]  XU5        X@l        XPl        X`l        g)a  Creates a new node for a kd-tree

If the node will be used within a tree, the axis and the sel_axis
function should be supplied.

sel_axis(axis) is used when creating subnodes of the current node. It
receives the axis of the parent node and returns the axis of the child
node. N)superrm   r   rc   rd   
dimensions)r   r   r   r   rc   rd   rq   rD   s          r   r   KDNode.__init__   s%     	fd$T7	 $r   c                    U n [        U/UR                  S9  UR                  c  Xl        U$ XR                     UR                  UR                     :  a<  UR                  c"  UR                  U5      Ul        UR                  $ UR                  nO;UR                  c"  UR                  U5      Ul        UR                  $ UR                  nM  )z
Adds a point to the current node or iteratively
descends to one of its children.

Users should call add() only to the topmost tree.
)rq   )check_dimensionalityrq   r   rc   r   create_subnoder   )r   pointcurrents      r   add
KDNode.add   s      %W5G5GH ||#$ \\"W\\',,%??<<'#*#9#9%#@GL"<<'%llG==($+$:$:5$AGM"==(%mmG) r   c                     U R                  UU R                  U R                  5      U R                  U R                  S9$ )z'Creates a subnode for the current node rc   rd   rq   )rD   rd   rc   rq   )r   r   s     r   ru   KDNode.create_subnode   s:     ~~d]]499-??  , 	,r   c                     U R                   (       a-  U R                   R                  [        U R                  5      u  pO,U R                  R                  [
        U R                  5      u  pXb  U4$ U 4$ )z~Finds a replacement for the current node

The replacement is returned as a
(replacement-node, replacements-parent-node) tuple )r   extreme_childminrc   r   r9   )r   r4   parents      r   find_replacementKDNode.find_replacement
  s[     :: JJ44S$))DME6 II33CCME!3v>>>>r   c                 @    U R                   U:X  d  gUSL =(       d    X L $ )z4checks if self's point (and maybe identity) matches FNrJ   r   rv   rb   s      r   should_removeKDNode.should_remove  s"    yyE!/$,/r   c                    U (       d  gU R                  X5      (       a  U R                  U5      $ U R                  (       aA  U R                  R                  X5      (       a!  U R                  R                  U5      U l        OQU R                  (       a@  U R                  R                  X5      (       a   U R                  R                  U5      U l        XR                     U R
                  U R                     ::  a1  U R                  (       a   U R                  R                  X5      U l        XR                     U R
                  U R                     :  a1  U R                  (       a   U R                  R                  X5      U l        U $ )a  Removes the node with the given point from the tree

Returns the new root node of the (sub)tree.

If there are multiple points matching "point", only one is removed. The
optional "node" parameter is used for checking the identity, once the
removeal candidate is decided.N)r   _remover   r   rc   r   remover   s      r   r   KDNode.remove!  s	     e**<<&& 9900==		))%0DIZZDJJ44UAA++E2DJ tyy33yy II,,U9	tyy33zz!ZZ..u;
r   c                    U R                   (       a	  S U l        U $ U R                  5       u  p#U R                  U R                  pTUR                  UR                  sU l        U l        XBLa  UOU XRLa  UOU sUl        Ul        UR
                  U R
                  sU l        Ul        X0La5  UR                  U5      nUR                  X`5        UR                  X5        U$ UR                  X5        U$ r   )	r!   r   r   r   r   rc   r?   r5   r   )r   rv   rootmax_ptmp_ltmp_rr>   s          r   r   KDNode._removeF  s    
 <<DIK
 ++- yy$**u $		4::	4:).):uO`efj	4:#yy$))	49 %%d+COOC&LL%
  KK$r   c                    U R                   (       a  U R                   R                  5       OSnU R                  (       a  U R                  R                  5       OSn[        X-
  5      S:  a  g[	        S U R
                   5       5      $ )ztReturns True if the (sub)tree is balanced

The tree is balanced if the heights of both subtrees differ at most by
1 r   r0   Fc              3   >   #    U  H  u  pUR                   v   M     g 7fr   )is_balancedr   r   _s      r   r   %KDNode.is_balanced.<locals>.<genexpr>s  s     ;]TQ1==]s   )r   r:   r   absr   r   )r   left_heightright_heights      r   r   KDNode.is_balancedf  s`     -1IIdii&&(1.2jjtzz((*a{)*Q.;T]];;;r   c                 r    [        U R                  5        Vs/ s H  oR                  PM     sn5      $ s  snf )z8
Returns the (possibly new) root of the rebalanced tree
)creater*   r   r%   s     r   	rebalanceKDNode.rebalancev  s)    
 t||~6~!vv~6776s   4c                 T    [         R                  " U R                  U   X   -
  S5      $ )zQ
Squared distance at the given axis between
the current Node and the given point
   )mathpowr   )r   rv   rc   s      r   	axis_distKDNode.axis_dist~  s$    
 xx		$%+5q99r   c           	          [        U R                  5      n[        U Vs/ s H  o0R                  X5      PM     sn5      $ s  snf )z?
Squared distance between the current Node
and the given point
)rangerq   sumr   )r   rv   ris       r   distKDNode.dist  s6    
 $//"a8aNN5,a8998s   A c                    ^^ US:  a  [        S5      eTc  U4S jnOUU4S jn/ nU R                  TX%U[        R                  " 5       5        [	        USS9 VVVs/ s H
  u  pgoU* 4PM     snnn$ s  snnnf )a  Return the k nearest neighbors of point and their distances

point must be an actual point, not a node.

k is the number of results to return. The actual results can be less
(if there aren't more nodes to return) or more in case of equal
distances.

dist is a distance function, expecting two points and returning a
distance value. Distance values can be any compareable type.

The result is an ordered list of (node, distance) tuples.
r0   zk must be greater than 0.c                 &   > U R                  T5      $ r   r   nrv   s    r   <lambda>#KDNode.search_knn.<locals>.<lambda>  s    r   c                 *   > T" U R                   T5      $ r   rJ   )r   r   rv   s    r   r   r     s    affe!4r   T)reverse)re   _search_node	itertoolscountsorted)	r   rv   kr   get_distresultsdr   rb   s	    ` `     r   
search_knnKDNode.search_knn  sr     q5899<.H4H%Xy7HI .4GT-JK-JzqTr
-JKKKs   A2c                 8   U (       d  g U" U 5      nU* [        U5      U 4n[        U5      U:  a$  U* US   S   :  a  [        R                  " X75        O[        R                  " X75        U R
                  U R                     nXR                     U-
  n	X-  n
XR                     U:  a+  U R                  b  U R                  R                  XX4U5        O*U R                  b  U R                  R                  XX4U5        U
* US   S   :  d  [        U5      U:  a  XR                     U R
                  U R                     :  a,  U R                  b  U R                  R                  XX4U5        g g U R                  b  U R                  R                  XX4U5        g g g Nr   )
nextlenheapqheapreplaceheappushr   rc   r   r   r   )r   rv   r   r   r   counternodeDistitemsplit_plane
plane_distplane_dist2s              r   r   KDNode._search_node  so   D> 	4=$/w<1y71:a=(!!'0NN7)ii		* 99%3
 - k)yy$		&&uGLzz%

'''WM <'!*Q-'3w<!+;YY$))DII"66::)JJ++Eg,35 * 99(II**5W+24 ) ,<r   c           	      N    [        [        U R                  USU5      5      S5      $ )a  
Search the nearest node of the given point

point must be an actual point, not a node. The nearest node to the
point is returned. If a location of an actual node is used, the Node
with this location will be returned (not its neighbor).

dist is a distance function, expecting two points and returning a
distance value. Distance values can be any compareable type.

The result is a (node, distance) tuple.
r0   N)r   iterr   )r   rv   r   s      r   	search_nnKDNode.search_nn  s#     D4894@@r   c                    U (       d  g U" U 5      nXR:  a  UR                  U R                  5        U R                  U R                     nXR                     Xb-   ::  a)  U R                  b  U R                  R	                  XX45        XR                     Xb-
  :  a+  U R
                  b  U R
                  R	                  XX45        g g g r   )appendr   rc   r   _search_nn_distr   )r   rv   r   r   r   r   r   s          r   r   KDNode._search_nn_dist  s    D>?
..
# ii		* {11yy$		))%wI{11zz%

**5J & 2r   c                 >   ^ / nU4S jnU R                  TX$U5        U$ )z
Search the n nearest nodes of the given point which are within given
distance

point must be a location, not a node. A list containing the n nearest
nodes to the point within the distance will be returned.
c                 &   > U R                  T5      $ r   r   r   s    r   r   'KDNode.search_nn_dist.<locals>.<lambda>  s    QVVE]r   )r   )r   rv   distancebestr   r   s    `    r   search_nn_distKDNode.search_nn_dist  s&     *UHx@r   c                    U (       d  gU R                   (       a?  U R                  U R                     U R                   R                  U R                     :  a  gU R                  (       a?  U R                  U R                     U R                  R                  U R                     :  a  g[	        S U R
                   5       5      =(       d    U R                  $ )zSChecks recursively if the tree is valid

It is valid if each node splits correctly TFc              3   F   #    U  H  u  pUR                  5       v   M     g 7fr   )is_validr   s      r   r   "KDNode.is_valid.<locals>.<genexpr>$  s     :MDA1::<<Mr   )r   r   rc   r   r   r   r!   r    s    r   r   KDNode.is_valid  s     99499-		tyy0II::$))DII.1KK:DMM::JdllJr   c                    ^ U4S jnU (       a  U S4/O/ nU R                    VVs/ s H  u  pVUR                  UT5      PM     nnnU VVs/ s H  u  pXXXb  UOU 4PM     nnnXG-   n	U	(       d  gU" XS9$ s  snnf s  snnf )zReturns a child of the subtree and its parent

The child is selected by sel_func which is either min or max
(or a different function with similar semantics). c                 (   > U S   R                   T   $ r   rJ   )child_parentrc   s    r   r   &KDNode.extreme_child.<locals>.<lambda>-  s    |A';';D'Ar   N)NNkey)r   r~   )
r   sel_funcrc   max_keymer   r   	child_maxr   
candidatess
     `       r   r~   KDNode.extreme_child'  s     B  $tTl^AEOQ__Xt4	OCLM941am69	Mn

00 PMs   A4A:)rc   r   rq   r   r   rd   )NNNNNNr   )rE   rW   rX   rY   rZ   r   rk   rx   ru   r   r   r   r   r[   r   r   r   r   r   r   r   r   r   r   r~   r]   __classcell__)rD   s   @r   rm   rm      s    B ?C&*%  , ,@ , , ? ?0 ! !H  > < <8::L@+4\ A A"K*    K K"1 1r   rm   c           	      v  ^^ U (       d  T(       d  [        S5      eU (       a  [        U T5      mU=(       d    U4S jnU (       d  [        UTTS9$ [        U 5      n U R	                  U4S jS9  [        U 5      S-  nX   n[        U SU TU" T5      5      n[        XS-   S TU" T5      5      n[        XVUTUTS	9$ )
a  Creates a kd-tree from a list of points

All points in the list must be of the same dimensionality.

If no point_list is given, an empty tree is created. The number of
dimensions has to be given instead.

If both a point_list and dimensions are given, the numbers must agree.

Axis is the axis on which the root-node should split.

sel_axis(axis) is used when creating subnodes of a node. It receives the
axis of the parent node and returns the axis of the child node. z0either point_list or dimensions must be providedc                    > U S-   T-  $ )Nr0   r^   )	prev_axisrq   s    r   r   create.<locals>.<lambda>V  s    y{j.Hr   )rd   rc   rq   c                    > U T   $ r   r^   )rv   rc   s    r   r   r   ]  s	    eDkr   r   r   Nr0   r{   )re   rt   rm   listsortr   r   )
point_listrq   rc   rd   medianlocr   r   s    ``     r   r   r   @  s     jKLL	)*jA
 IHHxdzJJ j!JOO1O2_!FC:gv&
HTNCD:qjk*JGE#UZXXr   c                 z    U=(       d    [        U S   5      nU  H  n[        U5      U:w  d  M  [        S5      e   U$ )Nr   z>All Points in the point_list must have the same dimensionality)r   re   )r   rq   r   s      r   rt   rt   f  s?    1s:a=1Jq6Z]^^  r   c              #     #    [        5       nUR                  U 5        U(       a  UR                  5       nUv   U(       d  UR                  (       a2  UR                  UR                  =(       d    UR	                  5       5        U(       d  UR
                  (       a2  UR                  UR
                  =(       d    UR	                  5       5        U(       a  M  gg7f)zReturns an iterator over the tree in level-order

If include_all is set to True, empty parts of the tree are filled
with dummy entries and the iterator becomes infinite. N)r   r   popleftr   rD   r   )treeinclude_allqrb   s       r   level_orderr   p  s}      	AHHTN
yy{
$))HHTYY2$.."23$**HHTZZ34>>#34 !s   CCCc                    [        XR                  5       S-
  5      n[        SU5      nSnSnSn[        U SS9 H  n	US:X  a!  [	        5         [	        5         [	        SU-  SS9  [        XR-  U-  5      n
U	(       a  [        U	R                  5      OSR                  U
5      n[	        USS9  US-  nXv:X  a  SnUS-  nUS-  nX:  d  M    O   [	        5         [	        5         g	)
zPrints the tree to stdout r0   r   r   T)r    )end N)	r   r:   r   r   printr8   strr   center)r   	max_level
node_widthleft_paddingr:   	max_width	per_levelin_levellevelrb   widthnode_strs               r   	visualizer    s     KKM!O,FAvIIHEDd3q=GG#l",I(23&*C		N::5AhC A HNINE>) 4, 
G	Gr   )NNr   Nr   )F)d   
      )rZ   
__future__r   r   r   operatorr   collectionsr   	functoolsr   
__author____version____website____license__objectr   rk   rm   r   rt   r   r  r^   r   r   <module>r     sn    &      0
5_6 _D q1T q1j#YL5(!r   