cgma
KDTree Class Reference

#include <KdTree.hpp>

List of all members.

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

FSBoundingBoxgetbox (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

Detailed Description

Definition at line 49 of file KdTree.hpp.


Constructor & Destructor Documentation

Definition at line 36 of file KdTree.cpp.

{
  epsilonkd = 1.e-6;
}

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; 
}

Member Function Documentation

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]

Definition at line 293 of file KdTree.cpp.

{
double xlen, ylen, zlen;

  xlen = box->xmax - box->xmin;
  ylen = box->ymax - box->ymin;
  zlen = box->zmax - box->zmin;
  
  if ( (xlen >= ylen) && (xlen >= zlen) ) return XCUT; 
  else if ( ylen >= zlen ) return YCUT;
  else return ZCUT;
}
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;
  }   

Member Data Documentation

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.

Definition at line 63 of file KdTree.hpp.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines