@@ -431,39 +431,86 @@ def does_overlap(self, aabb, method='DFS'):
431431 This function checks if the limits overlap any leaf nodes in the tree.
432432 It returns true if there is an overlap.
433433
434+ *New in version 2.6.0*
435+
436+ This method also supports overlap checks with another instance of the
437+ AABBTree class.
438+
434439 Args:
435- aabb (AABB): The AABB to check.
440+ aabb (AABB or AABBTree ): The AABB or AABBTree to check.
436441 method (str): {'DFS'|'BFS'} Method for traversing the tree.
437442 Setting 'DFS' performs a depth-first search and 'BFS' performs
438443 a breadth-first search. Defaults to 'DFS'.
439444
440445 Returns:
441446 bool: True if overlaps with a leaf node of tree.
442447 """
448+ if isinstance (aabb , AABB ):
449+ tree = AABBTree (aabb = aabb )
450+ else :
451+ tree = aabb
452+
443453 if method == 'DFS' :
454+ if self .is_leaf and tree .is_leaf :
455+ return self .aabb .overlaps (tree .aabb )
456+
444457 if self .is_leaf :
445- return self .aabb .overlaps (aabb )
458+ left_over = tree .left .aabb .overlaps (self .aabb )
459+ right_over = tree .right .aabb .overlaps (self .aabb )
460+
461+ if left_over and tree .left .does_overlap (self , method ):
462+ return True
463+ if right_over and tree .right .does_overlap (self , method ):
464+ return True
465+ return False
466+ if tree .is_leaf :
467+ left_over = self .left .aabb .overlaps (tree .aabb )
468+ right_over = self .right .aabb .overlaps (tree .aabb )
469+
470+ if left_over and self .left .does_overlap (tree , method ):
471+ return True
472+ if right_over and self .right .does_overlap (tree , method ):
473+ return True
474+ return False
475+
476+ # If both `self` and `tree` are trees
477+ if not self .aabb .overlaps (tree .aabb ):
478+ return False
446479
447- left_aabb_over = self .left .aabb .overlaps (aabb )
448- right_aabb_over = self .right .aabb .overlaps (aabb )
480+ left_left = self .left .aabb .overlaps (tree .left .aabb )
481+ left_right = self .left .aabb .overlaps (tree .right .aabb )
482+ right_left = self .right .aabb .overlaps (tree .left .aabb )
483+ right_right = self .right .aabb .overlaps (tree .right .aabb )
449484
450- if left_aabb_over and self .left .does_overlap (aabb ):
485+ if left_left and self .left .does_overlap (tree . left , method ):
451486 return True
452- if right_aabb_over and self .right .does_overlap (aabb ):
487+ if left_right and self .left .does_overlap (tree .right , method ):
488+ return True
489+ if right_left and self .right .does_overlap (tree .left , method ):
490+ return True
491+ if right_right and self .right .does_overlap (tree .right , method ):
453492 return True
454493 return False
455494
456495 if method == 'BFS' :
457496 q = deque ()
458- q .append (self )
497+ q .append (( self , tree ) )
459498 while len (q ) > 0 :
460- node = q .popleft ()
461- overlaps = node .aabb .overlaps (aabb )
462- if overlaps and node .is_leaf :
499+ s_node , t_node = q .popleft ()
500+ overlaps = s_node .aabb .overlaps (t_node . aabb )
501+ if overlaps and s_node . is_leaf and t_node .is_leaf :
463502 return True
464- if overlaps :
465- q .append (node .left )
466- q .append (node .right )
503+ if overlaps and s_node .is_leaf :
504+ q .append ((s_node , t_node .left ))
505+ q .append ((s_node , t_node .right ))
506+ elif overlaps and t_node .is_leaf :
507+ q .append ((s_node .left , t_node ))
508+ q .append ((s_node .right , t_node ))
509+ elif overlaps :
510+ q .append ((s_node .left , t_node .left ))
511+ q .append ((s_node .left , t_node .right ))
512+ q .append ((s_node .right , t_node .left ))
513+ q .append ((s_node .right , t_node .right ))
467514 return False
468515
469516 e_str = "method should be 'DFS' or 'BFS', not " + str (method )
@@ -474,88 +521,115 @@ def overlap_aabbs(self, aabb, method='DFS'):
474521
475522 This function gets each overlapping AABB.
476523
524+ *New in version 2.6.0*
525+
526+ This method also supports overlap checks with another instance of the
527+ AABBTree class.
528+
477529 Args:
478- aabb (AABB): The AABB to check.
530+ aabb (AABB or AABBTree ): The AABB or AABBTree to check.
479531 method (str): {'DFS'|'BFS'} Method for traversing the tree.
480532 Setting 'DFS' performs a depth-first search and 'BFS' performs
481533 a breadth-first search. Defaults to 'DFS'.
482534
483535 Returns:
484536 list: AABB objects in AABBTree that overlap with the input.
485537 """
486- aabbs = []
487-
488- if method == 'DFS' :
489- is_leaf = self .is_leaf
490- if is_leaf and self .does_overlap (aabb ):
491- aabbs .append (self .aabb )
492- elif is_leaf :
493- pass
494- else :
495- if self .left .aabb .overlaps (aabb ):
496- aabbs .extend (self .left .overlap_aabbs (aabb ))
497-
498- if self .right .aabb .overlaps (aabb ):
499- aabbs .extend (self .right .overlap_aabbs (aabb ))
500- elif method == 'BFS' :
501- q = deque ()
502- q .append (self )
503- while len (q ) > 0 :
504- node = q .popleft ()
505- if node .aabb .overlaps (aabb ):
506- if node .is_leaf :
507- aabbs .append (node .aabb )
508- else :
509- q .append (node .left )
510- q .append (node .right )
511- else :
512- e_str = "method should be 'DFS' or 'BFS', not " + str (method )
513- raise ValueError (e_str )
514- return aabbs
538+ pairs = self ._overlap_pairs (aabb , method )
539+ if len (pairs ) == 0 :
540+ return []
541+ boxes , _ = zip (* pairs )
542+ return list (boxes )
515543
516544 def overlap_values (self , aabb , method = 'DFS' ):
517545 """Get values of overlapping AABBs
518546
519547 This function gets the value field of each overlapping AABB.
520548
549+ *New in version 2.6.0*
550+
551+ This method also supports overlap checks with another instance of the
552+ AABBTree class.
553+
521554 Args:
522- aabb (AABB): The AABB to check.
555+ aabb (AABB or AABBTree ): The AABB or AABBTree to check.
523556 method (str): {'DFS'|'BFS'} Method for traversing the tree.
524557 Setting 'DFS' performs a depth-first search and 'BFS' performs
525558 a breadth-first search. Defaults to 'DFS'.
526559
527560 Returns:
528561 list: Value fields of each node that overlaps.
529562 """
530- values = []
563+ pairs = self ._overlap_pairs (aabb , method )
564+ if len (pairs ) == 0 :
565+ return []
566+ _ , values = zip (* pairs )
567+ return list (values )
568+
569+ def _overlap_pairs (self , aabb , method = 'DFS' ):
570+ """Get overlapping AABBs and values in (AABB, value) pairs
571+
572+ *New in version 2.6.0*
573+
574+ This function gets each overlapping AABB and its value.
575+
576+ Args:
577+ aabb (AABB or AABBTree): The AABB or AABBTree to check.
578+ method (str): {'DFS'|'BFS'} Method for traversing the tree.
579+ Setting 'DFS' performs a depth-first search and 'BFS' performs
580+ a breadth-first search. Defaults to 'DFS'.
581+
582+ Returns:
583+ list: (AABB, value) pairs in AABBTree that overlap with the input.
584+ """
585+ if isinstance (aabb , AABB ):
586+ tree = AABBTree (aabb = aabb )
587+ else :
588+ tree = aabb
589+
590+ pairs = []
531591
532592 if method == 'DFS' :
533- is_leaf = self .is_leaf
534- if is_leaf and self .does_overlap (aabb ):
535- values .append (self .value )
536- elif is_leaf :
593+ if self .is_leaf and self .does_overlap (tree , method ):
594+ pairs .append ((self .aabb , self .value ))
595+ elif self .is_leaf :
537596 pass
597+ elif tree .is_leaf :
598+ for branch in (self .left , self .right ):
599+ pairs .extend (branch ._overlap_pairs (tree , method ))
538600 else :
539- if self .left .aabb .overlaps (aabb ):
540- values .extend (self .left .overlap_values (aabb ))
601+ for s_branch in (self .left , self .right ):
602+ for t_branch in (tree .left , tree .right ):
603+ pairs .extend (s_branch ._overlap_pairs (t_branch , method ))
541604
542- if self .right .aabb .overlaps (aabb ):
543- values .extend (self .right .overlap_values (aabb ))
544605 elif method == 'BFS' :
545606 q = deque ()
546- q .append (self )
607+ q .append (( self , tree ) )
547608 while len (q ) > 0 :
548- node = q .popleft ()
549- if node .aabb .overlaps (aabb ):
550- if node .is_leaf :
551- values .append (node .value )
609+ s_node , t_node = q .popleft ()
610+ if s_node .aabb .overlaps (t_node .aabb ):
611+ if s_node .is_leaf and t_node .is_leaf :
612+ pairs .append ((s_node .aabb , s_node .value ))
613+ elif s_node .is_leaf :
614+ q .append ((s_node , t_node .left ))
615+ q .append ((s_node , t_node .right ))
616+ elif t_node .is_leaf :
617+ q .append ((s_node .left , t_node ))
618+ q .append ((s_node .right , t_node ))
552619 else :
553- q .append (node .left )
554- q .append (node .right )
620+ q .append ((s_node .left , t_node .left ))
621+ q .append ((s_node .left , t_node .right ))
622+ q .append ((s_node .right , t_node .left ))
623+ q .append ((s_node .right , t_node .right ))
555624 else :
556625 e_str = "method should be 'DFS' or 'BFS', not " + str (method )
557626 raise ValueError (e_str )
558- return values
627+
628+ if len (pairs ) < 2 :
629+ return pairs
630+ boxes , _ = zip (* pairs )
631+ u_pairs = [p for i , p in enumerate (pairs ) if p [0 ] not in boxes [:i ]]
632+ return u_pairs
559633
560634
561635def _merge (lims1 , lims2 ):
0 commit comments