00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <math.h>
00029 #include <pcl/surface/3rdparty/poisson4/marching_cubes_poisson.h>
00030
00032
00034
00035 namespace pcl
00036 {
00037 namespace poisson
00038 {
00039
00040 int Square::AntipodalCornerIndex(int idx){
00041 int x,y;
00042 FactorCornerIndex(idx,x,y);
00043 return CornerIndex( (x+1)%2 , (y+1)%2 );
00044 }
00045 int Square::CornerIndex(int x,int y){return (y<<1)|x;}
00046 void Square::FactorCornerIndex(int idx,int& x,int& y){
00047 x=(idx>>0)%2;
00048 y=(idx>>1)%2;
00049 }
00050 int Square::EdgeIndex(int orientation,int i){
00051 switch(orientation){
00052 case 0:
00053 if(!i) {return 0;}
00054 else {return 2;}
00055 case 1:
00056 if(!i) {return 3;}
00057 else {return 1;}
00058 };
00059 return -1;
00060 }
00061 void Square::FactorEdgeIndex(int idx,int& orientation,int& i){
00062 switch(idx){
00063 case 0: case 2:
00064 orientation=0;
00065 i=idx/2;
00066 return;
00067 case 1: case 3:
00068 orientation=1;
00069 i=((idx/2)+1)%2;
00070 return;
00071 };
00072 }
00073 void Square::EdgeCorners(int idx,int& c1,int& c2){
00074 int orientation,i;
00075 FactorEdgeIndex(idx,orientation,i);
00076 switch(orientation){
00077 case 0:
00078 c1=CornerIndex(0,i);
00079 c2=CornerIndex(1,i);
00080 break;
00081 case 1:
00082 c1=CornerIndex(i,0);
00083 c2=CornerIndex(i,1);
00084 break;
00085 };
00086 }
00087 int Square::ReflectEdgeIndex(int idx,int edgeIndex){
00088 int orientation=edgeIndex%2;
00089 int o,i;
00090 FactorEdgeIndex(idx,o,i);
00091 if(o!=orientation){return idx;}
00092 else{return EdgeIndex(o,(i+1)%2);}
00093 }
00094 int Square::ReflectCornerIndex(int idx,int edgeIndex){
00095 int orientation=edgeIndex%2;
00096 int x,y;
00097 FactorCornerIndex(idx,x,y);
00098 switch(orientation){
00099 case 0: return CornerIndex((x+1)%2,y);
00100 case 1: return CornerIndex(x,(y+1)%2);
00101 };
00102 return -1;
00103 }
00104
00105
00106
00108
00110 int Cube::CornerIndex(int x,int y,int z){return (z<<2)|(y<<1)|x;}
00111 void Cube::FactorCornerIndex(int idx,int& x,int& y,int& z){
00112 x=(idx>>0)%2;
00113 y=(idx>>1)%2;
00114 z=(idx>>2)%2;
00115 }
00116 int Cube::EdgeIndex(int orientation,int i,int j){return (i | (j<<1))|(orientation<<2);}
00117 void Cube::FactorEdgeIndex( int idx , int& orientation , int& i , int &j )
00118 {
00119 orientation=idx>>2;
00120 i = (idx&1);
00121 j = (idx&2)>>1;
00122 }
00123 int Cube::FaceIndex(int x,int y,int z){
00124 if (x<0) {return 0;}
00125 else if (x>0) {return 1;}
00126 else if (y<0) {return 2;}
00127 else if (y>0) {return 3;}
00128 else if (z<0) {return 4;}
00129 else if (z>0) {return 5;}
00130 else {return -1;}
00131 }
00132 int Cube::FaceIndex(int dir,int offSet){return (dir<<1)|offSet;}
00133
00134 void Cube::FactorFaceIndex(int idx,int& x,int& y,int& z){
00135 x=y=z=0;
00136 switch(idx){
00137 case 0: x=-1; break;
00138 case 1: x= 1; break;
00139 case 2: y=-1; break;
00140 case 3: y= 1; break;
00141 case 4: z=-1; break;
00142 case 5: z= 1; break;
00143 };
00144 }
00145 void Cube::FactorFaceIndex(int idx,int& dir,int& offSet){
00146 dir = idx>>1;
00147 offSet=idx &1;
00148 }
00149
00150 int Cube::FaceAdjacentToEdges(int eIndex1,int eIndex2){
00151 int f1,f2,g1,g2;
00152 FacesAdjacentToEdge(eIndex1,f1,f2);
00153 FacesAdjacentToEdge(eIndex2,g1,g2);
00154 if(f1==g1 || f1==g2){return f1;}
00155 if(f2==g1 || f2==g2){return f2;}
00156 return -1;
00157 }
00158
00159 void Cube::FacesAdjacentToEdge(int eIndex,int& f1Index,int& f2Index){
00160 int orientation,i1,i2;
00161 FactorEdgeIndex(eIndex,orientation,i1,i2);
00162 i1<<=1;
00163 i2<<=1;
00164 i1--;
00165 i2--;
00166 switch(orientation){
00167 case 0:
00168 f1Index=FaceIndex( 0,i1, 0);
00169 f2Index=FaceIndex( 0, 0,i2);
00170 break;
00171 case 1:
00172 f1Index=FaceIndex(i1, 0, 0);
00173 f2Index=FaceIndex( 0, 0,i2);
00174 break;
00175 case 2:
00176 f1Index=FaceIndex(i1, 0, 0);
00177 f2Index=FaceIndex( 0,i2, 0);
00178 break;
00179 };
00180 }
00181 void Cube::EdgeCorners(int idx,int& c1,int& c2){
00182 int orientation,i1,i2;
00183 FactorEdgeIndex(idx,orientation,i1,i2);
00184 switch(orientation){
00185 case 0:
00186 c1=CornerIndex(0,i1,i2);
00187 c2=CornerIndex(1,i1,i2);
00188 break;
00189 case 1:
00190 c1=CornerIndex(i1,0,i2);
00191 c2=CornerIndex(i1,1,i2);
00192 break;
00193 case 2:
00194 c1=CornerIndex(i1,i2,0);
00195 c2=CornerIndex(i1,i2,1);
00196 break;
00197 };
00198 }
00199 void Cube::FaceCorners(int idx,int& c1,int& c2,int& c3,int& c4){
00200 int i=idx%2;
00201 switch(idx/2){
00202 case 0:
00203 c1=CornerIndex(i,0,0);
00204 c2=CornerIndex(i,1,0);
00205 c3=CornerIndex(i,0,1);
00206 c4=CornerIndex(i,1,1);
00207 return;
00208 case 1:
00209 c1=CornerIndex(0,i,0);
00210 c2=CornerIndex(1,i,0);
00211 c3=CornerIndex(0,i,1);
00212 c4=CornerIndex(1,i,1);
00213 return;
00214 case 2:
00215 c1=CornerIndex(0,0,i);
00216 c2=CornerIndex(1,0,i);
00217 c3=CornerIndex(0,1,i);
00218 c4=CornerIndex(1,1,i);
00219 return;
00220 }
00221 }
00222 int Cube::AntipodalCornerIndex(int idx){
00223 int x,y,z;
00224 FactorCornerIndex(idx,x,y,z);
00225 return CornerIndex((x+1)%2,(y+1)%2,(z+1)%2);
00226 }
00227 int Cube::FaceReflectFaceIndex(int idx,int faceIndex){
00228 if(idx/2!=faceIndex/2){return idx;}
00229 else{
00230 if(idx%2) {return idx-1;}
00231 else {return idx+1;}
00232 }
00233 }
00234 int Cube::FaceReflectEdgeIndex(int idx,int faceIndex){
00235 int orientation=faceIndex/2;
00236 int o,i,j;
00237 FactorEdgeIndex(idx,o,i,j);
00238 if(o==orientation){return idx;}
00239 switch(orientation){
00240 case 0: return EdgeIndex(o,(i+1)%2,j);
00241 case 1:
00242 switch(o){
00243 case 0: return EdgeIndex(o,(i+1)%2,j);
00244 case 2: return EdgeIndex(o,i,(j+1)%2);
00245 };
00246 case 2: return EdgeIndex(o,i,(j+1)%2);
00247 };
00248 return -1;
00249 }
00250 int Cube::FaceReflectCornerIndex(int idx,int faceIndex){
00251 int orientation=faceIndex/2;
00252 int x,y,z;
00253 FactorCornerIndex(idx,x,y,z);
00254 switch(orientation){
00255 case 0: return CornerIndex((x+1)%2,y,z);
00256 case 1: return CornerIndex(x,(y+1)%2,z);
00257 case 2: return CornerIndex(x,y,(z+1)%2);
00258 };
00259 return -1;
00260 }
00261 int Cube::EdgeReflectCornerIndex(int idx,int edgeIndex){
00262 int orientation,x,y,z;
00263 FactorEdgeIndex(edgeIndex,orientation,x,y);
00264 FactorCornerIndex(idx,x,y,z);
00265 switch(orientation){
00266 case 0: return CornerIndex( x ,(y+1)%2,(z+1)%2);
00267 case 1: return CornerIndex((x+1)%2, y ,(z+1)%2);
00268 case 2: return CornerIndex((x+1)%2,(y+1)%2, z );
00269 };
00270 return -1;
00271 }
00272 int Cube::EdgeReflectEdgeIndex(int edgeIndex){
00273 int o,i1,i2;
00274 FactorEdgeIndex(edgeIndex,o,i1,i2);
00275 return Cube::EdgeIndex(o,(i1+1)%2,(i2+1)%2);
00276 }
00277
00278
00280
00282
00283
00284
00285
00286
00287
00288 const int* MarchingSquares::edgeMask()
00289 {
00290 const static int edgeMask_local[1<<Square::CORNERS]=
00291 {
00292 0,
00293 9,
00294 3,
00295 10,
00296 12,
00297 5,
00298 15,
00299 6,
00300 6,
00301 15,
00302 5,
00303 12,
00304 10,
00305 3,
00306 9,
00307 0,
00308 };
00309 return edgeMask_local;
00310 }
00311
00312 int MarchingSquares::edges(int i, int j)
00313 {
00314 const static int edges_local[1<<Square::CORNERS][MAX_EDGES*2+1] =
00315 {
00316 { -1, -1, -1, -1, -1},
00317 { 3, 0, -1, -1, -1},
00318 { 0, 1, -1, -1, -1},
00319 { 3, 1, -1, -1, -1},
00320 { 2, 3, -1, -1, -1},
00321 { 2, 0, -1, -1, -1},
00322 { 0, 1, 2, 3, -1},
00323 { 1, 2, -1, -1, -1},
00324 { 2, 1, -1, -1, -1},
00325 { 3, 0, 1, 2, -1},
00326 { 0, 2, -1, -1, -1},
00327 { 3, 2, -1, -1, -1},
00328 { 1, 3, -1, -1, -1},
00329 { 1, 0, -1, -1, -1},
00330 { 0, 3, -1, -1, -1},
00331 { -1, -1, -1, -1, -1},
00332 };
00333 return edges_local[i][j];
00334 }
00335
00336 double& MarchingSquares::vertexList(int i, int j)
00337 {
00338 static double vertexList_local[Square::EDGES][2];
00339 return vertexList_local[i][j];
00340 }
00341
00342
00343 int MarchingSquares::GetIndex(const double v[Square::CORNERS],double iso){
00344 int idx=0;
00345 for(int i=0;i<Square::CORNERS;i++){if(v[i]<iso){idx|=(1<<i);}}
00346 return idx;
00347 }
00348
00349 int MarchingSquares::IsAmbiguous(const double v[Square::CORNERS],double isoValue){
00350 int idx=GetIndex(v,isoValue);
00351 return (idx==5) || (idx==10);
00352 }
00353 int MarchingSquares::AddEdges(const double v[Square::CORNERS],double iso,Edge* isoEdges){
00354 int idx,nEdges=0;
00355 Edge e;
00356
00357 idx=GetIndex(v,iso);
00358
00359
00360 if (!edgeMask()[idx]) return 0;
00361
00362
00363 int i,j,ii=1;
00364 for(i=0;i<12;i++){
00365 if(edgeMask()[idx] & ii){SetVertex(i,v,iso);}
00366 ii<<=1;
00367 }
00368
00369 for (i=0;edges(idx, i)!=-1;i+=2) {
00370 for(j=0;j<2;j++){
00371 e.p[0][j]=vertexList(edges(idx, i+0), j);
00372 e.p[1][j]=vertexList(edges(idx, i+1), j);
00373 }
00374 isoEdges[nEdges++]=e;
00375 }
00376 return nEdges;
00377 }
00378
00379 int MarchingSquares::AddEdgeIndices(const double v[Square::CORNERS],double iso,int* isoIndices){
00380 int idx,nEdges=0;
00381
00382 idx=GetIndex(v,iso);
00383
00384
00385 if (!edgeMask()[idx]) return 0;
00386
00387
00388 for(int i=0;edges(idx, i)!=-1;i+=2){
00389 for(int j=0;j<2;j++){isoIndices[i+j]=edges(idx, i+j);}
00390 nEdges++;
00391 }
00392 return nEdges;
00393 }
00394 void MarchingSquares::SetVertex(int e,const double values[Square::CORNERS],double iso){
00395 int o,i,c1,c2;
00396 Square::FactorEdgeIndex(e,o,i);
00397 Square::EdgeCorners(e,c1,c2);
00398 switch(o){
00399 case 0:
00400 vertexList(e, 0)=Interpolate(values[c1]-iso,values[c2]-iso);
00401 vertexList(e, 1)=i;
00402 break;
00403 case 1:
00404 vertexList(e, 1)=Interpolate(values[c1]-iso,values[c2]-iso);
00405 vertexList(e, 0)=i;
00406 break;
00407 }
00408 }
00409 double MarchingSquares::Interpolate(double v1,double v2){return v1/(v1-v2);}
00410
00411
00413
00415 const int* MarchingCubes::edgeMask()
00416 {
00417 static const int edgeMast_local[1<<Cube::CORNERS]=
00418 {
00419 0, 273, 545, 816, 2082, 2355, 2563, 2834,
00420 1042, 1283, 1587, 1826, 3120, 3361, 3601, 3840,
00421 324, 85, 869, 628, 2406, 2167, 2887, 2646,
00422 1366, 1095, 1911, 1638, 3444, 3173, 3925, 3652,
00423 644, 917, 165, 436, 2726, 2999, 2183, 2454,
00424 1686, 1927, 1207, 1446, 3764, 4005, 3221, 3460,
00425 960, 721, 481, 240, 3042, 2803, 2499, 2258,
00426 2002, 1731, 1523, 1250, 4080, 3809, 3537, 3264,
00427 2184, 2457, 2729, 3000, 170, 443, 651, 922,
00428 3226, 3467, 3771, 4010, 1208, 1449, 1689, 1928,
00429 2508, 2269, 3053, 2812, 494, 255, 975, 734,
00430 3550, 3279, 4095, 3822, 1532, 1261, 2013, 1740,
00431 2572, 2845, 2093, 2364, 558, 831, 15, 286,
00432 3614, 3855, 3135, 3374, 1596, 1837, 1053, 1292,
00433 2888, 2649, 2409, 2168, 874, 635, 331, 90,
00434 3930, 3659, 3451, 3178, 1912, 1641, 1369, 1096,
00435 1096, 1369, 1641, 1912, 3178, 3451, 3659, 3930,
00436 90, 331, 635, 874, 2168, 2409, 2649, 2888,
00437 1292, 1053, 1837, 1596, 3374, 3135, 3855, 3614,
00438 286, 15, 831, 558, 2364, 2093, 2845, 2572,
00439 1740, 2013, 1261, 1532, 3822, 4095, 3279, 3550,
00440 734, 975, 255, 494, 2812, 3053, 2269, 2508,
00441 1928, 1689, 1449, 1208, 4010, 3771, 3467, 3226,
00442 922, 651, 443, 170, 3000, 2729, 2457, 2184,
00443 3264, 3537, 3809, 4080, 1250, 1523, 1731, 2002,
00444 2258, 2499, 2803, 3042, 240, 481, 721, 960,
00445 3460, 3221, 4005, 3764, 1446, 1207, 1927, 1686,
00446 2454, 2183, 2999, 2726, 436, 165, 917, 644,
00447 3652, 3925, 3173, 3444, 1638, 1911, 1095, 1366,
00448 2646, 2887, 2167, 2406, 628, 869, 85, 324,
00449 3840, 3601, 3361, 3120, 1826, 1587, 1283, 1042,
00450 2834, 2563, 2355, 2082, 816, 545, 273, 0
00451 };
00452 return edgeMast_local;
00453 }
00454
00455 int MarchingCubes::triangles(int i, int j)
00456 {
00457 static const int triangles_local[1<<Cube::CORNERS][MAX_TRIANGLES*3+1] = {
00458 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00459 { 0, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00460 { 5, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00461 { 8, 9, 5, 8, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00462 { 1, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00463 { 0, 4, 8, 1, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00464 { 9, 11, 1, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00465 { 8, 9, 11, 8, 11, 1, 8, 1, 4, -1, -1, -1, -1, -1, -1, -1},
00466 { 4, 1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00467 { 10, 8, 0, 10, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00468 { 5, 0, 9, 4, 1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00469 { 10, 8, 9, 10, 9, 5, 10, 5, 1, -1, -1, -1, -1, -1, -1, -1},
00470 { 11, 10, 4, 11, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00471 { 11, 10, 8, 11, 8, 0, 11, 0, 5, -1, -1, -1, -1, -1, -1, -1},
00472 { 9, 11, 10, 9, 10, 4, 9, 4, 0, -1, -1, -1, -1, -1, -1, -1},
00473 { 8, 9, 11, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00474 { 8, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00475 { 6, 2, 0, 4, 6, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00476 { 6, 2, 8, 5, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00477 { 5, 4, 6, 9, 5, 6, 2, 9, 6, -1, -1, -1, -1, -1, -1, -1},
00478 { 1, 5, 11, 8, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00479 { 1, 5, 11, 6, 2, 0, 4, 6, 0, -1, -1, -1, -1, -1, -1, -1},
00480 { 6, 2, 8, 9, 11, 1, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1},
00481 { 9, 11, 2, 2, 11, 1, 2, 1, 6, 6, 1, 4, -1, -1, -1, -1},
00482 { 1, 10, 4, 2, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00483 { 2, 0, 1, 6, 2, 1, 10, 6, 1, -1, -1, -1, -1, -1, -1, -1},
00484 { 5, 0, 9, 4, 1, 10, 8, 6, 2, -1, -1, -1, -1, -1, -1, -1},
00485 { 5, 2, 9, 5, 6, 2, 5, 1, 6, 1, 10, 6, -1, -1, -1, -1},
00486 { 2, 8, 6, 4, 5, 11, 4, 11, 10, -1, -1, -1, -1, -1, -1, -1},
00487 { 5, 2, 0, 6, 2, 5, 11, 6, 5, 10, 6, 11, -1, -1, -1, -1},
00488 { 9, 11, 10, 9, 10, 4, 9, 4, 0, 8, 6, 2, -1, -1, -1, -1},
00489 { 9, 11, 2, 2, 11, 6, 10, 6, 11, -1, -1, -1, -1, -1, -1, -1},
00490 { 9, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00491 { 7, 9, 2, 4, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00492 { 0, 2, 7, 0, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00493 { 7, 5, 4, 2, 7, 4, 8, 2, 4, -1, -1, -1, -1, -1, -1, -1},
00494 { 7, 9, 2, 5, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00495 { 1, 5, 11, 0, 4, 8, 9, 2, 7, -1, -1, -1, -1, -1, -1, -1},
00496 { 1, 0, 2, 1, 2, 7, 1, 7, 11, -1, -1, -1, -1, -1, -1, -1},
00497 { 1, 7, 11, 1, 2, 7, 1, 4, 2, 4, 8, 2, -1, -1, -1, -1},
00498 { 4, 1, 10, 9, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00499 { 7, 9, 2, 0, 1, 10, 0, 10, 8, -1, -1, -1, -1, -1, -1, -1},
00500 { 4, 1, 10, 2, 7, 5, 0, 2, 5, -1, -1, -1, -1, -1, -1, -1},
00501 { 2, 10, 8, 1, 10, 2, 7, 1, 2, 5, 1, 7, -1, -1, -1, -1},
00502 { 7, 9, 2, 10, 4, 5, 11, 10, 5, -1, -1, -1, -1, -1, -1, -1},
00503 { 11, 10, 8, 11, 8, 0, 11, 0, 5, 9, 2, 7, -1, -1, -1, -1},
00504 { 11, 10, 7, 7, 10, 4, 7, 4, 2, 2, 4, 0, -1, -1, -1, -1},
00505 { 11, 10, 7, 7, 10, 2, 8, 2, 10, -1, -1, -1, -1, -1, -1, -1},
00506 { 7, 9, 8, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00507 { 4, 6, 7, 0, 4, 7, 9, 0, 7, -1, -1, -1, -1, -1, -1, -1},
00508 { 6, 7, 5, 8, 6, 5, 0, 8, 5, -1, -1, -1, -1, -1, -1, -1},
00509 { 4, 6, 7, 5, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00510 { 5, 11, 1, 8, 6, 7, 9, 8, 7, -1, -1, -1, -1, -1, -1, -1},
00511 { 4, 6, 7, 0, 4, 7, 9, 0, 7, 11, 1, 5, -1, -1, -1, -1},
00512 { 8, 1, 0, 11, 1, 8, 6, 11, 8, 7, 11, 6, -1, -1, -1, -1},
00513 { 11, 6, 7, 1, 6, 11, 6, 1, 4, -1, -1, -1, -1, -1, -1, -1},
00514 { 1, 10, 4, 6, 7, 9, 6, 9, 8, -1, -1, -1, -1, -1, -1, -1},
00515 { 0, 1, 9, 9, 1, 10, 9, 10, 7, 7, 10, 6, -1, -1, -1, -1},
00516 { 6, 7, 5, 8, 6, 5, 0, 8, 5, 1, 10, 4, -1, -1, -1, -1},
00517 { 1, 7, 5, 10, 7, 1, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1},
00518 { 11, 10, 4, 11, 4, 5, 7, 9, 8, 6, 7, 8, -1, -1, -1, -1},
00519 { 0, 6, 9, 9, 6, 7, 6, 0, 5, 5, 11, 10, 5, 10, 6, -1},
00520 { 8, 7, 0, 6, 7, 8, 4, 0, 7, 11, 10, 4, 7, 11, 4, -1},
00521 { 11, 10, 6, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00522 { 11, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00523 { 0, 4, 8, 11, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00524 { 9, 5, 0, 11, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00525 { 11, 7, 3, 4, 8, 9, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
00526 { 3, 1, 5, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00527 { 0, 4, 8, 7, 3, 1, 5, 7, 1, -1, -1, -1, -1, -1, -1, -1},
00528 { 3, 1, 0, 3, 0, 9, 3, 9, 7, -1, -1, -1, -1, -1, -1, -1},
00529 { 7, 8, 9, 4, 8, 7, 3, 4, 7, 1, 4, 3, -1, -1, -1, -1},
00530 { 1, 10, 4, 3, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00531 { 3, 11, 7, 8, 0, 1, 10, 8, 1, -1, -1, -1, -1, -1, -1, -1},
00532 { 4, 1, 10, 5, 0, 9, 11, 7, 3, -1, -1, -1, -1, -1, -1, -1},
00533 { 10, 8, 9, 10, 9, 5, 10, 5, 1, 11, 7, 3, -1, -1, -1, -1},
00534 { 4, 5, 7, 4, 7, 3, 4, 3, 10, -1, -1, -1, -1, -1, -1, -1},
00535 { 10, 8, 3, 3, 8, 0, 3, 0, 7, 7, 0, 5, -1, -1, -1, -1},
00536 { 4, 3, 10, 4, 7, 3, 4, 0, 7, 0, 9, 7, -1, -1, -1, -1},
00537 { 10, 8, 3, 3, 8, 7, 9, 7, 8, -1, -1, -1, -1, -1, -1, -1},
00538 { 11, 7, 3, 8, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00539 { 11, 7, 3, 2, 0, 4, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
00540 { 11, 7, 3, 8, 6, 2, 5, 0, 9, -1, -1, -1, -1, -1, -1, -1},
00541 { 5, 4, 6, 9, 5, 6, 2, 9, 6, 3, 11, 7, -1, -1, -1, -1},
00542 { 8, 6, 2, 3, 1, 5, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
00543 { 3, 1, 5, 3, 5, 7, 6, 2, 0, 4, 6, 0, -1, -1, -1, -1},
00544 { 3, 1, 0, 3, 0, 9, 3, 9, 7, 2, 8, 6, -1, -1, -1, -1},
00545 { 9, 4, 2, 2, 4, 6, 4, 9, 7, 7, 3, 1, 7, 1, 4, -1},
00546 { 8, 6, 2, 11, 7, 3, 4, 1, 10, -1, -1, -1, -1, -1, -1, -1},
00547 { 2, 0, 1, 6, 2, 1, 10, 6, 1, 11, 7, 3, -1, -1, -1, -1},
00548 { 5, 0, 9, 4, 1, 10, 8, 6, 2, 11, 7, 3, -1, -1, -1, -1},
00549 { 11, 7, 3, 5, 2, 9, 5, 6, 2, 5, 1, 6, 1, 10, 6, -1},
00550 { 4, 5, 7, 4, 7, 3, 4, 3, 10, 6, 2, 8, -1, -1, -1, -1},
00551 { 10, 5, 3, 3, 5, 7, 5, 10, 6, 6, 2, 0, 6, 0, 5, -1},
00552 { 8, 6, 2, 4, 3, 10, 4, 7, 3, 4, 0, 7, 0, 9, 7, -1},
00553 { 9, 7, 10, 10, 7, 3, 10, 6, 9, 6, 2, 9, -1, -1, -1, -1},
00554 { 3, 11, 9, 2, 3, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00555 { 4, 8, 0, 2, 3, 11, 2, 11, 9, -1, -1, -1, -1, -1, -1, -1},
00556 { 0, 2, 3, 0, 3, 11, 0, 11, 5, -1, -1, -1, -1, -1, -1, -1},
00557 { 2, 3, 8, 8, 3, 11, 8, 11, 4, 4, 11, 5, -1, -1, -1, -1},
00558 { 2, 3, 1, 2, 1, 5, 2, 5, 9, -1, -1, -1, -1, -1, -1, -1},
00559 { 2, 3, 1, 2, 1, 5, 2, 5, 9, 0, 4, 8, -1, -1, -1, -1},
00560 { 0, 2, 3, 0, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00561 { 2, 3, 8, 8, 3, 4, 1, 4, 3, -1, -1, -1, -1, -1, -1, -1},
00562 { 1, 10, 4, 9, 2, 3, 11, 9, 3, -1, -1, -1, -1, -1, -1, -1},
00563 { 10, 8, 0, 10, 0, 1, 3, 11, 9, 2, 3, 9, -1, -1, -1, -1},
00564 { 0, 2, 3, 0, 3, 11, 0, 11, 5, 1, 10, 4, -1, -1, -1, -1},
00565 { 5, 2, 11, 11, 2, 3, 2, 5, 1, 1, 10, 8, 1, 8, 2, -1},
00566 { 10, 2, 3, 9, 2, 10, 4, 9, 10, 5, 9, 4, -1, -1, -1, -1},
00567 { 5, 10, 0, 0, 10, 8, 10, 5, 9, 9, 2, 3, 9, 3, 10, -1},
00568 { 0, 2, 4, 4, 2, 10, 3, 10, 2, -1, -1, -1, -1, -1, -1, -1},
00569 { 10, 8, 2, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00570 { 11, 9, 8, 3, 11, 8, 6, 3, 8, -1, -1, -1, -1, -1, -1, -1},
00571 { 0, 11, 9, 3, 11, 0, 4, 3, 0, 6, 3, 4, -1, -1, -1, -1},
00572 { 11, 5, 3, 5, 0, 3, 0, 6, 3, 0, 8, 6, -1, -1, -1, -1},
00573 { 3, 4, 6, 11, 4, 3, 4, 11, 5, -1, -1, -1, -1, -1, -1, -1},
00574 { 3, 1, 6, 6, 1, 5, 6, 5, 8, 8, 5, 9, -1, -1, -1, -1},
00575 { 0, 6, 9, 4, 6, 0, 5, 9, 6, 3, 1, 5, 6, 3, 5, -1},
00576 { 3, 1, 6, 6, 1, 8, 0, 8, 1, -1, -1, -1, -1, -1, -1, -1},
00577 { 3, 1, 4, 3, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00578 { 11, 9, 8, 3, 11, 8, 6, 3, 8, 4, 1, 10, -1, -1, -1, -1},
00579 { 3, 9, 6, 11, 9, 3, 10, 6, 9, 0, 1, 10, 9, 0, 10, -1},
00580 { 4, 1, 10, 11, 5, 3, 5, 0, 3, 0, 6, 3, 0, 8, 6, -1},
00581 { 5, 10, 6, 1, 10, 5, 6, 11, 5, 6, 3, 11, -1, -1, -1, -1},
00582 { 10, 5, 3, 4, 5, 10, 6, 3, 5, 9, 8, 6, 5, 9, 6, -1},
00583 { 6, 3, 10, 9, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00584 { 3, 10, 0, 0, 10, 4, 0, 8, 3, 8, 6, 3, -1, -1, -1, -1},
00585 { 6, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00586 { 10, 3, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00587 { 3, 6, 10, 0, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00588 { 5, 0, 9, 10, 3, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00589 { 3, 6, 10, 8, 9, 5, 8, 5, 4, -1, -1, -1, -1, -1, -1, -1},
00590 { 11, 1, 5, 10, 3, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00591 { 0, 4, 8, 1, 5, 11, 10, 3, 6, -1, -1, -1, -1, -1, -1, -1},
00592 { 10, 3, 6, 0, 9, 11, 1, 0, 11, -1, -1, -1, -1, -1, -1, -1},
00593 { 8, 9, 11, 8, 11, 1, 8, 1, 4, 10, 3, 6, -1, -1, -1, -1},
00594 { 4, 1, 3, 6, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00595 { 0, 1, 3, 8, 0, 3, 6, 8, 3, -1, -1, -1, -1, -1, -1, -1},
00596 { 5, 0, 9, 3, 6, 4, 1, 3, 4, -1, -1, -1, -1, -1, -1, -1},
00597 { 8, 9, 6, 6, 9, 5, 6, 5, 3, 3, 5, 1, -1, -1, -1, -1},
00598 { 6, 4, 5, 6, 5, 11, 6, 11, 3, -1, -1, -1, -1, -1, -1, -1},
00599 { 0, 6, 8, 0, 3, 6, 0, 5, 3, 5, 11, 3, -1, -1, -1, -1},
00600 { 3, 9, 11, 0, 9, 3, 6, 0, 3, 4, 0, 6, -1, -1, -1, -1},
00601 { 8, 9, 6, 6, 9, 3, 11, 3, 9, -1, -1, -1, -1, -1, -1, -1},
00602 { 2, 8, 10, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00603 { 3, 2, 0, 10, 3, 0, 4, 10, 0, -1, -1, -1, -1, -1, -1, -1},
00604 { 5, 0, 9, 8, 10, 3, 8, 3, 2, -1, -1, -1, -1, -1, -1, -1},
00605 { 9, 3, 2, 10, 3, 9, 5, 10, 9, 4, 10, 5, -1, -1, -1, -1},
00606 { 11, 1, 5, 2, 8, 10, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1},
00607 { 3, 2, 0, 10, 3, 0, 4, 10, 0, 5, 11, 1, -1, -1, -1, -1},
00608 { 9, 11, 1, 9, 1, 0, 2, 8, 10, 3, 2, 10, -1, -1, -1, -1},
00609 { 10, 2, 4, 3, 2, 10, 1, 4, 2, 9, 11, 1, 2, 9, 1, -1},
00610 { 1, 3, 2, 4, 1, 2, 8, 4, 2, -1, -1, -1, -1, -1, -1, -1},
00611 { 0, 1, 3, 2, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00612 { 1, 3, 2, 4, 1, 2, 8, 4, 2, 9, 5, 0, -1, -1, -1, -1},
00613 { 9, 3, 2, 5, 3, 9, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
00614 { 3, 2, 11, 11, 2, 8, 11, 8, 5, 5, 8, 4, -1, -1, -1, -1},
00615 { 5, 2, 0, 11, 2, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1},
00616 { 4, 3, 8, 8, 3, 2, 3, 4, 0, 0, 9, 11, 0, 11, 3, -1},
00617 { 9, 11, 3, 9, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00618 { 10, 3, 6, 9, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00619 { 9, 2, 7, 10, 3, 6, 0, 4, 8, -1, -1, -1, -1, -1, -1, -1},
00620 { 10, 3, 6, 7, 5, 0, 7, 0, 2, -1, -1, -1, -1, -1, -1, -1},
00621 { 7, 5, 4, 2, 7, 4, 8, 2, 4, 10, 3, 6, -1, -1, -1, -1},
00622 { 10, 3, 6, 9, 2, 7, 1, 5, 11, -1, -1, -1, -1, -1, -1, -1},
00623 { 10, 3, 6, 9, 2, 7, 1, 5, 11, 0, 4, 8, -1, -1, -1, -1},
00624 { 1, 0, 2, 1, 2, 7, 1, 7, 11, 3, 6, 10, -1, -1, -1, -1},
00625 { 10, 3, 6, 1, 7, 11, 1, 2, 7, 1, 4, 2, 4, 8, 2, -1},
00626 { 9, 2, 7, 6, 4, 1, 6, 1, 3, -1, -1, -1, -1, -1, -1, -1},
00627 { 0, 1, 3, 8, 0, 3, 6, 8, 3, 7, 9, 2, -1, -1, -1, -1},
00628 { 0, 2, 7, 0, 7, 5, 4, 1, 3, 6, 4, 3, -1, -1, -1, -1},
00629 { 2, 5, 8, 7, 5, 2, 6, 8, 5, 1, 3, 6, 5, 1, 6, -1},
00630 { 6, 4, 5, 6, 5, 11, 6, 11, 3, 7, 9, 2, -1, -1, -1, -1},
00631 { 9, 2, 7, 0, 6, 8, 0, 3, 6, 0, 5, 3, 5, 11, 3, -1},
00632 { 3, 4, 11, 6, 4, 3, 7, 11, 4, 0, 2, 7, 4, 0, 7, -1},
00633 { 11, 3, 8, 8, 3, 6, 8, 2, 11, 2, 7, 11, -1, -1, -1, -1},
00634 { 9, 8, 10, 7, 9, 10, 3, 7, 10, -1, -1, -1, -1, -1, -1, -1},
00635 { 9, 0, 7, 0, 4, 7, 4, 3, 7, 4, 10, 3, -1, -1, -1, -1},
00636 { 8, 10, 0, 0, 10, 3, 0, 3, 5, 5, 3, 7, -1, -1, -1, -1},
00637 { 10, 5, 4, 3, 5, 10, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
00638 { 9, 8, 10, 7, 9, 10, 3, 7, 10, 1, 5, 11, -1, -1, -1, -1},
00639 { 1, 5, 11, 9, 0, 7, 0, 4, 7, 4, 3, 7, 4, 10, 3, -1},
00640 { 11, 0, 7, 1, 0, 11, 3, 7, 0, 8, 10, 3, 0, 8, 3, -1},
00641 { 7, 1, 4, 11, 1, 7, 4, 3, 7, 4, 10, 3, -1, -1, -1, -1},
00642 { 4, 9, 8, 7, 9, 4, 1, 7, 4, 3, 7, 1, -1, -1, -1, -1},
00643 { 7, 1, 3, 9, 1, 7, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
00644 { 8, 7, 0, 0, 7, 5, 7, 8, 4, 4, 1, 3, 4, 3, 7, -1},
00645 { 5, 1, 3, 7, 5, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00646 { 3, 4, 11, 11, 4, 5, 4, 3, 7, 7, 9, 8, 7, 8, 4, -1},
00647 { 3, 9, 0, 7, 9, 3, 0, 11, 3, 0, 5, 11, -1, -1, -1, -1},
00648 { 3, 7, 11, 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00649 { 3, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00650 { 6, 10, 11, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00651 { 0, 4, 8, 10, 11, 7, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1},
00652 { 9, 5, 0, 6, 10, 11, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
00653 { 8, 9, 5, 8, 5, 4, 6, 10, 11, 7, 6, 11, -1, -1, -1, -1},
00654 { 5, 7, 6, 5, 6, 10, 5, 10, 1, -1, -1, -1, -1, -1, -1, -1},
00655 { 5, 7, 6, 5, 6, 10, 5, 10, 1, 4, 8, 0, -1, -1, -1, -1},
00656 { 1, 0, 10, 10, 0, 9, 10, 9, 6, 6, 9, 7, -1, -1, -1, -1},
00657 { 1, 7, 10, 10, 7, 6, 7, 1, 4, 4, 8, 9, 4, 9, 7, -1},
00658 { 7, 6, 4, 7, 4, 1, 7, 1, 11, -1, -1, -1, -1, -1, -1, -1},
00659 { 11, 0, 1, 8, 0, 11, 7, 8, 11, 6, 8, 7, -1, -1, -1, -1},
00660 { 7, 6, 4, 7, 4, 1, 7, 1, 11, 5, 0, 9, -1, -1, -1, -1},
00661 { 11, 6, 1, 7, 6, 11, 5, 1, 6, 8, 9, 5, 6, 8, 5, -1},
00662 { 4, 5, 7, 4, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00663 { 5, 7, 0, 0, 7, 8, 6, 8, 7, -1, -1, -1, -1, -1, -1, -1},
00664 { 7, 6, 9, 9, 6, 0, 4, 0, 6, -1, -1, -1, -1, -1, -1, -1},
00665 { 8, 9, 7, 8, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00666 { 8, 10, 11, 2, 8, 11, 7, 2, 11, -1, -1, -1, -1, -1, -1, -1},
00667 { 10, 11, 4, 4, 11, 7, 4, 7, 0, 0, 7, 2, -1, -1, -1, -1},
00668 { 8, 10, 11, 2, 8, 11, 7, 2, 11, 5, 0, 9, -1, -1, -1, -1},
00669 { 9, 4, 2, 5, 4, 9, 7, 2, 4, 10, 11, 7, 4, 10, 7, -1},
00670 { 1, 8, 10, 2, 8, 1, 5, 2, 1, 7, 2, 5, -1, -1, -1, -1},
00671 { 1, 7, 10, 5, 7, 1, 4, 10, 7, 2, 0, 4, 7, 2, 4, -1},
00672 { 7, 1, 9, 9, 1, 0, 1, 7, 2, 2, 8, 10, 2, 10, 1, -1},
00673 { 7, 2, 9, 10, 1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00674 { 8, 4, 2, 4, 1, 2, 1, 7, 2, 1, 11, 7, -1, -1, -1, -1},
00675 { 11, 0, 1, 7, 0, 11, 0, 7, 2, -1, -1, -1, -1, -1, -1, -1},
00676 { 5, 0, 9, 8, 4, 2, 4, 1, 2, 1, 7, 2, 1, 11, 7, -1},
00677 { 2, 5, 1, 9, 5, 2, 1, 7, 2, 1, 11, 7, -1, -1, -1, -1},
00678 { 4, 5, 8, 8, 5, 2, 7, 2, 5, -1, -1, -1, -1, -1, -1, -1},
00679 { 7, 2, 0, 5, 7, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00680 { 7, 2, 4, 4, 2, 8, 4, 0, 7, 0, 9, 7, -1, -1, -1, -1},
00681 { 7, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00682 { 10, 11, 9, 6, 10, 9, 2, 6, 9, -1, -1, -1, -1, -1, -1, -1},
00683 { 10, 11, 9, 6, 10, 9, 2, 6, 9, 0, 4, 8, -1, -1, -1, -1},
00684 { 5, 10, 11, 6, 10, 5, 0, 6, 5, 2, 6, 0, -1, -1, -1, -1},
00685 { 2, 5, 8, 8, 5, 4, 5, 2, 6, 6, 10, 11, 6, 11, 5, -1},
00686 { 10, 1, 6, 1, 5, 6, 5, 2, 6, 5, 9, 2, -1, -1, -1, -1},
00687 { 0, 4, 8, 10, 1, 6, 1, 5, 6, 5, 2, 6, 5, 9, 2, -1},
00688 { 1, 0, 10, 10, 0, 6, 2, 6, 0, -1, -1, -1, -1, -1, -1, -1},
00689 { 2, 6, 1, 1, 6, 10, 1, 4, 2, 4, 8, 2, -1, -1, -1, -1},
00690 { 11, 9, 1, 1, 9, 2, 1, 2, 4, 4, 2, 6, -1, -1, -1, -1},
00691 { 8, 1, 6, 0, 1, 8, 2, 6, 1, 11, 9, 2, 1, 11, 2, -1},
00692 { 11, 6, 1, 1, 6, 4, 6, 11, 5, 5, 0, 2, 5, 2, 6, -1},
00693 { 2, 6, 8, 11, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00694 { 6, 4, 2, 2, 4, 9, 5, 9, 4, -1, -1, -1, -1, -1, -1, -1},
00695 { 5, 9, 6, 6, 9, 2, 6, 8, 5, 8, 0, 5, -1, -1, -1, -1},
00696 { 0, 2, 6, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00697 { 2, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00698 { 8, 10, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00699 { 0, 11, 9, 4, 11, 0, 11, 4, 10, -1, -1, -1, -1, -1, -1, -1},
00700 { 5, 10, 11, 0, 10, 5, 10, 0, 8, -1, -1, -1, -1, -1, -1, -1},
00701 { 4, 10, 11, 5, 4, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00702 { 1, 8, 10, 5, 8, 1, 8, 5, 9, -1, -1, -1, -1, -1, -1, -1},
00703 { 9, 4, 10, 0, 4, 9, 10, 5, 9, 10, 1, 5, -1, -1, -1, -1},
00704 { 0, 8, 10, 1, 0, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00705 { 10, 1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00706 { 4, 9, 8, 1, 9, 4, 9, 1, 11, -1, -1, -1, -1, -1, -1, -1},
00707 { 1, 11, 9, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00708 { 11, 0, 8, 5, 0, 11, 8, 1, 11, 8, 4, 1, -1, -1, -1, -1},
00709 { 11, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00710 { 5, 9, 8, 4, 5, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00711 { 9, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00712 { 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00713 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
00714 };
00715
00716 return triangles_local[i][j];
00717 }
00718 const int* MarchingCubes::cornerMap()
00719 {
00720 static const int cornerMap_local[Cube::CORNERS]={0,1,3,2,4,5,7,6};
00721 return cornerMap_local;
00722 }
00723 double& MarchingCubes::vertexList(int i, int j)
00724 {
00725 static double vertexList_local[Cube::EDGES][3];
00726 return vertexList_local[i][j];
00727 }
00728
00729 int MarchingCubes::GetIndex(const double v[Cube::CORNERS],double iso){
00730 int idx=0;
00731 if (v[Cube::CornerIndex(0,0,0)] < iso) idx |= 1;
00732 if (v[Cube::CornerIndex(1,0,0)] < iso) idx |= 2;
00733 if (v[Cube::CornerIndex(1,1,0)] < iso) idx |= 4;
00734 if (v[Cube::CornerIndex(0,1,0)] < iso) idx |= 8;
00735 if (v[Cube::CornerIndex(0,0,1)] < iso) idx |= 16;
00736 if (v[Cube::CornerIndex(1,0,1)] < iso) idx |= 32;
00737 if (v[Cube::CornerIndex(1,1,1)] < iso) idx |= 64;
00738 if (v[Cube::CornerIndex(0,1,1)] < iso) idx |= 128;
00739 return idx;
00740 }
00741 int MarchingCubes::GetFaceIndex(const double values[Cube::CORNERS],double iso,int faceIndex){
00742 int i,j,x,y,z,idx=0;
00743 double v[2][2];
00744 Cube::FactorFaceIndex(faceIndex,x,y,z);
00745 if (x<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(0,i,j)];}}}
00746 else if (x>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(1,i,j)];}}}
00747 else if (y<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,0,j)];}}}
00748 else if (y>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,1,j)];}}}
00749 else if (z<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,j,0)];}}}
00750 else if (z>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,j,1)];}}}
00751 if (v[0][0] < iso) idx |= 1;
00752 if (v[1][0] < iso) idx |= 2;
00753 if (v[1][1] < iso) idx |= 4;
00754 if (v[0][1] < iso) idx |= 8;
00755 return idx;
00756 }
00757 int MarchingCubes::IsAmbiguous(const double v[Cube::CORNERS],double isoValue,int faceIndex){
00758 int idx=GetFaceIndex(v,isoValue,faceIndex);
00759 return (idx==5) || (idx==10);
00760 }
00761 int MarchingCubes::HasRoots(const double v[Cube::CORNERS],double isoValue,int faceIndex){
00762 int idx=GetFaceIndex(v,isoValue,faceIndex);
00763 return (idx!=0) && (idx !=15);
00764 }
00765 int MarchingCubes::HasRoots(const double v[Cube::CORNERS],double isoValue){
00766 int idx=GetIndex(v,isoValue);
00767 if(idx==0 || idx==255){return 0;}
00768 else{return 1;}
00769 }
00770 int MarchingCubes::HasRoots(int mcIndex){
00771 if(mcIndex==0 || mcIndex==255){return 0;}
00772 else{return 1;}
00773 }
00774 int MarchingCubes::AddTriangles( const double v[Cube::CORNERS] , double iso , Triangle* isoTriangles )
00775 {
00776 int idx,ntriang=0;
00777 Triangle tri;
00778
00779 idx=GetIndex(v,iso);
00780
00781
00782 if (!edgeMask()[idx]) return 0;
00783
00784
00785 int i,j,ii=1;
00786 for(i=0;i<12;i++){
00787 if(edgeMask()[idx] & ii){SetVertex(i,v,iso);}
00788 ii<<=1;
00789 }
00790
00791 for( i=0 ; triangles(idx, i)!=-1 ; i+=3 )
00792 {
00793 for(j=0;j<3;j++){
00794 tri.p[0][j]=vertexList(triangles(idx, i+0), j);
00795 tri.p[1][j]=vertexList(triangles(idx, i+1), j);
00796 tri.p[2][j]=vertexList(triangles(idx, i+2), j);
00797 }
00798 isoTriangles[ntriang++]=tri;
00799 }
00800 return ntriang;
00801 }
00802
00803 int MarchingCubes::AddTriangleIndices(const double v[Cube::CORNERS],double iso,int* isoIndices){
00804 int idx,ntriang=0;
00805
00806 idx=GetIndex(v,iso);
00807
00808
00809 if (!edgeMask()[idx]) return 0;
00810
00811
00812 for(int i=0;triangles(idx, i)!=-1;i+=3){
00813 for(int j=0;j<3;j++){isoIndices[i+j]=triangles(idx, i+j);}
00814 ntriang++;
00815 }
00816 return ntriang;
00817 }
00818
00819 void MarchingCubes::SetVertex( int e , const double values[Cube::CORNERS] , double iso )
00820 {
00821 double t;
00822 int o , i1 , i2;
00823 Cube::FactorEdgeIndex( e , o , i1 , i2 );
00824 switch( o )
00825 {
00826 case 0:
00827 t = Interpolate( values[ Cube::CornerIndex( 0 , i1 , i2 ) ] - iso , values[ Cube::CornerIndex( 1 , i1 , i2 ) ] - iso );
00828 vertexList(e, 0) = t , vertexList(e, 1) = i1 , vertexList(e, 2) = i2;
00829 break;
00830 case 1:
00831 t = Interpolate( values[ Cube::CornerIndex( i1 , 0 , i2 ) ] - iso , values[ Cube::CornerIndex( i1 , 1 , i2 ) ] - iso );
00832 vertexList(e, 0) = i1 , vertexList(e, 1) = t , vertexList(e, 2) = i2;
00833 break;
00834 case 2:
00835 t = Interpolate( values[ Cube::CornerIndex( i1 , i2 , 0 ) ] - iso , values[ Cube::CornerIndex( i1 , i2 , 1 ) ] - iso );
00836 vertexList(e, 0) = i1 , vertexList(e, 1) = i2 , vertexList(e, 2) = t;
00837 break;
00838 }
00839 }
00840 double MarchingCubes::Interpolate( double v1 , double v2 ) { return v1/(v1-v2); }
00841
00842
00844 int MarchingCubes::GetIndex(const float v[Cube::CORNERS],float iso){
00845 int idx=0;
00846 if (v[Cube::CornerIndex(0,0,0)] < iso) idx |= 1;
00847 if (v[Cube::CornerIndex(1,0,0)] < iso) idx |= 2;
00848 if (v[Cube::CornerIndex(1,1,0)] < iso) idx |= 4;
00849 if (v[Cube::CornerIndex(0,1,0)] < iso) idx |= 8;
00850 if (v[Cube::CornerIndex(0,0,1)] < iso) idx |= 16;
00851 if (v[Cube::CornerIndex(1,0,1)] < iso) idx |= 32;
00852 if (v[Cube::CornerIndex(1,1,1)] < iso) idx |= 64;
00853 if (v[Cube::CornerIndex(0,1,1)] < iso) idx |= 128;
00854 return idx;
00855 }
00856 int MarchingCubes::GetFaceIndex(const float values[Cube::CORNERS],float iso,int faceIndex){
00857 int i,j,x,y,z,idx=0;
00858 double v[2][2];
00859 Cube::FactorFaceIndex(faceIndex,x,y,z);
00860 if (x<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(0,i,j)];}}}
00861 else if (x>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(1,i,j)];}}}
00862 else if (y<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,0,j)];}}}
00863 else if (y>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,1,j)];}}}
00864 else if (z<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,j,0)];}}}
00865 else if (z>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(i,j,1)];}}}
00866 if (v[0][0] < iso) idx |= 1;
00867 if (v[1][0] < iso) idx |= 2;
00868 if (v[1][1] < iso) idx |= 4;
00869 if (v[0][1] < iso) idx |= 8;
00870 return idx;
00871 }
00872 int MarchingCubes::GetFaceIndex(int mcIndex,int faceIndex){
00873 int i,j,x,y,z,idx=0;
00874 int v[2][2];
00875 Cube::FactorFaceIndex(faceIndex,x,y,z);
00876 if (x<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=mcIndex&(1<<MarchingCubes::cornerMap()[Cube::CornerIndex(0,i,j)]);}}}
00877 else if (x>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=mcIndex&(1<<MarchingCubes::cornerMap()[Cube::CornerIndex(1,i,j)]);}}}
00878 else if (y<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=mcIndex&(1<<MarchingCubes::cornerMap()[Cube::CornerIndex(i,0,j)]);}}}
00879 else if (y>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=mcIndex&(1<<MarchingCubes::cornerMap()[Cube::CornerIndex(i,1,j)]);}}}
00880 else if (z<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=mcIndex&(1<<MarchingCubes::cornerMap()[Cube::CornerIndex(i,j,1)]);}}}
00881 else if (z>0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=mcIndex&(1<<MarchingCubes::cornerMap()[Cube::CornerIndex(i,j,1)]);}}}
00882 if (v[0][0]) idx |= 1;
00883 if (v[1][0]) idx |= 2;
00884 if (v[1][1]) idx |= 4;
00885 if (v[0][1]) idx |= 8;
00886 return idx;
00887 }
00888 int MarchingCubes::IsAmbiguous(const float v[Cube::CORNERS],float isoValue,int faceIndex){
00889 int idx=GetFaceIndex(v,isoValue,faceIndex);
00890 return (idx==5) || (idx==10);
00891 }
00892 int MarchingCubes::IsAmbiguous(int mcIndex,int faceIndex){
00893 int idx=GetFaceIndex(mcIndex,faceIndex);
00894 return (idx==5) || (idx==10);
00895 }
00896 int MarchingCubes::HasRoots(const float v[Cube::CORNERS],float isoValue){
00897 int idx=GetIndex(v,isoValue);
00898 if(idx==0 || idx==255){return 0;}
00899 else{return 1;}
00900 }
00901 int MarchingCubes::HasRoots(const float v[Cube::CORNERS],float isoValue,int faceIndex){
00902 int idx=GetFaceIndex(v,isoValue,faceIndex);
00903 return (idx!=0) && (idx!=15);
00904 }
00905 int MarchingCubes::HasFaceRoots(int mcIndex,int faceIndex){
00906 int idx=GetFaceIndex(mcIndex,faceIndex);
00907 return (idx!=0) && (idx!=15);
00908 }
00909 int MarchingCubes::HasEdgeRoots(int mcIndex,int edgeIndex){
00910 int c1,c2;
00911 Cube::EdgeCorners(edgeIndex,c1,c2);
00912 if( ( (mcIndex&(1<<MarchingCubes::cornerMap()[c1])) && (mcIndex&(1<<MarchingCubes::cornerMap()[c2]))) ||
00913 (!(mcIndex&(1<<MarchingCubes::cornerMap()[c1])) && !(mcIndex&(1<<MarchingCubes::cornerMap()[c2])))){return 0;}
00914 else{return 1;}
00915 }
00916 int MarchingCubes::AddTriangles(const float v[Cube::CORNERS],float iso,Triangle* isoTriangles){
00917 int idx,ntriang=0;
00918 Triangle tri;
00919
00920 idx=GetIndex(v,iso);
00921
00922
00923 if (!edgeMask()[idx]) return 0;
00924
00925
00926 int i,j,ii=1;
00927 for( i=0 ; i<12 ; i++ )
00928 {
00929 if(edgeMask()[idx] & ii) SetVertex( i , v , iso );
00930 ii<<=1;
00931 }
00932
00933 for (i=0;triangles(idx, i)!=-1;i+=3) {
00934 for(j=0;j<3;j++){
00935 tri.p[0][j]=vertexList(triangles(idx, i+0), j);
00936 tri.p[1][j]=vertexList(triangles(idx, i+1), j);
00937 tri.p[2][j]=vertexList(triangles(idx, i+2), j);
00938 }
00939 isoTriangles[ntriang++]=tri;
00940 }
00941 return ntriang;
00942 }
00943
00944 int MarchingCubes::AddTriangleIndices( const float v[Cube::CORNERS] , float iso , int* isoIndices )
00945 {
00946 int idx,ntriang=0;
00947 idx=GetIndex(v,iso);
00948
00949 if (!edgeMask()[idx]) return 0;
00950
00951 for(int i=0;triangles(idx, i)!=-1;i+=3){
00952 for(int j=0;j<3;j++){isoIndices[i+j]=triangles(idx, i+j);}
00953 ntriang++;
00954 }
00955 return ntriang;
00956 }
00957 int MarchingCubes::AddTriangleIndices( int idx , int* isoIndices )
00958 {
00959 int ntriang=0;
00960
00961
00962 if (!edgeMask()[idx]) return 0;
00963
00964
00965 for(int i=0;triangles(idx, i)!=-1;i+=3){
00966 for(int j=0;j<3;j++){isoIndices[i+j]=triangles(idx, i+j);}
00967 ntriang++;
00968 }
00969 return ntriang;
00970 }
00971
00972 void MarchingCubes::SetVertex( int e , const float values[Cube::CORNERS] , float iso )
00973 {
00974 double t;
00975 int o , i1 , i2;
00976 Cube::FactorEdgeIndex( e , o , i1 , i2 );
00977 switch( o )
00978 {
00979 case 0:
00980 t = Interpolate( values[ Cube::CornerIndex( 0 , i1 , i2 ) ] - iso , values[ Cube::CornerIndex( 1 , i1 , i2 ) ] - iso );
00981 vertexList(e, 0) = t , vertexList(e, 1) = i1 , vertexList(e, 2) = i2;
00982 break;
00983 case 1:
00984 t = Interpolate( values[ Cube::CornerIndex( i1 , 0 , i2 ) ] - iso , values[ Cube::CornerIndex( i1 , 1 , i2 ) ] - iso );
00985 vertexList(e, 0) = i1 , vertexList(e, 1) = t , vertexList(e, 2) = i2;
00986 break;
00987 case 2:
00988 t = Interpolate( values[ Cube::CornerIndex( i1 , i2 , 0 ) ] - iso , values[ Cube::CornerIndex( i1 , i2 , 1 ) ] - iso );
00989 vertexList(e, 0) = i1 , vertexList(e, 1) = i2 , vertexList(e, 2) = t;
00990 break;
00991 }
00992 }
00993 float MarchingCubes::Interpolate( float v1 , float v2 ){ return v1/(v1-v2); }
00994
00995 }
00996 }