@@ -306,6 +306,23 @@ namespace octomap {
306
306
}
307
307
}
308
308
309
+ template <class NODE ,class I >
310
+ void OcTreeBaseImpl<NODE,I>::deleteNodeChildren(NODE* node, const OcTreeKey& key, unsigned int depth,
311
+ const DeletionCallback& deletion_notifier){
312
+ if (node->children != NULL ) {
313
+ key_type center_offset_key = tree_max_val >> (depth + 1 );
314
+ for (unsigned int i=0 ; i<8 ; i++) {
315
+ if (node->children [i] != NULL ){
316
+ OcTreeKey child_key;
317
+ computeChildKey (i, center_offset_key, key, child_key);
318
+ this ->deleteNodeRecurs (static_cast <NODE*>(node->children [i]), child_key, depth + 1 , deletion_notifier);
319
+ }
320
+ }
321
+ delete[] node->children ;
322
+ node->children = NULL ;
323
+ }
324
+ }
325
+
309
326
template <class NODE ,class I >
310
327
inline key_type OcTreeBaseImpl<NODE,I>::coordToKey(double coordinate, unsigned depth) const {
311
328
assert (depth <= tree_depth);
@@ -575,6 +592,24 @@ namespace octomap {
575
592
return deleteNodeRecurs (root, 0 , depth, key);
576
593
}
577
594
595
+ template <class NODE ,class I >
596
+ void OcTreeBaseImpl<NODE,I>::deleteAABB(const point3d& min, const point3d& max, bool invert,
597
+ DeletionCallback deletion_notifier) {
598
+ OcTreeKey min_key, max_key;
599
+ coordToKeyClamped (min, min_key);
600
+ coordToKeyClamped (max, max_key);
601
+ deleteAABB (min_key, max_key, invert, deletion_notifier);
602
+ }
603
+
604
+ template <class NODE ,class I >
605
+ void OcTreeBaseImpl<NODE,I>::deleteAABB(const OcTreeKey& min, const OcTreeKey& max, bool invert,
606
+ DeletionCallback deletion_notifier) {
607
+ octomap::OcTreeKey root_key (tree_max_val, tree_max_val, tree_max_val);
608
+ if (deleteAABBRecurs (min, max, root, root_key, 0 , tree_depth, invert, deletion_notifier)) {
609
+ root = NULL ;
610
+ }
611
+ }
612
+
578
613
template <class NODE ,class I >
579
614
void OcTreeBaseImpl<NODE,I>::clear() {
580
615
if (this ->root ){
@@ -775,6 +810,127 @@ namespace octomap {
775
810
return false ;
776
811
}
777
812
813
+ template <class NODE ,class I >
814
+ void OcTreeBaseImpl<NODE,I>::deleteNodeRecurs(NODE* node, const OcTreeKey& key, unsigned int depth,
815
+ const DeletionCallback& deletion_notifier){
816
+ assert (node);
817
+ assert (deletion_notifier);
818
+
819
+ if (!nodeHasChildren (node)) {
820
+ // Only notify for leaf nodes
821
+ deletion_notifier (this , node, key, depth);
822
+ }
823
+
824
+ // Always call delete node children in the rare case there is a children
825
+ // pointer area in an inner node but all children pointers are NULL
826
+ deleteNodeChildren (node, key, depth, deletion_notifier);
827
+
828
+ delete node;
829
+ tree_size--;
830
+ size_changed = true ;
831
+ }
832
+
833
+ template <class NODE ,class I >
834
+ bool OcTreeBaseImpl<NODE,I>::deleteAABBRecurs(const OcTreeKey& min,
835
+ const OcTreeKey& max,
836
+ NODE* node,
837
+ const OcTreeKey& key,
838
+ unsigned int depth,
839
+ unsigned int max_depth,
840
+ bool invert,
841
+ const DeletionCallback& deletion_notifier) {
842
+ bool delete_node = false ;
843
+ bool skip_delete_notification = false ;
844
+ if (node != NULL && depth <= tree_depth && depth <= max_depth) {
845
+ #ifndef NDEBUG
846
+ if (depth < tree_depth)
847
+ {
848
+ unsigned int mask = (1 << (tree_depth - depth - 1 )) - 1 ;
849
+ assert ((key[0 ] & mask) == 0 );
850
+ assert ((key[1 ] & mask) == 0 );
851
+ assert ((key[2 ] & mask) == 0 );
852
+ }
853
+ #endif
854
+ if (min[0 ] > max[0 ] || min[1 ] > max[1 ] || min[2 ] > max[2 ]) {
855
+ // The box has no volume.
856
+ if (invert) {
857
+ // A non-positive volume box and we are to delete everything outside
858
+ // of it. Delete the node.
859
+ delete_node = true ;
860
+ } else {
861
+ // A non-positive volume box and we are to delete everything inside
862
+ // of it. Do nothing.
863
+ }
864
+ } else {
865
+ key_type key_size_down = tree_max_val >> depth;
866
+ key_type key_size_up = (tree_max_val-1 ) >> depth;
867
+
868
+ assert (key[0 ] - key_size_down <= key[0 ] + key_size_up);
869
+ assert (key[1 ] - key_size_down <= key[1 ] + key_size_up);
870
+ assert (key[2 ] - key_size_down <= key[2 ] + key_size_up);
871
+ bool inside = ((min[0 ] <= (key[0 ] - key_size_down)) && (max[0 ] >= (key[0 ] + key_size_up)) &&
872
+ (min[1 ] <= (key[1 ] - key_size_down)) && (max[1 ] >= (key[1 ] + key_size_up)) &&
873
+ (min[2 ] <= (key[2 ] - key_size_down)) && (max[2 ] >= (key[2 ] + key_size_up)));
874
+ bool outside = !((min[0 ] <= (key[0 ] + key_size_up)) && (max[0 ] >= (key[0 ] - key_size_down)) &&
875
+ (min[1 ] <= (key[1 ] + key_size_up)) && (max[1 ] >= (key[1 ] - key_size_down)) &&
876
+ (min[2 ] <= (key[2 ] + key_size_up)) && (max[2 ] >= (key[2 ] - key_size_down)));
877
+ assert (!(inside && outside));
878
+ if ((inside && invert) || (outside && !invert)) {
879
+ // Nothing to do, we are entirely out of the deletion target
880
+ } else if ((inside && !invert) || (outside && invert)) {
881
+ // The entire area is inside the deletion area.
882
+ delete_node = true ;
883
+ } else if (depth < max_depth) {
884
+ // At this point the current, inner node is both inside and oustide
885
+ // the bounds (it crosses the boundary).
886
+ // It is not possible to be at the tree_depth unless somehow at the
887
+ // tree_depth we were neither inside or outside the bounding keys
888
+ assert (depth < tree_depth);
889
+ // Expand if pruned leaf.
890
+ if (!nodeHasChildren (node)) {
891
+ expandNode (node);
892
+ }
893
+
894
+ key_type center_offset_key = tree_max_val >> (depth + 1 );
895
+ for (unsigned int i=0 ; i<8 ; i++) {
896
+ if (nodeChildExists (node, i)) {
897
+ OcTreeKey child_key;
898
+ computeChildKey (i, center_offset_key, key, child_key);
899
+
900
+ if (deleteAABBRecurs (min, max,
901
+ getNodeChild (node, i), child_key, depth + 1 ,
902
+ max_depth, invert, deletion_notifier)) {
903
+ setNodeChild (node, i, NULL );
904
+ }
905
+ }
906
+ }
907
+
908
+ // If we have no more children left, this inner node can be removed
909
+ if (!nodeHasChildren (node)) {
910
+ delete_node = true ;
911
+ // prevent notification, as this is not a leaf
912
+ skip_delete_notification = true ;
913
+ } else {
914
+ // It should not be possible to prune this node unless there is a
915
+ // logic bug above, because we should have deleted at least one of
916
+ // our children.
917
+ assert (pruneNode (node) == false );
918
+ // Update the inner node's expiry to track the min of all children
919
+ node->updateOccupancyChildren ();
920
+ }
921
+ }
922
+ }
923
+ }
924
+ if (delete_node) {
925
+ if (deletion_notifier && !skip_delete_notification) {
926
+ deleteNodeRecurs (node, key, depth, deletion_notifier);
927
+ } else {
928
+ deleteNodeRecurs (node);
929
+ }
930
+ }
931
+ return delete_node;
932
+ }
933
+
778
934
template <class NODE ,class I >
779
935
void OcTreeBaseImpl<NODE,I>::pruneRecurs(NODE* node, unsigned int depth,
780
936
unsigned int max_depth, unsigned int & num_pruned) {
0 commit comments