Blender V2.61 - r43446

octree.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Tao Ju
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00023 #include "octree.h"
00024 #include <Eigen/Dense>
00025 #include <limits>
00026 #include <time.h>
00027 
00034 /* set to non-zero value to enable debugging output */
00035 #define DC_DEBUG 0
00036 
00037 #if DC_DEBUG
00038 /* enable debug printfs */
00039 #define dc_printf printf
00040 #else
00041 /* disable debug printfs */
00042 #define dc_printf(...) do {} while(0)
00043 #endif
00044 
00045 Octree::Octree( ModelReader* mr,
00046                 DualConAllocOutput alloc_output_func,
00047                 DualConAddVert add_vert_func,
00048                 DualConAddQuad add_quad_func,
00049                 DualConFlags flags, DualConMode dualcon_mode, int depth,
00050                 float threshold, float sharpness )
00051     : use_flood_fill(flags & DUALCON_FLOOD_FILL),
00052       /* note on `use_manifold':
00053          
00054          After playing around with this option, the only case I could
00055          find where this option gives different results is on
00056          relatively thin corners. Sometimes along these corners two
00057          vertices from seperate sides will be placed in the same
00058          position, so hole gets filled with a 5-sided face, where two
00059          of those vertices are in the same 3D location. If
00060          `use_manifold' is disabled, then the modifier doesn't
00061          generate two separate vertices so the results end up as all
00062          quads.
00063 
00064          Since the results are just as good with all quads, there
00065          doesn't seem any reason to allow this to be toggled in
00066          Blender. -nicholasbishop
00067        */
00068       use_manifold(false),
00069       hermite_num(sharpness),
00070       mode(dualcon_mode),
00071       alloc_output(alloc_output_func),
00072       add_vert(add_vert_func),
00073       add_quad(add_quad_func)
00074 {
00075     this->thresh = threshold ;
00076     this->reader = mr ;
00077     this->dimen = 1 << GRID_DIMENSION ;
00078     this->range = reader->getBoundingBox( this->origin ) ;
00079     this->nodeCount = this->nodeSpace = 0;
00080     this->maxDepth = depth ;
00081     this->mindimen = ( dimen >> maxDepth ) ;
00082     this->minshift = ( GRID_DIMENSION - maxDepth ) ;
00083     this->buildTable( ) ;
00084 
00085     flood_bytes = use_flood_fill ? FLOOD_FILL_BYTES : 0;
00086     leaf_extra_bytes = flood_bytes + CINDY_BYTES;
00087 
00088 #ifdef USE_HERMIT
00089     leaf_node_bytes = 7 + leaf_extra_bytes;
00090 #else
00091     leaf_node_bytes = 3 + leaf_extra_bytes;
00092 #endif
00093 
00094 #ifdef QIANYI
00095     dc_printf("Origin: (%f %f %f), Dimension: %f\n", origin[0], origin[1], origin[2], range) ;
00096 #endif
00097 
00098     this->maxTrianglePerCell = 0 ;
00099 
00100     // Initialize memory
00101 #ifdef IN_VERBOSE_MODE
00102     dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2] ) ;
00103     dc_printf("Initialize memory...\n") ;
00104 #endif
00105     initMemory( ) ;
00106     this->root = createInternal( 0 ) ;
00107 
00108     // Read MC table
00109 #ifdef IN_VERBOSE_MODE
00110     dc_printf("Reading contour table...\n") ;
00111 #endif
00112     this->cubes = new Cubes();
00113 
00114 }
00115 
00116 Octree::~Octree( )
00117 {
00118     freeMemory( ) ;
00119 }
00120 
00121 void Octree::scanConvert()
00122 {
00123     // Scan triangles
00124 #if DC_DEBUG
00125     clock_t start, finish ;
00126     start = clock( ) ;
00127 #endif
00128     
00129     this->addTrian( ) ;
00130     this->resetMinimalEdges( ) ;
00131     this->preparePrimalEdgesMask( this->root ) ;
00132 
00133 #if DC_DEBUG
00134     finish = clock( ) ;
00135     dc_printf("Time taken: %f seconds                   \n", 
00136         (double)(finish - start) / CLOCKS_PER_SEC ) ;
00137 #endif
00138 
00139     // Generate signs
00140     // Find holes
00141 #if DC_DEBUG
00142     dc_printf("Patching...\n") ;
00143     start = clock( ) ;
00144 #endif
00145     this->trace( ) ;
00146 #if DC_DEBUG
00147     finish = clock( ) ;
00148     dc_printf("Time taken: %f seconds \n",  (double)(finish - start) / CLOCKS_PER_SEC ) ;
00149 #ifdef IN_VERBOSE_MODE
00150     dc_printf("Holes: %d Average Length: %f Max Length: %d \n", numRings, (float)totRingLengths / (float) numRings, maxRingLength ) ;
00151 #endif
00152 #endif
00153     
00154     // Check again
00155     int tnumRings = numRings ;
00156     this->trace( ) ;
00157 #ifdef IN_VERBOSE_MODE
00158     dc_printf("Holes after patching: %d \n", numRings) ;
00159 #endif  
00160     numRings = tnumRings ;
00161 
00162 #if DC_DEBUG
00163     dc_printf("Building signs...\n") ;
00164     start = clock( ) ;
00165 #endif
00166     this->buildSigns( ) ;
00167 #if DC_DEBUG
00168     finish = clock( ) ;
00169     dc_printf("Time taken: %f seconds \n",  (double)(finish - start) / CLOCKS_PER_SEC ) ;
00170 #endif
00171 
00172     if(use_flood_fill) {
00173         /*
00174           start = clock( ) ;
00175           this->floodFill( ) ;
00176           // Check again
00177           tnumRings = numRings ;
00178           this->trace( ) ;
00179           dc_printf("Holes after filling: %d \n", numRings) ;
00180           numRings = tnumRings ;
00181           this->buildSigns( ) ;
00182           finish = clock( ) ;
00183           dc_printf("Time taken: %f seconds \n",    (double)(finish - start) / CLOCKS_PER_SEC ) ;
00184         */
00185 #if DC_DEBUG
00186         start = clock( ) ;
00187         dc_printf("Removing components...\n");
00188 #endif
00189         this->floodFill( ) ;
00190         this->buildSigns( ) ;
00191         //  dc_printf("Checking...\n");
00192         //  this->floodFill( ) ;
00193 #if DC_DEBUG
00194         finish = clock( ) ;
00195         dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC ) ;
00196 #endif
00197     }
00198 
00199     // Output
00200 #ifdef OUTPUT_REPAIRED
00201 #if DC_DEBUG
00202     start = clock( ) ;
00203 #endif
00204     writeOut();
00205 #if DC_DEBUG
00206     finish = clock( ) ;
00207 #endif
00208     // dc_printf("Time taken: %f seconds \n",   (double)(finish - start) / CLOCKS_PER_SEC ) ;
00209 #ifdef CINDY
00210     this->writeTags( "tags.txt" ) ;
00211     dc_printf("Tags output to tags.txt\n") ;
00212 #endif
00213 
00214 #endif
00215 
00216     // Print info
00217 #ifdef IN_VERBOSE_MODE
00218     printMemUsage( ) ;
00219 #endif
00220 }
00221 
00222 #if 0
00223 void Octree::writeOut( char* fname )
00224 {
00225     dc_printf( "\n" ) ;
00226     if ( strstr( fname, ".ply" ) != NULL )
00227     {
00228         dc_printf("Writing PLY file format.\n") ;
00229         this->outType = 1 ;
00230         writePLY( fname ) ;
00231     } 
00232     else if ( strstr( fname, ".off" ) != NULL )
00233     {
00234         dc_printf("Writing OFF file format.\n") ;
00235         this->outType = 0 ;
00236         writeOFF( fname ) ;
00237     }
00238     else if ( strstr( fname, ".sof" ) != NULL )
00239     {
00240         dc_printf("Writing Signed Octree File format.\n") ;
00241         this->outType = 2 ;
00242         writeOctree( fname ) ;
00243     }
00244     else if ( strstr( fname, ".dcf" ) != NULL )
00245     {
00246 #ifdef USE_HERMIT
00247         dc_printf("Writing Dual Contouring File format.\n") ;
00248         this->outType = 3 ;
00249         writeDCF( fname ) ;
00250 #else
00251         dc_printf("Can not write Dual Contouring File format in non-DC mode.\n") ;
00252 #endif
00253     }
00254 #ifdef USE_HERMIT
00255     else if ( strstr( fname, ".sog" ) != NULL )
00256     {
00257         dc_printf("Writing signed octree with geometry.\n") ;
00258         this->outType = 4 ;
00259         writeOctreeGeom( fname ) ;
00260     }
00261 #endif
00262     /*
00263     else if ( strstr( fname, ".sof" ) != NULL )
00264     {
00265         dc_printf("Writing SOF file format.\n") ;
00266         this->outType = 2 ;
00267         writeOctree( fname ) ;
00268     }
00269     */
00270     else
00271     {
00272         dc_printf("Unknown output format.\n") ;
00273     }
00274 
00275 }
00276 #endif
00277 
00278 void Octree::initMemory( )
00279 {
00280 #ifdef USE_HERMIT
00281     const int leaf_node_bytes = 7;
00282 #else
00283     const int leaf_node_bytes = 3;
00284 #endif
00285 
00286     if(use_flood_fill) {
00287         const int bytes = leaf_node_bytes + CINDY_BYTES + FLOOD_FILL_BYTES;
00288         this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ;
00289         this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ;
00290         this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ;
00291         this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ;
00292     }
00293     else {
00294         const int bytes = leaf_node_bytes + CINDY_BYTES;
00295         this->leafalloc[ 0 ] = new MemoryAllocator< bytes > ( ) ;
00296         this->leafalloc[ 1 ] = new MemoryAllocator< bytes + EDGE_BYTES > ( ) ;
00297         this->leafalloc[ 2 ] = new MemoryAllocator< bytes + EDGE_BYTES * 2 > ( ) ;
00298         this->leafalloc[ 3 ] = new MemoryAllocator< bytes + EDGE_BYTES * 3 > ( ) ;
00299     }
00300 
00301     this->alloc[ 0 ] = new MemoryAllocator< INTERNAL_NODE_BYTES > ( ) ;
00302     this->alloc[ 1 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES > ( ) ;
00303     this->alloc[ 2 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*2 > ( ) ;
00304     this->alloc[ 3 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*3 > ( ) ;
00305     this->alloc[ 4 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*4 > ( ) ;
00306     this->alloc[ 5 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*5 > ( ) ;
00307     this->alloc[ 6 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*6 > ( ) ;
00308     this->alloc[ 7 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*7 > ( ) ;
00309     this->alloc[ 8 ] = new MemoryAllocator< INTERNAL_NODE_BYTES + POINTER_BYTES*8 > ( ) ;
00310 }
00311 
00312 void Octree::freeMemory( )
00313 {
00314     for ( int i = 0 ; i < 9 ; i ++ )
00315     {
00316         alloc[i]->destroy() ;
00317         delete alloc[i] ;
00318     }
00319 
00320     for ( int i = 0 ; i < 4 ; i ++ )
00321     {
00322         leafalloc[i]->destroy() ;
00323         delete leafalloc[i] ;
00324     }
00325 }
00326 
00327 void Octree::printMemUsage( )
00328 {
00329     int totalbytes = 0 ;
00330     dc_printf("********* Internal nodes: \n") ;
00331     for ( int i = 0 ; i < 9 ; i ++ )
00332     {
00333         this->alloc[ i ]->printInfo() ;
00334 
00335         totalbytes += alloc[i]->getAll( ) * alloc[i]->getBytes() ;
00336     }
00337     dc_printf("********* Leaf nodes: \n") ;
00338     int totalLeafs = 0 ;
00339     for ( int i = 0 ; i < 4 ; i ++ )
00340     {
00341         this->leafalloc[ i ]->printInfo() ;
00342 
00343         totalbytes += leafalloc[i]->getAll( ) * leafalloc[i]->getBytes() ;
00344         totalLeafs += leafalloc[i]->getAllocated() ;
00345     }
00346     
00347     dc_printf("Total allocated bytes on disk: %d \n", totalbytes) ;
00348     dc_printf("Total leaf nodes: %d\n", totalLeafs ) ;
00349 }
00350 
00351 void Octree::resetMinimalEdges( )
00352 {
00353     this->cellProcParity( this->root, 0, maxDepth ) ;
00354 }
00355 
00356 void Octree::writeModel( char* fname )
00357 {
00358     reader->reset() ;
00359 
00360     int nFace = reader->getNumTriangles() ;
00361     Triangle* trian ;
00362     // int unitcount = 10000;
00363     int count = 0 ;
00364     int nVert = nFace * 3 ;
00365     FILE* modelfout = fopen( "model.off", "w" ) ;
00366     fprintf( modelfout, "OFF\n" ) ;
00367     fprintf( modelfout, "%d %d 0\n", nVert, nFace ) ;
00368 
00369     //int total = this->reader->getNumTriangles() ;
00370     dc_printf( "Start writing model to OFF...\n" ) ;
00371     srand(0) ;
00372     while ( ( trian = reader->getNextTriangle() ) != NULL )
00373     {
00374         // Drop polygons
00375         {
00376             int i, j ;
00377 
00378             // Blow up the triangle
00379             float mid[3] = {0, 0, 0} ;
00380             for ( i = 0 ; i < 3 ; i ++ )
00381                 for ( j = 0 ; j < 3 ; j ++ )
00382                 {
00383                     trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ;
00384 
00385                     mid[j] += trian->vt[i][j] / 3 ;
00386                 }
00387                 
00388                 // Generate projections
00389                 // LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ;
00390                 int trig[3][3] ;
00391 
00392                 // Blowing up the triangle to the grid
00393                 for ( i = 0 ; i < 3 ; i ++ )
00394                     for (  j = 0 ; j < 3 ; j ++ )
00395                     {
00396                         trig[i][j] = (int) (trian->vt[i][j]) ;
00397                         // Perturb end points, if set so
00398                     }
00399 
00400                     
00401                     for ( i = 0 ; i < 3 ; i ++ )
00402                     {
00403                         fprintf( modelfout, "%f %f %f\n", 
00404                             (float)(((double) trig[i][0] / dimen) * range  + origin[0]) ,
00405                             (float)(((double) trig[i][1] / dimen) * range  + origin[1]) ,
00406                             (float)(((double) trig[i][2] / dimen) * range  + origin[2]) ) ;
00407                     }
00408         }
00409         delete trian ;
00410 
00411         count ++ ;
00412         
00413     }
00414 
00415     for ( int i = 0 ; i < nFace ; i ++ )
00416     {
00417         fprintf( modelfout, "3 %d %d %d\n", 3 * i + 2, 3 * i + 1, 3 * i  ) ;
00418     }
00419 
00420     fclose( modelfout ) ;
00421 
00422 }
00423 
00424 #ifdef CINDY
00425 void Octree::writeTags( char* fname )
00426 {
00427     FILE* fout = fopen( fname, "w" ) ;
00428 
00429     clearCindyBits( root, maxDepth ) ;
00430     readVertices() ;
00431     outputTags( root, maxDepth, fout ) ;
00432 
00433     fclose ( fout ) ;
00434 }
00435 
00436 void Octree::readVertices( )
00437 {
00438     int total = this->reader->getNumVertices() ;
00439     reader->reset() ;
00440     float v[3] ;
00441     int st[3] = {0,0,0};
00442     int unitcount = 1000 ;
00443     dc_printf( "\nRead in original %d vertices...\n", total ) ;
00444 
00445     for ( int i = 0 ; i < total ; i ++ )
00446     {
00447         reader->getNextVertex( v ) ;
00448         // Blowing up the triangle to the grid
00449         float mid[3] = {0, 0, 0} ;
00450         for ( int j = 0 ; j < 3 ; j ++ )
00451         {
00452             v[j] = dimen * ( v[j] - origin[j] ) / range ;
00453         }
00454 
00455 //      dc_printf("vertex: %f %f %f, dimen: %d\n", v[0], v[1], v[2], dimen ) ;
00456         readVertex ( root, st, dimen, maxDepth, v, i ) ;
00457 
00458         
00459         if ( i % unitcount == 0 )
00460         {
00461             putchar ( 13 ) ;
00462 
00463             switch ( ( i / unitcount ) % 4 )
00464             {
00465             case 0 : dc_printf("-");
00466                 break ;
00467             case 1 : dc_printf("/") ;
00468                 break ;
00469             case 2 : dc_printf("|");
00470                 break ;
00471             case 3 : dc_printf("\\") ;
00472                 break ;
00473             }
00474 
00475             float percent = (float) i / total ;
00476             /*
00477             int totbars = 50 ;
00478             int bars = (int)( percent * totbars ) ;
00479             for ( int i = 0 ; i < bars ; i ++ )
00480             {
00481                 putchar( 219 ) ;
00482             }
00483             for ( i = bars ; i < totbars ; i ++ )
00484             {
00485                 putchar( 176 ) ;
00486             }
00487             */
00488 
00489             dc_printf(" %d vertices: ", i ) ;
00490             dc_printf( " %f%% complete.", 100 * percent ) ;
00491         }
00492         
00493     }
00494     putchar ( 13 ) ;
00495     dc_printf("                                             \n");
00496 }
00497 
00498 void Octree::readVertex(  UCHAR* node, int st[3], int len, int height, float v[3], int index )
00499 {
00500     int nst[3] ;
00501     nst[0] = ( (int) v[0] / mindimen ) * mindimen ;
00502     nst[1] = ( (int) v[1] / mindimen ) * mindimen ;
00503     nst[2] = ( (int) v[2] / mindimen ) * mindimen ;
00504 
00505     UCHAR* cell = this->locateLeafCheck( nst ) ;
00506     if ( cell == NULL )
00507     {
00508         dc_printf("Cell %d %d %d is not found!\n", nst[0]/ mindimen, nst[1]/ mindimen, nst[2]/ mindimen) ;
00509         return ;
00510     }
00511 
00512     setOriginalIndex( cell, index ) ;
00513 
00514 
00515     /*
00516     int i ;
00517     if ( height == 0 )
00518     {
00519         // Leaf cell, assign index
00520         dc_printf("Setting: %d\n", index ) ;
00521         setOriginalIndex( node, index ) ;
00522     }
00523     else
00524     {
00525         len >>= 1 ;
00526         // Internal cell, check and recur
00527         int x = ( v[0] > st[0] + len ) ? 1 : 0 ;
00528         int y = ( v[1] > st[1] + len ) ? 1 : 0 ;
00529         int z = ( v[2] > st[2] + len ) ? 1 : 0 ;
00530         int child = x * 4 + y * 2 + z ;
00531 
00532         int count = 0 ;
00533         for ( i = 0 ; i < 8 ; i ++ )
00534         {
00535             if ( i == child && hasChild( node, i ) )
00536             {
00537                 int nst[3] ;
00538                 nst[0] = st[0] + vertmap[i][0] * len ;
00539                 nst[1] = st[1] + vertmap[i][1] * len ;
00540                 nst[2] = st[2] + vertmap[i][2] * len ;
00541 
00542                 dc_printf("Depth: %d -- child %d vertex: %f %f %f in %f %f %f\n", height - 1, child, v[0]/mindimen, v[1]/mindimen, v[2]/mindimen, 
00543                     nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, len/mindimen ) ;
00544                 
00545                 readVertex( getChild( node, count ), nst, len, height - 1, v, index ) ;
00546                 count ++ ;
00547             }
00548         }
00549     }
00550     */
00551 }
00552 
00553 void Octree::outputTags( UCHAR* node, int height, FILE* fout )
00554 {
00555     int i ;
00556 
00557     if ( height == 0 )
00558     {
00559         // Leaf cell, generate
00560         int smask = getSignMask( node ) ;
00561 
00562         if(use_manifold) {
00563             int comps = manifold_table[ smask ].comps ;
00564             if ( comps != 1 )
00565             {
00566                 return ;
00567             }
00568         }
00569         else
00570         {
00571             if ( smask == 0 || smask == 255 )
00572             {
00573                 return ;
00574             }
00575         }
00576 
00577         int rindex = getMinimizerIndex( node ) ;
00578         int oindex = getOriginalIndex( node ) ;
00579 
00580         if ( oindex >= 0 )
00581         {
00582             fprintf( fout, "%d: %d\n", rindex, oindex ) ;
00583         }
00584 
00585     }
00586     else
00587     {
00588         // Internal cell, recur
00589         int count = 0 ;
00590         for ( i = 0 ; i < 8 ; i ++ )
00591         {
00592             if ( hasChild( node, i ) )
00593             {
00594                 outputTags( getChild( node, count ), height - 1, fout ) ;
00595                 count ++ ;
00596             }
00597         }
00598     }
00599 }
00600 
00601 void Octree::clearCindyBits( UCHAR* node, int height )
00602 {
00603     int i;
00604 
00605     if ( height == 0 )
00606     {
00607         // Leaf cell, 
00608         {
00609             setOriginalIndex( node, - 1 ) ;
00610         }
00611     }
00612     else
00613     {
00614         // Internal cell, recur
00615         int count = 0 ;
00616         for ( i = 0 ; i < 8 ; i ++ )
00617         {
00618             if ( hasChild( node, i ) )
00619             {
00620                 clearCindyBits( getChild( node, count ), height - 1 ) ;
00621                 count ++ ;
00622             }
00623         }
00624     }   
00625 }
00626 #endif
00627 
00628 void Octree::addTrian( )
00629 {
00630     Triangle* trian ;
00631     int count = 0 ;
00632     
00633 #if DC_DEBUG
00634     int total = this->reader->getNumTriangles() ;
00635     int unitcount = 1000 ;
00636     dc_printf( "\nScan converting to depth %d...\n", maxDepth ) ;
00637 #endif
00638 
00639     srand(0) ;
00640 
00641     while ( ( trian = reader->getNextTriangle() ) != NULL )
00642     {
00643         // Drop triangles
00644         {
00645             addTrian ( trian, count ) ;
00646         }
00647         delete trian ;
00648 
00649         count ++ ;
00650 
00651 #if DC_DEBUG
00652         if ( count % unitcount == 0 )
00653         {
00654             putchar ( 13 ) ;
00655 
00656             switch ( ( count / unitcount ) % 4 )
00657             {
00658             case 0 : dc_printf("-");
00659                 break ;
00660             case 1 : dc_printf("/") ;
00661                 break ;
00662             case 2 : dc_printf("|");
00663                 break ;
00664             case 3 : dc_printf("\\") ;
00665                 break ;
00666             }
00667 
00668             float percent = (float) count / total ;
00669             
00670             /*
00671             int totbars = 50 ;
00672             int bars = (int)( percent * totbars ) ;
00673             for ( int i = 0 ; i < bars ; i ++ )
00674             {
00675                 putchar( 219 ) ;
00676             }
00677             for ( i = bars ; i < totbars ; i ++ )
00678             {
00679                 putchar( 176 ) ;
00680             }
00681             */
00682 
00683             dc_printf(" %d triangles: ", count ) ;
00684             dc_printf( " %f%% complete.", 100 * percent ) ;
00685         }
00686 #endif
00687         
00688     }
00689     putchar ( 13 ) ;
00690 }
00691 
00692 void Octree::addTrian( Triangle* trian, int triind )
00693 {
00694     int i, j ;
00695 
00696     // Blowing up the triangle to the grid
00697     float mid[3] = {0, 0, 0} ;
00698     for ( i = 0 ; i < 3 ; i ++ )
00699         for ( j = 0 ; j < 3 ; j ++ )
00700         {
00701             trian->vt[i][j] = dimen * ( trian->vt[i][j] - origin[j] ) / range ;
00702             mid[j] += trian->vt[i][j] / 3 ;
00703         }
00704 
00705     // Generate projections
00706     LONG cube[2][3] = { { 0, 0, 0 }, { dimen, dimen, dimen } } ;
00707     LONG trig[3][3] ;
00708     
00709     for ( i = 0 ; i < 3 ; i ++ )
00710         for (  j = 0 ; j < 3 ; j ++ )
00711         {
00712             trig[i][j] = (LONG) (trian->vt[i][j]) ;
00713     // Perturb end points, if set so
00714         }
00715         
00716     // Add to the octree
00717     // int start[3] = { 0, 0, 0 } ;
00718     LONG errorvec = (LONG) ( 0 ) ;
00719     Projections* proj = new Projections( cube, trig, errorvec, triind ) ;
00720     root = addTrian( root, proj, maxDepth ) ;
00721     
00722     delete proj->inherit ;
00723     delete proj ;
00724 }
00725 
00726 
00727 UCHAR* Octree::addTrian( UCHAR* node, Projections* p, int height )
00728 {
00729     int i ;
00730     int vertdiff[8][3] = {{0,0,0},{0,0,1},{0,1,-1},{0,0,1},{1,-1,-1},{0,0,1},{0,1,-1},{0,0,1}} ;
00731     UCHAR boxmask = p->getBoxMask( ) ;
00732     Projections* subp = new Projections( p ) ;
00733     
00734     int count = 0 ;
00735     int tempdiff[3] = {0,0,0} ;
00736     for ( i = 0 ; i < 8 ; i ++ )
00737     {
00738         tempdiff[0] += vertdiff[i][0] ;
00739         tempdiff[1] += vertdiff[i][1] ;
00740         tempdiff[2] += vertdiff[i][2] ;
00741 
00742         /* Quick pruning using bounding box */
00743         if ( boxmask & ( 1 << i ) ) 
00744         {
00745             subp->shift( tempdiff ) ;
00746             tempdiff[0] = tempdiff[1] = tempdiff[2] = 0 ;
00747 
00748             /* Pruning using intersection test */
00749             if ( subp->isIntersecting() )
00750             // if ( subp->getIntersectionMasks( cedgemask, edgemask ) )
00751             {
00752                 if ( ! hasChild( node, i ) )
00753                 {
00754                     if ( height == 1 )
00755                     {
00756                         node = addLeafChild( node, i, count, createLeaf(0) ) ;
00757                     }
00758                     else
00759                     {
00760                         node = addInternalChild( node, i, count, createInternal(0) ) ;
00761                     }
00762                 }
00763                 UCHAR* chd = getChild( node, count ) ;
00764                         
00765                 if ( ! isLeaf( node, i ) )
00766                 {
00767                     // setChild( node, count, addTrian ( chd, subp, height - 1, vertmask[i], edgemask ) ) ;
00768                     setChild( node, count, addTrian ( chd, subp, height - 1 ) ) ;
00769                 }
00770                 else
00771                 {
00772                     setChild( node, count, updateCell( chd, subp ) ) ;
00773                 }
00774             }
00775         }
00776 
00777         if ( hasChild( node, i ) )
00778         {
00779             count ++ ;
00780         }
00781     }
00782 
00783     delete subp ;
00784     return node ;
00785 }
00786 
00787 UCHAR* Octree::updateCell( UCHAR* node, Projections* p )
00788 {
00789     int i ;
00790 
00791     // Edge connectivity
00792     int mask[3] = { 0, 4, 8 } ;
00793     int oldc = 0, newc = 0 ;
00794     float offs[3] ;
00795 #ifdef USE_HERMIT
00796     float a[3], b[3], c[3] ;
00797 #endif
00798 
00799     for ( i = 0 ; i < 3 ; i ++ )
00800     {
00801         if ( ! getEdgeParity( node, mask[i] ) )
00802         {
00803             if ( p->isIntersectingPrimary( i ) )
00804             {
00805                 // this->actualQuads ++ ;
00806                 setEdge( node, mask[i] ) ;
00807                 offs[ newc ] = p->getIntersectionPrimary( i ) ;
00808 #ifdef USE_HERMIT
00809                 a[ newc ] = (float) p->inherit->norm[0] ;
00810                 b[ newc ] = (float) p->inherit->norm[1] ;
00811                 c[ newc ] = (float) p->inherit->norm[2] ;
00812 #endif
00813                 newc ++ ;
00814             }
00815         }
00816         else
00817         {
00818 #ifndef USE_HERMIT
00819             offs[ newc ] = getEdgeOffset( node, oldc ) ;
00820 #else
00821             offs[ newc ] = getEdgeOffsetNormal( node, oldc, a[ newc ], b[ newc ], c[ newc ] ) ;
00822 #endif
00823 
00824 //          if ( p->isIntersectingPrimary( i ) )
00825             {
00826                 // dc_printf("Multiple intersections!\n") ;
00827                 
00828 //              setPatchEdge( node, i ) ;
00829             }
00830             
00831             oldc ++ ;
00832             newc ++ ;
00833         }
00834     }
00835 
00836     if ( newc > oldc )
00837     {
00838         // New offsets added, update this node
00839 #ifndef USE_HERMIT
00840         node = updateEdgeOffsets( node, oldc, newc, offs ) ;
00841 #else
00842         node = updateEdgeOffsetsNormals( node, oldc, newc, offs, a, b, c ) ;
00843 #endif
00844     }
00845 
00846 
00847 
00848     return node ;
00849 }
00850 
00851 void Octree::preparePrimalEdgesMask( UCHAR* node )
00852 {
00853     int count = 0 ;
00854     for ( int i = 0 ; i < 8 ; i ++ )
00855     {
00856         if ( hasChild( node, i ) )
00857         {
00858             if ( isLeaf( node, i ) )
00859             {
00860                 createPrimalEdgesMask( getChild( node, count ) ) ;
00861             }
00862             else
00863             {
00864                 preparePrimalEdgesMask( getChild( node, count ) ) ;
00865             }
00866 
00867             count ++ ;
00868         }
00869     }
00870 }
00871 
00872 void Octree::trace( )
00873 {
00874     int st[3] = { 0, 0, 0, } ;
00875     this->numRings = 0 ;
00876     this->totRingLengths = 0 ;
00877     this->maxRingLength = 0 ;
00878 
00879     PathList* chdpath = NULL ;
00880     this->root = trace( this->root, st, dimen, maxDepth, chdpath ) ;
00881 
00882     if ( chdpath != NULL )
00883     {
00884         dc_printf("there are incomplete rings.\n") ;    
00885         printPaths( chdpath ) ;
00886     };
00887 }
00888 
00889 UCHAR* Octree::trace( UCHAR* node, int* st, int len, int depth, PathList*& paths)
00890 {
00891     UCHAR* newnode = node ;
00892     len >>= 1 ;
00893     PathList* chdpaths[ 8 ] ;
00894     UCHAR* chd[ 8 ] ;
00895     int nst[ 8 ][ 3 ] ;
00896     int i, j ;
00897 
00898     // Get children paths
00899     int chdleaf[ 8 ] ;
00900     fillChildren( newnode, chd, chdleaf ) ;
00901 
00902     // int count = 0 ;
00903     for ( i = 0 ; i < 8 ; i ++ )
00904     {
00905         for ( j = 0 ; j < 3 ; j ++ )
00906         {
00907             nst[ i ][ j ] = st[ j ] + len * vertmap[ i ][ j ] ;
00908         }
00909 
00910         if ( chd[ i ] == NULL || isLeaf( node, i ) )
00911         {
00912             chdpaths[ i ] = NULL ;
00913         }
00914         else
00915         {
00916             trace( chd[ i ], nst[i], len, depth - 1, chdpaths[ i ] ) ;
00917         }
00918     }
00919 
00920     // Get connectors on the faces
00921     PathList* conn[ 12 ] ;
00922     UCHAR* nf[2] ;
00923     int lf[2] ;
00924     int df[2] = { depth - 1, depth - 1 } ;
00925     int* nstf[ 2 ];
00926 
00927     fillChildren( newnode, chd, chdleaf ) ;
00928 
00929     for ( i = 0 ; i < 12 ; i ++ )
00930     {
00931         int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] };
00932         
00933         for ( int j = 0 ; j < 2 ; j ++ )
00934         {
00935             lf[j] = chdleaf[ c[j] ] ;
00936             nf[j] = chd[ c[j] ] ;
00937             nstf[j] = nst[ c[j] ] ;
00938         }
00939 
00940         conn[ i ] = NULL ;
00941         
00942         findPaths( nf, lf, df, nstf, depth - 1, cellProcFaceMask[ i ][ 2 ], conn[ i ] ) ;
00943 
00944         //if ( conn[i] )
00945         //{
00946         //      printPath( conn[i] ) ;
00947         //}
00948     }
00949     
00950     // Connect paths
00951     PathList* rings = NULL ;
00952     combinePaths( chdpaths[0], chdpaths[1], conn[8], rings ) ;
00953     combinePaths( chdpaths[2], chdpaths[3], conn[9], rings ) ;
00954     combinePaths( chdpaths[4], chdpaths[5], conn[10], rings ) ;
00955     combinePaths( chdpaths[6], chdpaths[7], conn[11], rings ) ;
00956 
00957     combinePaths( chdpaths[0], chdpaths[2], conn[4], rings ) ;
00958     combinePaths( chdpaths[4], chdpaths[6], conn[5], rings ) ;
00959     combinePaths( chdpaths[0], NULL, conn[6], rings ) ;
00960     combinePaths( chdpaths[4], NULL, conn[7], rings ) ;
00961 
00962     combinePaths( chdpaths[0], chdpaths[4], conn[0], rings ) ;
00963     combinePaths( chdpaths[0], NULL, conn[1], rings ) ;
00964     combinePaths( chdpaths[0], NULL, conn[2], rings ) ;
00965     combinePaths( chdpaths[0], NULL, conn[3], rings ) ;
00966 
00967     // By now, only chdpaths[0] and rings have contents
00968 
00969     // Process rings
00970     if ( rings )
00971     {
00972         // printPath( rings ) ;
00973 
00974         /* Let's count first */
00975         PathList* trings = rings ;
00976         while ( trings )
00977         {
00978             this->numRings ++ ;
00979             this->totRingLengths += trings->length ;
00980             if ( trings->length > this->maxRingLength )
00981             {
00982                 this->maxRingLength = trings->length ;
00983             }
00984             trings = trings->next ;
00985         }
00986 
00987         // printPath( rings ) ;
00988         newnode = patch( newnode, st, ( len << 1 ), rings ) ;
00989     }
00990 
00991     // Return incomplete paths
00992     paths = chdpaths[0] ;
00993     return newnode ;
00994 }
00995 
00996 void Octree::findPaths( UCHAR* node[2], int leaf[2], int depth[2], int* st[2], int maxdep, int dir, PathList*& paths )
00997 {
00998     if ( ! ( node[0] && node[1] ) )
00999     {
01000         return ;
01001     }
01002 
01003     if ( ! ( leaf[0] && leaf[1] ) )
01004     {
01005         // Not at the bottom, recur
01006 
01007         // Fill children nodes
01008         int i, j ;
01009         UCHAR* chd[ 2 ][ 8 ] ;
01010         int chdleaf[ 2 ][ 8 ] ;
01011         int nst[ 2 ][ 8 ][ 3 ] ;
01012 
01013         for ( j = 0 ; j < 2 ; j ++ )
01014         {
01015             if ( ! leaf[j] )
01016             {
01017                 fillChildren( node[j], chd[j], chdleaf[j] ) ;
01018 
01019                 int len = ( dimen >> ( maxDepth - depth[j] + 1 ) ) ;
01020                 for ( i = 0 ; i < 8 ; i ++ )
01021                 {
01022                     for ( int k = 0 ; k < 3 ; k ++ )
01023                     {
01024                         nst[ j ][ i ][ k ] = st[ j ][ k ] + len * vertmap[ i ][ k ] ;
01025                     }
01026                 }
01027 
01028             }
01029         }
01030 
01031         // 4 face calls
01032         UCHAR* nf[2] ;
01033         int df[2] ;
01034         int lf[2] ;
01035         int* nstf[2] ;
01036         for ( i = 0 ; i < 4 ; i ++ )
01037         {
01038             int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] };
01039             for ( int j = 0 ; j < 2 ; j ++ )
01040             {
01041                 if ( leaf[j] )
01042                 {
01043                     lf[j] = leaf[j] ;
01044                     nf[j] = node[j] ;
01045                     df[j] = depth[j] ;
01046                     nstf[j] = st[j] ;
01047                 }
01048                 else
01049                 {
01050                     lf[j] = chdleaf[ j ][ c[j] ] ;
01051                     nf[j] = chd[ j ][ c[j] ] ;
01052                     df[j] = depth[j] - 1 ;
01053                     nstf[j] = nst[ j ][ c[j] ] ;
01054                 }
01055             }
01056             findPaths( nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ], paths ) ;
01057         }
01058 
01059     }
01060     else
01061     {
01062         // At the bottom, check this face
01063         int ind = ( depth[0] == maxdep ? 0 : 1 ) ;
01064         int fcind = 2 * dir + ( 1 - ind ) ;
01065         if ( getFaceParity( node[ ind ], fcind ) )
01066         {
01067             // Add into path
01068             PathElement* ele1 = new PathElement ;
01069             PathElement* ele2 = new PathElement ;
01070 
01071             ele1->pos[0] = st[0][0] ;
01072             ele1->pos[1] = st[0][1] ;
01073             ele1->pos[2] = st[0][2] ;
01074 
01075             ele2->pos[0] = st[1][0] ;
01076             ele2->pos[1] = st[1][1] ;
01077             ele2->pos[2] = st[1][2] ;
01078 
01079             ele1->next = ele2 ;
01080             ele2->next = NULL ;
01081 
01082             PathList* lst = new PathList ;
01083             lst->head = ele1 ;
01084             lst->tail = ele2 ;
01085             lst->length = 2 ;
01086             lst->next = paths ;
01087             paths = lst ;
01088 
01089             // int l = ( dimen >> maxDepth ) ;
01090         }
01091     }
01092 
01093 }
01094 
01095 void Octree::combinePaths( PathList*& list1, PathList* list2, PathList* paths, PathList*& rings )
01096 {
01097     // Make new list of paths
01098     PathList* nlist = NULL ;
01099 
01100     // Search for each connectors in paths
01101     PathList* tpaths = paths ;
01102     PathList* tlist, * pre ;
01103     while ( tpaths )
01104     {
01105         PathList* singlist = tpaths ;
01106         PathList* templist ;
01107         tpaths = tpaths->next ;
01108         singlist->next = NULL ;
01109 
01110         // Look for hookup in list1
01111         tlist = list1 ;
01112         pre = NULL ;
01113         while ( tlist )
01114         {
01115             if (  (templist = combineSinglePath( list1, pre, tlist, singlist, NULL, singlist )) != NULL )
01116             {
01117                 singlist = templist ;
01118                 continue ;
01119             }
01120             pre = tlist ;
01121             tlist = tlist->next ;
01122         }
01123 
01124         // Look for hookup in list2
01125         tlist = list2 ;
01126         pre = NULL ;
01127         while ( tlist )
01128         {
01129             if (  (templist = combineSinglePath( list2, pre, tlist, singlist, NULL, singlist )) != NULL )
01130             {
01131                 singlist = templist ;
01132                 continue ;
01133             }
01134             pre = tlist ;
01135             tlist = tlist->next ;
01136         }
01137 
01138         // Look for hookup in nlist
01139         tlist = nlist ;
01140         pre = NULL ;
01141         while ( tlist )
01142         {
01143             if (  (templist = combineSinglePath( nlist, pre, tlist, singlist, NULL, singlist )) != NULL )
01144             {
01145                 singlist = templist ;
01146                 continue ;
01147             }
01148             pre = tlist ;
01149             tlist = tlist->next ;
01150         }
01151 
01152         // Add to nlist or rings
01153         if ( isEqual( singlist->head, singlist->tail ) )
01154         {
01155             PathElement* temp = singlist->head ;
01156             singlist->head = temp->next ;
01157             delete temp ;
01158             singlist->length -- ;
01159             singlist->tail->next = singlist->head ;
01160 
01161             singlist->next = rings ;
01162             rings = singlist ;
01163         }
01164         else
01165         {
01166             singlist->next = nlist ;
01167             nlist = singlist ;
01168         }
01169 
01170     }
01171 
01172     // Append list2 and nlist to the end of list1 
01173     tlist = list1 ;
01174     if ( tlist != NULL )
01175     {
01176         while ( tlist->next != NULL )
01177         {
01178             tlist = tlist->next ;
01179         }
01180         tlist->next = list2 ;
01181     }
01182     else
01183     {
01184         tlist = list2 ;
01185         list1 = list2 ;
01186     }
01187 
01188     if ( tlist != NULL )
01189     {
01190         while ( tlist->next != NULL )
01191         {
01192             tlist = tlist->next ;
01193         }
01194         tlist->next = nlist ;
01195     }
01196     else
01197     {
01198         tlist = nlist ;
01199         list1 = nlist ;
01200     }
01201 
01202 }
01203 
01204 PathList* Octree::combineSinglePath( PathList*& head1, PathList* pre1, PathList*& list1, PathList*& head2, PathList* pre2, PathList*& list2 )
01205 {
01206     if ( isEqual( list1->head, list2->head ) || isEqual( list1->tail, list2->tail ) )
01207     {
01208         // Reverse the list
01209         if ( list1->length < list2->length )
01210         {
01211             // Reverse list1
01212             PathElement* prev = list1->head ;
01213             PathElement* next = prev->next ;
01214             prev->next = NULL ;
01215             while ( next != NULL )
01216             {
01217                 PathElement* tnext = next->next ;
01218                 next->next = prev ;
01219 
01220                 prev = next ;
01221                 next = tnext ;
01222             }
01223 
01224             list1->tail = list1->head ;
01225             list1->head = prev ;
01226         }
01227         else
01228         {
01229             // Reverse list2
01230             PathElement* prev = list2->head ;
01231             PathElement* next = prev->next ;
01232             prev->next = NULL ;
01233             while ( next != NULL )
01234             {
01235                 PathElement* tnext = next->next ;
01236                 next->next = prev ;
01237 
01238                 prev = next ;
01239                 next = tnext ;
01240             }
01241 
01242             list2->tail = list2->head ;
01243             list2->head = prev ;
01244         }
01245     }   
01246     
01247     if ( isEqual( list1->head, list2->tail ) )
01248     {
01249 
01250         // Easy case
01251         PathElement* temp = list1->head->next ;
01252         delete list1->head ;
01253         list2->tail->next = temp ;
01254 
01255         PathList* nlist = new PathList ;
01256         nlist->length = list1->length + list2->length - 1 ;
01257         nlist->head = list2->head ;
01258         nlist->tail = list1->tail ;
01259         nlist->next = NULL ;
01260 
01261         deletePath( head1, pre1, list1 ) ;
01262         deletePath( head2, pre2, list2 ) ;
01263 
01264         return nlist ;
01265     } 
01266     else if ( isEqual( list1->tail, list2->head ) )
01267     {
01268         // Easy case
01269         PathElement* temp = list2->head->next ;
01270         delete list2->head ;
01271         list1->tail->next = temp ;
01272 
01273         PathList* nlist = new PathList ;
01274         nlist->length = list1->length + list2->length - 1 ;
01275         nlist->head = list1->head ;
01276         nlist->tail = list2->tail ;
01277         nlist->next = NULL ;
01278 
01279         deletePath( head1, pre1, list1 ) ;
01280         deletePath( head2, pre2, list2 ) ;
01281 
01282         return nlist ;
01283     }
01284 
01285     return NULL ;
01286 }
01287 
01288 void Octree::deletePath( PathList*& head, PathList* pre, PathList*& curr )
01289 {
01290     PathList* temp = curr ;
01291     curr = temp->next ;
01292     delete temp ;
01293 
01294     if ( pre == NULL )
01295     {
01296         head = curr ;
01297     }
01298     else
01299     {
01300         pre->next = curr ;
01301     }
01302 }
01303 
01304 void Octree::printElement( PathElement* ele )
01305 {
01306     if ( ele != NULL )
01307     {
01308         dc_printf( " (%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2] ) ;
01309     }
01310 }
01311 
01312 void Octree::printPath( PathList* path )
01313 {
01314     PathElement* n = path->head;
01315     int same = 0 ;
01316 
01317 #if DC_DEBUG
01318     int len = ( dimen >> maxDepth ) ;
01319 #endif
01320     while ( n && ( same == 0 || n != path->head ) )
01321     {
01322         same ++ ;
01323         dc_printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ;
01324         n = n->next ;
01325     }
01326 
01327     if ( n == path->head )
01328     {
01329         dc_printf(" Ring!\n") ;
01330     }
01331     else
01332     {
01333         dc_printf(" %p end!\n", n) ;
01334     }
01335 }
01336 
01337 void Octree::printPath( PathElement* path )
01338 {
01339     PathElement *n = path;
01340     int same = 0 ;
01341 #if DC_DEBUG
01342     int len = ( dimen >> maxDepth ) ; 
01343 #endif
01344     while ( n && ( same == 0 || n != path ) )
01345     {
01346         same ++ ;
01347         dc_printf( " (%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len ) ;
01348         n = n->next ;
01349     }
01350 
01351     if ( n == path )
01352     {
01353         dc_printf(" Ring!\n") ;
01354     }
01355     else
01356     {
01357         dc_printf(" %p end!\n", n) ;
01358     }
01359 
01360 }
01361 
01362 
01363 void Octree::printPaths( PathList* path )
01364 {
01365     PathList* iter = path ;
01366     int i = 0 ;
01367     while ( iter != NULL )
01368     {
01369         dc_printf("Path %d:\n", i) ;
01370         printPath( iter ) ;
01371         iter = iter->next ;
01372         i ++ ;
01373     }
01374 }
01375 
01376 UCHAR* Octree::patch( UCHAR* node, int st[3], int len, PathList* rings )
01377 {
01378 #ifdef IN_DEBUG_MODE
01379     dc_printf("Call to PATCH with rings: \n");
01380     printPaths( rings ) ;
01381 #endif
01382 
01383     /* Do nothing but couting 
01384     PathList* tlist = rings ;
01385     PathList* ttlist ;
01386     PathElement* telem, * ttelem ;
01387     while ( tlist!= NULL )
01388     {
01389         // printPath( tlist ) ;
01390         this->numRings ++ ;
01391         this->totRingLengths += tlist->length ;
01392         if ( tlist->length > this->maxRingLength )
01393         {
01394             this->maxRingLength = tlist->length ;
01395         }
01396         ttlist = tlist ;
01397         tlist = tlist->next ;
01398     }
01399     return node ;
01400     */
01401     
01402 
01403     /* Pass onto separate calls in each direction */
01404     UCHAR* newnode = node ;
01405     if ( len == mindimen )
01406     {
01407         dc_printf("Error! should have no list by now.\n") ;
01408         exit(0) ;
01409     }
01410     
01411     // YZ plane
01412     PathList* xlists[2] ;
01413     newnode = patchSplit( newnode, st, len, rings, 0, xlists[0], xlists[1] ) ;
01414     
01415     // XZ plane
01416     PathList* ylists[4] ;
01417     newnode = patchSplit( newnode, st, len, xlists[0], 1, ylists[0], ylists[1] ) ;
01418     newnode = patchSplit( newnode, st, len, xlists[1], 1, ylists[2], ylists[3] ) ;
01419     
01420     // XY plane
01421     PathList* zlists[8] ;
01422     newnode = patchSplit( newnode, st, len, ylists[0], 2, zlists[0], zlists[1] ) ;
01423     newnode = patchSplit( newnode, st, len, ylists[1], 2, zlists[2], zlists[3] ) ;
01424     newnode = patchSplit( newnode, st, len, ylists[2], 2, zlists[4], zlists[5] ) ;
01425     newnode = patchSplit( newnode, st, len, ylists[3], 2, zlists[6], zlists[7] ) ;
01426     
01427     // Recur
01428     len >>= 1 ;
01429     int count = 0 ;
01430     for ( int i = 0 ; i < 8 ; i ++ )
01431     {
01432         if ( zlists[i] != NULL )
01433         {
01434             int nori[3] = { 
01435                 st[0] + len * vertmap[i][0] , 
01436                 st[1] + len * vertmap[i][1] , 
01437                 st[2] + len * vertmap[i][2] } ;
01438             patch( getChild( newnode , count ), nori, len, zlists[i] ) ;
01439         }
01440 
01441         if ( hasChild( newnode, i ) )
01442         {
01443             count ++ ;
01444         }
01445     }
01446 #ifdef IN_DEBUG_MODE
01447     dc_printf("Return from PATCH\n") ;
01448 #endif
01449     return newnode ;
01450     
01451 }
01452 
01453 
01454 UCHAR* Octree::patchSplit( UCHAR* node, int st[3], int len, PathList* rings, int dir, PathList*& nrings1, PathList*& nrings2 )
01455 {
01456 #ifdef IN_DEBUG_MODE
01457     dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir);
01458     printPaths( rings ) ;
01459 #endif
01460 
01461     UCHAR* newnode = node ;
01462     nrings1 = NULL ;
01463     nrings2 = NULL ;
01464     PathList* tmp ;
01465     while ( rings != NULL )
01466     {
01467         // Process this ring
01468         newnode = patchSplitSingle( newnode, st, len, rings->head, dir, nrings1, nrings2 ) ;
01469         
01470         // Delete this ring from the group
01471         tmp = rings ;
01472         rings = rings->next ;
01473         delete tmp ;
01474     }
01475 
01476 #ifdef IN_DEBUG_MODE
01477     dc_printf("Return from PATCHSPLIT with \n");
01478     dc_printf("Rings gourp 1:\n") ;
01479     printPaths( nrings1 ) ;
01480     dc_printf("Rings group 2:\n") ;
01481     printPaths( nrings2 ) ;
01482 #endif
01483 
01484     return newnode ;
01485 }
01486 
01487 UCHAR* Octree::patchSplitSingle( UCHAR* node, int st[3], int len, PathElement* head, int dir, PathList*& nrings1, PathList*& nrings2 )
01488 {
01489 #ifdef IN_DEBUG_MODE
01490     dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir );
01491     printPath( head ) ;
01492 #endif
01493 
01494     UCHAR* newnode = node ;
01495 
01496     if ( head == NULL )
01497     {
01498 #ifdef IN_DEBUG_MODE
01499         dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n") ;
01500 #endif
01501         return newnode;
01502     }
01503     else
01504     {
01505         // printPath( head ) ;
01506     }
01507     
01508     // Walk along the ring to find pair of intersections
01509     PathElement* pre1 = NULL ;
01510     PathElement* pre2 = NULL ;
01511     int side = findPair ( head, st[ dir ] + len / 2 , dir, pre1, pre2 ) ;
01512     
01513     /*
01514     if ( pre1 == pre2 )
01515     {
01516         int edgelen = ( dimen >> maxDepth ) ;
01517         dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen) ;
01518         printPath( head ) ;
01519         exit( 0 ) ;
01520     }
01521     */
01522     
01523     if ( side )
01524     {
01525         // Entirely on one side
01526         PathList* nring = new PathList( ) ;
01527         nring->head = head ;
01528         
01529         if ( side == -1 )
01530         {
01531             nring->next = nrings1 ;
01532             nrings1 = nring ;
01533         }
01534         else
01535         {
01536             nring->next = nrings2 ;
01537             nrings2 = nring ;
01538         }
01539     }
01540     else
01541     {
01542         // Break into two parts
01543         PathElement* nxt1 = pre1->next ;
01544         PathElement* nxt2 = pre2->next ;
01545         pre1->next = nxt2 ;
01546         pre2->next = nxt1 ;
01547 
01548         newnode = connectFace( newnode, st, len, dir, pre1, pre2 ) ;
01549     
01550         if ( isEqual( pre1, pre1->next ) )
01551         {
01552             if ( pre1 == pre1->next )
01553             {
01554                 delete pre1 ;
01555                 pre1 = NULL ;
01556             }
01557             else
01558             {
01559                 PathElement* temp = pre1->next ;
01560                 pre1->next = temp->next ;
01561                 delete temp ;
01562             }
01563         }
01564         if ( isEqual( pre2, pre2->next ) )
01565         {
01566             if ( pre2 == pre2->next )
01567             {
01568                 delete pre2 ;
01569                 pre2 = NULL ;
01570             }
01571             else
01572             {
01573                 PathElement* temp = pre2->next ;
01574                 pre2->next = temp->next ;
01575                 delete temp ;
01576             }
01577         }
01578 
01579         compressRing ( pre1 ) ;
01580         compressRing ( pre2 ) ;
01581         
01582         // Recur
01583         newnode = patchSplitSingle( newnode, st, len, pre1, dir, nrings1, nrings2 ) ;
01584         newnode = patchSplitSingle( newnode, st, len, pre2, dir, nrings1, nrings2 ) ;
01585         
01586     }
01587 
01588 #ifdef IN_DEBUG_MODE
01589     dc_printf("Return from PATCHSPLITSINGLE with \n");
01590     dc_printf("Rings gourp 1:\n") ;
01591     printPaths( nrings1 ) ;
01592     dc_printf("Rings group 2:\n") ;
01593     printPaths( nrings2 ) ;
01594 #endif
01595 
01596     return newnode ;
01597 }
01598 
01599 UCHAR* Octree::connectFace( UCHAR* node, int st[3], int len, int dir, PathElement* f1, PathElement* f2 )
01600 {
01601 #ifdef IN_DEBUG_MODE
01602     dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len );
01603     dc_printf("Path (low side): \n" ) ;
01604     printPath( f1 ) ;
01605 //  checkPath( f1 ) ;
01606     dc_printf("Path (high side): \n" ) ;
01607     printPath( f2 ) ;
01608 //  checkPath( f2 ) ;
01609 #endif
01610 
01611     UCHAR* newnode = node ;
01612 
01613     // Setup 2D 
01614     int pos = st[ dir ] + len / 2 ;
01615     int xdir = ( dir + 1 ) % 3 ;
01616     int ydir = ( dir + 2 ) % 3 ;
01617     
01618     // Use existing intersections on f1 and f2
01619     int x1, y1, x2, y2 ;
01620     float p1, q1, p2, q2 ;
01621 
01622     getFacePoint( f2->next, dir, x1, y1, p1, q1 ) ;
01623     getFacePoint( f2, dir, x2, y2, p2, q2 ) ;
01624  
01625     float dx = x2 + p2 - x1 - p1 ;
01626     float dy = y2 + q2 - y1 - q1 ;
01627     
01628     // Do adapted Bresenham line drawing
01629     float rx = p1, ry = q1 ;
01630     int incx = 1, incy = 1 ; 
01631     int lx = x1, ly = y1 ;
01632     int hx = x2, hy = y2 ;
01633     int choice ;
01634     if ( x2 < x1 )
01635     {
01636         incx = -1 ;
01637         rx = 1 - rx ;
01638         lx = x2 ;
01639         hx = x1 ;
01640     }
01641     if ( y2 < y1 )
01642     {
01643         incy = -1 ;
01644         ry = 1 - ry ;
01645         ly = y2 ;
01646         hy = y1 ;
01647     }
01648     
01649     float sx = dx * incx ;
01650     float sy = dy * incy ;
01651     
01652     int ori[3] ;
01653     ori[ dir ] = pos / mindimen ;
01654     ori[ xdir ] = x1 ;
01655     ori[ ydir ] = y1 ;
01656     int walkdir ;
01657     int inc ;
01658     float alpha ;
01659 
01660     PathElement* curEleN = f1 ;
01661     PathElement* curEleP = f2->next ;
01662     UCHAR *nodeN = NULL, *nodeP = NULL ;
01663     UCHAR *curN = locateLeaf( newnode, len, f1->pos ) ;
01664     UCHAR *curP = locateLeaf( newnode, len, f2->next->pos ) ;
01665     if ( curN == NULL || curP == NULL )
01666     {
01667         exit(0) ;
01668     }
01669     int stN[3], stP[3] ;
01670     int lenN, lenP ;
01671     
01672     /* Unused code, leaving for posterity
01673 
01674     float stpt[3], edpt[3] ;
01675     stpt[ dir ] = edpt[ dir ] = (float) pos ;
01676     stpt[ xdir ] = ( x1 + p1 ) * mindimen ;
01677     stpt[ ydir ] = ( y1 + q1 ) * mindimen ;
01678     edpt[ xdir ] = ( x2 + p2 ) * mindimen ;
01679     edpt[ ydir ] = ( y2 + q2 ) * mindimen ;
01680     */
01681     while( ori[ xdir ] != x2 || ori[ ydir ] != y2 )
01682     {
01683         int next ;
01684         if ( sy * (1 - rx) > sx * (1 - ry) )
01685         {
01686             choice = 1 ; 
01687             next = ori[ ydir ] + incy ;
01688             if ( next < ly || next > hy ) 
01689             {
01690                 choice = 4 ;
01691                 next = ori[ xdir ] + incx ;
01692             }
01693         }
01694         else
01695         {
01696             choice = 2 ;
01697             next = ori[ xdir ] + incx ;
01698             if ( next < lx || next > hx ) 
01699             {
01700                 choice = 3 ;
01701                 next = ori[ ydir ] + incy ;
01702             }
01703         }
01704         
01705         if ( choice & 1 )
01706         {
01707             ori[ ydir ] = next ;
01708             if ( choice == 1 )
01709             {
01710                 rx += ( sy == 0 ? 0 : (1 - ry) * sx / sy  ) ; 
01711                 ry = 0 ;
01712             }
01713             
01714             walkdir = 2 ;
01715             inc = incy ;
01716             alpha = x2 < x1 ? 1 - rx : rx ;
01717         }
01718         else
01719         {
01720             ori[ xdir ] = next ;
01721             if ( choice == 2 )
01722             {
01723                 ry += ( sx == 0 ? 0 : (1 - rx) * sy / sx ) ;
01724                 rx = 0 ;    
01725             }
01726             
01727             walkdir = 1 ;
01728             inc = incx ;
01729             alpha = y2 < y1 ? 1 - ry : ry ;
01730         }
01731         
01732 
01733 
01734         // Get the exact location of the marcher
01735         int nori[3] = { ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen } ;
01736         float spt[3] = { (float) nori[0], (float) nori[1], (float) nori[2] } ;
01737         spt[ ( dir + ( 3 - walkdir ) ) % 3 ] += alpha * mindimen ;
01738         if ( inc < 0 )
01739         {
01740             spt[ ( dir + walkdir ) % 3 ] += mindimen ;
01741         }
01742         
01743         // dc_printf("new x,y: %d %d\n", ori[ xdir ] / edgelen, ori[ ydir ] / edgelen ) ;
01744         // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir ) ;
01745         // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2] ) ;
01746 
01747         // Locate the current cells on both sides
01748         newnode = locateCell( newnode, st, len, nori, dir, 1, nodeN, stN, lenN ) ;
01749         newnode = locateCell( newnode, st, len, nori, dir, 0, nodeP, stP, lenP ) ;
01750 
01751         updateParent( newnode, len, st ) ;
01752 
01753         int flag = 0 ;
01754         // Add the cells to the rings and fill in the patch
01755         PathElement* newEleN ;
01756         if ( curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2] )
01757         {
01758             if ( curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] || curEleN->next->pos[2] != stN[2] )
01759             {
01760                 newEleN = new PathElement ;
01761                 newEleN->next = curEleN->next ;
01762                 newEleN->pos[0] = stN[0] ;
01763                 newEleN->pos[1] = stN[1] ;
01764                 newEleN->pos[2] = stN[2] ;
01765 
01766                 curEleN->next = newEleN ;
01767             }
01768             else
01769             {
01770                 newEleN = curEleN->next ;
01771             }
01772             curN = patchAdjacent( newnode, len, curEleN->pos, curN, newEleN->pos, nodeN, walkdir, inc, dir, 1, alpha ) ;
01773 
01774             curEleN = newEleN ;
01775             flag ++ ;
01776         }
01777 
01778         PathElement* newEleP ;
01779         if ( curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2] )
01780         {
01781             if ( f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2] )
01782             {
01783                 newEleP = new PathElement ;
01784                 newEleP->next = curEleP ;
01785                 newEleP->pos[0] = stP[0] ;
01786                 newEleP->pos[1] = stP[1] ;
01787                 newEleP->pos[2] = stP[2] ;
01788 
01789                 f2->next = newEleP ;
01790             }
01791             else
01792             {
01793                 newEleP = f2 ;
01794             }
01795             curP = patchAdjacent( newnode, len, curEleP->pos, curP, newEleP->pos, nodeP, walkdir, inc, dir, 0, alpha ) ;
01796 
01797 
01798 
01799             curEleP = newEleP ;
01800             flag ++ ;
01801         }
01802 
01803             
01804         /*
01805         if ( flag == 0 )
01806         {
01807             dc_printf("error: non-synchronized patching! at \n") ;
01808         }
01809         */
01810     }
01811 
01812 #ifdef IN_DEBUG_MODE
01813     dc_printf("Return from CONNECTFACE with \n");
01814     dc_printf("Path (low side):\n") ;
01815     printPath( f1 ) ;
01816     checkPath( f1 ) ;
01817     dc_printf("Path (high side):\n") ;
01818     printPath( f2 ) ;
01819     checkPath( f2 ) ;
01820 #endif
01821 
01822 
01823     return newnode ;
01824 }
01825 
01826 UCHAR* Octree::patchAdjacent( UCHAR* node, int len, int st1[3], UCHAR* leaf1, int st2[3], UCHAR* leaf2, int walkdir, int inc, int dir, int side, float alpha )
01827 {
01828 #ifdef IN_DEBUG_MODE
01829     dc_printf("Before patching.\n") ;
01830     printInfo( st1 ) ;
01831     printInfo( st2 ) ;
01832     dc_printf("-----------------%d %d %d ; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2] ) ;
01833 #endif
01834 
01835     // Get edge index on each leaf
01836     int edgedir = ( dir + ( 3 - walkdir ) ) % 3 ;
01837     int incdir = ( dir + walkdir ) % 3 ;
01838     int ind1 = ( edgedir == 1 ? ( dir + 3 - edgedir ) % 3 - 1 : 2 - ( dir + 3 - edgedir ) % 3 ) ;
01839     int ind2 = ( edgedir == 1 ? ( incdir + 3 - edgedir ) % 3 - 1 : 2 - ( incdir + 3 - edgedir ) % 3 ) ;
01840 
01841     int eind1 = ( ( edgedir << 2 ) | ( side << ind1 ) | ( ( inc > 0 ? 1 : 0 ) << ind2 ) ) ;
01842     int eind2 = ( ( edgedir << 2 ) | ( side << ind1 ) | ( ( inc > 0 ? 0 : 1 ) << ind2 ) ) ;
01843 
01844 #ifdef IN_DEBUG_MODE
01845     dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ;
01846     /*
01847     if ( alpha < 0 || alpha > 1 )
01848     {
01849         dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha ) ;
01850         printInfo( st1 ) ;
01851         printInfo( st2 ) ;
01852     }
01853     */
01854 #endif
01855 
01856     // Flip edge parity
01857     UCHAR* nleaf1 = flipEdge( leaf1, eind1, alpha ) ;
01858     UCHAR* nleaf2 = flipEdge( leaf2, eind2, alpha ) ;
01859 
01860     // Update parent link
01861     updateParent( node, len, st1, nleaf1 ) ;
01862     updateParent( node, len, st2, nleaf2 ) ;
01863     // updateParent( nleaf1, mindimen, st1 ) ;
01864     // updateParent( nleaf2, mindimen, st2 ) ;
01865 
01866     /*
01867     float m[3] ;
01868     dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2] ) ;
01869     getMinimizer( leaf1, m ) ;
01870     dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2] ) ;
01871     getMinimizer( leaf2, m ) ;
01872     dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2] ) ;
01873     */      
01874 
01875 #ifdef IN_DEBUG_MODE
01876     dc_printf("After patching.\n") ;
01877     printInfo( st1 ) ;
01878     printInfo( st2 ) ;
01879 #endif
01880     return nleaf2 ;
01881 }
01882 
01883 UCHAR* Octree::locateCell( UCHAR* node, int st[3], int len, int ori[3], int dir, int side, UCHAR*& rleaf, int rst[3], int& rlen )
01884 {
01885 #ifdef IN_DEBUG_MODE
01886     // dc_printf("Call to LOCATECELL with node ") ;
01887     // printNode( node ) ;
01888 #endif
01889     UCHAR* newnode = node ;
01890     int i ;
01891     len >>= 1 ;
01892     int ind = 0 ;
01893     for ( i = 0 ; i < 3 ; i ++ )
01894     {
01895         ind <<= 1 ;
01896         if ( i == dir && side == 1 )
01897         {
01898             ind |= ( ori[ i ] <= ( st[ i ] + len ) ? 0 : 1 ) ;
01899         }
01900         else
01901         {
01902             ind |= ( ori[ i ] < ( st[ i ] + len ) ? 0 : 1 ) ;
01903         }
01904     }
01905 
01906 #ifdef IN_DEBUG_MODE
01907     // dc_printf("In LOCATECELL index of ori (%d %d %d) with dir %d side %d in st (%d %d %d, %d) is: %d\n",
01908     //  ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind ) ;
01909 #endif
01910 
01911     rst[0] = st[0] + vertmap[ ind ][ 0 ] * len ;
01912     rst[1] = st[1] + vertmap[ ind ][ 1 ] * len ;
01913     rst[2] = st[2] + vertmap[ ind ][ 2 ] * len ;
01914     
01915     if ( hasChild( newnode, ind ) )
01916     {
01917         int count = getChildCount( newnode, ind ) ;
01918         UCHAR* chd = getChild( newnode, count ) ;
01919         if ( isLeaf( newnode, ind ) )
01920         {
01921             rleaf = chd ;
01922             rlen = len ;
01923         }
01924         else
01925         {
01926             // Recur
01927             setChild( newnode, count, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ) ) ;
01928         }
01929     }
01930     else
01931     {
01932         // Create a new child here
01933         if ( len == this->mindimen )
01934         {
01935             UCHAR* chd = createLeaf( 0 ) ;
01936             newnode = addChild( newnode, ind, chd, 1 ) ;
01937             rleaf = chd ;
01938             rlen = len ;
01939         }
01940         else
01941         {
01942             // Subdivide the empty cube
01943             UCHAR* chd = createInternal( 0 ) ;
01944             newnode = addChild( newnode, ind, locateCell( chd, rst, len, ori, dir, side, rleaf, rst, rlen ), 0 ) ;
01945         }
01946     }
01947     
01948 #ifdef IN_DEBUG_MODE
01949     // dc_printf("Return from LOCATECELL with node ") ;
01950     // printNode( newnode ) ;
01951 #endif
01952     return newnode ;
01953 }
01954 
01955 void Octree::checkElement( PathElement* ele )
01956 {
01957     /*
01958     if ( ele != NULL && locateLeafCheck( ele->pos ) != ele->node )
01959     {
01960         dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift);
01961         exit( 0 ) ;
01962     }
01963     */
01964 }
01965 
01966 void Octree::checkPath( PathElement* path )
01967 {
01968     PathElement *n = path ;
01969     int same = 0 ;
01970     while ( n && ( same == 0 || n != path ) )
01971     {
01972         same ++ ;
01973         checkElement( n ) ;
01974         n = n->next ;
01975     }
01976 
01977 }
01978 
01979 void Octree::testFacePoint( PathElement* e1, PathElement* e2 )
01980 {
01981     int i ;
01982     PathElement * e = NULL ;
01983     for ( i = 0 ; i < 3 ; i ++ )
01984     {
01985         if ( e1->pos[i] != e2->pos[i] )
01986         {
01987             if ( e1->pos[i] < e2->pos[i] )
01988             {
01989                 e = e2 ;
01990             }
01991             else
01992             {
01993                 e = e1 ;
01994             }
01995             break ;
01996         }
01997     }
01998 
01999     int x, y ;
02000     float p, q ;
02001     dc_printf("Test.") ;
02002     getFacePoint( e, i, x, y, p, q ) ;
02003 }
02004 
02005 void Octree::getFacePoint( PathElement* leaf, int dir, int& x, int& y, float& p, float& q )
02006 {
02007     // Find average intersections
02008     float avg[3] = {0, 0, 0} ;
02009     float off[3] ;
02010     int num = 0, num2 = 0 ;
02011 
02012     UCHAR* leafnode = locateLeaf( leaf->pos ) ;
02013     for ( int i = 0 ; i < 4 ; i ++ )
02014     {
02015         int edgeind = faceMap[ dir * 2 ][ i ] ;
02016         int nst[3] ;
02017         for ( int j = 0 ; j < 3 ; j ++ )
02018         {
02019             nst[j] = leaf->pos[j] + mindimen * vertmap[ edgemap[ edgeind][ 0 ] ][ j ] ;
02020         }
02021 
02022         if ( getEdgeIntersectionByIndex( nst, edgeind / 4, off, 1 ) )
02023         {
02024             avg[0] += off[0] ;
02025             avg[1] += off[1] ;
02026             avg[2] += off[2] ;
02027             num ++ ;
02028         }
02029         if ( getEdgeParity( leafnode, edgeind ) )
02030         {
02031             num2 ++ ;
02032         }
02033     }
02034     if ( num == 0 )
02035     {
02036         dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n", dir, leaf->pos[0]>>minshift, leaf->pos[1]>>minshift, leaf->pos[2]>>minshift, num2);
02037         avg[0] = (float) leaf->pos[0] ;
02038         avg[1] = (float) leaf->pos[1] ;
02039         avg[2] = (float) leaf->pos[2] ;
02040     }
02041     else
02042     {
02043         
02044         avg[0] /= num ;
02045         avg[1] /= num ;
02046         avg[2] /= num ;
02047         
02048         //avg[0] = (float) leaf->pos[0];
02049         //avg[1] = (float) leaf->pos[1];
02050         //avg[2] = (float) leaf->pos[2];
02051     }
02052     
02053     int xdir = ( dir + 1 ) % 3 ;
02054     int ydir = ( dir + 2 ) % 3 ;
02055 
02056     float xf = avg[ xdir ] ;
02057     float yf = avg[ ydir ] ;
02058 
02059 #ifdef IN_DEBUG_MODE
02060     // Is it outside?
02061     // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2 ;
02062     /*
02063     float* m = ( leaf == leaf1 ? m1 : m2 ) ;
02064     if ( xf < leaf->pos[ xdir ] || 
02065          yf < leaf->pos[ ydir ] ||
02066          xf > leaf->pos[ xdir ] + leaf->len ||
02067          yf > leaf->pos[ ydir ] + leaf->len)
02068     {
02069         dc_printf("Outside cube (%d %d %d), %d : %d %d %f %f\n", leaf->pos[ 0 ], leaf->pos[1], leaf->pos[2], leaf->len, 
02070                         pos, dir, xf, yf) ;
02071 
02072         // For now, snap to cell
02073         xf = m[ xdir ] ;
02074         yf = m[ ydir ] ;
02075     }
02076     */
02077 
02078     /*
02079     if ( alpha < 0 || alpha > 1 ||
02080          xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len || 
02081          yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len )
02082     {
02083         dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node ) ;
02084         dc_printf("GETFACEPOINT result: (%d %d %d) %d min: (%f %f %f) ;(%d %d %d) %d min: (%f %f %f).\n",
02085             leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2], 
02086             leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]);
02087         dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf ) ;
02088     }
02089     */
02090 #endif
02091     
02092 
02093     // Get the integer and float part
02094     x = ( ( leaf->pos[ xdir ] ) >> minshift ) ;
02095     y = ( ( leaf->pos[ ydir ] ) >> minshift ) ;
02096 
02097     p = ( xf - leaf->pos[ xdir ] ) / mindimen ;
02098     q = ( yf - leaf->pos[ ydir ] ) / mindimen ;
02099 
02100 
02101 #ifdef IN_DEBUG_MODE
02102     dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf ) ;
02103 #endif
02104 }
02105 
02106 int Octree::findPair( PathElement* head, int pos, int dir, PathElement*& pre1, PathElement*& pre2 )
02107 {
02108     int side = getSide ( head, pos, dir ) ;
02109     PathElement* cur = head ;
02110     PathElement* anchor ;
02111     PathElement* ppre1, *ppre2 ;
02112     
02113     // Start from this face, find a pair
02114     anchor = cur ;
02115     ppre1 = cur ;
02116     cur = cur->next ;
02117     while ( cur != anchor && ( getSide( cur, pos, dir ) == side ) )
02118     {
02119         ppre1 = cur ;
02120         cur = cur->next ;
02121     }
02122     if ( cur == anchor )
02123     {
02124         // No pair found
02125         return side ;
02126     }
02127     
02128     side = getSide( cur, pos, dir ) ;
02129     ppre2 = cur ;
02130     cur = cur->next ;
02131     while ( getSide( cur, pos, dir ) == side )
02132     {
02133         ppre2 = cur ;
02134         cur = cur->next ;
02135     }
02136     
02137     
02138     // Switch pre1 and pre2 if we start from the higher side
02139     if ( side == -1 )
02140     {
02141         cur = ppre1 ;
02142         ppre1 = ppre2 ;
02143         ppre2 = cur ;
02144     }
02145 
02146     pre1 = ppre1 ;
02147     pre2 = ppre2 ;
02148     
02149     return 0 ;
02150 }
02151 
02152 int Octree::getSide( PathElement* e, int pos, int dir )
02153 {
02154     return ( e->pos[ dir ] < pos ? -1 : 1 ) ;
02155 }
02156 
02157 int Octree::isEqual( PathElement* e1, PathElement* e2 )
02158 {
02159     return ( e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2] ) ;
02160 }
02161 
02162 void Octree::compressRing( PathElement*& ring )
02163 {
02164     if ( ring == NULL )
02165     {
02166         return ;
02167     }
02168 #ifdef IN_DEBUG_MODE
02169     dc_printf("Call to COMPRESSRING with path: \n" );
02170     printPath( ring ) ;
02171 #endif
02172 
02173     PathElement* cur = ring->next->next ;
02174     PathElement* pre = ring->next ;
02175     PathElement* prepre = ring ;
02176     PathElement* anchor = prepre ;
02177     
02178     do
02179     {
02180         while ( isEqual( cur, prepre ) )
02181         {
02182             // Delete
02183             if ( cur == prepre )
02184             {
02185                 // The ring has shrinked to a point
02186                 delete pre ;
02187                 delete cur ;
02188                 anchor = NULL ;
02189                 break ;
02190             }
02191             else
02192             {
02193                 prepre->next = cur->next ;
02194                 delete pre ;
02195                 delete cur ;
02196                 pre = prepre->next ;
02197                 cur = pre->next ;
02198                 anchor = prepre ;
02199             }
02200         }
02201         
02202         if ( anchor == NULL )
02203         {
02204             break ;
02205         }
02206         
02207         prepre = pre ;
02208         pre = cur ;
02209         cur = cur->next ;
02210     } while ( prepre != anchor ) ;
02211     
02212     ring = anchor ;
02213 
02214 #ifdef IN_DEBUG_MODE
02215     dc_printf("Return from COMPRESSRING with path: \n" );
02216     printPath( ring ) ;
02217 #endif
02218 }
02219 
02220 void Octree::buildSigns( )
02221 {
02222     // First build a lookup table
02223     // dc_printf("Building up look up table...\n") ;
02224     int size = 1 << 12 ;
02225     unsigned char table[ 1 << 12 ] ;
02226     for ( int i = 0 ; i < size ; i ++ )
02227     {
02228         table[i] = 0 ;
02229     }
02230     for ( int i = 0 ; i < 256 ; i ++ )
02231     {
02232         int ind = 0 ;
02233         for ( int j = 11 ; j >= 0 ; j -- )
02234         {
02235             ind <<= 1 ;
02236             if ( ( ( i >> edgemap[j][0] ) & 1 ) ^ ( ( i >> edgemap[j][1] ) & 1 ) )
02237             {
02238                 ind |= 1 ;
02239             }
02240         }
02241 
02242         table[ ind ] = i ;
02243     }
02244 
02245     // Next, traverse the grid
02246     int sg = 1 ;
02247     int cube[8] ;
02248     buildSigns( table, this->root, 0, sg, cube ) ;
02249 }
02250 
02251 void Octree::buildSigns( unsigned char table[], UCHAR* node, int isLeaf, int sg, int rvalue[8] )
02252 {
02253     if ( node == NULL )
02254     {
02255         for ( int i = 0 ; i < 8 ; i ++ )
02256         {
02257             rvalue[i] = sg ;
02258         }
02259         return ;
02260     }
02261 
02262     if ( isLeaf == 0 )
02263     {
02264         // Internal node
02265         UCHAR* chd[8] ;
02266         int leaf[8] ;
02267         fillChildren( node, chd, leaf ) ;
02268 
02269         // Get the signs at the corners of the first cube
02270         rvalue[0] = sg ;
02271         int oris[8] ;
02272         buildSigns( table, chd[0], leaf[0], sg, oris ) ;
02273 
02274         // Get the rest
02275         int cube[8] ;
02276         for ( int i = 1 ; i < 8 ; i ++ )
02277         {
02278             buildSigns( table, chd[i], leaf[i], oris[i], cube ) ;
02279             rvalue[i] = cube[i] ;
02280         }
02281 
02282     }
02283     else
02284     {
02285         // Leaf node
02286         generateSigns( node, table, sg ) ;
02287 
02288         for ( int i = 0 ; i < 8 ; i ++ )
02289         {
02290             rvalue[i] = getSign( node, i ) ;
02291         }
02292     }
02293 }
02294 
02295 void Octree::floodFill( )
02296 {
02297     // int threshold = (int) ((dimen/mindimen) * (dimen/mindimen) * 0.5f) ;
02298     int st[3] = { 0, 0, 0 } ;
02299 
02300     // First, check for largest component
02301     // size stored in -threshold
02302     this->clearProcessBits( root, maxDepth ) ;
02303     int threshold = this->floodFill( root, st, dimen, maxDepth, 0 ) ;
02304 
02305     // Next remove
02306     dc_printf("Largest component: %d\n", threshold);
02307     threshold *= thresh ;
02308     dc_printf("Removing all components smaller than %d\n", threshold) ;
02309 
02310     int st2[3] = { 0, 0, 0 } ;
02311     this->clearProcessBits( root, maxDepth ) ;
02312     this->floodFill( root, st2, dimen, maxDepth, threshold ) ;
02313 
02314 }
02315 
02316 void Octree::clearProcessBits( UCHAR* node, int height )
02317 {
02318     int i;
02319 
02320     if ( height == 0 )
02321     {
02322         // Leaf cell, 
02323         for ( i = 0 ; i < 12 ; i ++ )
02324         {
02325             setOutProcess( node, i ) ;
02326         }
02327     }
02328     else
02329     {
02330         // Internal cell, recur
02331         int count = 0 ;
02332         for ( i = 0 ; i < 8 ; i ++ )
02333         {
02334             if ( hasChild( node, i ) )
02335             {
02336                 clearProcessBits( getChild( node, count ), height - 1 ) ;
02337                 count ++ ;
02338             }
02339         }
02340     }   
02341 }
02342 
02343 /*
02344 void Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold )
02345 {
02346     int i, j;
02347 
02348     if ( height == 0 )
02349     {
02350         // Leaf cell, 
02351         int par, inp ;
02352 
02353         // Test if the leaf has intersection edges
02354         for ( i = 0 ; i < 12 ; i ++ )
02355         {
02356             par = getEdgeParity( node, i ) ;
02357             inp = isInProcess( node, i ) ;
02358 
02359             if ( par == 1 && inp == 0 )
02360             {
02361                 // Intersection edge, hasn't been processed
02362                 // Let's start filling
02363                 GridQueue* queue = new GridQueue() ;
02364                 int total = 1 ;
02365 
02366                 // Set to in process
02367                 int mst[3] ;
02368                 mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len ;
02369                 mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len ;
02370                 mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
02371                 int mdir = i / 4 ;
02372                 setInProcessAll( mst, mdir ) ;
02373 
02374                 // Put this edge into queue
02375                 queue->pushQueue( mst, mdir ) ;
02376 
02377                 // Queue processing
02378                 int nst[3], dir ;
02379                 while ( queue->popQueue( nst, dir ) == 1 )
02380                 {
02381                     // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ;
02382                     // locations
02383                     int stMask[3][3] = {
02384                         { 0, 0 - len, 0 - len },
02385                         { 0 - len, 0, 0 - len },
02386                         { 0 - len, 0 - len, 0 }
02387                     };
02388                     int cst[2][3] ;
02389                     for ( j = 0 ; j < 3 ; j ++ )
02390                     {
02391                         cst[0][j] = nst[j] ;
02392                         cst[1][j] = nst[j] + stMask[ dir ][ j ] ;
02393                     }
02394 
02395                     // cells 
02396                     UCHAR* cs[2] ;
02397                     for ( j = 0 ; j < 2 ; j ++ )
02398                     {
02399                         cs[ j ] = locateLeaf( cst[j] ) ;
02400                     }
02401 
02402                     // Middle sign
02403                     int s = getSign( cs[0], 0 ) ;
02404 
02405                     // Masks
02406                     int fcCells[4] = {1,0,1,0};
02407                     int fcEdges[3][4][3] = {
02408                         {{9,2,11},{8,1,10},{5,1,7},{4,2,6}},
02409                         {{10,6,11},{8,5,9},{1,5,3},{0,6,2}},
02410                         {{6,10,7},{4,9,5},{2,9,3},{0,10,1}}
02411                     };
02412 
02413                     // Search for neighboring connected intersection edges
02414                     for ( int find = 0 ; find < 4 ; find ++ )
02415                     {
02416                         int cind = fcCells[find] ;
02417                         int eind, edge ;
02418                         if ( s == 0 )
02419                         {
02420                             // Original order
02421                             for ( eind = 0 ; eind < 3 ; eind ++ )
02422                             {
02423                                 edge = fcEdges[dir][find][eind] ;
02424                                 if ( getEdgeParity( cs[cind], edge ) == 1 )
02425                                 {
02426                                     break ;
02427                                 }
02428                             }
02429                         }
02430                         else
02431                         {
02432                             // Inverse order
02433                             for ( eind = 2 ; eind >= 0 ; eind -- )
02434                             {
02435                                 edge = fcEdges[dir][find][eind] ;
02436                                 if ( getEdgeParity( cs[cind], edge ) == 1 )
02437                                 {
02438                                     break ;
02439                                 }
02440                             }
02441                         }
02442                         
02443                         if ( eind == 3 || eind == -1 )
02444                         {
02445                             dc_printf("Wrong! this is not a consistent sign. %d\n", eind );
02446                         }
02447                         else 
02448                         {
02449                             int est[3] ;
02450                             est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ;
02451                             est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ;
02452                             est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ;
02453                             int edir = edge / 4 ;
02454                             
02455                             if ( isInProcess( cs[cind], edge ) == 0 )
02456                             {
02457                                 setInProcessAll( est, edir ) ;
02458                                 queue->pushQueue( est, edir ) ;
02459                                 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02460                                 total ++ ;
02461                             }
02462                             else
02463                             {
02464                                 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02465                             }
02466                         }
02467                         
02468                     }
02469 
02470                 }
02471 
02472                 dc_printf("Size of component: %d ", total) ;
02473 
02474                 if ( total > threshold )
02475                 {
02476                     dc_printf("Maintained.\n") ;
02477                     continue ;
02478                 }
02479                 dc_printf("Less then %d, removing...\n", threshold) ;
02480 
02481                 // We have to remove this noise
02482 
02483                 // Flip parity
02484                 // setOutProcessAll( mst, mdir ) ;
02485                 flipParityAll( mst, mdir ) ;
02486 
02487                 // Put this edge into queue
02488                 queue->pushQueue( mst, mdir ) ;
02489 
02490                 // Queue processing
02491                 while ( queue->popQueue( nst, dir ) == 1 )
02492                 {
02493                     // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ;
02494                     // locations
02495                     int stMask[3][3] = {
02496                         { 0, 0 - len, 0 - len },
02497                         { 0 - len, 0, 0 - len },
02498                         { 0 - len, 0 - len, 0 }
02499                     };
02500                     int cst[2][3] ;
02501                     for ( j = 0 ; j < 3 ; j ++ )
02502                     {
02503                         cst[0][j] = nst[j] ;
02504                         cst[1][j] = nst[j] + stMask[ dir ][ j ] ;
02505                     }
02506 
02507                     // cells 
02508                     UCHAR* cs[2] ;
02509                     for ( j = 0 ; j < 2 ; j ++ )
02510                     {
02511                         cs[ j ] = locateLeaf( cst[j] ) ;
02512                     }
02513 
02514                     // Middle sign
02515                     int s = getSign( cs[0], 0 ) ;
02516 
02517                     // Masks
02518                     int fcCells[4] = {1,0,1,0};
02519                     int fcEdges[3][4][3] = {
02520                         {{9,2,11},{8,1,10},{5,1,7},{4,2,6}},
02521                         {{10,6,11},{8,5,9},{1,5,3},{0,6,2}},
02522                         {{6,10,7},{4,9,5},{2,9,3},{0,10,1}}
02523                     };
02524 
02525                     // Search for neighboring connected intersection edges
02526                     for ( int find = 0 ; find < 4 ; find ++ )
02527                     {
02528                         int cind = fcCells[find] ;
02529                         int eind, edge ;
02530                         if ( s == 0 )
02531                         {
02532                             // Original order
02533                             for ( eind = 0 ; eind < 3 ; eind ++ )
02534                             {
02535                                 edge = fcEdges[dir][find][eind] ;
02536                                 if ( isInProcess( cs[cind], edge ) == 1 )
02537                                 {
02538                                     break ;
02539                                 }
02540                             }
02541                         }
02542                         else
02543                         {
02544                             // Inverse order
02545                             for ( eind = 2 ; eind >= 0 ; eind -- )
02546                             {
02547                                 edge = fcEdges[dir][find][eind] ;
02548                                 if ( isInProcess( cs[cind], edge ) == 1 )
02549                                 {
02550                                     break ;
02551                                 }
02552                             }
02553                         }
02554                         
02555                         if ( eind == 3 || eind == -1 )
02556                         {
02557                             dc_printf("Wrong! this is not a consistent sign. %d\n", eind );
02558                         }
02559                         else 
02560                         {
02561                             int est[3] ;
02562                             est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ;
02563                             est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ;
02564                             est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ;
02565                             int edir = edge / 4 ;
02566                             
02567                             if ( getEdgeParity( cs[cind], edge ) == 1 )
02568                             {
02569                                 flipParityAll( est, edir ) ;
02570                                 queue->pushQueue( est, edir ) ;
02571                                 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02572                                 total ++ ;
02573                             }
02574                             else
02575                             {
02576                                 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02577                             }
02578                         }
02579                         
02580                     }
02581 
02582                 }
02583 
02584             }
02585         }
02586     }
02587     else
02588     {
02589         // Internal cell, recur
02590         int count = 0 ;
02591         len >>= 1 ;
02592         for ( i = 0 ; i < 8 ; i ++ )
02593         {
02594             if ( hasChild( node, i ) )
02595             {
02596                 int nst[3] ;
02597                 nst[0] = st[0] + vertmap[i][0] * len ;
02598                 nst[1] = st[1] + vertmap[i][1] * len ;
02599                 nst[2] = st[2] + vertmap[i][2] * len ;
02600                 
02601                 floodFill( getChild( node, count ), nst, len, height - 1, threshold ) ;
02602                 count ++ ;
02603             }
02604         }
02605     }
02606 }
02607 */
02608 
02609 int Octree::floodFill( UCHAR* node, int st[3], int len, int height, int threshold )
02610 {
02611     int i, j;
02612     int maxtotal = 0 ;
02613 
02614     if ( height == 0 )
02615     {
02616         // Leaf cell, 
02617         int par, inp ;
02618 
02619         // Test if the leaf has intersection edges
02620         for ( i = 0 ; i < 12 ; i ++ )
02621         {
02622             par = getEdgeParity( node, i ) ;
02623             inp = isInProcess( node, i ) ;
02624 
02625             if ( par == 1 && inp == 0 )
02626             {
02627                 // Intersection edge, hasn't been processed
02628                 // Let's start filling
02629                 GridQueue* queue = new GridQueue() ;
02630                 int total = 1 ;
02631 
02632                 // Set to in process
02633                 int mst[3] ;
02634                 mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len ;
02635                 mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len ;
02636                 mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
02637                 int mdir = i / 4 ;
02638                 setInProcessAll( mst, mdir ) ;
02639 
02640                 // Put this edge into queue
02641                 queue->pushQueue( mst, mdir ) ;
02642 
02643                 // Queue processing
02644                 int nst[3], dir ;
02645                 while ( queue->popQueue( nst, dir ) == 1 )
02646                 {
02647                     // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ;
02648                     // locations
02649                     int stMask[3][3] = {
02650                         { 0, 0 - len, 0 - len },
02651                         { 0 - len, 0, 0 - len },
02652                         { 0 - len, 0 - len, 0 }
02653                     };
02654                     int cst[2][3] ;
02655                     for ( j = 0 ; j < 3 ; j ++ )
02656                     {
02657                         cst[0][j] = nst[j] ;
02658                         cst[1][j] = nst[j] + stMask[ dir ][ j ] ;
02659                     }
02660 
02661                     // cells 
02662                     UCHAR* cs[2] ;
02663                     for ( j = 0 ; j < 2 ; j ++ )
02664                     {
02665                         cs[ j ] = locateLeaf( cst[j] ) ;
02666                     }
02667 
02668                     // Middle sign
02669                     int s = getSign( cs[0], 0 ) ;
02670 
02671                     // Masks
02672                     int fcCells[4] = {1,0,1,0};
02673                     int fcEdges[3][4][3] = {
02674                         {{9,2,11},{8,1,10},{5,1,7},{4,2,6}},
02675                         {{10,6,11},{8,5,9},{1,5,3},{0,6,2}},
02676                         {{6,10,7},{4,9,5},{2,9,3},{0,10,1}}
02677                     };
02678 
02679                     // Search for neighboring connected intersection edges
02680                     for ( int find = 0 ; find < 4 ; find ++ )
02681                     {
02682                         int cind = fcCells[find] ;
02683                         int eind, edge ;
02684                         if ( s == 0 )
02685                         {
02686                             // Original order
02687                             for ( eind = 0 ; eind < 3 ; eind ++ )
02688                             {
02689                                 edge = fcEdges[dir][find][eind] ;
02690                                 if ( getEdgeParity( cs[cind], edge ) == 1 )
02691                                 {
02692                                     break ;
02693                                 }
02694                             }
02695                         }
02696                         else
02697                         {
02698                             // Inverse order
02699                             for ( eind = 2 ; eind >= 0 ; eind -- )
02700                             {
02701                                 edge = fcEdges[dir][find][eind] ;
02702                                 if ( getEdgeParity( cs[cind], edge ) == 1 )
02703                                 {
02704                                     break ;
02705                                 }
02706                             }
02707                         }
02708                         
02709                         if ( eind == 3 || eind == -1 )
02710                         {
02711                             dc_printf("Wrong! this is not a consistent sign. %d\n", eind );
02712                         }
02713                         else 
02714                         {
02715                             int est[3] ;
02716                             est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ;
02717                             est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ;
02718                             est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ;
02719                             int edir = edge / 4 ;
02720                             
02721                             if ( isInProcess( cs[cind], edge ) == 0 )
02722                             {
02723                                 setInProcessAll( est, edir ) ;
02724                                 queue->pushQueue( est, edir ) ;
02725                                 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02726                                 total ++ ;
02727                             }
02728                             else
02729                             {
02730                                 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02731                             }
02732                         }
02733                         
02734                     }
02735 
02736                 }
02737 
02738                 dc_printf("Size of component: %d ", total) ;
02739 
02740                 if ( threshold == 0 )
02741                 {
02742                     // Measuring stage
02743                     if ( total > maxtotal )
02744                     {
02745                         maxtotal = total ;
02746                     }
02747                     dc_printf(".\n") ;
02748                     continue ;
02749                 }
02750                 
02751                 if ( total >= threshold )
02752                 {
02753                     dc_printf("Maintained.\n") ;
02754                     continue ;
02755                 }
02756                 dc_printf("Less then %d, removing...\n", threshold) ;
02757 
02758                 // We have to remove this noise
02759 
02760                 // Flip parity
02761                 // setOutProcessAll( mst, mdir ) ;
02762                 flipParityAll( mst, mdir ) ;
02763 
02764                 // Put this edge into queue
02765                 queue->pushQueue( mst, mdir ) ;
02766 
02767                 // Queue processing
02768                 while ( queue->popQueue( nst, dir ) == 1 )
02769                 {
02770                     // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir) ;
02771                     // locations
02772                     int stMask[3][3] = {
02773                         { 0, 0 - len, 0 - len },
02774                         { 0 - len, 0, 0 - len },
02775                         { 0 - len, 0 - len, 0 }
02776                     };
02777                     int cst[2][3] ;
02778                     for ( j = 0 ; j < 3 ; j ++ )
02779                     {
02780                         cst[0][j] = nst[j] ;
02781                         cst[1][j] = nst[j] + stMask[ dir ][ j ] ;
02782                     }
02783 
02784                     // cells 
02785                     UCHAR* cs[2] ;
02786                     for ( j = 0 ; j < 2 ; j ++ )
02787                     {
02788                         cs[ j ] = locateLeaf( cst[j] ) ;
02789                     }
02790 
02791                     // Middle sign
02792                     int s = getSign( cs[0], 0 ) ;
02793 
02794                     // Masks
02795                     int fcCells[4] = {1,0,1,0};
02796                     int fcEdges[3][4][3] = {
02797                         {{9,2,11},{8,1,10},{5,1,7},{4,2,6}},
02798                         {{10,6,11},{8,5,9},{1,5,3},{0,6,2}},
02799                         {{6,10,7},{4,9,5},{2,9,3},{0,10,1}}
02800                     };
02801 
02802                     // Search for neighboring connected intersection edges
02803                     for ( int find = 0 ; find < 4 ; find ++ )
02804                     {
02805                         int cind = fcCells[find] ;
02806                         int eind, edge ;
02807                         if ( s == 0 )
02808                         {
02809                             // Original order
02810                             for ( eind = 0 ; eind < 3 ; eind ++ )
02811                             {
02812                                 edge = fcEdges[dir][find][eind] ;
02813                                 if ( isInProcess( cs[cind], edge ) == 1 )
02814                                 {
02815                                     break ;
02816                                 }
02817                             }
02818                         }
02819                         else
02820                         {
02821                             // Inverse order
02822                             for ( eind = 2 ; eind >= 0 ; eind -- )
02823                             {
02824                                 edge = fcEdges[dir][find][eind] ;
02825                                 if ( isInProcess( cs[cind], edge ) == 1 )
02826                                 {
02827                                     break ;
02828                                 }
02829                             }
02830                         }
02831                         
02832                         if ( eind == 3 || eind == -1 )
02833                         {
02834                             dc_printf("Wrong! this is not a consistent sign. %d\n", eind );
02835                         }
02836                         else 
02837                         {
02838                             int est[3] ;
02839                             est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len ;
02840                             est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len ;
02841                             est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len ;
02842                             int edir = edge / 4 ;
02843                             
02844                             if ( getEdgeParity( cs[cind], edge ) == 1 )
02845                             {
02846                                 flipParityAll( est, edir ) ;
02847                                 queue->pushQueue( est, edir ) ;
02848                                 // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02849                                 total ++ ;
02850                             }
02851                             else
02852                             {
02853                                 // dc_printf("Processed, not pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir) ;
02854                             }
02855                         }
02856                         
02857                     }
02858 
02859                 }
02860 
02861             }
02862         }
02863 
02864     }
02865     else
02866     {
02867         // Internal cell, recur
02868         int count = 0 ;
02869         len >>= 1 ;
02870         for ( i = 0 ; i < 8 ; i ++ )
02871         {
02872             if ( hasChild( node, i ) )
02873             {
02874                 int nst[3] ;
02875                 nst[0] = st[0] + vertmap[i][0] * len ;
02876                 nst[1] = st[1] + vertmap[i][1] * len ;
02877                 nst[2] = st[2] + vertmap[i][2] * len ;
02878                 
02879                 int d = floodFill( getChild( node, count ), nst, len, height - 1, threshold ) ;
02880                 if ( d > maxtotal)
02881                 {
02882                     maxtotal = d ;
02883                 }
02884                 count ++ ;
02885             }
02886         }
02887     }
02888 
02889 
02890     return maxtotal ;
02891 
02892 }
02893 
02894 void Octree::writeOut()
02895 {
02896     int numQuads = 0 ;
02897     int numVertices = 0 ;
02898     int numEdges = 0 ;
02899 #ifdef USE_HERMIT
02900     countIntersection( root, maxDepth, numQuads, numVertices, numEdges ) ;
02901 #else
02902     countIntersection( root, maxDepth, numQuads, numVertices ) ;
02903     numEdges = numQuads * 3 / 2 ;
02904 #endif
02905     dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads ) ;
02906     output_mesh = alloc_output(numVertices, numQuads);  
02907     int offset = 0 ;
02908     int st[3] = { 0, 0, 0 } ;
02909 
02910     // First, output vertices
02911     offset = 0 ;
02912     actualVerts = 0 ;
02913     actualQuads = 0 ;
02914 #ifdef USE_HERMIT
02915     generateMinimizer( root, st, dimen, maxDepth, offset ) ;
02916     cellProcContour( this->root, 0, maxDepth ) ;
02917     dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads ) ;
02918 #else
02919     writeVertex( root, st, dimen, maxDepth, offset, out ) ;
02920     writeQuad( root, st, dimen, maxDepth, out ) ;
02921     dc_printf("Vertices written: %d Triangles written: %d \n", offset, actualQuads ) ;
02922 #endif
02923 }
02924 
02925 #if 0
02926 void Octree::writePLY( char* fname )
02927 {
02928     int numQuads = 0 ;
02929     int numVertices = 0 ;
02930     int numEdges = 0 ;
02931 #ifdef USE_HERMIT
02932     countIntersection( root, maxDepth, numQuads, numVertices, numEdges ) ;
02933 #else
02934     countIntersection( root, maxDepth, numQuads, numVertices ) ;
02935     numEdges = numQuads * 3 / 2 ;
02936 #endif
02937     // int euler = numVertices + numQuads - numEdges ;
02938     // int genus =  ( 2 - euler ) / 2 ;
02939     // dc_printf("%d vertices %d quads %d edges\n", numVertices, numQuads, numEdges ) ;
02940     // dc_printf("Genus: %d Euler: %d\n", genus, euler ) ;
02941 
02942     FILE* fout = fopen ( fname, "wb" ) ;
02943     dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads ) ;
02944     PLYWriter::writeHeader( fout, numVertices, numQuads ) ;
02945     int offset = 0 ;
02946     int st[3] = { 0, 0, 0 } ;
02947 
02948     // First, output vertices
02949     offset = 0 ;
02950     actualVerts = 0 ;
02951     actualQuads = 0 ;
02952 #ifdef USE_HERMIT
02953     generateMinimizer( root, st, dimen, maxDepth, offset, fout ) ;
02954 #ifdef TESTMANIFOLD
02955     testfout = fopen("test.txt", "w");
02956     fprintf(testfout, "{");
02957 #endif
02958     cellProcContour( this->root, 0, maxDepth, fout ) ;
02959 #ifdef TESTMANIFOLD
02960     fprintf(testfout, "}");
02961     fclose( testfout ) ;
02962 #endif
02963     dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads ) ;
02964 #else
02965     writeVertex( root, st, dimen, maxDepth, offset, fout ) ;
02966     writeQuad( root, st, dimen, maxDepth, fout ) ;
02967     dc_printf("Vertices written: %d Triangles written: %d \n", offset, actualQuads ) ;
02968 #endif
02969 
02970 
02971     fclose( fout ) ;
02972 }
02973 #endif
02974 
02975 void Octree::writeOctree( char* fname ) 
02976 {
02977     FILE* fout = fopen ( fname, "wb" ) ;
02978 
02979     int sized = ( 1 << maxDepth ) ;
02980     fwrite( &sized, sizeof( int ), 1, fout ) ;
02981     writeOctree( fout, root, maxDepth ) ;
02982     dc_printf("Grid dimension: %d\n", sized ) ;
02983 
02984 
02985     fclose( fout ) ;
02986 }
02987 void Octree::writeOctree( FILE* fout, UCHAR* node, int depth )
02988 {
02989     char type ;
02990     if ( depth > 0 )
02991     {
02992         type = 0 ;
02993         fwrite( &type, sizeof( char ), 1, fout ) ;
02994 
02995         // Get sign at the center
02996         char sg = (char) getSign( getChild( node, 0 ), depth - 1, 7 - getChildIndex( node, 0 ) ) ;
02997 
02998         int t = 0 ;
02999         for ( int i = 0 ; i < 8 ; i ++ )
03000         {
03001             if ( hasChild( node, i ) )
03002             {
03003                 writeOctree( fout, getChild( node, t ), depth - 1 ) ;
03004                 t ++ ;
03005             }
03006             else
03007             {
03008                 type = 1 ;
03009                 fwrite( &type, sizeof( char ), 1, fout ) ;
03010                 fwrite( &sg, sizeof( char ), 1, fout ) ;
03011             }
03012         }
03013     }
03014     else
03015     {
03016         type = 2 ;
03017         fwrite( &type, sizeof( char ), 1, fout ) ;
03018         fwrite( &(node[2]), sizeof ( UCHAR ), 1, fout );
03019     }
03020 }
03021 
03022 #ifdef USE_HERMIT
03023 #if 0
03024 void Octree::writeOctreeGeom( char* fname ) 
03025 {
03026     FILE* fout = fopen ( fname, "wb" ) ;
03027 
03028     // Write header
03029     char header[]="SOG.Format 1.0";
03030     int nlen = 128 - 4 * 4 - strlen(header) - 1 ;
03031     char* header2 = new char[ nlen ];
03032     for ( int i = 0 ; i < nlen ; i ++ )
03033     {
03034         header2[i] = '\0';
03035     }
03036     fwrite( header, sizeof( char ), strlen(header) + 1, fout ) ;
03037     fwrite( origin, sizeof( float ), 3, fout ) ;
03038     fwrite( &range, sizeof( float ), 1, fout ) ;
03039     fwrite( header2, sizeof( char ), nlen, fout ) ;
03040 
03041     
03042     int sized = ( 1 << maxDepth ) ;
03043     int st[3] = {0,0,0};
03044     fwrite( &sized, sizeof( int ), 1, fout ) ;
03045 
03046     writeOctreeGeom( fout, root, st, dimen, maxDepth ) ;
03047     dc_printf("Grid dimension: %d\n", sized ) ;
03048 
03049 
03050     fclose( fout ) ;
03051 }
03052 #endif
03053 void Octree::writeOctreeGeom( FILE* fout, UCHAR* node, int st[3], int len, int depth ) 
03054 {
03055     char type ;
03056     if ( depth > 0 )
03057     {
03058         type = 0 ;
03059         fwrite( &type, sizeof( char ), 1, fout ) ;
03060 
03061         // Get sign at the center
03062         char sg = (char) getSign( getChild( node, 0 ), depth - 1, 7 - getChildIndex( node, 0 ) ) ;
03063 
03064         int t = 0 ;
03065         len >>= 1 ;
03066         for ( int i = 0 ; i < 8 ; i ++ )
03067         {
03068             if ( hasChild( node, i ) )
03069             {
03070                 int nst[3] ;
03071                 nst[0] = st[0] + vertmap[i][0] * len ;
03072                 nst[1] = st[1] + vertmap[i][1] * len ;
03073                 nst[2] = st[2] + vertmap[i][2] * len ;
03074                 writeOctreeGeom( fout, getChild( node, t ), nst, len, depth - 1 ) ;
03075                 t ++ ;
03076             }
03077             else
03078             {
03079                 type = 1 ;
03080                 fwrite( &type, sizeof( char ), 1, fout ) ;
03081                 fwrite( &sg, sizeof( char ), 1, fout ) ;
03082             }
03083         }
03084     }
03085     else
03086     {
03087         type = 2 ;
03088         fwrite( &type, sizeof( char ), 1, fout ) ;
03089         fwrite( &(node[2]), sizeof ( UCHAR ), 1, fout );
03090 
03091         // Compute minimizer
03092         // First, find minimizer
03093         float rvalue[3] ;
03094         rvalue[0] = (float) st[0] + len / 2 ;
03095         rvalue[1] = (float) st[1] + len / 2 ;
03096         rvalue[2] = (float) st[2] + len / 2 ;
03097         computeMinimizer( node, st, len, rvalue ) ;
03098 
03099         // Update
03100         // float flen = len * range / dimen ; 
03101         for ( int j = 0 ; j < 3 ; j ++ )
03102         {
03103             rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ;
03104         }
03105 
03106         fwrite( rvalue, sizeof ( float ), 3, fout );
03107     }
03108 }
03109 #endif
03110 
03111 #ifdef USE_HERMIT
03112 void Octree::writeDCF( char* fname )
03113 {
03114     FILE* fout = fopen ( fname, "wb" ) ;
03115 
03116     // Writing out version
03117     char version[10] = "multisign";
03118     fwrite ( &version, sizeof ( char ), 10, fout );
03119 
03120     // Writing out size
03121     int sized = ( 1 << maxDepth ) ;
03122     fwrite( &sized, sizeof( int ), 1, fout ) ;
03123     fwrite( &sized, sizeof( int ), 1, fout ) ;
03124     fwrite( &sized, sizeof( int ), 1, fout ) ;
03125 
03126     int st[3] = {0, 0, 0} ;
03127     writeDCF( fout, root, maxDepth, st, dimen ) ;
03128     
03129     dc_printf("Grid dimension: %d\n", sized ) ;
03130     fclose( fout ) ;
03131 }
03132 
03133 void Octree::writeDCF( FILE* fout, UCHAR* node, int height, int st[3], int len )
03134 {
03135     nodetype type ;
03136     if ( height > 0 )
03137     {
03138         type = 0 ;
03139         len >>= 1 ;
03140         fwrite( &type, sizeof( nodetype ), 1, fout ) ;
03141 
03142         // Get sign at the center
03143         signtype sg = 1 - (signtype) getSign( getChild( node, 0 ), height - 1, 7 - getChildIndex( node, 0 ) ) ;
03144 
03145         int t = 0 ;
03146         for ( int i = 0 ; i < 8 ; i ++ )
03147         {
03148             if ( hasChild( node, i ) )
03149             {
03150                 int nst[3] ;
03151                 nst[0] = st[0] + vertmap[i][0] * len ;
03152                 nst[1] = st[1] + vertmap[i][1] * len ;
03153                 nst[2] = st[2] + vertmap[i][2] * len ;
03154 
03155 
03156                 writeDCF( fout, getChild( node, t ), height - 1, nst, len ) ;
03157                 t ++ ;
03158             }
03159             else
03160             {
03161                 type = 1 ;
03162                 fwrite( &type, sizeof( nodetype ), 1, fout ) ;
03163                 fwrite ( &(sg), sizeof ( signtype ), 1, fout );
03164             }
03165         }
03166     }
03167     else
03168     {
03169         type = 2 ;
03170         fwrite( &type, sizeof( nodetype ), 1, fout ) ;
03171 
03172         // Write signs
03173         signtype sgn[8] ;
03174         for ( int i = 0 ; i < 8 ; i ++ )
03175         {
03176             sgn[ i ] = 1 - (signtype) getSign( node, i ) ;
03177         }
03178         fwrite (sgn, sizeof (signtype), 8, fout );
03179 
03180         // Write edge data
03181         float pts[12], norms[12][3] ;
03182         int parity[12] ;
03183         fillEdgeOffsetsNormals( node, st, len, pts, norms, parity ) ;
03184 
03185         numtype zero = 0, one = 1 ;
03186         for ( int i = 0 ; i < 12 ; i ++ )
03187         {
03188             int par = getEdgeParity( node, i ) ;
03189             // Let's check first
03190             if ( par )
03191             {
03192                 if ( sgn[ edgemap[i][0] ] == sgn[ edgemap[i][1] ] )
03193                 {
03194                     dc_printf("Wrong! Parity: %d Sign: %d %d\n", parity[i], sgn[ edgemap[i][0] ], sgn[ edgemap[i][1] ]);
03195                     exit(0) ;
03196                 }
03197                 if ( parity[ i ] == 0 )
03198                 {
03199                     dc_printf("Wrong! No intersection found.\n");
03200                     exit(0) ;
03201                 }
03202                 fwrite( &one, sizeof ( numtype ) , 1, fout ) ;
03203                 fwrite( &(pts[i]), sizeof( float ), 1, fout ) ;
03204                 fwrite( norms[i], sizeof( float ), 3, fout ) ;
03205 
03206             }
03207             else
03208             {
03209                 if ( sgn[ edgemap[i][0] ] != sgn[ edgemap[i][1] ] )
03210                 {
03211                     dc_printf("Wrong! Parity: %d Sign: %d %d\n", parity[i], sgn[ edgemap[i][0] ], sgn[ edgemap[i][1] ]);
03212                     exit(0) ;
03213                 }
03214                 fwrite ( &zero, sizeof ( numtype ) , 1, fout );
03215             }
03216         }
03217     }
03218 }
03219 #endif
03220 
03221 
03222 void Octree::writeOpenEdges( FILE* fout )
03223 {
03224     // Total number of rings
03225     fprintf( fout, "%d\n", numRings ) ;
03226     dc_printf("Number of rings to write: %d\n", numRings) ;
03227 
03228     // Write each ring
03229     PathList* tlist = ringList ;
03230     for ( int i = 0 ; i < numRings ; i ++ )
03231     {
03232         fprintf(fout, "%d\n", tlist->length) ;
03233         // dc_printf("Ring length: %d\n", tlist->length ) ;
03234         PathElement* cur = tlist->head ;
03235         for ( int j = 0 ; j < tlist->length ; j ++ )
03236         {
03237             float cent[3] ;
03238             float flen = mindimen * range / dimen ; 
03239             for ( int k = 0 ; k < 3 ; k ++ )
03240             {
03241                 cent[ k ] = cur->pos[ k ] * range / dimen + origin[ k ] + flen / 2 ;
03242             }
03243             fprintf(fout, "%f %f %f\n", cent[0], cent[1], cent[2]) ;
03244             cur = cur->next ;
03245         }
03246 
03247         tlist = tlist->next ;
03248     }
03249 }
03250 
03251 #ifndef USE_HERMIT
03252 void Octree::countIntersection( UCHAR* node, int height, int& nquad, int& nvert )
03253 {
03254     if ( height > 0 )
03255     {
03256         int total = getNumChildren( node ) ;
03257         for ( int i = 0 ; i < total ; i ++ )
03258         {
03259             countIntersection( getChild( node, i ), height - 1, nquad, nvert ) ;
03260         }
03261     }
03262     else
03263     {
03264         int mask = getSignMask( node ) ;
03265         nvert += getNumEdges2( node ) ;
03266         nquad += cubes->getNumTriangle( mask ) ;
03267 
03268     }
03269 }
03270 
03271 void Octree::writeVertex( UCHAR* node, int st[3], int len, int height, int& offset, FILE* fout )
03272 {
03273     int i ;
03274 
03275     if ( height == 0 )
03276     {
03277         // Leaf cell, generate
03278         int emap[] = { 0, 4, 8 } ;
03279         for ( int i = 0 ; i < 3 ; i ++ )
03280         {
03281             if ( getEdgeParity( node, emap[i] ) )
03282             {
03283                 // Get intersection location
03284                 int count = getEdgeCount( node, i ) ;
03285                 float off = getEdgeOffset( node, count ) ;
03286 
03287                 float rvalue[3] ;
03288                 rvalue[0] = (float) st[0] ;
03289                 rvalue[1] = (float) st[1] ;
03290                 rvalue[2] = (float) st[2] ;
03291                 rvalue[i] += off * mindimen ;
03292 
03293                 // Update
03294                 float fnst[3] ;
03295                 float flen = len * range / dimen ; 
03296                 for ( int j = 0 ; j < 3 ; j ++ )
03297                 {
03298                     rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ;
03299                     fnst[ j ] = st[ j ] * range / dimen + origin[ j ] ;
03300                 }
03301 
03302                 if ( this->outType == 0 )
03303                 {
03304                     fprintf( fout, "%f %f %f\n", rvalue[0], rvalue[1], rvalue[2] ) ;
03305                 }
03306                 else if ( this->outType == 1 )
03307                 {
03308                     PLYWriter::writeVertex( fout, rvalue ) ;
03309                 }
03310                 
03311                 // Store the index
03312                 setEdgeIntersectionIndex( node, count, offset ) ;
03313                 offset ++ ;
03314             }
03315         }
03316 
03317     }
03318     else
03319     {
03320         // Internal cell, recur
03321         int count = 0 ;
03322         len >>= 1 ;
03323         for ( i = 0 ; i < 8 ; i ++ )
03324         {
03325             if ( hasChild( node, i ) )
03326             {
03327                 int nst[3] ;
03328                 nst[0] = st[0] + vertmap[i][0] * len ;
03329                 nst[1] = st[1] + vertmap[i][1] * len ;
03330                 nst[2] = st[2] + vertmap[i][2] * len ;
03331                 
03332                 writeVertex( getChild( node, count ), nst, len, height - 1, offset, fout ) ;
03333                 count ++ ;
03334             }
03335         }
03336     }
03337 }
03338 
03339 void Octree::writeQuad( UCHAR* node, int st[3], int len, int height, FILE* fout )
03340 {
03341     int i ;
03342     if ( height == 0 )
03343     {
03344         int mask = getSignMask( node ) ;
03345         int num = cubes->getNumTriangle( mask ) ;
03346         int indices[12] ;
03347         fillEdgeIntersectionIndices( node, st, len, indices ) ;
03348         int einds[3], ind[3] ;
03349 
03350         //int flag1 = 0 ;
03351         //int flag2 = 0 ;
03352         for ( i = 0 ; i < num ; i ++ )
03353         {
03354             int color = 0 ;
03355             cubes->getTriangle( mask, i, einds ) ;
03356             // dc_printf("(%d %d %d) ", einds[0], einds[1], einds[2] ) ;
03357             
03358             for ( int j = 0 ; j < 3 ; j ++ )
03359             {
03360                 ind[j] = indices[ einds[j] ] ;
03361                 /*
03362                 if ( ind[j] == 78381 )
03363                 {
03364                     flag1 = 1 ;
03365                 }
03366                 if ( ind[j] == 78384 )
03367                 {
03368                     flag2 = 1 ;
03369                 }
03370                 */
03371             }
03372 
03373             if ( this->outType == 0 )
03374             {
03375                 // OFF
03376                 int numpoly = ( color ? -3 : 3 ) ;
03377                 fprintf(fout, "%d %d %d %d\n", numpoly, ind[0], ind[1], ind[2] ) ;
03378                 actualQuads ++ ;
03379             }
03380             else if ( this->outType == 1 )
03381             {
03382                 // PLY
03383                 PLYWriter::writeFace( fout, 3, ind ) ;
03384                 actualQuads ++ ;
03385             }
03386         }
03387 
03388         /*
03389         if (flag1 && flag2)
03390         {
03391             dc_printf("%d\n", mask);
03392             cubes->printTriangles( mask ) ;
03393         }
03394         */
03395     }
03396     else
03397     {
03398         // Internal cell, recur
03399         int count = 0 ;
03400         len >>= 1 ;
03401         for ( i = 0 ; i < 8 ; i ++ )
03402         {
03403             if ( hasChild( node, i ) )
03404             {
03405                 int nst[3] ;
03406                 nst[0] = st[0] + vertmap[i][0] * len ;
03407                 nst[1] = st[1] + vertmap[i][1] * len ;
03408                 nst[2] = st[2] + vertmap[i][2] * len ;
03409                 
03410                 writeQuad( getChild( node, count ), nst, len, height - 1, fout ) ;
03411                 count ++ ;
03412             }
03413         }
03414     }
03415 }
03416 
03417 #endif
03418 
03419 
03420 #ifdef USE_HERMIT
03421 void Octree::countIntersection( UCHAR* node, int height, int& nedge, int& ncell, int& nface )
03422 {
03423     if ( height > 0 )
03424     {
03425         int total = getNumChildren( node ) ;
03426         for ( int i = 0 ; i < total ; i ++ )
03427         {
03428             countIntersection( getChild( node, i ), height - 1, nedge, ncell, nface ) ;
03429         }
03430     }
03431     else
03432     {
03433         nedge += getNumEdges2( node ) ;
03434 
03435         int smask = getSignMask( node ) ;
03436         
03437         if(use_manifold)
03438         {
03439             int comps = manifold_table[ smask ].comps ;
03440             ncell += comps ;
03441         }
03442         else {
03443             if ( smask > 0 && smask < 255 )
03444             {
03445                 ncell ++ ;
03446             }
03447         }
03448         
03449         for ( int i = 0 ; i < 3 ; i ++ )
03450         {
03451             if ( getFaceEdgeNum( node, i * 2 ) )
03452             {
03453                 nface ++ ;
03454             }
03455         }
03456     }
03457 }
03458 
03459 /* from http://eigen.tuxfamily.org/bz/show_bug.cgi?id=257 */
03460 template<typename _Matrix_Type_>
03461 void pseudoInverse(const _Matrix_Type_ &a,
03462                    _Matrix_Type_ &result,
03463                    double epsilon = std::numeric_limits<typename _Matrix_Type_::Scalar>::epsilon())
03464 {
03465     Eigen::JacobiSVD< _Matrix_Type_ > svd = a.jacobiSvd(Eigen::ComputeFullU |
03466                                                         Eigen::ComputeFullV);
03467 
03468     typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(),
03469                                                                   a.rows()) *
03470         svd.singularValues().array().abs().maxCoeff();
03471 
03472     result = svd.matrixV() *
03473         _Matrix_Type_((svd.singularValues().array().abs() >
03474                        tolerance).select(svd.singularValues().
03475                                          array().inverse(), 0)).asDiagonal() *
03476         svd.matrixU().adjoint();
03477 }
03478 
03479 void solve_least_squares(const float halfA[], const float b[],
03480                          const float midpoint[], float rvalue[])
03481 {
03482     /* calculate pseudo-inverse */
03483     Eigen::MatrixXf A(3, 3), pinv(3, 3);
03484     A << halfA[0], halfA[1], halfA[2],
03485          halfA[1], halfA[3], halfA[4],
03486          halfA[2], halfA[4], halfA[5];
03487     pseudoInverse(A, pinv);
03488 
03489     Eigen::Vector3f b2(b), mp(midpoint), result;
03490     b2 = b2 + A * -mp;
03491     result = pinv * b2 + mp;
03492 
03493     for(int i = 0; i < 3; i++)
03494         rvalue[i] = result(i);
03495 }
03496 
03497 void minimize(float rvalue[3], float mp[3], const float pts[12][3],
03498               const float norms[12][3], const int parity[12])
03499 {
03500     float ata[6] = { 0, 0, 0, 0, 0, 0 };
03501     float atb[3] = { 0, 0, 0 } ;
03502     int ec = 0 ;
03503     
03504     for ( int i = 0 ; i < 12 ; i ++ )
03505     {
03506         // if ( getEdgeParity( leaf, i) )
03507         if ( parity[ i ] )
03508         {
03509             const float* norm = norms[i] ;
03510             const float* p = pts[i] ;
03511 
03512             // QEF
03513             ata[ 0 ] += (float) ( norm[ 0 ] * norm[ 0 ] );
03514             ata[ 1 ] += (float) ( norm[ 0 ] * norm[ 1 ] );
03515             ata[ 2 ] += (float) ( norm[ 0 ] * norm[ 2 ] );
03516             ata[ 3 ] += (float) ( norm[ 1 ] * norm[ 1 ] );
03517             ata[ 4 ] += (float) ( norm[ 1 ] * norm[ 2 ] );
03518             ata[ 5 ] += (float) ( norm[ 2 ] * norm[ 2 ] );
03519             
03520             double pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2] ;
03521             
03522             atb[ 0 ] += (float) ( norm[ 0 ] * pn ) ;
03523             atb[ 1 ] += (float) ( norm[ 1 ] * pn ) ;
03524             atb[ 2 ] += (float) ( norm[ 2 ] * pn ) ;
03525 
03526             // Minimizer
03527             mp[0] += p[0] ;
03528             mp[1] += p[1] ;
03529             mp[2] += p[2] ;
03530             
03531             ec ++ ;
03532         }
03533     }
03534 
03535     if ( ec == 0 )
03536     {
03537         return ;
03538     }
03539     mp[0] /= ec ;
03540     mp[1] /= ec ;
03541     mp[2] /= ec ;
03542     
03543     // Solve least squares
03544     solve_least_squares(ata, atb, mp, rvalue);
03545 }
03546 
03547 void Octree::computeMinimizer( UCHAR* leaf, int st[3], int len, float rvalue[3] )
03548 {
03549     // First, gather all edge intersections
03550     float pts[12][3], norms[12][3] ;
03551     // fillEdgeIntersections( leaf, st, len, pts, norms ) ;
03552     int parity[12] ;
03553     fillEdgeIntersections( leaf, st, len, pts, norms, parity ) ;
03554 
03555     // Next, construct QEF and minimizer
03556     float mp[3] = {0, 0, 0};
03557     minimize(rvalue, mp, pts, norms, parity);
03558     
03559     /* Restraining the location of the minimizer */
03560     float nh1 = hermite_num * len ;
03561     float nh2 = ( 1 + hermite_num ) * len ;
03562     if((mode == DUALCON_MASS_POINT || mode == DUALCON_CENTROID) ||
03563         ( rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 ||
03564           rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2 ))
03565     {
03566         if(mode == DUALCON_CENTROID) {
03567             // Use centroids
03568             rvalue[0] = (float) st[0] + len / 2 ;
03569             rvalue[1] = (float) st[1] + len / 2 ;
03570             rvalue[2] = (float) st[2] + len / 2 ;
03571         }
03572         else {
03573             // Use mass point instead
03574             rvalue[0] = mp[0] ;
03575             rvalue[1] = mp[1] ;
03576             rvalue[2] = mp[2] ;
03577         }
03578     }
03579 }
03580 
03581 void Octree::generateMinimizer( UCHAR* node, int st[3], int len, int height, int& offset )
03582 {
03583     int i, j ;
03584 
03585     if ( height == 0 )
03586     {
03587         // Leaf cell, generate
03588 
03589         // First, find minimizer
03590         float rvalue[3] ;
03591         rvalue[0] = (float) st[0] + len / 2 ;
03592         rvalue[1] = (float) st[1] + len / 2 ;
03593         rvalue[2] = (float) st[2] + len / 2 ;
03594         computeMinimizer( node, st, len, rvalue ) ;
03595 
03596         // Update
03597         //float fnst[3] ;
03598         for ( j = 0 ; j < 3 ; j ++ )
03599         {
03600             rvalue[ j ] = rvalue[ j ] * range / dimen + origin[ j ] ;
03601             //fnst[ j ] = st[ j ] * range / dimen + origin[ j ] ;
03602         }
03603 
03604         int mult = 0, smask = getSignMask( node ) ;
03605         
03606         if(use_manifold)
03607         {
03608             mult = manifold_table[ smask ].comps ;
03609         }
03610         else
03611         {
03612             if ( smask > 0 && smask < 255 )
03613             {
03614                 mult = 1 ;
03615             }
03616         }
03617 
03618         for ( j = 0 ; j < mult ; j ++ )
03619         {
03620             add_vert(output_mesh, rvalue);
03621         }
03622         
03623         // Store the index
03624         setMinimizerIndex( node, offset ) ;
03625 
03626         offset += mult ;
03627     }
03628     else
03629     {
03630         // Internal cell, recur
03631         int count = 0 ;
03632         len >>= 1 ;
03633         for ( i = 0 ; i < 8 ; i ++ )
03634         {
03635             if ( hasChild( node, i ) )
03636             {
03637                 int nst[3] ;
03638                 nst[0] = st[0] + vertmap[i][0] * len ;
03639                 nst[1] = st[1] + vertmap[i][1] * len ;
03640                 nst[2] = st[2] + vertmap[i][2] * len ;
03641                 
03642                 generateMinimizer( getChild( node, count ), nst, len, height - 1, offset ) ;
03643                 count ++ ;
03644             }
03645         }
03646     }
03647 }
03648 
03649 void Octree::processEdgeWrite( UCHAR* node[4], int depth[4], int maxdep, int dir )
03650 {
03651     //int color = 0 ;
03652 
03653     int i = 3 ;
03654     {
03655         if ( getEdgeParity( node[i], processEdgeMask[dir][i] ) )
03656         {
03657             int flip = 0 ;
03658             int edgeind = processEdgeMask[dir][i] ;
03659             if ( getSign( node[i], edgemap[ edgeind ][ 1 ] ) > 0 )
03660             {
03661                 flip = 1 ;
03662             }
03663             
03664             int num = 0 ;
03665             {
03666                 int ind[8];
03667                 if(use_manifold)
03668                 {
03669                     /* Deprecated
03670                        int ind[4] = {
03671                        getMinimizerIndex( node[0], processEdgeMask[dir][0] ),
03672                        getMinimizerIndex( node[1], processEdgeMask[dir][1] ),
03673                        getMinimizerIndex( node[3], processEdgeMask[dir][3] ),
03674                        getMinimizerIndex( node[2], processEdgeMask[dir][2] )
03675                        } ;
03676                        num = 4 ;
03677                     */
03678                     int vind[2] ;
03679                     int seq[4] = {0,1,3,2};
03680                     for ( int k = 0 ; k < 4 ; k ++ )
03681                     {
03682                         getMinimizerIndices( node[seq[k]], processEdgeMask[dir][seq[k]], vind ) ;
03683                         ind[num] = vind[0] ; 
03684                         num ++ ;
03685                     
03686                         if ( vind[1] != -1 )
03687                         {
03688                             ind[num] = vind[1] ; 
03689                             num ++ ;
03690                             if ( flip == 0 )
03691                             {
03692                                 ind[num-1] = vind[0] ;
03693                                 ind[num-2] = vind[1] ;
03694                             }
03695                         }
03696                     }
03697 #ifdef TESTMANIFOLD                     
03698                     if ( num != 4 )
03699                     {
03700                         dc_printf("Polygon: %d\n", num);
03701                     }
03702                     for ( k = 0 ; k < num ; k ++ )
03703                     {
03704                         fprintf(testfout, "{%d,%d},", ind[k], ind[(k+1)%num] );
03705                     }
03706 #endif
03707 
03708                     /* we don't use the manifold option, but if it is
03709                        ever enabled again note that it can output
03710                        non-quads */
03711                 }
03712                 else {
03713                     if(flip) {
03714                         ind[0] = getMinimizerIndex( node[2] );
03715                         ind[1] = getMinimizerIndex( node[3] );
03716                         ind[2] = getMinimizerIndex( node[1] );
03717                         ind[3] = getMinimizerIndex( node[0] );
03718                     }
03719                     else {
03720                         ind[0] = getMinimizerIndex( node[0] );
03721                         ind[1] = getMinimizerIndex( node[1] );
03722                         ind[2] = getMinimizerIndex( node[3] );
03723                         ind[3] = getMinimizerIndex( node[2] );
03724                     }
03725                     
03726                     add_quad(output_mesh, ind);
03727                 }
03728                 /*
03729                 if ( this->outType == 0 )
03730                 {
03731                     // OFF
03732 
03733                     num = ( color ? -num : num ) ;
03734 
03735                     fprintf(fout, "%d ", num);
03736 
03737                     if ( flip )
03738                     {
03739                         for ( int k = num - 1 ; k >= 0 ; k -- )
03740                         {
03741                             fprintf(fout, "%d ", ind[k] ) ;
03742                         }
03743                     }
03744                     else
03745                     {
03746                         for ( int k = 0 ; k < num ; k ++ )
03747                         {
03748                             fprintf(fout, "%d ", ind[k] ) ;
03749                         }
03750                     }
03751 
03752                     fprintf( fout, "\n") ;
03753 
03754                     actualQuads ++ ;
03755                 }
03756                 else if ( this->outType == 1 )
03757                 {
03758                     // PLY
03759 
03760                     if ( flip )
03761                     {
03762                         int tind[8];
03763                         for ( int k = num - 1 ; k >= 0 ; k -- )
03764                         {
03765                             tind[k] = ind[num-1-k] ;
03766                         }
03767                         // PLYWriter::writeFace( fout, num, tind ) ;
03768                     }
03769                     else
03770                     {
03771                             // PLYWriter::writeFace( fout, num, ind ) ;
03772                     }
03773 
03774                     actualQuads ++ ;
03775                     }*/
03776             }
03777             return ;
03778         }
03779         else
03780         {
03781             return ;
03782         }
03783     }
03784 }
03785 
03786 
03787 void Octree::edgeProcContour( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir )
03788 {
03789     if ( ! ( node[0] && node[1] && node[2] && node[3] ) )
03790     {
03791         return ;
03792     }
03793     if ( leaf[0] && leaf[1] && leaf[2] && leaf[3] )
03794     {
03795         processEdgeWrite( node, depth, maxdep, dir ) ;
03796     }
03797     else
03798     {
03799         int i, j ;
03800         UCHAR* chd[ 4 ][ 8 ] ;
03801         for ( j = 0 ; j < 4 ; j ++ )
03802         {
03803             for ( i = 0 ; i < 8 ; i ++ )
03804             {
03805                 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i ) )? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
03806             }
03807         }
03808 
03809         // 2 edge calls
03810         UCHAR* ne[4] ;
03811         int le[4] ;
03812         int de[4] ;
03813         for ( i = 0 ; i < 2 ; i ++ )
03814         {
03815             int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 
03816                            edgeProcEdgeMask[ dir ][ i ][ 1 ], 
03817                            edgeProcEdgeMask[ dir ][ i ][ 2 ], 
03818                            edgeProcEdgeMask[ dir ][ i ][ 3 ] } ;
03819 
03820             for ( int j = 0 ; j < 4 ; j ++ )
03821             {
03822                 if ( leaf[j] )
03823                 {
03824                     le[j] = leaf[j] ;
03825                     ne[j] = node[j] ;
03826                     de[j] = depth[j] ;
03827                 }
03828                 else
03829                 {
03830                     le[j] = isLeaf( node[j], c[j] ) ;
03831                     ne[j] = chd[ j ][ c[j] ] ;
03832                     de[j] = depth[j] - 1 ;
03833                 }
03834             }
03835 
03836             edgeProcContour( ne, le, de, maxdep - 1, edgeProcEdgeMask[ dir ][ i ][ 4 ] ) ;
03837         }
03838 
03839     }
03840 }
03841 
03842 void Octree::faceProcContour( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir )
03843 {
03844     if ( ! ( node[0] && node[1] ) )
03845     {
03846         return ;
03847     }
03848 
03849     if ( ! ( leaf[0] && leaf[1] ) )
03850     {
03851         int i, j ;
03852         // Fill children nodes
03853         UCHAR* chd[ 2 ][ 8 ] ;
03854         for ( j = 0 ; j < 2 ; j ++ )
03855         {
03856             for ( i = 0 ; i < 8 ; i ++ )
03857             {
03858                 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i )) ? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
03859             }
03860         }
03861 
03862         // 4 face calls
03863         UCHAR* nf[2] ;
03864         int df[2] ;
03865         int lf[2] ;
03866         for ( i = 0 ; i < 4 ; i ++ )
03867         {
03868             int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] };
03869             for ( int j = 0 ; j < 2 ; j ++ )
03870             {
03871                 if ( leaf[j] )
03872                 {
03873                     lf[j] = leaf[j] ;
03874                     nf[j] = node[j] ;
03875                     df[j] = depth[j] ;
03876                 }
03877                 else
03878                 {
03879                     lf[j] = isLeaf( node[j], c[j] ) ;
03880                     nf[j] = chd[ j ][ c[j] ] ;
03881                     df[j] = depth[j] - 1 ;
03882                 }
03883             }
03884             faceProcContour( nf, lf, df, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ] ) ;
03885         }
03886 
03887         // 4 edge calls
03888         int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ;
03889         UCHAR* ne[4] ;
03890         int le[4] ;
03891         int de[4] ;
03892             
03893         for ( i = 0 ; i < 4 ; i ++ )
03894         {
03895             int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ],
03896                          faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] };
03897             int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ;
03898 
03899             for ( int j = 0 ; j < 4 ; j ++ )
03900             {
03901                 if ( leaf[order[j]] )
03902                 {
03903                     le[j] = leaf[order[j]] ;
03904                     ne[j] = node[order[j]] ;
03905                     de[j] = depth[order[j]] ;
03906                 }
03907                 else
03908                 {
03909                     le[j] = isLeaf( node[order[j]], c[j] ) ;
03910                     ne[j] = chd[ order[ j ] ][ c[j] ] ;
03911                     de[j] = depth[order[j]] - 1 ;
03912                 }
03913             }
03914 
03915             edgeProcContour( ne, le, de, maxdep - 1, faceProcEdgeMask[ dir ][ i ][ 5 ] ) ;
03916         }
03917     }
03918 }
03919 
03920 
03921 void Octree::cellProcContour( UCHAR* node, int leaf, int depth )
03922 {
03923     if ( node == NULL )
03924     {
03925         return ;
03926     }
03927 
03928     if ( ! leaf )
03929     {
03930         int i ;
03931 
03932         // Fill children nodes
03933         UCHAR* chd[ 8 ] ;
03934         for ( i = 0 ; i < 8 ; i ++ )
03935         {
03936             chd[ i ] = ((!leaf) && hasChild( node, i )) ? getChild( node, getChildCount( node, i ) ) : NULL ;
03937         }
03938 
03939         // 8 Cell calls
03940         for ( i = 0 ; i < 8 ; i ++ )
03941         {
03942             cellProcContour( chd[ i ], isLeaf( node, i ), depth - 1 ) ;
03943         }
03944 
03945         // 12 face calls
03946         UCHAR* nf[2] ;
03947         int lf[2] ;
03948         int df[2] = { depth - 1, depth - 1 } ;
03949         for ( i = 0 ; i < 12 ; i ++ )
03950         {
03951             int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] };
03952 
03953             lf[0] = isLeaf( node, c[0] ) ;
03954             lf[1] = isLeaf( node, c[1] ) ;
03955 
03956             nf[0] = chd[ c[0] ] ;
03957             nf[1] = chd[ c[1] ] ;
03958 
03959             faceProcContour( nf, lf, df, depth - 1, cellProcFaceMask[ i ][ 2 ] ) ;
03960         }
03961 
03962         // 6 edge calls
03963         UCHAR* ne[4] ;
03964         int le[4] ;
03965         int de[4] = { depth - 1, depth - 1, depth - 1, depth - 1 } ;
03966         for ( i = 0 ; i < 6 ; i ++ )
03967         {
03968             int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] };
03969 
03970             for ( int j = 0 ; j < 4 ; j ++ )
03971             {
03972                 le[j] = isLeaf( node, c[j] ) ;
03973                 ne[j] = chd[ c[j] ] ;
03974             }
03975 
03976             edgeProcContour( ne, le, de, depth - 1, cellProcEdgeMask[ i ][ 4 ] ) ;
03977         }
03978     }
03979     
03980 }
03981 
03982 #endif
03983 
03984 
03985 
03986 void Octree::processEdgeParity( UCHAR* node[4], int depth[4], int maxdep, int dir )
03987 {
03988     int con = 0 ;
03989     for ( int i = 0 ; i < 4 ; i ++ )
03990     {
03991         // Minimal cell
03992         // if ( op == 0 )
03993         {
03994             if ( getEdgeParity( node[i], processEdgeMask[dir][i] ) )
03995             {
03996                 con = 1 ;
03997                 break ;
03998             }
03999         }
04000     }
04001 
04002     if ( con == 1 )
04003     {
04004         for ( int i = 0 ; i < 4 ; i ++ )
04005         {
04006             setEdge( node[ i ], processEdgeMask[dir][i] ) ;
04007         }
04008     }
04009     
04010 }
04011 
04012 void Octree::edgeProcParity( UCHAR* node[4], int leaf[4], int depth[4], int maxdep, int dir )
04013 {
04014     if ( ! ( node[0] && node[1] && node[2] && node[3] ) )
04015     {
04016         return ;
04017     }
04018     if ( leaf[0] && leaf[1] && leaf[2] && leaf[3] )
04019     {
04020         processEdgeParity( node, depth, maxdep, dir ) ;
04021     }
04022     else
04023     {
04024         int i, j ;
04025         UCHAR* chd[ 4 ][ 8 ] ;
04026         for ( j = 0 ; j < 4 ; j ++ )
04027         {
04028             for ( i = 0 ; i < 8 ; i ++ )
04029             {
04030                 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i ) )? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
04031             }
04032         }
04033 
04034         // 2 edge calls
04035         UCHAR* ne[4] ;
04036         int le[4] ;
04037         int de[4] ;
04038         for ( i = 0 ; i < 2 ; i ++ )
04039         {
04040             int c[ 4 ] = { edgeProcEdgeMask[ dir ][ i ][ 0 ], 
04041                            edgeProcEdgeMask[ dir ][ i ][ 1 ], 
04042                            edgeProcEdgeMask[ dir ][ i ][ 2 ], 
04043                            edgeProcEdgeMask[ dir ][ i ][ 3 ] } ;
04044 
04045             // int allleaf = 1 ;
04046             for ( int j = 0 ; j < 4 ; j ++ )
04047             {
04048 
04049                 if ( leaf[j] )
04050                 {
04051                     le[j] = leaf[j] ;
04052                     ne[j] = node[j] ;
04053                     de[j] = depth[j] ;
04054                 }
04055                 else
04056                 {
04057                     le[j] = isLeaf( node[j], c[j] ) ;
04058                     ne[j] = chd[ j ][ c[j] ] ;
04059                     de[j] = depth[j] - 1 ;
04060 
04061                 }
04062 
04063             }
04064 
04065             edgeProcParity( ne, le, de, maxdep - 1, edgeProcEdgeMask[ dir ][ i ][ 4 ] ) ;
04066         }
04067 
04068     }
04069 }
04070 
04071 void Octree::faceProcParity( UCHAR* node[2], int leaf[2], int depth[2], int maxdep, int dir )
04072 {
04073     if ( ! ( node[0] && node[1] ) )
04074     {
04075         return ;
04076     }
04077 
04078     if ( ! ( leaf[0] && leaf[1] ) )
04079     {
04080         int i, j ;
04081         // Fill children nodes
04082         UCHAR* chd[ 2 ][ 8 ] ;
04083         for ( j = 0 ; j < 2 ; j ++ )
04084         {
04085             for ( i = 0 ; i < 8 ; i ++ )
04086             {
04087                 chd[ j ][ i ] = ((!leaf[j]) && hasChild( node[j], i )) ? getChild( node[j], getChildCount( node[j], i ) ) : NULL ;
04088             }
04089         }
04090 
04091         // 4 face calls
04092         UCHAR* nf[2] ;
04093         int df[2] ;
04094         int lf[2] ;
04095         for ( i = 0 ; i < 4 ; i ++ )
04096         {
04097             int c[2] = { faceProcFaceMask[ dir ][ i ][ 0 ], faceProcFaceMask[ dir ][ i ][ 1 ] };
04098             for ( int j = 0 ; j < 2 ; j ++ )
04099             {
04100                 if ( leaf[j] )
04101                 {
04102                     lf[j] = leaf[j] ;
04103                     nf[j] = node[j] ;
04104                     df[j] = depth[j] ;
04105                 }
04106                 else
04107                 {
04108                     lf[j] = isLeaf( node[j], c[j] ) ;
04109                     nf[j] = chd[ j ][ c[j] ] ;
04110                     df[j] = depth[j] - 1 ;
04111                 }
04112             }
04113             faceProcParity( nf, lf, df, maxdep - 1, faceProcFaceMask[ dir ][ i ][ 2 ] ) ;
04114         }
04115 
04116         // 4 edge calls
04117         int orders[2][4] = {{ 0, 0, 1, 1 }, { 0, 1, 0, 1 }} ;
04118         UCHAR* ne[4] ;
04119         int le[4] ;
04120         int de[4] ;
04121             
04122         for ( i = 0 ; i < 4 ; i ++ )
04123         {
04124             int c[4] = { faceProcEdgeMask[ dir ][ i ][ 1 ], faceProcEdgeMask[ dir ][ i ][ 2 ],
04125                          faceProcEdgeMask[ dir ][ i ][ 3 ], faceProcEdgeMask[ dir ][ i ][ 4 ] };
04126             int* order = orders[ faceProcEdgeMask[ dir ][ i ][ 0 ] ] ;
04127 
04128             for ( int j = 0 ; j < 4 ; j ++ )
04129             {
04130                 if ( leaf[order[j]] )
04131                 {
04132                     le[j] = leaf[order[j]] ;
04133                     ne[j] = node[order[j]] ;
04134                     de[j] = depth[order[j]] ;
04135                 }
04136                 else
04137                 {
04138                     le[j] = isLeaf( node[order[j]], c[j] ) ;
04139                     ne[j] = chd[ order[ j ] ][ c[j] ] ;
04140                     de[j] = depth[order[j]] - 1 ;
04141                 }
04142             }
04143 
04144             edgeProcParity( ne, le, de, maxdep - 1, faceProcEdgeMask[ dir ][ i ][ 5 ] ) ;
04145         }
04146     }
04147 }
04148 
04149 
04150 void Octree::cellProcParity( UCHAR* node, int leaf, int depth )
04151 {
04152     if ( node == NULL )
04153     {
04154         return ;
04155     }
04156 
04157     if ( ! leaf )
04158     {
04159         int i ;
04160 
04161         // Fill children nodes
04162         UCHAR* chd[ 8 ] ;
04163         for ( i = 0 ; i < 8 ; i ++ )
04164         {
04165             chd[ i ] = ((!leaf) && hasChild( node, i )) ? getChild( node, getChildCount( node, i ) ) : NULL ;
04166         }
04167 
04168         // 8 Cell calls
04169         for ( i = 0 ; i < 8 ; i ++ )
04170         {
04171             cellProcParity( chd[ i ], isLeaf( node, i ), depth - 1 ) ;
04172         }
04173 
04174         // 12 face calls
04175         UCHAR* nf[2] ;
04176         int lf[2] ;
04177         int df[2] = { depth - 1, depth - 1 } ;
04178         for ( i = 0 ; i < 12 ; i ++ )
04179         {
04180             int c[ 2 ] = { cellProcFaceMask[ i ][ 0 ], cellProcFaceMask[ i ][ 1 ] };
04181 
04182             lf[0] = isLeaf( node, c[0] ) ;
04183             lf[1] = isLeaf( node, c[1] ) ;
04184 
04185             nf[0] = chd[ c[0] ] ;
04186             nf[1] = chd[ c[1] ] ;
04187 
04188             faceProcParity( nf, lf, df, depth - 1, cellProcFaceMask[ i ][ 2 ] ) ;
04189         }
04190 
04191         // 6 edge calls
04192         UCHAR* ne[4] ;
04193         int le[4] ;
04194         int de[4] = { depth - 1, depth - 1, depth - 1, depth - 1 } ;
04195         for ( i = 0 ; i < 6 ; i ++ )
04196         {
04197             int c[ 4 ] = { cellProcEdgeMask[ i ][ 0 ], cellProcEdgeMask[ i ][ 1 ], cellProcEdgeMask[ i ][ 2 ], cellProcEdgeMask[ i ][ 3 ] };
04198 
04199             for ( int j = 0 ; j < 4 ; j ++ )
04200             {
04201                 le[j] = isLeaf( node, c[j] ) ;
04202                 ne[j] = chd[ c[j] ] ;
04203             }
04204 
04205             edgeProcParity( ne, le, de, depth - 1, cellProcEdgeMask[ i ][ 4 ] ) ;
04206         }
04207     }
04208     
04209 }
04210 
04211 /* definitions for global arrays */
04212 const int edgemask[3] = {5, 3, 6};
04213 
04214 const int faceMap[6][4] = {
04215     {4, 8, 5, 9},
04216     {6, 10, 7, 11},
04217     {0, 8, 1, 10},
04218     {2, 9, 3, 11},
04219     {0, 4, 2, 6},
04220     {1, 5, 3, 7}
04221 };
04222 
04223 const int cellProcFaceMask[12][3] = {
04224     {0, 4, 0},
04225     {1, 5, 0},
04226     {2, 6, 0},
04227     {3, 7, 0},
04228     {0, 2, 1},
04229     {4, 6, 1},
04230     {1, 3, 1},
04231     {5, 7, 1},
04232     {0, 1, 2},
04233     {2, 3, 2},
04234     {4, 5, 2},
04235     {6, 7, 2}
04236 };
04237 
04238 const int cellProcEdgeMask[6][5] = {
04239     {0, 1, 2, 3, 0},
04240     {4, 5, 6, 7, 0},
04241     {0, 4, 1, 5, 1},
04242     {2, 6, 3, 7, 1},
04243     {0, 2, 4, 6, 2},
04244     {1, 3, 5, 7, 2}
04245 };
04246 
04247 const int faceProcFaceMask[3][4][3] = {
04248     {{4, 0, 0},
04249      {5, 1, 0},
04250      {6, 2, 0},
04251      {7, 3, 0}},
04252     {{2, 0, 1},
04253      {6, 4, 1},
04254      {3, 1, 1},
04255      {7, 5, 1}},
04256     {{1, 0, 2},
04257      {3, 2, 2},
04258      {5, 4, 2},
04259      {7, 6, 2}}
04260 };
04261 
04262 const int faceProcEdgeMask[3][4][6] = {
04263     {{1, 4, 0, 5, 1, 1},
04264      {1, 6, 2, 7, 3, 1},
04265      {0, 4, 6, 0, 2, 2},
04266      {0, 5, 7, 1, 3, 2}},
04267     {{0, 2, 3, 0, 1, 0},
04268      {0, 6, 7, 4, 5, 0},
04269      {1, 2, 0, 6, 4, 2},
04270      {1, 3, 1, 7, 5, 2}},
04271     {{1, 1, 0, 3, 2, 0},
04272      {1, 5, 4, 7, 6, 0},
04273      {0, 1, 5, 0, 4, 1},
04274      {0, 3, 7, 2, 6, 1}}
04275 };
04276 
04277 const int edgeProcEdgeMask[3][2][5] = {
04278     {{3, 2, 1, 0, 0},
04279      {7, 6, 5, 4, 0}},
04280     {{5, 1, 4, 0, 1},
04281      {7, 3, 6, 2, 1}},
04282     {{6, 4, 2, 0, 2},
04283      {7, 5, 3, 1, 2}},
04284 };
04285 
04286 const int processEdgeMask[3][4] = {
04287     {3, 2, 1, 0},
04288     {7, 5, 6, 4},
04289     {11, 10, 9, 8}
04290 };
04291 
04292 const int dirCell[3][4][3] = {
04293     {{0, -1, -1},
04294      {0, -1, 0},
04295      {0, 0, -1},
04296      {0, 0, 0}},
04297     {{-1, 0, -1},
04298      {-1, 0, 0},
04299      {0, 0, -1},
04300      {0, 0, 0}},
04301     {{-1, -1, 0},
04302      {-1, 0, 0},
04303      {0, -1, 0},
04304      {0, 0, 0}}
04305 };
04306 
04307 const int dirEdge[3][4] = {
04308     {3, 2, 1, 0},
04309     {7, 6, 5, 4},
04310     {11, 10, 9, 8}
04311 };