49 #ifndef __UT_SpatialTree__
50 #define __UT_SpatialTree__
63 #define MIN_NODE_SIZE 1e-3
69 bool accept(
int objectno)
const {
return myAccept; }
75 template<
class T,
class S,
class B,
int N>
78 enum { BranchFactor = 1 <<
N };
115 const A &accepter)
const;
133 const A &accepter)
const;
140 int max_objects)
const
143 pt, objects, distances2, radius, max_objects,
149 {
return mySubDStrategy; }
158 bool isLeaf()
const {
return !myChildren; }
159 void steal(
Node &node);
166 struct NodeChildPointer
168 NodeChildPointer(
const Node &node) :
169 myNode(node), myChildIndex(0)
179 os <<
"UT_SpatialTree:\n";
185 std::stack<NodeChildPointer> nodes;
186 nodes.push(NodeChildPointer(*myRoot));
187 while(!nodes.empty())
189 const Node &node = nodes.top().myNode;
190 int &child_idx = nodes.top().myChildIndex;
193 for (
size_t i = 0; i < nodes.size(); i++) os <<
" ";
194 os <<
"Node [" << &node <<
"] - Object count: "
195 << node.myObjects.entries() <<
"\n";
197 if (child_idx < BranchFactor && !node.isLeaf())
198 nodes.push(NodeChildPointer(node.myChildren[child_idx++]));
207 bool atEnd()
const {
return myNodeStack.empty(); }
211 while(!myNodeStack.empty())
213 NodeChildPointer &
top = myNodeStack.top();
214 if (top.myNode.isLeaf() ||
215 top.myChildIndex >= BranchFactor)
221 myNodeStack.push(NodeChildPointer(
222 top.myNode.myChildren[top.myChildIndex++]));
232 if (myNodeStack.empty())
235 const NodeChildPointer &
top = myNodeStack.top();
236 return top.myNode.myObjects;
243 if (myNodeStack.empty() || other.myNodeStack.empty())
244 return myNodeStack.empty() && other.myNodeStack.empty();
246 NodeChildPointer &
top = myNodeStack.top();
247 NodeChildPointer &other_top = other.myNodeStack.top();
248 return top.myNode == other_top.myNode &&
249 top.myChildIndex == other_top.myChildIndex;
254 return !(*
this == other);
263 myNodeStack.push(NodeChildPointer(*root));
267 std::stack<NodeChildPointer> myNodeStack;
291 const fpreal *max2)
const;
311 int getChildContainer(
324 int getFirstChild(
int less,
int more)
const;
329 bool getNextChild(
int &childno,
int less,
int more)
const;
351 const fpreal *max2)
const;
387 : myMinSize(min_size)
388 , myMinObjects(min_objects)
389 , myMaxDepth(max_depth)
395 template<
class T,
class B>
406 if (depth >= myMaxDepth ||
407 objects.
entries() <= myMinObjects)
410 for (idimension = 0; idimension < ndimensions;++idimension)
412 if (max[idimension] - min[idimension] < myMinSize)
425 template<
class T,
class S,
class B,
int N>
431 template<
class T,
class S,
class B,
int N>
437 template<
class T,
class S,
class B,
int N>
446 myObjects.entries(0);
448 ::memcpy(myCenter, node.myCenter,
N *
sizeof(
fpreal));
450 myChildren = node.myChildren;
453 for (iobject = 0; iobject < node.myObjects.entries(); ++iobject)
454 myObjects.append(node.myObjects(iobject));
458 template<
class T,
class S,
class B,
int N>
464 , mySubDStrategy(subd_strategy)
465 , myBoundsProvider(bounds_provider)
471 ::memcpy(myMin, min,
N *
sizeof(
fpreal));
472 ::memcpy(myMax, max,
N *
sizeof(
fpreal));
475 template<
class T,
class S,
class B,
int N>
478 , mySubDStrategy(subd_strategy)
479 , myBoundsProvider(bounds_provider)
485 ::memset(myMin, 0,
N *
sizeof(
fpreal));
486 ::memset(myMax, 0,
N *
sizeof(
fpreal));
489 template<
class T,
class S,
class B,
int N>
495 template<
class T,
class S,
class B,
int N>
500 const fpreal *bounds_min, *bounds_max;
501 fpreal bounds_min_buf[
N], bounds_max_buf[
N];
507 bounds_min = myBoundsProvider->getMin(
object, bounds_min_buf);
508 bounds_max = myBoundsProvider->getMax(
object, bounds_max_buf);
511 if (!isInside(myMin, myMax, bounds_min, bounds_max))
512 expand(bounds_min, bounds_max);
514 UT_ASSERT(isInside(myMin, myMax, bounds_min, bounds_max));
517 ::memcpy(min, myMin,
N *
sizeof(
fpreal));
518 ::memcpy(max, myMax,
N *
sizeof(
fpreal));
525 myRoot = node =
new Node();
526 getCenter(myMin, myMax,
myRoot->myCenter);
536 while (!node->isLeaf())
538 childno = getChildContainer(node->myCenter, bounds_min);
539 if (childno != getChildContainer(node->myCenter, bounds_max))
543 childno, min, max, node->myCenter, child_min, child_max);
544 node = &node->myChildren[childno];
545 UT_ASSERT(isInside(child_min,child_max,bounds_min,bounds_max));
546 ::memcpy(min, child_min,
N *
sizeof(
fpreal));
547 ::memcpy(max, child_max,
N *
sizeof(
fpreal));
555 node->myObjects.append(
object);
559 subdivide(node, depth, min, max);
562 template<
class T,
class S,
class B,
int N>
569 int childno, idimension;
575 ::memcpy(myMin, min,
N *
sizeof(
fpreal));
576 ::memcpy(myMax, max,
N *
sizeof(
fpreal));
578 else if (
myRoot->isLeaf())
580 expand(myMin, myMax, min, max);
581 getCenter(myMin, myMax,
myRoot->myCenter);
586 while (!isInside(myMin, myMax, min, max))
591 for (idimension = 0; idimension <
N; ++idimension)
596 size = myMax[idimension] - myMin[idimension];
597 center[0] = (myMin[idimension] + myMax[idimension]) / 2.0;
598 center[1] = (min[idimension] + max[idimension]) / 2.0;
600 if (center[0] < center[1])
603 childno |= 1 << idimension;
604 root->myCenter[idimension] = myMax[idimension];
605 myMax[idimension] +=
size;
610 root->myCenter[idimension] = myMin[idimension];
611 myMin[idimension] -=
size;
617 initChildren(root, myMin, myMax);
618 root->myChildren[childno].steal(*
myRoot);
626 template<
class T,
class S,
class B,
int N>
635 for (idimension = 0; idimension <
N; ++idimension)
637 min1[idimension] =
SYSmin(min1[idimension], min2[idimension]);
638 max1[idimension] =
SYSmax(max1[idimension], max2[idimension]);
642 template<
class T,
class S,
class B,
int N>
650 for (idimension = 0; idimension <
N; ++idimension)
651 center[idimension] = (min[idimension] + max[idimension]) / 2.0;
654 template<
class T,
class S,
class B,
int N>
665 for (idimension = 0; idimension <
N; ++idimension)
667 if ((childno & (1 << idimension)) != 0)
669 child_min[idimension] = min[idimension];
670 child_max[idimension] = center[idimension];
674 child_min[idimension] = center[idimension];
675 child_max[idimension] = max[idimension];
680 template<
class T,
class S,
class B,
int N>
685 int childno, idimension;
689 for (idimension = 0; idimension <
N; ++idimension)
691 if (pt[idimension] < center[idimension])
692 childno |= 1 << idimension;
695 UT_ASSERT(0 <= childno && childno < BranchFactor);
700 template<
class T,
class S,
class B,
int N>
725 template<
class T,
class S,
class B,
int N>
729 int free,
mask, idimension;
737 for (idimension = 0; idimension <
N; ++idimension)
739 mask = 1 << idimension;
740 UT_ASSERT((less & mask) != 0 || (more & mask) != 0);
742 if ((free & mask) != 0)
745 if ((childno & mask) != 0)
750 UT_ASSERT(childno < BranchFactor || idimension == N);
752 return idimension <
N;
755 template<
class T,
class S,
class B,
int N>
760 const A &accepter)
const
763 const fpreal *bounds_min, *bounds_max;
764 fpreal bounds_min_buf[
N], bounds_max_buf[
N];
765 int iobject, childno;
777 for (iobject = 0; iobject < node->myObjects.entries(); ++iobject)
780 bounds_min = myBoundsProvider->getMin(
781 node->myObjects(iobject), bounds_min_buf);
782 bounds_max = myBoundsProvider->getMax(
783 node->myObjects(iobject), bounds_max_buf);
785 if (isInside(bounds_min, bounds_max, pt) &&
786 accepter.accept(node->myObjects(iobject)))
787 objects.
append(node->myObjects(iobject));
794 childno = getChildContainer(node->myCenter, pt);
795 node = &node->myChildren[childno];
799 template<
class T,
class S,
class B,
int N>
807 const A &accepter)
const
818 int iobject, idimension, ichild;
819 int childno, ptchildno,
index, nchildren;
820 int max_stack_size, stack_size, less,
more, diff;
826 if (!
myRoot || max_objects <= 0)
830 max_stack_size = (myDepth - 1) * BranchFactor + 1;
831 node_stack = (Node **)
UTstackAlloc(max_stack_size *
sizeof(Node *));
834 childnos = (
int *)
UTstackAlloc(2 * BranchFactor *
sizeof(
int));
835 indices = childnos + BranchFactor;
839 radius2 = radius * radius;
846 while (stack_size > 0)
852 while (stack_size > 0 && dist_stack[--stack_size] >= radius2)
858 node = node_stack[stack_size];
860 center = node->myCenter;
864 for (iobject = 0; iobject < node->myObjects.entries(); ++iobject)
866 dist2 = myBoundsProvider->getDistance2(
867 node->myObjects(iobject), pt);
869 if (dist2 < radius2 && accepter.accept(node->myObjects(iobject)))
882 if (objects.
entries() == max_objects)
883 radius2 = distances2.
last();
893 for (idimension = 0; idimension <
N; ++idimension)
895 dim_dists2[idimension] = pt[idimension] - center[idimension];
896 dim_dists2[idimension] *= dim_dists2[idimension];
898 if (dim_dists2[idimension] <= radius2)
900 less |= 1 << idimension;
901 more |= 1 << idimension;
903 else if (pt[idimension] < center[idimension])
904 less |= 1 << idimension;
906 more |= 1 << idimension;
911 ptchildno = getChildContainer(center, pt);
912 childno = getFirstChild(less, more);
917 diff = ptchildno ^ childno;
920 for (idimension = 0; idimension <
N; ++idimension)
922 if ((diff & (1 << idimension)) != 0)
923 dist2 += dim_dists2[idimension];
926 childnos[nchildren] = childno;
927 child_dists[nchildren] = dist2;
930 while (getNextChild(childno, less, more));
932 sort(child_dists, nchildren, indices);
936 for (ichild = nchildren - 1; ichild >= 0; --ichild)
938 childno = childnos[indices[ichild]];
939 node_stack[stack_size] = &node->myChildren[childno];
940 dist_stack[stack_size] = child_dists[indices[ichild]];
958 template<
class T,
class S,
class B,
int N>
972 node->myChildren =
new Node[BranchFactor];
975 for (ichild = 0; ichild < BranchFactor; ++ichild)
977 getChildBounds(ichild, min, max, node->myCenter, child_min, child_max);
978 getCenter(child_min, child_max, node->myChildren[ichild].myCenter);
982 template<
class T,
class S,
class B,
int N>
990 for (idimension = 0; idimension <
N; ++idimension)
992 if (pt[idimension] < min[idimension] ||
993 pt[idimension] > max[idimension])
1000 template<
class T,
class S,
class B,
int N>
1005 const fpreal *max2)
const
1009 for (idimension = 0; idimension <
N; ++idimension)
1011 if (min2[idimension] < min1[idimension] ||
1012 max2[idimension] > max1[idimension])
1019 template<
class T,
class S,
class B,
int N>
1025 for (i = 0; i <
n; ++i)
1028 for (i = 0; i <
n; ++i)
1030 for (j = i + 1; j <
n; ++
j)
1032 if (values[indices[j]] < values[indices[i]])
1035 indices[i] = indices[
j];
1042 template<
class T,
class S,
class B,
int N>
1051 const fpreal *bounds_min, *bounds_max;
1052 fpreal bounds_min_buf[
N], bounds_max_buf[
N];
1054 int childno, ichild, iobject;
1060 subd = mySubDStrategy->subdivide(
1072 myDepth =
SYSmax(myDepth, depth + 1);
1075 initChildren(node, min, max);
1079 for (iobject = 0; iobject < node->myObjects.entries(); )
1082 bounds_min = myBoundsProvider->getMin(
1083 node->myObjects(iobject), bounds_min_buf);
1084 bounds_max = myBoundsProvider->getMax(
1085 node->myObjects(iobject), bounds_max_buf);
1088 childno = getChildContainer(node->myCenter, bounds_min);
1089 if (childno == getChildContainer(node->myCenter, bounds_max))
1091 child = &node->myChildren[childno];
1092 child->myObjects.append(node->myObjects(iobject));
1093 node->myObjects.removeIndex(iobject);
1100 for (ichild = 0; ichild < BranchFactor; ++ichild)
1102 getChildBounds(ichild, min, max, node->myCenter, child_min, child_max);
1103 subdivide(&node->myChildren[ichild], depth + 1, child_min, child_max);
1107 #undef MIN_NODE_SIZE
GLsizei GLenum const void * indices
const UT_ValArray< T > & objects() const
const B * getBoundsProvider() const
Returns the bounds provider used by this tree.
NodeIterator leaf_end() const
UT_STAccepter(bool accept)
NodeIterator(const Node *root)
void getObjects(const fpreal *pt, UT_ValArray< T > &objects) const
bool operator!=(const NodeIterator &other)
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
~UT_SpatialTree()
Destructor.
UT_SpatialTree(S *subd_strategy, B *bounds_provider, const fpreal *min, const fpreal *max)
NodeIterator begin() const
#define UTstackAlloc(size)
bool accept(int objectno) const
void dump(std::ostream &os)
exint sortedInsert(const T &t, Comparator compare)
bool operator==(const NodeIterator &other)
bool subdivide(B *bounds_provider, const fpreal *min, const fpreal *max, const UT_ValArray< T > &objects, int depth, int ndimensions)
GLint GLint GLsizei GLsizei GLsizei depth
UT_STBasicSubD(fpreal min_size, int min_objects, int max_depth)
exint entries() const
Alias of size(). size() is preferred.
static int getMaxDimensions()
Return the maximum number of dimensions allowed.
GLenum GLsizei GLsizei GLint * values
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void getObjects(const fpreal *pt, UT_ValArray< T > &objects, const A &accepter) const
GA_API const UT_StringHolder N
int getObjects(const fpreal *pt, UT_ValArray< T > &objects, UT_FloatArray &distances2, fpreal radius, int max_objects) const
void truncate(exint maxsize)
Decreases, but never expands, to the given maxsize.
GLdouble GLdouble GLdouble top
void addObject(T object)
Add the specified object to the tree.
NodeIterator & operator++()
void sort(I begin, I end, const Pred &pred)
const S * getSubdivisionStrategy() const
Returns the subdivision strategy used by this tree.
exint insert(exint index)