68 childLeft->deleteChildren();
75 childRight->deleteChildren();
85 for(
unsigned int ui=0;ui<depth; ui++)
88 strm <<
"(" << loc.getValue(0)
89 <<
"," << loc.getValue(1) <<
"," << loc.getValue(2)
93 childLeft->dump(strm,depth+1);
96 childRight->dump(strm,depth+1);
144 root=buildRecurse(pts.begin(), pts.end(),0);
163 root=buildRecurse(pts.begin(), pts.end(),0);
167 K3DNodeApprox*K3DTreeApprox::buildRecurse(vector<Point3D>::iterator pts_start, vector<Point3D>::iterator pts_end,
unsigned int depth)
171 unsigned int curAxis=depth%3;
172 unsigned int ptsSize=pts_end - pts_start - 1;
179 unsigned int median =(ptsSize)/2;
186 sort(pts_start,pts_end,axisCmp);
189 node->
setLoc(*(pts_start + median));
193 node->
setLeft(buildRecurse(pts_start,pts_start + median,depth+1));
198 node->
setRight(buildRecurse(pts_start + median + 1, pts_end,depth+1));
214 const float deadDistSqr)
const 216 enum { NODE_FIRST_VISIT,
224 float domainStack[maxDepth+1][2];
225 unsigned int visitStack[maxDepth+1];
232 unsigned int stackTop;
233 unsigned int curAxis;
241 bestDistSqr =std::numeric_limits<float>::max();
242 curDomain=domainCube;
243 visit=NODE_FIRST_VISIT;
261 case NODE_FIRST_VISIT:
263 if(searchPt[curAxis] < curNode->
getLocVal(curAxis))
269 tmpEdge= curDomain.bounds[curAxis][1];
270 curDomain.bounds[curAxis][1] = curNode->
getLocVal(curAxis);
271 if(bestPoint && !curDomain.
intersects(*bestPoint,bestDistSqr))
273 curDomain.bounds[curAxis][1] = tmpEdge;
279 nodeStack[stackTop]=curNode;
280 visitStack[stackTop] = NODE_SECOND_VISIT;
281 domainStack[stackTop][1] = tmpEdge;
282 domainStack[stackTop][0]= curDomain.bounds[curAxis][0];
286 curNode=curNode->
left();
287 visit=NODE_FIRST_VISIT;
299 tmpEdge= curDomain.bounds[curAxis][0];
300 curDomain.bounds[curAxis][0] = curNode->
getLocVal(curAxis);
302 if(bestPoint && !curDomain.
intersects(*bestPoint,bestDistSqr))
304 curDomain.bounds[curAxis][0] =tmpEdge;
309 nodeStack[stackTop]=curNode;
310 visitStack[stackTop] = NODE_SECOND_VISIT;
311 domainStack[stackTop][0] = tmpEdge;
312 domainStack[stackTop][1]= curDomain.bounds[curAxis][1];
316 curNode=curNode->
right();
317 visit=NODE_FIRST_VISIT;
328 case NODE_SECOND_VISIT:
330 if(searchPt[curAxis]< curNode->
getLocVal(curAxis))
336 tmpEdge= curDomain.bounds[curAxis][0];
337 curDomain.bounds[curAxis][0] = curNode->
getLocVal(curAxis);
339 if(bestPoint && !curDomain.
intersects(*bestPoint,bestDistSqr))
341 curDomain.bounds[curAxis][0] = tmpEdge;
346 nodeStack[stackTop]=curNode;
347 visitStack[stackTop] = NODE_THIRD_VISIT;
348 domainStack[stackTop][0] = tmpEdge;
349 domainStack[stackTop][1]= curDomain.bounds[curAxis][1];
353 curNode=curNode->
right();
354 visit=NODE_FIRST_VISIT;
367 tmpEdge= curDomain.bounds[curAxis][1];
368 curDomain.bounds[curAxis][1] = curNode->
getLocVal(curAxis);
370 if(bestPoint && !curDomain.
intersects(*bestPoint,bestDistSqr))
372 curDomain.bounds[curAxis][1] = tmpEdge;
377 nodeStack[stackTop]=curNode;
378 visitStack[stackTop] = NODE_THIRD_VISIT;
379 domainStack[stackTop][1] = tmpEdge;
380 domainStack[stackTop][0]= curDomain.bounds[curAxis][0];
384 curNode=curNode->
left();
385 visit=NODE_FIRST_VISIT;
396 case NODE_THIRD_VISIT:
399 tmpDistSqr = curNode->
sqrDist(searchPt);
400 if(tmpDistSqr < bestDistSqr && tmpDistSqr > deadDistSqr)
402 bestDistSqr = tmpDistSqr;
407 ASSERT(stackTop%3 == curAxis)
416 ASSERT(stackTop < maxDepth+1);
420 visit=visitStack[stackTop];
421 curNode=nodeStack[stackTop];
422 curDomain.bounds[curAxis][0]=domainStack[stackTop][0];
423 curDomain.bounds[curAxis][1]=domainStack[stackTop][1];
425 ASSERT((stackTop)%3 == curAxis)
435 }
while(!(curNode==root && visit== NODE_THIRD_VISIT));
438 float rootDist = root->
sqrDist(searchPt);
439 if(rootDist < bestDistSqr && rootDist > deadDistSqr)
448 unsigned int num, vector<const Point3D *> &bestPts,
449 float deadDistSqr)
const 453 bestPts.reserve(num);
456 for(
unsigned int ui=0; ui<num; ui++)
465 bestPts.push_back(p);
467 sqrDist = p->
sqrDist(searchPt);
468 deadDistSqr = sqrDist+std::numeric_limits<float>::epsilon();
476 bool K3DTreeApprox::test()
481 pts.push_back(
Point3D(0,0.5,0.5));
482 pts.push_back(
Point3D(100,0,0));
492 TEST( p->
sqrDist(pts[1]) < 0.01,
"findNearest check");
float sqrDist(const Point3D &pt) const
Returns the square of distance to another Point3D.
float getLocVal(unsigned int pos) const
Obtain the coordinates at dimension "pos".
bool intersects(const Point3D &pt, float sqrRad) const
Checks if a point intersects a sphere of centre Pt, radius^2 sqrRad.
float sqrDist(const Point3D &pt) const
Obtain the distance between this node and another point.
const Point3D * getLocRef() const
Return a pointer to the point from the node.
void findKNearest(const Point3D &sourcePoint, const BoundCube &treeDomain, unsigned int numNNs, std::vector< const Point3D *> &results, float deadDistSqr=0.0f) const
Find the nearest N points.
K3DNodeApprox * left() const
Obtain pointer to left child.
void dump(std::ostream &) const
Textual output of tree. tabs are used to separate different levels of the tree.
A 3D point data class storage.
void setLeft(K3DNodeApprox *node)
Set the left child node.
K3DNodeApprox * right() const
Obtain pointer to right child.
~K3DTreeApprox()
Cleans up tree, deallocates nodes.
void setLoc(const Point3D &)
Set the point data associated with this node.
const Point3D * findNearest(const Point3D &, const BoundCube &, float deadDistSqr) const
Find the nearest point to a given P that lies outsid some dead zone.
void deleteChildren()
Recursively delete this node and all children.
Helper class to define a bounding cube.
void kill()
Destroy the tree contents.
void dump(std::ostream &, unsigned int) const
print the node data out to a given stream
void buildByRef(std::vector< Point3D > &pts)
Builds a balanced KD tree from a list of points.
void setAxis(unsigned int Axis)
Node Class for storing point.
Functor allowing for sorting of points in 3D.
Point3D getLoc() const
Return the point data from the ndoe.
void setRight(K3DNodeApprox *node)
Set the right child node.
void build(const std::vector< Point3D > &pts)
Builds a balanced KD tree from a list of points.
void setAxis(unsigned int newAxis)
Set the axis that this node operates on.