cgma
|
#include <KdTree.hpp>
Public Member Functions | |
KDTree () | |
~KDTree () | |
void | box_kdtree_intersect (FSBoundingBox &bbox, int *count, int *indexlist) const |
int | makeKDTree (int npoly, const FSBOXVECTOR &boxlist) |
Private Member Functions | |
FSBoundingBox * | getbox (int min, int max) |
void | find_the_median (int k, int l, int r, double *array, int *ia) |
int | getcuttingdirection (FSBoundingBox *box) |
void | SWAP (int &x, int &y) |
bool | rayintersectsbox (FSBoundingBox *box) |
double | MAXX (double a, double b) |
double | MINN (double a, double b) |
Private Attributes | |
double | epsilonkd |
int | numtris |
FSBoundingBox ** | treebox |
int * | nextbranch |
FSBOXVECTOR | boxlistptr |
int * | isequence |
double | rayxstart |
double | rayystart |
double | rayzstart |
double | dx |
double | dy |
double | dz |
Definition at line 49 of file KdTree.hpp.
KDTree::KDTree | ( | ) |
Definition at line 36 of file KdTree.cpp.
{ epsilonkd = 1.e-6; }
KDTree::~KDTree | ( | ) |
Definition at line 41 of file KdTree.cpp.
{ int i; FSBoundingBox* fsbb; for ( i = 0; i < 2*numtris-1; i++ ) { fsbb = treebox[i]; delete fsbb; } delete [] treebox; delete [] nextbranch; }
void KDTree::box_kdtree_intersect | ( | FSBoundingBox & | bbox, |
int * | count, | ||
int * | indexlist | ||
) | const |
Definition at line 219 of file KdTree.cpp.
{ int index, i, child; std::stack<int> mystack; *count = 0; if ( (bbox.xmax < (treebox[0]->xmin - epsilonkd) ) || (bbox.xmin > (treebox[0]->xmax + epsilonkd) ) || (bbox.ymax < (treebox[0]->ymin - epsilonkd) ) || (bbox.ymin > (treebox[0]->ymax + epsilonkd) ) || (bbox.zmax < (treebox[0]->zmin - epsilonkd) ) || (bbox.zmin > (treebox[0]->zmax + epsilonkd) ) ) return; // Gotta put something on the stack, so do the root node // evaluation here. if ( nextbranch[0] <= 0 ) { indexlist[*count] = -nextbranch[0]; *count += 1; return; } mystack.push(0); while ( mystack.size() > 0 ) { index = mystack.top(); mystack.pop(); child = nextbranch[index]; for ( i = 0; i < 2; i++ ) { if ( (bbox.xmax < (treebox[child+i]->xmin - epsilonkd) ) || (bbox.xmin > (treebox[child+i]->xmax + epsilonkd) ) || (bbox.ymax < (treebox[child+i]->ymin - epsilonkd) ) || (bbox.ymin > (treebox[child+i]->ymax + epsilonkd) ) || (bbox.zmax < (treebox[child+i]->zmin - epsilonkd) ) || (bbox.zmin > (treebox[child+i]->zmax + epsilonkd) ) ) continue; if ( nextbranch[child+i] <= 0 ) { indexlist[*count] = -nextbranch[child+i]; *count += 1; } else { mystack.push(child+i); } } } return; }
void KDTree::find_the_median | ( | int | k, |
int | l, | ||
int | r, | ||
double * | array, | ||
int * | ia | ||
) | [private] |
Definition at line 264 of file KdTree.cpp.
{ int i, j; double t; while ( r > l ) { t = array[ia[k]]; i = l; j = r; SWAP(ia[l],ia[k]); if ( array[ia[r]] > t ) SWAP(ia[l],ia[r]); while ( i < j ) { SWAP(ia[i],ia[j]); i += 1; j -= 1; while ( array[ia[i]] < t ) i++; while ( array[ia[j]] > t ) j--; } if ( array[ia[l]] == t ) SWAP(ia[l],ia[j]); else { j += 1; SWAP(ia[r],ia[j]); } if ( j <= k ) l = j + 1; if ( k <= j ) r = j - 1; } }
FSBoundingBox * KDTree::getbox | ( | int | min, |
int | max | ||
) | [private] |
Definition at line 188 of file KdTree.cpp.
{ FSBoundingBox *thisbox; int i; // Makes a bounding box and sets its size to include all of the boxes in the // sequence of bounding boxes from min to max of index isequence[]. Returns pointer // to this box. thisbox = new FSBoundingBox(1.e20,1.e20,1.e20,-1.e20,-1.e20,-1.e20); double xmin, ymin, zmin, xmax, ymax, zmax; for ( i = min; i <= max; i++ ) { xmin = boxlistptr[isequence[i]]->xmin; ymin = boxlistptr[isequence[i]]->ymin; zmin = boxlistptr[isequence[i]]->zmin; xmax = boxlistptr[isequence[i]]->xmax; ymax = boxlistptr[isequence[i]]->ymax; zmax = boxlistptr[isequence[i]]->zmax; if ( xmin < thisbox->xmin ) thisbox->xmin = xmin; if ( ymin < thisbox->ymin ) thisbox->ymin = ymin; if ( zmin < thisbox->zmin ) thisbox->zmin = zmin; if ( xmax > thisbox->xmax ) thisbox->xmax = xmax; if ( ymax > thisbox->ymax ) thisbox->ymax = ymax; if ( zmax > thisbox->zmax ) thisbox->zmax = zmax; } return thisbox; }
int KDTree::getcuttingdirection | ( | FSBoundingBox * | box | ) | [private] |
int KDTree::makeKDTree | ( | int | npoly, |
const FSBOXVECTOR & | boxlist | ||
) |
Definition at line 53 of file KdTree.cpp.
{ double *xcenterdata, *ycenterdata, *zcenterdata, *whichcut[3], *cutarray; int i, cuttingdir, min_tri_sequence_value, max_tri_sequence_value, median_value; double xcen, ycen, zcen; std::vector<TreeStack* > mytreestack; int icnt; TreeStack *thistreestack; FSBoundingBox *thisbox; numtris = npoly; boxlistptr = boxlist; isequence = new int[npoly]; xcenterdata = new double[npoly]; ycenterdata = new double[npoly]; zcenterdata = new double[npoly]; nextbranch = new int[2*npoly]; treebox = new FSBoundingBox*[2*npoly]; // Get the arrays of bounding box center points for x, y, and z. We will use // these arrays to find the median values along each direction. for ( i = 0; i < npoly; i++ ) { isequence[i] = i; xcen = 0.5*(boxlist[i]->xmin + boxlist[i]->xmax); ycen = 0.5*(boxlist[i]->ymin + boxlist[i]->ymax); zcen = 0.5*(boxlist[i]->zmin + boxlist[i]->zmax); xcenterdata[i] = xcen; ycenterdata[i] = ycen; zcenterdata[i] = zcen; } whichcut[0] = xcenterdata; whichcut[1] = ycenterdata; whichcut[2] = zcenterdata; // Get the bounding box of the root node -- the entire set of bounding boxes. thisbox = getbox(0,npoly-1); icnt = 0; treebox[icnt] = thisbox; nextbranch[icnt] = icnt; max_tri_sequence_value = npoly-1; min_tri_sequence_value = 0; if ( max_tri_sequence_value == 0 ) return 1; // Just one triangle in the data set. // Get the cutting direction for the next branch. cuttingdir = getcuttingdirection(thisbox); thistreestack = new TreeStack(min_tri_sequence_value, max_tri_sequence_value, cuttingdir,icnt); icnt++; mytreestack.push_back(thistreestack); while ( mytreestack.size() > 0 ) { TreeStack* thisone = mytreestack[mytreestack.size()-1]; mytreestack.pop_back(); cuttingdir = thisone->cuttingdir; min_tri_sequence_value = thisone->min; max_tri_sequence_value = thisone->max; median_value = (min_tri_sequence_value + max_tri_sequence_value)/2; cutarray = whichcut[cuttingdir]; find_the_median(median_value-min_tri_sequence_value,0, max_tri_sequence_value-min_tri_sequence_value, cutarray,&isequence[min_tri_sequence_value]); if ( min_tri_sequence_value == median_value ) { // This is a leaf. // FSBoundingBox *thisbox = boxlist[isequence[median_value]]; thisbox = new FSBoundingBox( boxlist[isequence[median_value]]->xmin, boxlist[isequence[median_value]]->ymin, boxlist[isequence[median_value]]->zmin, boxlist[isequence[median_value]]->xmax, boxlist[isequence[median_value]]->ymax, boxlist[isequence[median_value]]->zmax); treebox[icnt] = thisbox; nextbranch[icnt] = -isequence[median_value]; nextbranch[thisone->sequence] = icnt; icnt++; } else { thisbox = getbox(min_tri_sequence_value,median_value); nextbranch[thisone->sequence] = icnt; treebox[icnt] = thisbox; // nextbranch[icnt] = 11111; cuttingdir = getcuttingdirection(thisbox); thistreestack = new TreeStack(min_tri_sequence_value, median_value,cuttingdir,icnt); icnt++; mytreestack.push_back(thistreestack); } // The delete that follows is because we need to delete items that // were created and placed on mytreestack. This one comes from the pop() delete thisone; if ( median_value+1 == max_tri_sequence_value ) { // This is a leaf. // FSBoundingBox *thisbox = boxlist[isequence[max_tri_sequence_value]]; thisbox = new FSBoundingBox( boxlist[isequence[max_tri_sequence_value]]->xmin, boxlist[isequence[max_tri_sequence_value]]->ymin, boxlist[isequence[max_tri_sequence_value]]->zmin, boxlist[isequence[max_tri_sequence_value]]->xmax, boxlist[isequence[max_tri_sequence_value]]->ymax, boxlist[isequence[max_tri_sequence_value]]->zmax); treebox[icnt] = thisbox; nextbranch[icnt] = -isequence[max_tri_sequence_value]; icnt++; } else { thisbox = getbox(median_value+1,max_tri_sequence_value); treebox[icnt] = thisbox; // nextbranch[icnt] = 22222; cuttingdir = getcuttingdirection(thisbox); thistreestack = new TreeStack(median_value+1, max_tri_sequence_value, cuttingdir,icnt); icnt++; mytreestack.push_back(thistreestack); } } delete [] isequence; delete [] xcenterdata; delete [] ycenterdata; delete [] zcenterdata; return 1; }
double KDTree::MAXX | ( | double | a, |
double | b | ||
) | [inline, private] |
Definition at line 80 of file KdTree.hpp.
{ if ( a > b ) return a; else return b; }
double KDTree::MINN | ( | double | a, |
double | b | ||
) | [inline, private] |
Definition at line 84 of file KdTree.hpp.
{ if ( a < b ) return a; else return b; }
bool KDTree::rayintersectsbox | ( | FSBoundingBox * | box | ) | [private] |
Definition at line 307 of file KdTree.cpp.
{ double pmin, pmax, tmin, tmax; double dtemp; // Get the parametric distance along each direction from the min point to // the min and max box planes. If the min dist is grater than the max // dist, we have to swap them. Keep a running total of the max min and the // min max. The ray intersects the box iff tmin <= tmax and tmax >= 0.0. // Otherwise, the ray misses the box or points away from the box (with the // starting point outside). tmin = (box->xmin - rayxstart)/dx; tmax = (box->xmax - rayxstart)/dx; if ( tmin > tmax ) { dtemp = tmin; tmin = tmax; tmax = dtemp; } pmin = (box->ymin - rayystart)/dy; pmax = (box->ymax - rayystart)/dy; if ( pmin > pmax ) { dtemp = pmin; pmin = pmax; pmax = dtemp; } tmin = MAXX(pmin,tmin); tmax = MINN(pmax,tmax); if ( tmin > tmax ) return false; pmin = (box->zmin - rayzstart)/dz; pmax = (box->zmax - rayzstart)/dz; if ( pmin > pmax ) { dtemp = pmin; pmin = pmax; pmax = dtemp; } tmin = MAXX(pmin,tmin); tmax = MINN(pmax,tmax); if ( (tmax < 0.0) || (tmin > tmax) ) return false; return true; }
void KDTree::SWAP | ( | int & | x, |
int & | y | ||
) | [inline, private] |
Definition at line 71 of file KdTree.hpp.
{
int temp;
temp = x;
x = y;
y = temp;
}
FSBOXVECTOR KDTree::boxlistptr [private] |
Definition at line 65 of file KdTree.hpp.
double KDTree::dx [private] |
Definition at line 78 of file KdTree.hpp.
double KDTree::dy [private] |
Definition at line 78 of file KdTree.hpp.
double KDTree::dz [private] |
Definition at line 78 of file KdTree.hpp.
double KDTree::epsilonkd [private] |
Definition at line 61 of file KdTree.hpp.
int* KDTree::isequence [private] |
Definition at line 67 of file KdTree.hpp.
int* KDTree::nextbranch [private] |
Definition at line 64 of file KdTree.hpp.
int KDTree::numtris [private] |
Definition at line 62 of file KdTree.hpp.
double KDTree::rayxstart [private] |
Definition at line 78 of file KdTree.hpp.
double KDTree::rayystart [private] |
Definition at line 78 of file KdTree.hpp.
double KDTree::rayzstart [private] |
Definition at line 78 of file KdTree.hpp.
FSBoundingBox* * KDTree::treebox [private] |
Definition at line 63 of file KdTree.hpp.