added left-balanced kd-tree construction as another testcase
parent
9c1c16ab87
commit
0516aacfe2
|
@ -97,6 +97,9 @@ public:
|
||||||
enum EHeuristic {
|
enum EHeuristic {
|
||||||
/// Create a balanced tree by splitting along the median
|
/// Create a balanced tree by splitting along the median
|
||||||
EBalanced = 0,
|
EBalanced = 0,
|
||||||
|
|
||||||
|
/// Create a left-balanced tree
|
||||||
|
ELeftBalanced,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Use the sliding midpoint tree construction rule. This
|
* \brief Use the sliding midpoint tree construction rule. This
|
||||||
|
@ -365,10 +368,39 @@ protected:
|
||||||
case EBalanced: {
|
case EBalanced: {
|
||||||
/* Split along the median */
|
/* Split along the median */
|
||||||
split = rangeStart + (rangeEnd-rangeStart)/2;
|
split = rangeStart + (rangeEnd-rangeStart)/2;
|
||||||
|
axis = m_aabb.getLargestAxis();
|
||||||
std::nth_element(rangeStart, split, rangeEnd, CoordinateOrdering(axis));
|
std::nth_element(rangeStart, split, rangeEnd, CoordinateOrdering(axis));
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ELeftBalanced: {
|
||||||
|
size_t treeSize = rangeEnd-rangeStart;
|
||||||
|
/* Layer 0 contains one node */
|
||||||
|
size_t p = 1;
|
||||||
|
|
||||||
|
/* Traverse downwards until the first incompletely
|
||||||
|
filled tree level is encountered */
|
||||||
|
while (2*p <= treeSize)
|
||||||
|
p *= 2;
|
||||||
|
|
||||||
|
/* Calculate the number of filled slots in the last level */
|
||||||
|
size_t remaining = treeSize - p + 1;
|
||||||
|
|
||||||
|
if (2*remaining < p) {
|
||||||
|
/* Case 2: The last level contains too few nodes. Remove
|
||||||
|
overestimate from the left subtree node count and add
|
||||||
|
the remaining nodes */
|
||||||
|
p = (p >> 1) + remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
axis = m_aabb.getLargestAxis();
|
||||||
|
|
||||||
|
split = rangeStart + (p - 1);
|
||||||
|
std::nth_element(rangeStart, split, rangeEnd,
|
||||||
|
CoordinateOrdering(axis));
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
case ESlidingMidpoint: {
|
case ESlidingMidpoint: {
|
||||||
/* Sliding midpoint rule: find a split that is close to the spatial median */
|
/* Sliding midpoint rule: find a split that is close to the spatial median */
|
||||||
axis = m_aabb.getLargestAxis();
|
axis = m_aabb.getLargestAxis();
|
||||||
|
|
|
@ -130,10 +130,10 @@ public:
|
||||||
|
|
||||||
void test03_pointKDTree() {
|
void test03_pointKDTree() {
|
||||||
typedef TKDTree< BasicKDNode<Point2, Float> > KDTree2;
|
typedef TKDTree< BasicKDNode<Point2, Float> > KDTree2;
|
||||||
size_t nPoints = 20000;
|
size_t nPoints = 50000, nTries = 20;
|
||||||
ref<Random> random = new Random();
|
ref<Random> random = new Random();
|
||||||
|
|
||||||
for (int heuristic=0; heuristic<3; ++heuristic) {
|
for (int heuristic=0; heuristic<4; ++heuristic) {
|
||||||
KDTree2 kdtree(nPoints, (KDTree2::EHeuristic) heuristic);
|
KDTree2 kdtree(nPoints, (KDTree2::EHeuristic) heuristic);
|
||||||
|
|
||||||
for (size_t i=0; i<nPoints; ++i) {
|
for (size_t i=0; i<nPoints; ++i) {
|
||||||
|
@ -146,8 +146,10 @@ public:
|
||||||
if (heuristic == 0) {
|
if (heuristic == 0) {
|
||||||
Log(EInfo, "Testing the balanced kd-tree construction heuristic");
|
Log(EInfo, "Testing the balanced kd-tree construction heuristic");
|
||||||
} else if (heuristic == 1) {
|
} else if (heuristic == 1) {
|
||||||
Log(EInfo, "Testing the sliding midpoint kd-tree construction heuristic");
|
Log(EInfo, "Testing the left-balanced kd-tree construction heuristic");
|
||||||
} else if (heuristic == 2) {
|
} else if (heuristic == 2) {
|
||||||
|
Log(EInfo, "Testing the sliding midpoint kd-tree construction heuristic");
|
||||||
|
} else if (heuristic == 3) {
|
||||||
Log(EInfo, "Testing the voxel volume kd-tree construction heuristic");
|
Log(EInfo, "Testing the voxel volume kd-tree construction heuristic");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +158,7 @@ public:
|
||||||
Log(EInfo, "Construction time = %i ms, depth = %i", timer->getMilliseconds(), kdtree.getDepth());
|
Log(EInfo, "Construction time = %i ms, depth = %i", timer->getMilliseconds(), kdtree.getDepth());
|
||||||
|
|
||||||
for (int k=1; k<=10; ++k) {
|
for (int k=1; k<=10; ++k) {
|
||||||
size_t nTraversals = 0, nTries = 10;
|
size_t nTraversals = 0;
|
||||||
for (size_t it = 0; it < nTries; ++it) {
|
for (size_t it = 0; it < nTries; ++it) {
|
||||||
Point2 p(random->nextFloat(), random->nextFloat());
|
Point2 p(random->nextFloat(), random->nextFloat());
|
||||||
nTraversals += kdtree.nnSearch(p, k, results);
|
nTraversals += kdtree.nnSearch(p, k, results);
|
||||||
|
@ -170,7 +172,7 @@ public:
|
||||||
}
|
}
|
||||||
Log(EInfo, "Average number of traversals for a %i-nn query = " SIZE_T_FMT, k, nTraversals / nTries);
|
Log(EInfo, "Average number of traversals for a %i-nn query = " SIZE_T_FMT, k, nTraversals / nTries);
|
||||||
}
|
}
|
||||||
size_t nTraversals = 0, nTries = 10;
|
size_t nTraversals = 0;
|
||||||
for (size_t it = 0; it < nTries; ++it) {
|
for (size_t it = 0; it < nTries; ++it) {
|
||||||
Point2 p(random->nextFloat(), random->nextFloat());
|
Point2 p(random->nextFloat(), random->nextFloat());
|
||||||
nTraversals += kdtree.search(p, 0.05, results);
|
nTraversals += kdtree.search(p, 0.05, results);
|
||||||
|
|
Loading…
Reference in New Issue