11 #ifndef __UT_RTREEIMPL_H_INCLUDED__
12 #define __UT_RTREEIMPL_H_INCLUDED__
18 template<
typename BOX,
typename ITEM_INDEX_REP >
47 template<
typename BOX,
typename ITEM_INDEX_REP >
48 inline std::ostream& operator<<(std::ostream& os, const UT_BoxedItemT< BOX, ITEM_INDEX_REP >& bf)
52 os << bf.myBox <<
", ";
62 template<
typename BOX >
65 const BOX*
const begin,
71 for(
const BOX* i = begin; i !=
end; ++i )
73 bounding_box.absorbBox(*i);
79 template<
typename BOX,
typename ITEM_INDEX_REP >
86 static_assert( SYS_IsIntegral_v< ITEM_INDEX_REP > );
90 bounding_box = begin->
myBox;
94 bounding_box.absorbBox(i->myBox);
101 template<
typename ITEM_INDEX_REP,
int MAX_ORDER >
107 using Slot = std::make_unsigned_t< ITEM_INDEX_REP >;
121 for(
int s = 0;
s < MAX_ORDER; ++
s )
166 UT_ASSERT( (0 <= s) && (s < MAX_ORDER) );
169 return (
mySlots[s] & SLOT_MASK_INDEX);
177 for(
int s = 0;
s < MAX_ORDER; ++
s )
194 UT_ASSERT( (0 <= s) && (s < MAX_ORDER) );
197 return (
mySlots[s] & SLOT_MASK_INDEX);
232 if( size > MAX_ORDER )
239 while( m * MAX_ORDER < size )
250 const size_t num_subtrees_size_m( size / m );
256 num_nodes += num_subtrees_size_m * num_nodes_for_m;
261 const size_t num_remaining_items( size % m );
262 if( num_remaining_items > 0 )
281 template<
typename BOX,
typename ITEM_INDEX_REP >
284 template<
typename IS_LESS_THAN >
288 IS_LESS_THAN&& is_less_than,
289 const ITEM_INDEX_REP m,
290 const int num_subtrees
293 if( num_subtrees <= 1 )
301 const auto mid{ num_subtrees / 2 };
302 const auto i{ mid * m };
317 template<
typename BOX,
typename ITEM_INDEX_REP,
int MAX_ORDER >
318 inline RNodeT< ITEM_INDEX_REP, MAX_ORDER >*
328 static_assert( SYS_IsIntegral_v< ITEM_INDEX_REP > );
336 #if UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_PARANOID
344 RNode* node( shared_nodes_end++ );
350 Box*
const node_boxes( shared_boxes + ((node - shared_nodes) * MAX_ORDER) );
352 const size_t size(end - begin);
358 if( size > MAX_ORDER )
364 node->setInternal(
true);
369 ITEM_INDEX_REP m{ MAX_ORDER };
370 while( m * MAX_ORDER < size )
379 const int num_subtrees_size_m( size / m );
388 const int largest_axis = bounding_box.getLargestAxis();
392 return ( signAxisCenterComparison( largest_axis, a.
myBox,
b.myBox ) == 1 );
399 m, num_subtrees_size_m
407 for(
int s = 0;
s < num_subtrees_size_m; ++
s )
409 if( size - offset < m )
414 const size_t next_offset( offset + m );
421 begin + offset, begin + next_offset,
427 offset = next_offset;
431 const size_t num_remaining_items( size % m );
432 if( num_remaining_items > 0 )
435 UT_ASSERT_P( num_remaining_items == size - offset );
437 const size_t next_offset( offset + num_remaining_items );
442 node_boxes[num_subtrees_size_m],
444 begin + offset, begin + next_offset,
450 offset = next_offset;
461 node->setInternal(
false);
466 node_boxes[
s] = i->myBox;
467 node->assignItem(s, i->myItem);
475 template<
typename ITEM_INDEX_REP,
int MAX_ORDER,
typename ITEM_BOX,
typename FT >
485 static_assert( SYS_IsIntegral_v< ITEM_INDEX_REP > );
496 ((node - shared_nodes) * MAX_ORDER)
499 if( node->isInternal() )
501 for(
int s = 0;
s < MAX_ORDER; ++
s )
503 if( (node->mySlots[
s] & RNode::SLOT_MASK_INDEX) == RNode::SLOT_VALUE_EMPTY )
512 shared_nodes + node->getSubtree(s),
520 for( ; s < MAX_ORDER; ++
s )
522 if( ( node->mySlots[ s ] & RNode::SLOT_MASK_INDEX ) == RNode::SLOT_VALUE_EMPTY )
527 s_box[
s] = item_box[ node->getItemIndexRep( s ) ];
530 for( ; s < MAX_ORDER; ++
s )
539 template<
typename ITEM_INDEX,
int MAX_ORDER >
544 template<
typename FT,
typename QUERY_SHAPE,
typename ACCEPT_ITEM >
546 ACCEPT_ITEM&& accept_item,
550 const QUERY_SHAPE& query_shape
553 static_assert( SYS_IsIntegral_v< ItemIndexRep > );
562 const Box*
const node_boxes(
564 ((node - shared_nodes) * MAX_ORDER)
567 if( node->isInternal() )
569 for(
int s = 0;
s < MAX_ORDER; ++
s )
571 if( (node->mySlots[
s] & RNode::SLOT_MASK_INDEX) == RNode::SLOT_VALUE_EMPTY )
579 std::forward< ACCEPT_ITEM >( accept_item ),
581 shared_nodes + node->getSubtree( s ),
589 for(
int s = 0;
s < MAX_ORDER; ++
s )
591 if( (node->mySlots[
s] & RNode::SLOT_MASK_INDEX) == RNode::SLOT_VALUE_EMPTY )
598 accept_item( ITEM_INDEX{ node->getItemIndexRep( s ) } );
605 template<
typename ITEM_INDEX_REP,
int MAX_ORDER >
611 static_assert( SYS_IsIntegral_v< ITEM_INDEX_REP > );
617 if( node->isInternal() )
619 int max_depth_children(0);
621 for(
int s = 0;
s < MAX_ORDER; ++
s )
623 if( (node->mySlots[
s] & RNode::SLOT_MASK_INDEX) == RNode::SLOT_VALUE_EMPTY )
630 UTsubtreeComputeMaxDepth(shared_nodes, shared_nodes + node->getSubtree(
s))
634 return 1 + max_depth_children;
645 template<
typename FT >
647 const exint node_slot_box_size,
650 myNodeSlotBoxSize( node_slot_box_size ),
651 myNodeSlotBox( std::move( node_slot_box ) )
655 template<
typename FT >
657 myNodeSlotBoxSize(
a.myNodeSlotBoxSize ),
658 myNodeSlotBox( std::move(
a.myNodeSlotBox ) )
662 template<
typename ITEM_INDEX,
int MAX_ORDER >
663 template<
typename FT >
673 using ItemIndexRep = ItemIndex_UnderlyingIntegerType_t< ITEM_INDEX >;
681 UT_ASSERT( myNumItems < ( ItemIndexRep(1) << ( ( 8 *
sizeof(ItemIndexRep) ) - 2 ) ) );
685 for( ItemIndexRep i = 0; i < myNumItems; ++i )
687 const Box& box( item_box[ i ] );
697 if( num_boxed_items <= 0 )
732 std::cout <<
"RTree stats: " << std::endl;
733 std::cout <<
"Number of items: " <<
num_items << std::endl;
734 std::cout <<
"Tree size (in node): " <<
myNumNodes << std::endl;
735 std::cout <<
"MAX_ORDER (max children/items per node) = " << MAX_ORDER << std::endl;
737 std::cout <<
"Max tree depth: " << UTsubtreeComputeMaxDepth(
myNodes,
myRoot) << std::endl;
741 template<
typename ITEM_INDEX,
int MAX_ORDER >
742 template<
typename FT >
747 RTreeT( item_box.array(), item_box.
size() )
751 template<
typename ITEM_INDEX,
int MAX_ORDER >
756 myNumItems(
a.myNumItems )
764 template<
typename ITEM_INDEX,
int MAX_ORDER >
773 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
779 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
782 return constructRTree< ITEM_INDEX, MAX_ORDER >( item_box.array(), item_box.size() );
785 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
790 exint node_slot_box_size = -1;
794 UT_ASSERT( ItemIndexUnderlyingInteger< ITEM_INDEX >{}(
num_items ) == tree.myNumItems );
796 if( tree.myRoot ==
nullptr )
800 node_slot_box_size = 0;
801 node_slot_box.reset();
805 std::move( node_slot_box )
811 node_slot_box_size = MAX_ORDER * tree.myNumNodes;
812 node_slot_box = std::make_unique< Box[] >( node_slot_box_size );
827 std::move( node_slot_box )
831 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
837 template<
typename FT >
842 return configuration.myNodeSlotBoxSize *
sizeof(
Box);
845 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
850 const ITEM_INDEX num_items
856 UT_ASSERT( num_items == tree.myNumItems );
858 if( tree.myRoot ==
nullptr )
861 UT_ASSERT( configuration.myNodeSlotBoxSize == 0 );
862 UT_ASSERT( configuration.myNodeSlotBox ==
nullptr );
868 UT_ASSERT( configuration.myNodeSlotBoxSize = MAX_ORDER * tree.myNumNodes );
869 UT_ASSERT( configuration.myNodeSlotBox !=
nullptr );
874 configuration.myNodeSlotBox.get(),
881 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
888 updateConfiguration( configuration, tree, item_box.data(), ITEM_INDEX( item_box.size() ) );
891 template<
typename QUERY_SHAPE,
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
896 const QUERY_SHAPE& query_shape
902 [ &results ](
const ITEM_INDEX i ) { results.
append( i ); },
912 template<
typename ITEM_INDEX,
int MAX_ORDER,
typename FT,
typename QUERY_SHAPE,
typename ACCEPT_ITEM >
914 ACCEPT_ITEM&& accept_item,
917 const QUERY_SHAPE& query_shape
922 UT_ASSERT( configuration.myNodeSlotBoxSize == MAX_ORDER * tree.myNumNodes );
924 if( tree.myRoot ==
nullptr )
930 std::forward< ACCEPT_ITEM >( accept_item ),
932 configuration.myNodeSlotBox.get(),
933 tree.myRoot, query_shape
937 template<
typename ITEM_INDEX,
int MAX_ORDER >
940 using ItemIndexRep = ItemIndex_UnderlyingIntegerType_t< ITEM_INDEX >;
941 using RNode = RNodeT< ItemIndexRep, MAX_ORDER >;
943 return tree.myNumNodes *
sizeof(RNode);
946 template<
typename QUERY_SHAPE,
typename ITEM_INDEX,
int MAX_ORDER,
typename FT >
950 const QUERY_SHAPE& query_box,
951 ITEM_INDEX*
const items_begin
954 ITEM_INDEX* it = items_begin;
957 [ &it ](
const ITEM_INDEX i ) { *it++ = i; },
965 template<
typename FT >
968 return UT::constructRTree< UT_RTree16Int::ItemIndex, UT_RTree16Int::max_order, FT >( item_box );
971 template<
typename FT >
974 return UT::constructRTree< UT_RTree2Int::ItemIndex, UT_RTree2Int::max_order, FT >( item_box );
977 template<
typename FT >
980 return UT::constructRTree< UT_RTreeInt::ItemIndex, UT_RTreeInt::max_order, FT >( item_box,
num_items );
983 template<
typename FT >
986 return UT::constructRTree< UT_RTreeInt::ItemIndex, UT_RTreeInt::max_order, FT >( item_box );
989 template<
typename FT >
992 return UT::constructRTree< UT_RTree::ItemIndex, UT_RTree::max_order, FT >( item_box,
num_items );
995 template<
typename FT >
998 return UT::constructRTree< UT_RTree::ItemIndex, UT_RTree::max_order, FT >( item_box );
1001 template<
typename FT >
1004 return UT::constructRTreeConfiguration< UT_RTree2Int::ItemIndex, UT_RTree2Int::max_order, FT >( tree, item_box );
1007 template<
typename FT >
1010 return UT::constructRTreeConfiguration< UT_RTree16Int::ItemIndex, UT_RTree16Int::max_order, FT >( tree, item_box );
1013 template<
typename FT >
1016 return UT::constructRTreeConfiguration< UT_RTreeInt::ItemIndex, UT_RTreeInt::max_order, FT >( tree, item_box );
1019 template<
typename FT >
1022 return UT::constructRTreeConfiguration< UT_RTreeInt::ItemIndex, UT_RTreeInt::max_order, FT >( tree, item_box,
num_items );
1025 template<
typename FT >
1028 return UT::constructRTreeConfiguration< UT_RTree::ItemIndex, UT_RTree::max_order, FT >( tree, item_box );
1031 template<
typename FT >
1037 template<
typename FT >
1043 template<
typename FT >
1049 template<
typename FT >
1055 template<
typename FT >
1061 template<
typename FT >
1067 template<
typename FT >
1073 template<
typename FT >
1079 #endif // __UT_RTREEIMPL_H_INCLUDED__
static const Slot SLOT_MASK_INDEX
UT_RTree16IntConfigurationT< FT > UTconstructRTree16IntConfiguration(const UT_RTree16Int &tree, const UT_Array< UT_BoxT< FT > > &item_box)
std::make_unsigned_t< ITEM_INDEX_REP > Slot
auto UTmakeUniqueRTree2Int(const UT_Array< UT_BoxT< FT > > &item_box)
void UTnth_element(IT start, IT nth, IT end, COMPARE isAbeforeB)
void subtreeAssignItemBoxArray(UT_BoxT< FT > &bounding_box, UT_BoxT< FT > shared_boxes[], const RNodeT< ITEM_INDEX_REP, MAX_ORDER > shared_nodes[], const RNodeT< ITEM_INDEX_REP, MAX_ORDER > *const node, ITEM_BOX &&item_box)
void computeBoundingBoxItem(BOX &bounding_box, const UT_BoxedItemT< BOX, ITEM_INDEX_REP > *const begin, const UT_BoxedItemT< BOX, ITEM_INDEX_REP > *const end)
auto UTmakeUniqueRTree16Int(const UT_Array< UT_BoxT< FT > > &item_box)
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isEmpty() const IMATH_NOEXCEPT
auto UTmakeUniqueRTreeIntConfiguration(const UT_RTreeInt &tree, const UT_Array< UT_BoxT< FT > > &item_box)
RNodeT< ITEM_INDEX_REP, MAX_ORDER > * subtreeCreate(BOX &bounding_box, BOX shared_boxes[], UT_BoxedItemT< BOX, ITEM_INDEX_REP > *const begin, UT_BoxedItemT< BOX, ITEM_INDEX_REP > *const end, RNodeT< ITEM_INDEX_REP, MAX_ORDER > shared_nodes[], RNodeT< ITEM_INDEX_REP, MAX_ORDER > *&shared_nodes_end)
GLboolean GLboolean GLboolean GLboolean a
UT_BoxedItemT(const Box &box, const ItemIndexRep item)
exint heapMemoryUsage(const RTreeConfigurationT< FT > &configuration)
Slot getSubtree(const int s) const
constexpr void operator()(UT_BoxedItemT< BOX, ITEM_INDEX_REP > *const begin, UT_BoxedItemT< BOX, ITEM_INDEX_REP > *const end, IS_LESS_THAN &&is_less_than, const ITEM_INDEX_REP m, const int num_subtrees) const noexcept
ITEM_INDEX_REP ItemIndexRep
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
constexpr void operator()(ACCEPT_ITEM &&accept_item, const RNodeT< ItemIndexRep, MAX_ORDER > shared_nodes[], const UT_BoxT< FT > shared_boxes[], const RNodeT< ItemIndexRep, MAX_ORDER > *const node, const QUERY_SHAPE &query_shape) const noexcept
void assignSubtree(const int s, const Slot index_root_subtree)
auto UTmakeUniqueRTreeInt(const UT_Array< UT_BoxT< FT > > &item_box)
UT_RTree2IntConfigurationT< FT > UTconstructRTree2IntConfiguration(const UT_RTree2Int &tree, const UT_Array< UT_BoxT< FT > > &item_box)
UT_BoxedItemT< Box, ItemIndexRep > BoxedItem
RTreeT< ITEM_INDEX, MAX_ORDER > constructRTree(const UT_BoxT< FT > item_box[], const ITEM_INDEX num_items)
void assignItem(const int s, const ITEM_INDEX_REP item)
RTreeConfigurationT< FT > constructRTreeConfiguration(const UT::RTreeT< ITEM_INDEX, MAX_ORDER > &tree, const UT_BoxT< FT > item_box[], const ITEM_INDEX num_items)
SYS_FORCE_INLINE ITEM_INDEX_REP getItemIndexRep(const int s) const
UT_RTreeIntConfigurationT< FT > UTconstructRTreeIntConfiguration(const UT_RTreeInt &tree, const UT_Array< UT_BoxT< FT > > &item_box)
auto UTmakeUniqueRTree2IntConfiguration(const UT_RTree2Int &tree, const UT_Array< UT_BoxT< FT > > &item_box)
UT_RTreeConfigurationT< FT > UTconstructRTreeConfiguration(const UT_RTree &tree, const UT_Array< UT_BoxT< FT > > &item_box)
void computeBoundingBox(BOX &bounding_box, const BOX *const begin, const BOX *const end)
void forEachIntersecting(ACCEPT_ITEM &&accept_item, const RTreeT< ITEM_INDEX, MAX_ORDER > &tree, const RTreeConfigurationT< FT > &configuration, const QUERY_SHAPE &query_shape)
GLboolean GLboolean GLboolean b
UT_RTree UTconstructRTree(const UT_BoxT< FT > item_box[], const UT_RTree::ItemIndex num_items)
void updateConfiguration(RTreeConfigurationT< FT > &configuration, const RTreeT< ITEM_INDEX, MAX_ORDER > &tree, const UT_BoxT< FT > item_box[], const ITEM_INDEX num_items)
typename ItemIndex_UnderlyingIntegerType< ITEM_INDEX >::type ItemIndex_UnderlyingIntegerType_t
static const Slot SLOT_FLAG_INTERNAL
ItemIndex_UnderlyingIntegerType_t< ITEM_INDEX > ItemIndexRep
SYS_STATIC_ASSERT(MAX_ORDER >=2)
UT_RTreeInt UTconstructRTreeInt(const UT_BoxT< FT > item_box[], const UT_RTreeInt::ItemIndex num_items)
UT_RTree2Int UTconstructRTree2Int(const UT_Array< UT_BoxT< FT > > &item_box)
exint subtreeComputeMaxDepth(const RNodeT< ITEM_INDEX_REP, MAX_ORDER > shared_nodes[], const RNodeT< ITEM_INDEX_REP, MAX_ORDER > *const node)
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
size_t subtreeDetermineNumNodes(const int MAX_ORDER, const size_t size)
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects(const Box< Vec3< T >> &b, const Line3< T > &r, Vec3< T > &ip) IMATH_NOEXCEPT
static const Slot SLOT_VALUE_EMPTY
UT_ASSERT(myNumItems >=0)
void setInternal(const bool isInternal)
void clear()
Resets list to an empty list.
ItemIndexRep num_boxed_items
auto UTmakeUniqueRTree16IntConfiguration(const UT_RTree16Int &tree, const UT_Array< UT_BoxT< FT > > &item_box)
void getIntersecting(UT_Array< ITEM_INDEX > &results, const RTreeT< ITEM_INDEX, MAX_ORDER > &tree, const RTreeConfigurationT< FT > &configuration, const QUERY_SHAPE &query_shape)
ITEM_INDEX * getIntersectingRaw(const RTreeT< ITEM_INDEX, MAX_ORDER > &tree, const RTreeConfigurationT< FT > &configuration, const QUERY_SHAPE &query_shape, ITEM_INDEX *const items_begin)
UT_RTree16Int UTconstructRTree16Int(const UT_Array< UT_BoxT< FT > > &item_box)
ITEM_INDEX_REP countNumItems() const
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.