Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

adf.cpp

Go to the documentation of this file.
00001 /***********************************************************************
00002    Implementation of the ADF class.
00003  ***********************************************************************/
00004 
00005 #include "adf.h"
00006 #include "gmTNTconvert.h"
00007 
00008 REGISTER_IMPLICIT(ADF,"UnaryOp:ADF");
00009 
00010 // nan function for windows
00011 double nan() {  return std::numeric_limits<double>::quiet_NaN();};
00012 // ADF Implementation -------------------------------------------------------
00013 
00014 // Protected Methods --------------------------------------------------------
00015 
00016 void ADF::init_traversal_node(
00017     OctreeTraversalNode *  np,
00018     OctreeTraversalNode *  pp,
00019     int                    child )
00020 {
00021     ADFTraversalNode *  atp = (ADFTraversalNode *) np;
00022     ADFTraversalNode *  app = (ADFTraversalNode *) pp;
00023 
00024     // Handle the root.
00025 
00026     if ( child == -1 )
00027     {
00028         atp->address.set_to_root();
00029         return ;
00030     }
00031 
00032     // Just copy the parent address and adjust it properly.
00033 
00034     atp->address = app->address;
00035     atp->address.adjust_for_child(app->depth, child);
00036 }
00037 
00038 
00039 void ADF::copy_traversal_node(
00040     OctreeTraversalNode *  dp,
00041     OctreeTraversalNode *  sp )
00042 {
00043     Octree::copy_traversal_node(dp, sp);
00044 
00045     ADFTraversalNode *  adp = (ADFTraversalNode *) dp;
00046     ADFTraversalNode *  asp = (ADFTraversalNode *) sp;
00047 
00048     adp->address = asp->address;
00049     adp->samples[0] = asp->samples[0];
00050     adp->samples[1] = asp->samples[1];
00051     adp->samples[2] = asp->samples[2];
00052     adp->samples[3] = asp->samples[3];
00053     adp->samples[4] = asp->samples[4];
00054     adp->samples[5] = asp->samples[5];
00055     adp->samples[6] = asp->samples[6];
00056     adp->samples[7] = asp->samples[7];
00057 }
00058 
00059 /**
00060  * constructor using Implicit
00061  * \param imp a pointer to the implicit that is used to computer the values.
00062  * \param b a Box defining the region of space to evaluate proc() over.
00063  * \param error should be the tolerance that you want. ADF guarantees the approximated value is within this error tolerance.
00064  * \note This constructor just call createADF helper function, because serChildren also calls createADF.
00065  */
00066 ADF::ADF(Implicit *imp, Box<double> *b, double error)
00067 {
00068   createADF(imp, b, error);
00069 }
00070 
00071 ADF::~ADF()
00072 {
00073     delete rootp;
00074     delete node_factoryp;
00075 }
00076 
00077 /**
00078  * create ADF from a implicit, box, error
00079  * \param imp a pointer to the implicit that is used to computer the values.
00080  * \param b a Box defining the region of space to evaluate proc() over.
00081  * \param err should be the tolerance that you want. ADF guarantees the approximated value is within this error tolerance.
00082  * \note This constructor accuately calls refine and prune to create the data stucture, so it may take a long time.
00083  */
00084 void ADF::createADF(Implicit *imp, Box<double> *b, double err)
00085 {
00086   m_f = imp;
00087   box=b;
00088   epsilon = gmGOOGOL;
00089   center=gmVector3(box->center()[0],box->center()[1],box->center()[2]);
00090   // this should use the maximum length, now we assumes it is a cube.
00091   // this length is not the width of the cell, but it is half of it.
00092   length=box->width()*0.5;
00093 
00094   // precompute length table at each depth level
00095   // length at level 0 is the root leve and it is twice the current length
00096   length_table[0] = length*2;
00097   for(int i=1; i<16; i++)
00098     length_table[i] = length_table[i-1]*0.5;
00099 
00100   // Create the top-level node and its samples.
00101   ADFNode * ap = new ADFNode();
00102   ap->parentp = NULL;
00103   ap->childrenpp = NULL;
00104   ap->node_type = ADF_NODE_LEAF;
00105   rootp = ap;
00106 
00107   ADFTraversalNode atn;
00108   atn.center = center;
00109   atn.length = length;
00110   atn.depth = 0;
00111   atn.nodep = rootp;
00112   atn.address.set_to_root();
00113 
00114   atn.extract_samples_from(this);
00115 
00116   // Create the node factory.
00117   node_factoryp = new OctreeTraversalNodePool<ADFTraversalNode>(32, 1);
00118 
00119   // create the data using refiner and pruner
00120   ADFRefiner refiner;
00121   refiner.refine(this, err);
00122 
00123   ADFPruner pruner;
00124   pruner.prune(this);
00125 
00126 }
00127 
00128 // Public methods -----------------------------------------------------------
00129 
00130 /**
00131  * Overwrite the setChildren for UnaryOp. It then call createADF.
00132  * @param   children A vector of children (there should only be 1)
00133  * @returns False if there is not exactly 1 child in the vector.
00134  */
00135 
00136 bool ADF::setChildren(std::vector<Implicit*> children)
00137 {
00138   if (children.size() != 1)
00139     return false;
00140 
00141   // set implicit, box, epsilon
00142   // this is a default. need to be delete once implicit has a bounding box.
00143   Box<double> bbox(3);
00144   bbox[0].setInterval(-10,10);
00145   bbox[1].setInterval(-10,10);
00146   bbox[2].setInterval(-10,10);
00147   // default error is 1, makes the calculation faster.
00148   createADF(children[0],&bbox,1);
00149 
00150   return true;
00151 }
00152 
00153 /**
00154  * Retreives parameters.
00155  * @param q Parameter array.
00156  */
00157 void ADF::getq(double* q) 
00158 {
00159   q[0] = 0;
00160 
00161   // Check for child
00162   if (m_f!=NULL)
00163     m_f->getq(&q[1]);
00164 } // end getq
00165 
00166 /**
00167  * Assigns parameters.
00168  * @param q Parameter array.
00169  */
00170 void ADF::_setq(double* q) {
00171 
00172   //m_r = q[0];
00173 
00174   // Check for child
00175   if (m_f!=NULL)
00176     m_f->_setq(&q[1]);
00177 
00178 } // end _setq
00179 
00180 
00181 /**
00182  * Evaluation of dFdq.
00183  * @param x    Point to evaluate at.
00184  * @param dfdq Array representing dfdq.
00185  */
00186 void ADF::procq(gmVector3 x, double* dfdq) {
00187 
00188   if (m_f != NULL)//assert(m_f!=NULL);
00189   {
00190     dfdq[0] = -1;
00191     m_f->procq(x, &dfdq[1]);
00192   }
00193 
00194 } // end procq
00195 
00196 
00197 /**
00198  * Returns the # of parameters.
00199  */
00200 int ADF::qlen() 
00201 {
00202   int retval = 1;
00203   if (m_f!=NULL) 
00204     retval += m_f->qlen();
00205   return retval;
00206 } // end qlen
00207 
00208 
00209 /**
00210  * Retreives parameter names.
00211  * @param qn Paramater name array.
00212  */
00213 void ADF::getqname(char** qn) {
00214 
00215   qn[0] = "ADF";
00216 
00217   UnaryOp::getqname(qn);
00218 
00219 } // end getqname
00220 
00221 
00222 /**
00223  * Create a new sample for the given address.
00224  * First, convert the sample address to a point in space,
00225  * and then extract the new sample from the distance function, and store it.
00226  * @note changed after using new hashset and hashtable.
00227  */
00228 
00229 double ADF::get_sample(const ADFSampleAddress& addr, bool c)
00230 {
00231   #if !defined(hashflag)
00232   std::map<ADFSampleAddress, ADFSample, ADFSampleMap>::iterator i = sample_map.find(addr);
00233   #endif
00234   #if defined(hashflag)
00235   hashmap<ADFSampleAddress, ADFSample, ADFSampleHasher, ADFSampleMap>::iterator i = sample_map.find(addr);
00236   #endif
00237 
00238     if ( i != sample_map.end() ) 
00239     return ((*i).second.distance);
00240     if ( !c )
00241         return nan();
00242 
00243     gmVector3 p;
00244     addr.to_point(this, p);
00245   double ret;
00246   if (m_f!=NULL)
00247     ret = m_f->proc(p);
00248   ADFSample s(ret);
00249     sample_map.insert(std::pair<const ADFSampleAddress, ADFSample>(addr, s));
00250 
00251     return ret;
00252 }
00253 
00254 /**
00255  * return the distance and the normal of a point in the ADF
00256  * @param p a point in ADF
00257  * @param normal a pointer to return for the normal
00258  * @param threshold default to 0
00259  * @return distance from the point to the surface
00260  */
00261 
00262 double ADF::get_distance(const gmVector3& p, gmVector3 *normal, double threshold )
00263 {
00264     ADFTraversalNode n, n2;
00265     this->get_leaf_for_point(p, &n, &n2);
00266 
00267     // If it's a leaf, proceed to do a distance calculation and estimate the normal.
00268 
00269     ADFNode *  ap = (ADFNode *) n.nodep;
00270     if ( ap->node_type == ADF_NODE_LEAF )
00271     {
00272         n.extract_samples_from(this);
00273         double d = n.get_distance(p);
00274         if ( (normal != NULL) && (d <= threshold) )
00275             n.estimate_normal(p, normal);
00276     
00277         return d;
00278     }
00279 
00280     // Outside the accurate region.  Just return HUGE.
00281     // TBD: we could put a better bound on it.
00282 
00283     return gmGOOGOL;
00284 }
00285 
00286 /**
00287  * ADF virtual functions inherented from Geometric, just calls get_distance
00288  * in the orignal ADF
00289  * @param x a point in ADF
00290  * @return evaluation of function
00291  */
00292 #ifndef INTERVAL_EVAL_ONLY
00293 double ADF::proc(gmVector3 x)
00294 {
00295   if (m_f == NULL)
00296     return 0;
00297   else
00298     return get_distance(x);
00299 }
00300 #endif
00301 
00302 Intervald ADF::proc(Box<double> x)
00303 {
00304   Intervald retval;
00305   if (m_f != NULL)
00306     retval = Intervald(get_distance(convert(x.center())));
00307   return retval;
00308 }
00309 
00310 // ADFSampleAddress implementation ------------------------------------------
00311 
00312 /**
00313  * Offsets of the samples, in terms of addresses.  Here, we're offsetting
00314  * from the center of the cube.  The order is such that it is most likely
00315  * to find a violating sample first (assumes more interior == more likely to
00316  * fail).
00317  */
00318 const int ADF_sample_address_offset[][3] =
00319 {
00320     // Middle of cube
00321 
00322     { 0,  0,  0},
00323 
00324     // Middle of faces
00325 
00326     { 0,  0, -1},
00327     { 0, -1,  0},
00328     {-1,  0,  0},
00329     { 0,  0,  1},
00330     { 0,  1,  0},
00331     { 1,  0,  0},
00332 
00333     // Middle of edges
00334 
00335     { 0, -1, -1},
00336     {-1,  0, -1},
00337     {-1, -1,  0},
00338     { 0, -1,  1},
00339     {-1,  0,  1},
00340     {-1,  1,  0},
00341     { 0,  1, -1},
00342     { 1,  0, -1},
00343     { 1, -1,  0},
00344     { 0,  1,  1},
00345     { 1,  0,  1},
00346     { 1,  1,  0},
00347 };
00348 
00349 
00350 /**
00351  * Sample offsets, used for trilinear reconstructions.  Here, in contrast
00352  * to the above, we use the -,-,- corner as 0,0,0, as is used for the
00353  * trilinear reconstruction.  The order must match ADF_sample_address_offset.
00354  */
00355 const gmVector3 ADF_sample_offset[] =
00356 {
00357     // Middle of cube
00358 
00359     gmVector3(0.5, 0.5, 0.5),
00360 
00361     // Middle of faces
00362 
00363     gmVector3(0.5, 0.5,   0),
00364     gmVector3(0.5,   0, 0.5),
00365     gmVector3(  0, 0.5, 0.5),
00366     gmVector3(0.5, 0.5,   1),
00367     gmVector3(0.5,   1, 0.5),
00368     gmVector3(  1, 0.5, 0.5),
00369 
00370     // Middle of edges
00371 
00372     gmVector3(0.5,   0,   0),
00373     gmVector3(  0, 0.5,   0),
00374     gmVector3(  0,   0, 0.5),
00375     gmVector3(0.5,   0,   1),
00376     gmVector3(  0, 0.5,   1),
00377     gmVector3(  0,   1, 0.5),
00378     gmVector3(0.5,   1,   0),
00379     gmVector3(  1, 0.5,   0),
00380     gmVector3(  1,   0, 0.5),
00381     gmVector3(0.5,   1,   1),
00382     gmVector3(  1, 0.5,   1),
00383     gmVector3(  1,   1, 0.5)
00384 };
00385 
00386 
00387 void ADFSampleAddress::adjust_coordinate(
00388     int  coord,
00389     int  delta,
00390     int  depth )
00391 {
00392     // We start with the highest bit, and shift it right with added depth,
00393     // so that the depth may fluctuate (up to 15, of course), and so that the
00394     // address modification is simply an addition or subtraction.
00395 
00396     switch( delta )
00397     {
00398         case 1:
00399             address[coord] += (0x8000 >> depth);
00400             return ;
00401         case -1:
00402             address[coord] -= (0x8000 >> depth);
00403             return ;
00404         default:
00405             return ;
00406     }
00407 }
00408 
00409 /**
00410  * Root is at half the distance across the octree. So the root of the
00411  * octree is at 0x4000.
00412  *
00413  *   |--------|  0x8000
00414  *   |----|    0x4000
00415  *   |--|    0x2000
00416  *   |-|    0x1000 ...
00417  */
00418 void ADFSampleAddress::set_to_root()
00419 {
00420     // Note, the MSBit is for the entire length of the ADF; the root is
00421     // at the half-length.
00422 
00423     address[0] = 0x4000;
00424     address[1] = 0x4000;
00425     address[2] = 0x4000;
00426 }
00427 
00428 /**
00429  * Given the address for a cell, adjust the address so it
00430  * points to the given sample of the cell.
00431  * Depth is depth of current cell.
00432  * Sample is a number from 0 to 19 (same labeling as samples).
00433  * Sampling occurs at center of each cell, faces, edges (total 19).
00434  */
00435 void ADFSampleAddress::adjust_for_sample(
00436     int  depth,
00437     int  sample )
00438 {
00439     const int *  delta = ADF_sample_address_offset[sample];
00440     depth += 1;
00441     this->adjust_coordinate(0, delta[0], depth);
00442     this->adjust_coordinate(1, delta[1], depth);
00443     this->adjust_coordinate(2, delta[2], depth);
00444 }
00445 
00446 /**
00447  * Given the address for a cell, adjust the address so it
00448  * points to the given sample of the cell.
00449  * Depth is depth of current cell.
00450  * Sample is a number from 0 to 8 (same labeling as children).
00451  * Sampling occurs at (center of) vertices.
00452  */
00453 void ADFSampleAddress::adjust_for_corner_sample(
00454     int  depth,
00455     int  corner )
00456 {
00457     const int *  delta = octree_child_center_offset_ints[corner];
00458     depth += 1;
00459     this->adjust_coordinate(0, delta[0], depth);
00460     this->adjust_coordinate(1, delta[1], depth);
00461     this->adjust_coordinate(2, delta[2], depth);
00462 }
00463 
00464 
00465 /**
00466  * Samples in the center of one of the eight child cells.
00467  */
00468 void ADFSampleAddress::adjust_for_child(
00469     int  depth,
00470     int  child )
00471 {
00472     const int *  delta = octree_child_center_offset_ints[child];
00473     depth += 2;
00474     this->adjust_coordinate(0, delta[0], depth);
00475     this->adjust_coordinate(1, delta[1], depth);
00476     this->adjust_coordinate(2, delta[2], depth);
00477 }
00478 
00479 /**
00480  * Converts sample address to its spatial coordinats.
00481  * \param adfp Pointer to an ADF object
00482  * \param coord Coordinate to be converted (0=x, 1=y, 2=z)
00483  * Helper for to_point.
00484  */
00485 double ADFSampleAddress::coord_to_point(
00486     ADF *  adfp,
00487     int    coord ) const
00488 {
00489     double ret = adfp->center[coord] - adfp->length;
00490     for( unsigned short i=0x8000, j=0; i != 0; i >>= 1, j++ )
00491         if ( (i & address[coord]) != 0 )
00492             ret += adfp->length_table[j];
00493 
00494     return ret;
00495 }
00496 
00497 /**
00498  * Converts address to coordinates.
00499  */
00500 void ADFSampleAddress::to_point(
00501     ADF *  adfp,
00502     gmVector3&  ret ) const
00503 {
00504     ret[0] = this->coord_to_point(adfp, 0);
00505     ret[1] = this->coord_to_point(adfp, 1);
00506     ret[2] = this->coord_to_point(adfp, 2);
00507 }
00508 
00509 
00510 // ADFSampleHasher implementation -------------------------------------------
00511 // wen this may not be used because we are using STL set
00512 // This is based on code from a graphics gem for hashing 3D lattice addresses.
00513 
00514 #define NBITS4 8
00515 #define RBITS4 8
00516 #define MASK4 0x0360
00517 
00518 #define NBITS 8
00519 #define RBITS 8
00520 #define MASK 0x000F3C00
00521 #define HASH(a,b,c) ((((a&MASK)<<NBITS|b&MASK)<<NBITS|c&MASK)>>RBITS)
00522 
00523 int ADFSampleHasher::operator()(const ADFSampleAddress& addr) const
00524 {
00525 #if !defined (newhasher)
00526   return HASH(addr.address[0], addr.address[1], addr.address[2]);
00527 //  this is a test to show that the address are not used efficiently, because last 8 bits are always 0
00528 //  if (addr.address[0] & 0x00FF!=0)
00529 //    i=i;
00530 #endif
00531 
00532 #if defined (newhasher)
00533 // this is a better hasher
00534 //  if (addr.address[0]!=0)
00535 //    int i=0;
00536   int d=0x00FFFFFF;
00537   d=d&addr.address[0];
00538   d=d<<8;
00539   d=d|0x0000FFFF;
00540   d=d&(0x00FF0000|addr.address[1]);
00541   d=d|0x000000FF;
00542   int c=(0xFFFF0000|addr.address[2]);
00543   c=c >> 8;
00544   d=d&c;
00545   return d;
00546 #endif
00547 }
00548 
00549 /**
00550  * ADFSampleSet implementation
00551  * this is used to replace ADFSampleHasher
00552  * hash_set need an operator equal
00553  */
00554 bool ADFSampleSet::operator()(const ADFSampleAddress& a1, const ADFSampleAddress& a2) const
00555 {
00556   // compare x, y, z component
00557   if (a1.address[0]==a2.address[0])
00558     if (a1.address[1]==a2.address[1])
00559       if (a1.address[2]==a2.address[2])
00560         return false;
00561       else
00562         return (a1.address[2]<a2.address[2]);
00563     else
00564       return (a1.address[1]<a2.address[1]);
00565   else
00566     return (a1.address[0]<a2.address[0]);
00567 }
00568 
00569 /**
00570  * ADFSampleMap implementation
00571  * this is used to replace ADFSampleHasher
00572  * hash_set need an operator less than
00573  */
00574 bool ADFSampleMap::operator()(const ADFSampleAddress& a1, const ADFSampleAddress& a2) const
00575 {
00576   // compare x, y, z component
00577   if (a1.address[0]==a2.address[0])
00578     if (a1.address[1]==a2.address[1])
00579       if (a1.address[2]==a2.address[2])
00580         return false;
00581       else
00582         return (a1.address[2]<a2.address[2]);
00583     else
00584       return (a1.address[1]<a2.address[1]);
00585   else
00586     return (a1.address[0]<a2.address[0]);
00587 }
00588 
00589 
00590 // ADFRefiner implementation ------------------------------------------------
00591 
00592 /**
00593  * First, test that the node contains an iso-surface less than the accuracy_isosurface. 
00594  * If not, then there's no need to split. Of course, this test shouldn't be done on
00595  * the root node (and by not doing so, we're guaranteed to create the child samples
00596  * for the root node). 
00597  */
00598 bool ADFRefiner::should_split(ADFTraversalNode * atp)
00599 {
00600   // Validate the node according to the actual distances.  If
00601     // validation succeeds, mark the node as a leaf and return.
00602 
00603     ADFNode *  ap = (ADFNode *) atp->nodep;
00604     atp->extract_samples_from(adfp);
00605 
00606     if ( atp->is_reconstruction_valid(adfp) )
00607     {
00608         ap->node_type = ADF_NODE_LEAF;
00609         return false;
00610     }
00611 
00612     // Otherwise, we have to split.  Mark the node internal.
00613 
00614     ap->node_type = ADF_NODE_INTERNAL;
00615     return true;
00616 }
00617 
00618 
00619 /** Traverses to child nodes. Creates children if necessary.
00620  */
00621 bool ADFRefiner::iterate(OctreeTraversalNode *np )
00622 {
00623     ADFTraversalNode *  atp = (ADFTraversalNode *) np;
00624     ADFNode * ap = (ADFNode *) np->nodep;
00625 
00626     // Update the depth appropriately.
00627 
00628     if ( atp->depth > adfp->max_actual_depth )
00629         adfp->max_actual_depth = atp->depth;
00630 
00631     // Check to see if the node needs to be split.
00632     // should_split also sets the node_type appropriately for atp.
00633 
00634     if ( this->should_split(atp) )
00635     {
00636         // Create new nodes for the children.
00637  
00638         ap->childrenpp = (OctreeNode **) new ADFNode *[8];
00639         for( int i=0; i<8; i++ )
00640         {
00641             ap->childrenpp[i] = new ADFNode();
00642             ap->childrenpp[i]->parentp = ap;
00643             ((ADFNode *) ap->childrenpp[i])->node_type = ADF_NODE_LEAF;
00644         }
00645     }
00646 
00647     return true;
00648 }
00649            
00650 /** Checks tolerance and if not satisfied, continues to traverse.
00651  * \param ap Pointer to an ADF object
00652  * \param e Global tolerance
00653  */
00654 void ADFRefiner::refine(ADF * ap, double e)
00655 {
00656     // If the new tolerance is worse, do nothing.  Otherwise, record the
00657     // new tolerance, and traverse the octree.
00658 
00659     if ( ap->epsilon <= e )
00660         return ;
00661 
00662     ap->epsilon = e;
00663     adfp = ap;
00664     adfp->traverse(this);
00665 }
00666 
00667 
00668 // ADFTraversalNode implementation -------------------------------------
00669 
00670 /**
00671  * Collect the weights for bilinear interpolation within the unit square.
00672  * The order of weights is quadrant order, of course.  x and y should be
00673  * transformed to between 0 and 1, as well.
00674  *
00675  * @param x The x coordinate of the point to be weighted.
00676  * @param y The y coordinate of the point to be weighted.
00677  * @param weights On return, the weights.  Must have room for 4 items.
00678  */
00679 static void collect_bilinear_weights(
00680     double    x,
00681     double    y,
00682     double *  weights )
00683 {
00684     double xp = 1 - x;
00685     double yp = 1 - y;
00686 
00687     weights[0] = x  * y ;
00688     weights[1] = xp * y ;
00689     weights[2] = x  * yp;
00690     weights[3] = xp * yp;
00691 }
00692 
00693 
00694 /**
00695  * Collect the weights for trilinear interpolation within a unit cube.
00696  * The order of weights corresponds to the sample order, of course.
00697  *
00698  * @param p The point to be weighted.  Should be in the unit cube.
00699  * @param weights On return, the weights.  Must have room for 8 items.
00700  */
00701 static void collect_trilinear_weights(
00702     const gmVector3& p,
00703     double *    weights )
00704 {
00705     gmVector3 q(1 - p[0], 1 - p[1], 1 - p[2]);
00706     weights[0] = q[0] * q[1] * q[2];
00707     weights[1] = p[0] * q[1] * q[2];
00708     weights[2] = q[0] * p[1] * q[2];
00709     weights[3] = p[0] * p[1] * q[2];
00710     weights[4] = q[0] * q[1] * p[2];
00711     weights[5] = p[0] * q[1] * p[2];
00712     weights[6] = q[0] * p[1] * p[2];
00713     weights[7] = p[0] * p[1] * p[2];
00714 }
00715 
00716 /** Grabs samples from ADF and stores locally.
00717  * TraversalNode has its own sample array.
00718  */
00719 void ADFTraversalNode::extract_samples_from(ADF *  adfp )
00720 {
00721     ADFSampleAddress orig = address;
00722     for( int i=0; i<8; i++ )
00723     {
00724         // We adjust at depth - 1, since we want to add the half-length
00725         // of this depth, not the child depths.
00726 
00727         address.adjust_for_corner_sample(this->depth, i);
00728         samples[i] = adfp->get_sample(address, true);
00729         address = orig;
00730     }
00731 }
00732 
00733 /** Checks ADF node reconstruction against samples.
00734  * \todo this is place to change if we want to change the sampling testing with the new interval testing.
00735  */
00736 bool ADFTraversalNode::is_reconstruction_valid(ADF* adfp)
00737 {
00738     ADFSampleAddress orig = address;
00739     for ( int i=0; i<19; i++ )
00740     {
00741         // Get the reconstructed distance.
00742 
00743         double d1 = this->get_local_coord_distance(ADF_sample_offset[i]);
00744 
00745         // Get the actual distance.  We need to save and restore this node's
00746         // address while doing so.
00747 
00748         address.adjust_for_sample(this->depth, i);
00749         double d2 = adfp->get_sample(address, true);
00750         address = orig;
00751 
00752         // If the difference is great, the reconstruction is invalid.
00753 
00754         if ( fabs(d1 - d2) > adfp->epsilon )
00755             return false;
00756     }
00757 
00758     return true;
00759 }
00760 
00761 /** Returns the reconstructed distance at world-coordinate point p.
00762  */
00763 double ADFTraversalNode::get_distance(const gmVector3&  p )
00764 {
00765     // Transform the input into the coordinate system of the cell.
00766     // This results in a vector of values from 0,0,0 in the nnn corner
00767     // to 1,1,1 in the ppp corner.
00768 
00769     gmVector3 pp = p - this->center;
00770     pp /= (this->length*2);
00771     pp[0] += 0.5;
00772     pp[1] += 0.5;
00773     pp[2] += 0.5;
00774 
00775     return this->get_local_coord_distance(pp);
00776 }
00777 
00778 
00779 /** Returns the reconstructed distance at cell-coordinate point p.
00780  */
00781 double ADFTraversalNode::get_local_coord_distance(const gmVector3&  pp )
00782 {
00783     // Trilinearly interpolate.
00784 
00785     double weights[8];
00786     collect_trilinear_weights(pp, weights);
00787     double ret = this->samples[0]*weights[0] +
00788                  this->samples[1]*weights[1] +
00789                  this->samples[2]*weights[2] +
00790                  this->samples[3]*weights[3] +
00791                  this->samples[4]*weights[4] +
00792                  this->samples[5]*weights[5] +
00793                  this->samples[6]*weights[6] +
00794                  this->samples[7]*weights[7];
00795 
00796     return ret;
00797 }
00798 
00799 /** Returns (in normal) the central-differenced gradient at
00800  * world-coordinate point p.
00801  */
00802 void ADFTraversalNode::estimate_normal(
00803     const gmVector3&             p,
00804     gmVector3 *                  normal )
00805 {
00806     // Transform into the cell coordinate system.
00807 
00808     gmVector3 pp = p - this->center;
00809     pp /= (this->length*2);
00810     pp[0] += 0.5;
00811     pp[1] += 0.5;
00812     pp[2] += 0.5;
00813 
00814     // Essentially use central differences across the cell.
00815 
00816     // X difference.
00817 
00818     double weights[4];
00819     collect_bilinear_weights(pp[1], pp[2], weights);
00820     (*normal)[0]  =   weights[0]*this->samples[0] 
00821                     + weights[1]*this->samples[2] 
00822                     + weights[2]*this->samples[4] 
00823                     + weights[3]*this->samples[6] 
00824                     - weights[0]*this->samples[1] 
00825                     - weights[1]*this->samples[3] 
00826                     - weights[2]*this->samples[5] 
00827                     - weights[3]*this->samples[7];
00828 
00829     // Y difference.
00830 
00831     collect_bilinear_weights(pp[0], pp[2], weights);
00832     (*normal)[1]  =   weights[0]*this->samples[0] 
00833                     + weights[1]*this->samples[1] 
00834                     + weights[2]*this->samples[4] 
00835                     + weights[3]*this->samples[5] 
00836                     - weights[0]*this->samples[2] 
00837                     - weights[1]*this->samples[3] 
00838                     - weights[2]*this->samples[6] 
00839                     - weights[3]*this->samples[7];
00840     
00841     // Z difference.
00842 
00843     collect_bilinear_weights(pp[0], pp[1], weights);
00844     (*normal)[1]  =   weights[0]*this->samples[0] 
00845                     + weights[1]*this->samples[1] 
00846                     + weights[2]*this->samples[2] 
00847                     + weights[3]*this->samples[3] 
00848                     - weights[0]*this->samples[4] 
00849                     - weights[1]*this->samples[5] 
00850                     - weights[2]*this->samples[6] 
00851                     - weights[3]*this->samples[7];
00852 }
00853 
00854 
00855 // ADFPruner implementation ------------------------------------------------
00856 
00857 /** Pruner removes unused samples (and maybe cells).
00858  * Samples are unused if the cell isn't subdivided.
00859  * @note changed after new hashset and hashmap
00860  */
00861 void ADFPruner::prune(Octree * op)
00862 {
00863   #if !defined(hashflag)
00864   used_samplesp = new std::map<ADFSampleAddress, bool, ADFSampleMap>();
00865   #endif
00866   #if defined(hashflag)
00867   used_samplesp = new hashmap<ADFSampleAddress, bool, ADFSampleHasher, ADFSampleMap>();
00868   #endif
00869 
00870   OctreePruner::prune(op);
00871   // Delete all of the samples which weren't used.
00872   ADF *  adfp = (ADF *) op;
00873 
00874   /* old hasher
00875   */
00876   #if !defined(hashflag)
00877   std::map<ADFSampleAddress, ADFSample, ADFSampleMap>::iterator i;
00878   std::set<ADFSampleAddress, ADFSampleSet> to_remove;
00879   #endif
00880   #if defined(hashflag)
00881   hashmap<ADFSampleAddress, ADFSample, ADFSampleHasher, ADFSampleMap>::iterator i;
00882   hashset<ADFSampleAddress, ADFSampleHasher, ADFSampleSet> to_remove;
00883   #endif
00884   for( i = adfp->sample_map.begin(); i != adfp->sample_map.end(); ++i )
00885   {
00886     if ( used_samplesp->find(i->first) == used_samplesp->end() )
00887       to_remove.insert(i->first);
00888   }
00889 
00890   #if !defined(hashflag)
00891   std::set<ADFSampleAddress, ADFSampleSet>::iterator j;
00892   #endif
00893   #if defined(hashflag)
00894   hashset<ADFSampleAddress, ADFSampleHasher, ADFSampleSet>::iterator j;
00895   #endif
00896   for( j = to_remove.begin(); j != to_remove.end(); ++j )
00897     adfp->sample_map.erase(*j);
00898   // find duplicates and remove them.
00899   delete used_samplesp;
00900 }
00901 
00902 /** Indicates whether node np is used. Always returns true.
00903  * (Never want to prune cells, just samples.)
00904  * Side effect of marking the corner samples of leaf cells
00905  * as used.
00906  */
00907 bool ADFPruner::is_used(OctreeTraversalNode * np)
00908 {
00909     ADFNode *  ap = (ADFNode *) np->nodep;
00910 
00911     if ( ap->node_type == ADF_NODE_LEAF )
00912     {
00913         // Mark each of the corners of the node as used.
00914 
00915         ADFTraversalNode *  atp = (ADFTraversalNode *) np;
00916         ADFSampleAddress a;
00917         for( int i=0; i<8; i++ )
00918         {
00919             a = atp->address;
00920             a.adjust_for_corner_sample(atp->depth, i);
00921             (*used_samplesp)[a] = true;
00922         }
00923     }
00924 
00925     return true;
00926 }
00927 
00928 
00929 // ADFAnalyzer implementation ----------------------------------------------
00930 
00931 bool ADFAnalyzer::iterate(
00932     OctreeTraversalNode *  np )
00933 {
00934     OctreeAnalyzer::iterate(np);
00935 
00936     ADFNode *  ap = (ADFNode *) np->nodep;
00937 
00938     if ( node_type_countsp[0] == NULL )
00939     {
00940         node_type_countsp[0] = new int[octreep->max_actual_depth+1];
00941         node_type_countsp[1] = new int[octreep->max_actual_depth+1];
00942         node_type_countsp[2] = new int[octreep->max_actual_depth+1];
00943         node_type_countsp[3] = new int[octreep->max_actual_depth+1];
00944 
00945         for( int i=0; i<4; i++ )
00946             for( int j=0; j<octreep->max_actual_depth+1; j++ )
00947                 node_type_countsp[i][j] = 0;
00948     }
00949 
00950     node_type_countsp[ap->node_type][np->depth]++ ;
00951 
00952     return true;
00953 }
00954 
00955 
00956 void ADFAnalyzer::report_statistics_at_depth(int d)
00957 {
00958     OctreeAnalyzer::report_statistics_at_depth(d);
00959     std::cout << "  " << node_type_countsp[ADF_NODE_INTERIOR][d] << " interior / "
00960          << node_type_countsp[ADF_NODE_EXTERIOR][d] << " exterior / "
00961          << node_type_countsp[ADF_NODE_LEAF][d] << " true leaf\n";
00962 }
00963 
00964 
00965 void ADFAnalyzer::report_statistics()
00966 {
00967     OctreeAnalyzer::report_statistics();
00968 
00969     int totals[4];
00970     totals[0] = totals[1] = totals[2] = totals[3] = 0;
00971     for( int i=0; i<octreep->max_actual_depth + 1; i++ )
00972     {
00973         totals[0] += node_type_countsp[0][i];
00974         totals[1] += node_type_countsp[1][i];
00975         totals[2] += node_type_countsp[2][i];
00976         totals[3] += node_type_countsp[3][i];
00977     }
00978 
00979     ADF *  adfp = (ADF *) octreep;
00980     std::cout << "  Total interior: " << totals[ADF_NODE_INTERIOR] << "\n"
00981          << "  Total exterior: " << totals[ADF_NODE_EXTERIOR] << "\n"
00982          << "  Total true leaves: " << totals[ADF_NODE_LEAF] << "\n"
00983          << "  Total samples: " << adfp->sample_map.size() << "\n";
00984 }
00985 
00986 
00987 void ADFAnalyzer::reset()
00988 {
00989     OctreeAnalyzer::reset();
00990 
00991     if ( node_type_countsp[0] != NULL )
00992     {
00993         delete[] node_type_countsp[0];
00994         delete[] node_type_countsp[1];
00995         delete[] node_type_countsp[2];
00996         delete[] node_type_countsp[3];
00997         node_type_countsp[0] = NULL;
00998         node_type_countsp[1] = NULL;
00999         node_type_countsp[2] = NULL;
01000         node_type_countsp[3] = NULL;
01001     }
01002 }

Generated on Mon Jun 28 14:58:12 2004 for Advanced Surface Library by doxygen 1.3.4