Skip to content

Commit 6ce1dc4

Browse files
Merge pull request #1164 from Geode-solutions/generic-search-in-aabbtree
Generic search in aabbtree
2 parents 8054388 + 640b94c commit 6ce1dc4

File tree

2 files changed

+59
-131
lines changed

2 files changed

+59
-131
lines changed

include/geode/geometry/aabb.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,29 @@ namespace geode
195195
const InfiniteLine< dimension >& line,
196196
EvalIntersection& action ) const;
197197

198+
/*!
199+
* @brief Computes the intersections between any object (for which
200+
* intersection against an arbitrary axis-aligned bounding box can be
201+
* detected efficiently) and all element boxes.
202+
* @param[in] box_filter The functor to run to determine whether a box
203+
* is intersected by the searched object or not. The box may correspond
204+
* either to an internal tree node or to a tree element.
205+
* @param[in] action The functor to run when a tree element box is
206+
* intersected by the search object.
207+
* @tparam EvalBox this functor should have an operator() defined like
208+
* this: bool operator( const BoundingBox<dimension> & ) ;
209+
* @tparam EvalIntersection this functor should have an operator()
210+
* defined like this:
211+
* bool operator()( index_t cur_element_box ) ;
212+
* @note the operator define what to do with the box \p cur_element_box
213+
* if it is intersected by the searched object.
214+
* @note The returned boolean indicates if the search should stop or
215+
* continue. Return true to stop the search, false to continue.
216+
*/
217+
template < class EvalBox, class EvalIntersection >
218+
void compute_generic_element_bbox_intersections(
219+
const EvalBox& box_filter, EvalIntersection& action ) const;
220+
198221
/*!
199222
* @brief Computes the intersections between a given Segment and
200223
* all element boxes.

include/geode/geometry/detail/aabb_impl.hpp

Lines changed: 36 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -260,104 +260,6 @@ namespace geode
260260
}
261261
}
262262

263-
template < typename ACTION >
264-
bool bbox_intersect_recursive( const BoundingBox< dimension >& box,
265-
index_t node_index,
266-
index_t element_begin,
267-
index_t element_end,
268-
index_t depth,
269-
ACTION& action ) const
270-
271-
{
272-
OPENGEODE_ASSERT(
273-
node_index < tree_.size(), "Node out of tree range" );
274-
OPENGEODE_ASSERT( element_begin != element_end,
275-
"No iteration allowed start == end" );
276-
277-
// Prune sub-tree that does not have intersection
278-
if( !box.intersects( node( node_index ) ) )
279-
{
280-
return false;
281-
}
282-
283-
if( is_leaf( element_begin, element_end ) )
284-
{
285-
return action( mapping_morton( element_begin ) );
286-
}
287-
288-
const auto it = get_recursive_iterators(
289-
node_index, element_begin, element_end );
290-
if( depth > async_depth_ )
291-
{
292-
if( bbox_intersect_recursive( box, it.child_left, element_begin,
293-
it.element_middle, depth + 1, action ) )
294-
{
295-
return true;
296-
}
297-
return bbox_intersect_recursive( box, it.child_right,
298-
it.element_middle, element_end, depth + 1, action );
299-
}
300-
auto task = async::local_spawn( [&] {
301-
return bbox_intersect_recursive( box, it.child_left,
302-
element_begin, it.element_middle, depth + 1, action );
303-
} );
304-
if( bbox_intersect_recursive( box, it.child_right,
305-
it.element_middle, element_end, depth + 1, action ) )
306-
{
307-
return true;
308-
}
309-
return task.get();
310-
}
311-
312-
template < typename ACTION >
313-
bool triangle_intersect_recursive(
314-
const Triangle< dimension >& triangle,
315-
index_t node_index,
316-
index_t element_begin,
317-
index_t element_end,
318-
index_t depth,
319-
ACTION& action ) const
320-
{
321-
OPENGEODE_ASSERT(
322-
node_index < tree_.size(), "Node out of tree range" );
323-
OPENGEODE_ASSERT( element_begin != element_end,
324-
"No iteration allowed start == end" );
325-
326-
// Prune sub-tree that does not have intersection
327-
if( !node( node_index ).intersects( triangle ) )
328-
{
329-
return false;
330-
}
331-
332-
if( is_leaf( element_begin, element_end ) )
333-
{
334-
return action( mapping_morton( element_begin ) );
335-
}
336-
337-
const auto it = get_recursive_iterators(
338-
node_index, element_begin, element_end );
339-
if( depth > async_depth_ )
340-
{
341-
if( triangle_intersect_recursive( triangle, it.child_left,
342-
element_begin, it.element_middle, depth + 1, action ) )
343-
{
344-
return true;
345-
}
346-
return triangle_intersect_recursive( triangle, it.child_right,
347-
it.element_middle, element_end, depth + 1, action );
348-
}
349-
auto task = async::local_spawn( [&] {
350-
return triangle_intersect_recursive( triangle, it.child_left,
351-
element_begin, it.element_middle, depth + 1, action );
352-
} );
353-
if( triangle_intersect_recursive( triangle, it.child_right,
354-
it.element_middle, element_end, depth + 1, action ) )
355-
{
356-
return true;
357-
}
358-
return task.get();
359-
}
360-
361263
template < typename ACTION >
362264
bool self_intersect_recursive( index_t node_index1,
363265
index_t element_begin1,
@@ -523,8 +425,8 @@ namespace geode
523425
return task.get();
524426
}
525427

526-
template < typename Line, typename ACTION >
527-
bool line_intersect_recursive( const Line& line,
428+
template < typename BOX_FILTER, typename ACTION >
429+
bool generic_intersect_recursive( const BOX_FILTER& box_filter,
528430
index_t node_index,
529431
index_t element_begin,
530432
index_t element_end,
@@ -537,7 +439,7 @@ namespace geode
537439
"No iteration allowed start == end" );
538440

539441
// Prune sub-tree that does not have intersection
540-
if( !node( node_index ).intersects( line ) )
442+
if( !box_filter( node( node_index ) ) )
541443
{
542444
return false;
543445
}
@@ -551,19 +453,19 @@ namespace geode
551453
node_index, element_begin, element_end );
552454
if( depth > async_depth_ )
553455
{
554-
if( line_intersect_recursive( line, it.child_left,
456+
if( generic_intersect_recursive( box_filter, it.child_left,
555457
element_begin, it.element_middle, depth + 1, action ) )
556458
{
557459
return true;
558460
}
559-
return line_intersect_recursive( line, it.child_right,
461+
return generic_intersect_recursive( box_filter, it.child_right,
560462
it.element_middle, element_end, depth + 1, action );
561463
}
562464
auto task = async::local_spawn( [&] {
563-
return line_intersect_recursive( line, it.child_left,
465+
return generic_intersect_recursive( box_filter, it.child_left,
564466
element_begin, it.element_middle, depth + 1, action );
565467
} );
566-
if( line_intersect_recursive( line, it.child_right,
468+
if( generic_intersect_recursive( box_filter, it.child_right,
567469
it.element_middle, element_end, depth + 1, action ) )
568470
{
569471
return true;
@@ -669,12 +571,10 @@ namespace geode
669571
void AABBTree< dimension >::compute_bbox_element_bbox_intersections(
670572
const BoundingBox< dimension >& box, EvalIntersection& action ) const
671573
{
672-
if( nb_bboxes() == 0 )
673-
{
674-
return;
675-
}
676-
impl_->bbox_intersect_recursive(
677-
box, Impl::ROOT_INDEX, 0, nb_bboxes(), 0, action );
574+
const auto box_filter = [&box]( const auto& inner_box ) {
575+
return inner_box.intersects( box );
576+
};
577+
compute_generic_element_bbox_intersections( box_filter, action );
678578
}
679579

680580
template < index_t dimension >
@@ -709,50 +609,55 @@ namespace geode
709609
void AABBTree< dimension >::compute_ray_element_bbox_intersections(
710610
const Ray< dimension >& ray, EvalIntersection& action ) const
711611
{
712-
if( nb_bboxes() == 0 )
713-
{
714-
return;
715-
}
716-
impl_->line_intersect_recursive(
717-
ray, Impl::ROOT_INDEX, 0, nb_bboxes(), 0, action );
612+
const auto box_filter = [&ray]( const auto& box ) {
613+
return box.intersects( ray );
614+
};
615+
compute_generic_element_bbox_intersections( box_filter, action );
718616
}
719617

720618
template < index_t dimension >
721619
template < class EvalIntersection >
722620
void AABBTree< dimension >::compute_line_element_bbox_intersections(
723621
const InfiniteLine< dimension >& line, EvalIntersection& action ) const
622+
{
623+
const auto box_filter = [&line]( const auto& box ) {
624+
return box.intersects( line );
625+
};
626+
compute_generic_element_bbox_intersections( box_filter, action );
627+
}
628+
629+
template < index_t dimension >
630+
template < class EvalBox, class EvalIntersection >
631+
void AABBTree< dimension >::compute_generic_element_bbox_intersections(
632+
const EvalBox& box_filter, EvalIntersection& action ) const
724633
{
725634
if( nb_bboxes() == 0 )
726635
{
727636
return;
728637
}
729-
impl_->line_intersect_recursive(
730-
line, Impl::ROOT_INDEX, 0, nb_bboxes(), 0, action );
638+
impl_->generic_intersect_recursive(
639+
box_filter, Impl::ROOT_INDEX, 0, nb_bboxes(), 0, action );
731640
}
732641

733642
template < index_t dimension >
734643
template < class EvalIntersection >
735644
void AABBTree< dimension >::compute_triangle_element_bbox_intersections(
736645
const Triangle< dimension >& triangle, EvalIntersection& action ) const
737646
{
738-
if( nb_bboxes() == 0 )
739-
{
740-
return;
741-
}
742-
impl_->triangle_intersect_recursive(
743-
triangle, Impl::ROOT_INDEX, 0, nb_bboxes(), 0, action );
647+
const auto box_filter = [&triangle]( const auto& box ) {
648+
return box.intersects( triangle );
649+
};
650+
compute_generic_element_bbox_intersections( box_filter, action );
744651
}
745652

746653
template < index_t dimension >
747654
template < class EvalIntersection >
748655
void AABBTree< dimension >::compute_segment_element_bbox_intersections(
749656
const Segment< dimension >& segment, EvalIntersection& action ) const
750657
{
751-
if( nb_bboxes() == 0 )
752-
{
753-
return;
754-
}
755-
impl_->line_intersect_recursive(
756-
segment, Impl::ROOT_INDEX, 0, nb_bboxes(), 0, action );
658+
const auto box_filter = [&segment]( const auto& box ) {
659+
return box.intersects( segment );
660+
};
661+
compute_generic_element_bbox_intersections( box_filter, action );
757662
}
758663
} // namespace geode

0 commit comments

Comments
 (0)