00001
00002
00003
00004
00005 #include "adf.h"
00006 #include "gmTNTconvert.h"
00007
00008 REGISTER_IMPLICIT(ADF,"UnaryOp:ADF");
00009
00010
00011 double nan() { return std::numeric_limits<double>::quiet_NaN();};
00012
00013
00014
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
00025
00026 if ( child == -1 )
00027 {
00028 atp->address.set_to_root();
00029 return ;
00030 }
00031
00032
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
00061
00062
00063
00064
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
00079
00080
00081
00082
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
00091
00092 length=box->width()*0.5;
00093
00094
00095
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
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
00117 node_factoryp = new OctreeTraversalNodePool<ADFTraversalNode>(32, 1);
00118
00119
00120 ADFRefiner refiner;
00121 refiner.refine(this, err);
00122
00123 ADFPruner pruner;
00124 pruner.prune(this);
00125
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 bool ADF::setChildren(std::vector<Implicit*> children)
00137 {
00138 if (children.size() != 1)
00139 return false;
00140
00141
00142
00143 Box<double> bbox(3);
00144 bbox[0].setInterval(-10,10);
00145 bbox[1].setInterval(-10,10);
00146 bbox[2].setInterval(-10,10);
00147
00148 createADF(children[0],&bbox,1);
00149
00150 return true;
00151 }
00152
00153
00154
00155
00156
00157 void ADF::getq(double* q)
00158 {
00159 q[0] = 0;
00160
00161
00162 if (m_f!=NULL)
00163 m_f->getq(&q[1]);
00164 }
00165
00166
00167
00168
00169
00170 void ADF::_setq(double* q) {
00171
00172
00173
00174
00175 if (m_f!=NULL)
00176 m_f->_setq(&q[1]);
00177
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 void ADF::procq(gmVector3 x, double* dfdq) {
00187
00188 if (m_f != NULL)
00189 {
00190 dfdq[0] = -1;
00191 m_f->procq(x, &dfdq[1]);
00192 }
00193
00194 }
00195
00196
00197
00198
00199
00200 int ADF::qlen()
00201 {
00202 int retval = 1;
00203 if (m_f!=NULL)
00204 retval += m_f->qlen();
00205 return retval;
00206 }
00207
00208
00209
00210
00211
00212
00213 void ADF::getqname(char** qn) {
00214
00215 qn[0] = "ADF";
00216
00217 UnaryOp::getqname(qn);
00218
00219 }
00220
00221
00222
00223
00224
00225
00226
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
00256
00257
00258
00259
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
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
00281
00282
00283 return gmGOOGOL;
00284 }
00285
00286
00287
00288
00289
00290
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
00311
00312
00313
00314
00315
00316
00317
00318 const int ADF_sample_address_offset[][3] =
00319 {
00320
00321
00322 { 0, 0, 0},
00323
00324
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
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
00352
00353
00354
00355 const gmVector3 ADF_sample_offset[] =
00356 {
00357
00358
00359 gmVector3(0.5, 0.5, 0.5),
00360
00361
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
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
00393
00394
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
00411
00412
00413
00414
00415
00416
00417
00418 void ADFSampleAddress::set_to_root()
00419 {
00420
00421
00422
00423 address[0] = 0x4000;
00424 address[1] = 0x4000;
00425 address[2] = 0x4000;
00426 }
00427
00428
00429
00430
00431
00432
00433
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
00448
00449
00450
00451
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
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
00481
00482
00483
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
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
00511
00512
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
00528
00529
00530 #endif
00531
00532 #if defined (newhasher)
00533
00534
00535
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
00551
00552
00553
00554 bool ADFSampleSet::operator()(const ADFSampleAddress& a1, const ADFSampleAddress& a2) const
00555 {
00556
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
00571
00572
00573
00574 bool ADFSampleMap::operator()(const ADFSampleAddress& a1, const ADFSampleAddress& a2) const
00575 {
00576
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
00591
00592
00593
00594
00595
00596
00597
00598 bool ADFRefiner::should_split(ADFTraversalNode * atp)
00599 {
00600
00601
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
00613
00614 ap->node_type = ADF_NODE_INTERNAL;
00615 return true;
00616 }
00617
00618
00619
00620
00621 bool ADFRefiner::iterate(OctreeTraversalNode *np )
00622 {
00623 ADFTraversalNode * atp = (ADFTraversalNode *) np;
00624 ADFNode * ap = (ADFNode *) np->nodep;
00625
00626
00627
00628 if ( atp->depth > adfp->max_actual_depth )
00629 adfp->max_actual_depth = atp->depth;
00630
00631
00632
00633
00634 if ( this->should_split(atp) )
00635 {
00636
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
00651
00652
00653
00654 void ADFRefiner::refine(ADF * ap, double e)
00655 {
00656
00657
00658
00659 if ( ap->epsilon <= e )
00660 return ;
00661
00662 ap->epsilon = e;
00663 adfp = ap;
00664 adfp->traverse(this);
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
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
00696
00697
00698
00699
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
00717
00718
00719 void ADFTraversalNode::extract_samples_from(ADF * adfp )
00720 {
00721 ADFSampleAddress orig = address;
00722 for( int i=0; i<8; i++ )
00723 {
00724
00725
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
00734
00735
00736 bool ADFTraversalNode::is_reconstruction_valid(ADF* adfp)
00737 {
00738 ADFSampleAddress orig = address;
00739 for ( int i=0; i<19; i++ )
00740 {
00741
00742
00743 double d1 = this->get_local_coord_distance(ADF_sample_offset[i]);
00744
00745
00746
00747
00748 address.adjust_for_sample(this->depth, i);
00749 double d2 = adfp->get_sample(address, true);
00750 address = orig;
00751
00752
00753
00754 if ( fabs(d1 - d2) > adfp->epsilon )
00755 return false;
00756 }
00757
00758 return true;
00759 }
00760
00761
00762
00763 double ADFTraversalNode::get_distance(const gmVector3& p )
00764 {
00765
00766
00767
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
00780
00781 double ADFTraversalNode::get_local_coord_distance(const gmVector3& pp )
00782 {
00783
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
00800
00801
00802 void ADFTraversalNode::estimate_normal(
00803 const gmVector3& p,
00804 gmVector3 * normal )
00805 {
00806
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
00815
00816
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
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
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
00856
00857
00858
00859
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
00872 ADF * adfp = (ADF *) op;
00873
00874
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
00899 delete used_samplesp;
00900 }
00901
00902
00903
00904
00905
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
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
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 }