ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
MarchingCubes.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7 
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer. Redistributions in binary form must reproduce
10 the above copyright notice, this list of conditions and the following disclaimer
11 in the documentation and/or other materials provided with the distribution.
12 
13 Neither the name of the Johns Hopkins University nor the names of its contributors
14 may be used to endorse or promote products derived from this software without specific
15 prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 DAMAGE.
27 */
28 #include <math.h>
29 #include "MarchingCubes.h"
30 
32 // Square //
35  int x,y;
36  FactorCornerIndex(idx,x,y);
37  return CornerIndex( (x+1)%2 , (y+1)%2 );
38 }
39 int Square::CornerIndex( int x , int y ){ return (y<<1)|x; }
40 void Square::FactorCornerIndex( int idx , int& x , int& y ){ x=(idx>>0)&1 , y=(idx>>1)&1; }
41 int Square::EdgeIndex( int orientation , int i )
42 {
43  switch( orientation )
44  {
45  case 0: // x
46  if( !i ) return 0; // (0,0) -> (1,0)
47  else return 2; // (0,1) -> (1,1)
48  case 1: // y
49  if( !i ) return 3; // (0,0) -> (0,1)
50  else return 1; // (1,0) -> (1,1)
51  };
52  return -1;
53 }
54 void Square::FactorEdgeIndex(int idx,int& orientation,int& i){
55  switch(idx){
56  case 0: case 2:
57  orientation=0;
58  i=idx/2;
59  return;
60  case 1: case 3:
61  orientation=1;
62  i=((idx/2)+1)%2;
63  return;
64  };
65 }
66 void Square::EdgeCorners(int idx,int& c1,int& c2){
67  int orientation,i;
68  FactorEdgeIndex(idx,orientation,i);
69  switch(orientation){
70  case 0:
71  c1 = CornerIndex(0,i);
72  c2 = CornerIndex(1,i);
73  break;
74  case 1:
75  c1 = CornerIndex(i,0);
76  c2 = CornerIndex(i,1);
77  break;
78  };
79 }
80 int Square::ReflectEdgeIndex(int idx,int edgeIndex){
81  int orientation=edgeIndex%2;
82  int o,i;
83  FactorEdgeIndex(idx,o,i);
84  if(o!=orientation){return idx;}
85  else{return EdgeIndex(o,(i+1)%2);}
86 }
87 int Square::ReflectCornerIndex(int idx,int edgeIndex){
88  int orientation=edgeIndex%2;
89  int x,y;
90  FactorCornerIndex(idx,x,y);
91  switch(orientation){
92  case 0: return CornerIndex((x+1)%2,y);
93  case 1: return CornerIndex(x,(y+1)%2);
94  };
95  return -1;
96 }
97 
98 
99 
101 // Cube //
103 int Cube::CornerIndex( int x , int y , int z ){ return (z<<2)|(y<<1)|x; }
104 void Cube::FactorCornerIndex( int idx , int& x , int& y , int& z ){ x = (idx>>0)&1 , y = (idx>>1)&1 , z = (idx>>2)&1; }
105 int Cube::EdgeIndex(int orientation,int i,int j){return (i | (j<<1))|(orientation<<2);}
106 void Cube::FactorEdgeIndex( int idx , int& orientation , int& i , int &j )
107 {
108  orientation=idx>>2;
109  i = (idx&1);
110  j = (idx&2)>>1;
111 }
112 int Cube::FaceIndex( int x , int y , int z )
113 {
114  if ( x<0 ) return 0;
115  else if( x>0 ) return 1;
116  else if( y<0 ) return 2;
117  else if( y>0 ) return 3;
118  else if( z<0 ) return 4;
119  else if( z>0 ) return 5;
120  else return -1;
121 }
122 int Cube::FaceIndex( int dir , int offSet ){ return (dir<<1)|offSet; }
123 
124 void Cube::FactorFaceIndex( int idx , int& x , int& y , int& z )
125 {
126  x=y=z=0;
127  switch( idx )
128  {
129  case 0: x=-1; break;
130  case 1: x= 1; break;
131  case 2: y=-1; break;
132  case 3: y= 1; break;
133  case 4: z=-1; break;
134  case 5: z= 1; break;
135  };
136 }
137 void Cube::FactorFaceIndex( int idx , int& dir , int& offSet )
138 {
139  dir = idx>>1;
140  offSet=idx &1;
141 }
142 bool Cube::IsEdgeCorner( int cIndex , int e )
143 {
144  int o , i , j;
145  FactorEdgeIndex( e , o , i , j );
146  switch( o )
147  {
148  case 0: return (cIndex && 2)==(i<<1) && (cIndex && 4)==(j<<2);
149  case 1: return (cIndex && 1)==(i<<0) && (cIndex && 4)==(j<<2);
150  case 2: return (cIndex && 4)==(i<<2) && (cIndex && 2)==(j<<1);
151  default: return false;
152  }
153 }
154 bool Cube::IsFaceCorner( int cIndex , int f )
155 {
156  int dir , off;
157  FactorFaceIndex( f , dir , off );
158  return ( cIndex & (1<<dir) )==(off<<dir);
159 }
160 
161 int Cube::FaceAdjacentToEdges( int eIndex1 , int eIndex2 )
162 {
163  int f1,f2,g1,g2;
164  FacesAdjacentToEdge(eIndex1,f1,f2);
165  FacesAdjacentToEdge(eIndex2,g1,g2);
166  if(f1==g1 || f1==g2){return f1;}
167  if(f2==g1 || f2==g2){return f2;}
168  return -1;
169 }
170 
171 void Cube::FacesAdjacentToEdge( int eIndex , int& f1Index , int& f2Index )
172 {
173  int orientation,i1,i2;
174  FactorEdgeIndex(eIndex,orientation,i1,i2);
175  i1<<=1;
176  i2<<=1;
177  i1--;
178  i2--;
179  switch(orientation){
180  case 0:
181  f1Index=FaceIndex( 0,i1, 0);
182  f2Index=FaceIndex( 0, 0,i2);
183  break;
184  case 1:
185  f1Index=FaceIndex(i1, 0, 0);
186  f2Index=FaceIndex( 0, 0,i2);
187  break;
188  case 2:
189  f1Index=FaceIndex(i1, 0, 0);
190  f2Index=FaceIndex( 0,i2, 0);
191  break;
192  };
193 }
194 void Cube::EdgeCorners( int idx , int& c1 , int& c2 )
195 {
196  int orientation,i1,i2;
197  FactorEdgeIndex(idx,orientation,i1,i2);
198  switch(orientation){
199  case 0:
200  c1=CornerIndex(0,i1,i2);
201  c2=CornerIndex(1,i1,i2);
202  break;
203  case 1:
204  c1=CornerIndex(i1,0,i2);
205  c2=CornerIndex(i1,1,i2);
206  break;
207  case 2:
208  c1=CornerIndex(i1,i2,0);
209  c2=CornerIndex(i1,i2,1);
210  break;
211  };
212 }
213 void Cube::FaceCorners( int idx , int& c1 , int& c2 , int& c3 , int& c4 )
214 {
215  int i=idx%2;
216  switch(idx/2){
217  case 0:
218  c1=CornerIndex(i,0,0);
219  c2=CornerIndex(i,1,0);
220  c3=CornerIndex(i,0,1);
221  c4=CornerIndex(i,1,1);
222  return;
223  case 1:
224  c1=CornerIndex(0,i,0);
225  c2=CornerIndex(1,i,0);
226  c3=CornerIndex(0,i,1);
227  c4=CornerIndex(1,i,1);
228  return;
229  case 2:
230  c1=CornerIndex(0,0,i);
231  c2=CornerIndex(1,0,i);
232  c3=CornerIndex(0,1,i);
233  c4=CornerIndex(1,1,i);
234  return;
235  }
236 }
238 {
239  int x,y,z;
240  FactorCornerIndex(idx,x,y,z);
241  return CornerIndex((x+1)%2,(y+1)%2,(z+1)%2);
242 }
243 int Cube::FaceReflectFaceIndex( int idx , int faceIndex )
244 {
245  if(idx/2!=faceIndex/2) return idx;
246  else
247  {
248  if( idx%2 ) return idx-1;
249  else return idx+1;
250  }
251 }
252 int Cube::FaceReflectEdgeIndex( int idx , int faceIndex )
253 {
254  int orientation=faceIndex/2;
255  int o,i,j;
256  FactorEdgeIndex(idx,o,i,j);
257  if(o==orientation){return idx;}
258  switch(orientation){
259  case 0: return EdgeIndex(o,(i+1)%2,j);
260  case 1:
261  switch(o){
262  case 0: return EdgeIndex(o,(i+1)%2,j);
263  case 2: return EdgeIndex(o,i,(j+1)%2);
264  };
265  case 2: return EdgeIndex(o,i,(j+1)%2);
266  };
267  return -1;
268 }
269 int Cube::FaceReflectCornerIndex( int idx , int faceIndex )
270 {
271  int orientation=faceIndex/2;
272  int x,y,z;
273  FactorCornerIndex(idx,x,y,z);
274  switch(orientation){
275  case 0: return CornerIndex((x+1)%2,y,z);
276  case 1: return CornerIndex(x,(y+1)%2,z);
277  case 2: return CornerIndex(x,y,(z+1)%2);
278  };
279  return -1;
280 }
281 int Cube::EdgeReflectCornerIndex( int idx , int edgeIndex )
282 {
283  int orientation , x , y , z;
284  FactorEdgeIndex( edgeIndex , orientation , x , y );
285  FactorCornerIndex( idx , x , y , z );
286  switch(orientation)
287  {
288  case 0: return CornerIndex( x , (y+1)%2 , (z+1)%2 );
289  case 1: return CornerIndex( (x+1)%2 , y , (z+1)%2 );
290  case 2: return CornerIndex( (x+1)%2 , (y+1)%2 , z );
291  };
292  return -1;
293 }
294 int Cube::EdgeReflectEdgeIndex( int edgeIndex )
295 {
296  int o , i1 , i2;
297  FactorEdgeIndex( edgeIndex , o , i1 , i2 );
298  return Cube::EdgeIndex( o , (i1+1)%2 , (i2+1)%2 );
299 }
300 
301 
303 // MarchingSquares //
305 #if NEW_ORDERING
306 // #pragma message ( "[WARNING] Not clear if MarchingSquares::edgeMask and MarchingSquares::edges are set correctly" )
307 const int MarchingSquares::cornerMap[] = { 0 , 1 , 3 , 2 };
308 bool MarchingSquares::HasEdgeRoots( unsigned char mcIndex , int edgeIndex )
309 {
310  int c1 , c2;
311  Square::EdgeCorners( edgeIndex , c1 , c2 );
312  return !(
313  ( ( mcIndex&(1<<MarchingSquares::cornerMap[c1]) ) && ( mcIndex&(1<<MarchingSquares::cornerMap[c2])) )
314  ||
315  (!( mcIndex&(1<<MarchingSquares::cornerMap[c1]) ) && !( mcIndex&(1<<MarchingSquares::cornerMap[c2])) )
316  );
317 }
318 #endif // NEW_ORDERING
319 /*
320 0} // (0,0) -> (1,0)
321 1} // (1,0) -> (1,1)
322 2} // (0,1) -> (1,1)
323 3} // (0,0) -> (0,1)
324 */
326 {
327  0, // 0 -> -> ->
328  9, // 1 -> 0 -> (0,0) -> 0,3 -> 9
329  3, // 2 -> 1 -> (1,0) -> 0,1 -> 3
330  10, // 3 -> 0,1 -> (0,0) (1,0) -> 1,3 -> 10
331  12, // 4 -> 2 -> (0,1) -> 2,3 -> 12
332  5, // 5 -> 0,2 -> (0,0) (0,1) -> 0,2 -> 5
333  15, // 6 -> 1,2 -> (1,0) (0,1) -> 0,1,2,3 -> 15
334  6, // 7 -> 0,1,2 -> (0,0) (1,0) (0,1) -> 1,2 -> 6
335  6, // 8 -> 3 -> (1,1) -> 1,2 -> 6
336  15, // 9 -> 0,3 -> (0,0) (1,1) -> 0,1,2,3 -> 15
337  5, // 10 -> 1,3 -> (1,0) (1,1) -> 0,2 -> 5
338  12, // 11 -> 0,1,3 -> (0,0) (1,0) (1,1) -> 2,3 -> 12
339  10, // 12 -> 2,3 -> (0,1) (1,1) -> 1,3 -> 10
340  3, // 13 -> 0,2,3 -> (0,0) (0,1) (1,1) -> 0,1 -> 3
341  9, // 14 -> 1,2,3 -> (1,0) (0,1) (1,1) -> 0,3 -> 9
342  0, // 15 -> 0,1,2,3 -> (0,0) (1,0) (0,1) (1,1) ->
343 };
344 #if NEW_ORDERING
345 /*
346 0} // (0,0) -> (1,0)
347 1} // (1,0) -> (1,1)
348 2} // (0,1) -> (1,1)
349 3} // (0,0) -> (0,1)
350 */
351 const int MarchingSquares::edges[1<<Square::CORNERS][MAX_EDGES*2+1] =
352 {
353  // Positive to the right
355  { -1 , -1 , -1 , -1 , -1 } , // - - - -
356  { 3 , 0 , -1 , -1 , -1 } , // + - - -
357  { 0 , 1 , -1 , -1 , -1 } , // - + - -
358  { 3 , 1 , -1 , -1 , -1 } , // + + - -
359  { 1 , 2 , -1 , -1 , -1 } , // - - + -
360  { 3 , 2 , 1 , 0 , -1 } , // + - + -
361  { 0 , 2 , -1 , -1 , -1 } , // - + + -
362  { 3 , 2 , -1 , -1 , -1 } , // + + + -
363  // Now flip the edges
364  { 2 , 3 , -1 , -1 , -1 } , // - - - +
365  { 2 , 0 , -1 , -1 , -1 } , // + - - +
366  { 2 , 3 , 0 , 1 , -1 } , // - + - +
367  { 2 , 1 , -1 , -1 , -1 } , // + + - +
368  { 1 , 3 , -1 , -1 , -1 } , // - - + +
369  { 1 , 0 , -1 , -1 , -1 } , // + - + +
370  { 0 , 3 , -1 , -1 , -1 } , // - + + +
371  { -1 , -1 , -1 , -1 , -1 } , // + + + +
372 };
373 #else // !NEW_ORDERING
374 const int MarchingSquares::edges[1<<Square::CORNERS][MAX_EDGES*2+1] = {
375  { -1, -1, -1, -1, -1}, //
376  { 3, 0, -1, -1, -1}, // (0,0)
377  { 0, 1, -1, -1, -1}, // (1,0)
378  { 3, 1, -1, -1, -1}, // (0,0) (1,0)
379  { 2, 3, -1, -1, -1}, // (0,1)
380  { 2, 0, -1, -1, -1}, // (0,0) (0,1)
381  { 0, 1, 2, 3, -1}, // (1,0) (0,1)
382  { 1, 2, -1, -1, -1}, // (0,0) (1,0) (0,1)
383  { 2, 1, -1, -1, -1}, // (1,1)
384  { 3, 0, 1, 2, -1}, // (0,0) (1,1)
385  { 0, 2, -1, -1, -1}, // (1,0) (1,1)
386  { 3, 2, -1, -1, -1}, // (0,0) (1,0) (1,1)
387  { 1, 3, -1, -1, -1}, // (0,1) (1,1)
388  { 1, 0, -1, -1, -1}, // (0,0) (0,1) (1,1)
389  { 0, 3, -1, -1, -1}, // (1,0) (0,1) (1,1)
390  { -1, -1, -1, -1, -1}, // (0,0) (1,0) (0,1) (1,1)
391 };
392 #endif // NEW_ORDERING
393 
395 
396 unsigned char MarchingSquares::GetIndex( const double v[Square::CORNERS] , double iso )
397 {
398  unsigned char idx=0;
399 #if NEW_ORDERING
400  if( v[ Square::CornerIndex(0,0) ]<iso ) idx |= 1;
401  if( v[ Square::CornerIndex(1,0) ]<iso ) idx |= 2;
402  if( v[ Square::CornerIndex(1,1) ]<iso ) idx |= 4;
403  if( v[ Square::CornerIndex(0,1) ]<iso ) idx |= 8;
404 #else // !NEW_ORDERING
405  for( int i=0 ; i<Square::CORNERS ; i++ ) if( v[i]<iso ) idx|=(1<<i);
406 #endif // NEW_ORDERING
407  return idx;
408 }
409 unsigned char MarchingSquares::GetIndex( const float v[Square::CORNERS] , float iso )
410 {
411  unsigned char idx=0;
412 #if NEW_ORDERING
413  if( v[ Square::CornerIndex(0,0) ]<iso ) idx |= 1;
414  if( v[ Square::CornerIndex(1,0) ]<iso ) idx |= 2;
415  if( v[ Square::CornerIndex(1,1) ]<iso ) idx |= 4;
416  if( v[ Square::CornerIndex(0,1) ]<iso ) idx |= 8;
417 #else // !NEW_ORDERING
418  for( int i=0 ; i<Square::CORNERS ; i++ ) if( v[i]<iso ) idx|=(1<<i);
419 #endif // NEW_ORDERING
420  return idx;
421 }
422 
423 bool MarchingSquares::IsAmbiguous( const double v[Square::CORNERS] , double isoValue ){ return IsAmbiguous( GetIndex( v , isoValue ) ); }
424 bool MarchingSquares::HasRoots( unsigned char idx ){ return !(idx==0 || idx==15); }
425 #if NEW_ORDERING
426 bool MarchingSquares::IsAmbiguous( unsigned char idx ){ return (idx==5) || (idx==10); }
427 #else // !NEW_ORDERING
428 bool MarchingSquares::IsAmbiguous( unsigned char idx ){ return (idx==6) || (idx==9); }
429 #endif // NEW_ORDERING
430 int MarchingSquares::AddEdges(const double v[Square::CORNERS],double iso,Edge* isoEdges)
431 {
432  unsigned char idx;
433  int nEdges=0;
434  Edge e;
435 
436  idx=GetIndex(v,iso);
437 
438  /* Cube is entirely in/out of the surface */
439  if (!edgeMask[idx]) return 0;
440 
441  /* Find the vertices where the surface intersects the cube */
442  int i,j,ii=1;
443  for(i=0;i<12;i++){
444  if(edgeMask[idx] & ii){SetVertex(i,v,iso);}
445  ii<<=1;
446  }
447  /* Create the triangle */
448  for (i=0;edges[idx][i]!=-1;i+=2) {
449  for(j=0;j<2;j++){
450  e.p[0][j]=vertexList[edges[idx][i+0]][j];
451  e.p[1][j]=vertexList[edges[idx][i+1]][j];
452  }
453  isoEdges[nEdges++]=e;
454  }
455  return nEdges;
456 }
457 
458 int MarchingSquares::AddEdgeIndices( unsigned char mcIndex , int* isoIndices )
459 {
460  int nEdges = 0;
461  /* Square is entirely in/out of the surface */
462  if( !edgeMask[mcIndex] ) return 0;
463 
464  /* Create the edges */
465  for( int i=0 ; edges[mcIndex][i]!=-1 ; i+=2 )
466  {
467  for( int j=0 ; j<2 ; j++ ) isoIndices[i+j] = edges[mcIndex][i+j];
468  nEdges++;
469  }
470  return nEdges;
471 }
472 int MarchingSquares::AddEdgeIndices( const double v[Square::CORNERS] , double iso , int* isoIndices ){ return AddEdgeIndices( GetIndex( v , iso ) , isoIndices ); }
473 void MarchingSquares::SetVertex(int e,const double values[Square::CORNERS],double iso){
474  int o,i,c1,c2;
476  Square::EdgeCorners(e,c1,c2);
477  switch(o){
478  case 0:
479  vertexList[e][0]=Interpolate(values[c1]-iso,values[c2]-iso);
480  vertexList[e][1]=i;
481  break;
482  case 1:
483  vertexList[e][1]=Interpolate(values[c1]-iso,values[c2]-iso);
484  vertexList[e][0]=i;
485  break;
486  }
487 }
488 double MarchingSquares::Interpolate(double v1,double v2){return v1/(v1-v2);}
489 
490 
492 // MarchingCubes //
495  0, 273, 545, 816, 2082, 2355, 2563, 2834,
496  1042, 1283, 1587, 1826, 3120, 3361, 3601, 3840,
497  324, 85, 869, 628, 2406, 2167, 2887, 2646,
498  1366, 1095, 1911, 1638, 3444, 3173, 3925, 3652,
499  644, 917, 165, 436, 2726, 2999, 2183, 2454,
500  1686, 1927, 1207, 1446, 3764, 4005, 3221, 3460,
501  960, 721, 481, 240, 3042, 2803, 2499, 2258,
502  2002, 1731, 1523, 1250, 4080, 3809, 3537, 3264,
503  2184, 2457, 2729, 3000, 170, 443, 651, 922,
504  3226, 3467, 3771, 4010, 1208, 1449, 1689, 1928,
505  2508, 2269, 3053, 2812, 494, 255, 975, 734,
506  3550, 3279, 4095, 3822, 1532, 1261, 2013, 1740,
507  2572, 2845, 2093, 2364, 558, 831, 15, 286,
508  3614, 3855, 3135, 3374, 1596, 1837, 1053, 1292,
509  2888, 2649, 2409, 2168, 874, 635, 331, 90,
510  3930, 3659, 3451, 3178, 1912, 1641, 1369, 1096,
511  1096, 1369, 1641, 1912, 3178, 3451, 3659, 3930,
512  90, 331, 635, 874, 2168, 2409, 2649, 2888,
513  1292, 1053, 1837, 1596, 3374, 3135, 3855, 3614,
514  286, 15, 831, 558, 2364, 2093, 2845, 2572,
515  1740, 2013, 1261, 1532, 3822, 4095, 3279, 3550,
516  734, 975, 255, 494, 2812, 3053, 2269, 2508,
517  1928, 1689, 1449, 1208, 4010, 3771, 3467, 3226,
518  922, 651, 443, 170, 3000, 2729, 2457, 2184,
519  3264, 3537, 3809, 4080, 1250, 1523, 1731, 2002,
520  2258, 2499, 2803, 3042, 240, 481, 721, 960,
521  3460, 3221, 4005, 3764, 1446, 1207, 1927, 1686,
522  2454, 2183, 2999, 2726, 436, 165, 917, 644,
523  3652, 3925, 3173, 3444, 1638, 1911, 1095, 1366,
524  2646, 2887, 2167, 2406, 628, 869, 85, 324,
525  3840, 3601, 3361, 3120, 1826, 1587, 1283, 1042,
526  2834, 2563, 2355, 2082, 816, 545, 273, 0
527 };
528 const int MarchingCubes::triangles[1<<Cube::CORNERS][MAX_TRIANGLES*3+1] = {
529  { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
530  { 0, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
531  { 5, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
532  { 8, 9, 5, 8, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
533  { 1, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
534  { 0, 4, 8, 1, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
535  { 9, 11, 1, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
536  { 8, 9, 11, 8, 11, 1, 8, 1, 4, -1, -1, -1, -1, -1, -1, -1},
537  { 4, 1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
538  { 10, 8, 0, 10, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
539  { 5, 0, 9, 4, 1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
540  { 10, 8, 9, 10, 9, 5, 10, 5, 1, -1, -1, -1, -1, -1, -1, -1},
541  { 11, 10, 4, 11, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
542  { 11, 10, 8, 11, 8, 0, 11, 0, 5, -1, -1, -1, -1, -1, -1, -1},
543  { 9, 11, 10, 9, 10, 4, 9, 4, 0, -1, -1, -1, -1, -1, -1, -1},
544  { 8, 9, 11, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
545  { 8, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
546  { 6, 2, 0, 4, 6, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
547  { 6, 2, 8, 5, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
548  { 5, 4, 6, 9, 5, 6, 2, 9, 6, -1, -1, -1, -1, -1, -1, -1},
549  { 1, 5, 11, 8, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
550  { 1, 5, 11, 6, 2, 0, 4, 6, 0, -1, -1, -1, -1, -1, -1, -1},
551  { 6, 2, 8, 9, 11, 1, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1},
552  { 9, 11, 2, 2, 11, 1, 2, 1, 6, 6, 1, 4, -1, -1, -1, -1},
553  { 1, 10, 4, 2, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
554  { 2, 0, 1, 6, 2, 1, 10, 6, 1, -1, -1, -1, -1, -1, -1, -1},
555  { 5, 0, 9, 4, 1, 10, 8, 6, 2, -1, -1, -1, -1, -1, -1, -1},
556  { 5, 2, 9, 5, 6, 2, 5, 1, 6, 1, 10, 6, -1, -1, -1, -1},
557  { 2, 8, 6, 4, 5, 11, 4, 11, 10, -1, -1, -1, -1, -1, -1, -1},
558  { 5, 2, 0, 6, 2, 5, 11, 6, 5, 10, 6, 11, -1, -1, -1, -1},
559  { 9, 11, 10, 9, 10, 4, 9, 4, 0, 8, 6, 2, -1, -1, -1, -1},
560  { 9, 11, 2, 2, 11, 6, 10, 6, 11, -1, -1, -1, -1, -1, -1, -1},
561  { 9, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
562  { 7, 9, 2, 4, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
563  { 0, 2, 7, 0, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
564  { 7, 5, 4, 2, 7, 4, 8, 2, 4, -1, -1, -1, -1, -1, -1, -1},
565  { 7, 9, 2, 5, 11, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
566  { 1, 5, 11, 0, 4, 8, 9, 2, 7, -1, -1, -1, -1, -1, -1, -1},
567  { 1, 0, 2, 1, 2, 7, 1, 7, 11, -1, -1, -1, -1, -1, -1, -1},
568  { 1, 7, 11, 1, 2, 7, 1, 4, 2, 4, 8, 2, -1, -1, -1, -1},
569  { 4, 1, 10, 9, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
570  { 7, 9, 2, 0, 1, 10, 0, 10, 8, -1, -1, -1, -1, -1, -1, -1},
571  { 4, 1, 10, 2, 7, 5, 0, 2, 5, -1, -1, -1, -1, -1, -1, -1},
572  { 2, 10, 8, 1, 10, 2, 7, 1, 2, 5, 1, 7, -1, -1, -1, -1},
573  { 7, 9, 2, 10, 4, 5, 11, 10, 5, -1, -1, -1, -1, -1, -1, -1},
574  { 11, 10, 8, 11, 8, 0, 11, 0, 5, 9, 2, 7, -1, -1, -1, -1},
575  { 11, 10, 7, 7, 10, 4, 7, 4, 2, 2, 4, 0, -1, -1, -1, -1},
576  { 11, 10, 7, 7, 10, 2, 8, 2, 10, -1, -1, -1, -1, -1, -1, -1},
577  { 7, 9, 8, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
578  { 4, 6, 7, 0, 4, 7, 9, 0, 7, -1, -1, -1, -1, -1, -1, -1},
579  { 6, 7, 5, 8, 6, 5, 0, 8, 5, -1, -1, -1, -1, -1, -1, -1},
580  { 4, 6, 7, 5, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
581  { 5, 11, 1, 8, 6, 7, 9, 8, 7, -1, -1, -1, -1, -1, -1, -1},
582  { 4, 6, 7, 0, 4, 7, 9, 0, 7, 11, 1, 5, -1, -1, -1, -1},
583  { 8, 1, 0, 11, 1, 8, 6, 11, 8, 7, 11, 6, -1, -1, -1, -1},
584  { 11, 6, 7, 1, 6, 11, 6, 1, 4, -1, -1, -1, -1, -1, -1, -1},
585  { 1, 10, 4, 6, 7, 9, 6, 9, 8, -1, -1, -1, -1, -1, -1, -1},
586  { 0, 1, 9, 9, 1, 10, 9, 10, 7, 7, 10, 6, -1, -1, -1, -1},
587  { 6, 7, 5, 8, 6, 5, 0, 8, 5, 1, 10, 4, -1, -1, -1, -1},
588  { 1, 7, 5, 10, 7, 1, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1},
589  { 11, 10, 4, 11, 4, 5, 7, 9, 8, 6, 7, 8, -1, -1, -1, -1},
590  { 0, 6, 9, 9, 6, 7, 6, 0, 5, 5, 11, 10, 5, 10, 6, -1},
591  { 8, 7, 0, 6, 7, 8, 4, 0, 7, 11, 10, 4, 7, 11, 4, -1},
592  { 11, 10, 6, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
593  { 11, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
594  { 0, 4, 8, 11, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
595  { 9, 5, 0, 11, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
596  { 11, 7, 3, 4, 8, 9, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
597  { 3, 1, 5, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
598  { 0, 4, 8, 7, 3, 1, 5, 7, 1, -1, -1, -1, -1, -1, -1, -1},
599  { 3, 1, 0, 3, 0, 9, 3, 9, 7, -1, -1, -1, -1, -1, -1, -1},
600  { 7, 8, 9, 4, 8, 7, 3, 4, 7, 1, 4, 3, -1, -1, -1, -1},
601  { 1, 10, 4, 3, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
602  { 3, 11, 7, 8, 0, 1, 10, 8, 1, -1, -1, -1, -1, -1, -1, -1},
603  { 4, 1, 10, 5, 0, 9, 11, 7, 3, -1, -1, -1, -1, -1, -1, -1},
604  { 10, 8, 9, 10, 9, 5, 10, 5, 1, 11, 7, 3, -1, -1, -1, -1},
605  { 4, 5, 7, 4, 7, 3, 4, 3, 10, -1, -1, -1, -1, -1, -1, -1},
606  { 10, 8, 3, 3, 8, 0, 3, 0, 7, 7, 0, 5, -1, -1, -1, -1},
607  { 4, 3, 10, 4, 7, 3, 4, 0, 7, 0, 9, 7, -1, -1, -1, -1},
608  { 10, 8, 3, 3, 8, 7, 9, 7, 8, -1, -1, -1, -1, -1, -1, -1},
609  { 11, 7, 3, 8, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
610  { 11, 7, 3, 2, 0, 4, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
611  { 11, 7, 3, 8, 6, 2, 5, 0, 9, -1, -1, -1, -1, -1, -1, -1},
612  { 5, 4, 6, 9, 5, 6, 2, 9, 6, 3, 11, 7, -1, -1, -1, -1},
613  { 8, 6, 2, 3, 1, 5, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
614  { 3, 1, 5, 3, 5, 7, 6, 2, 0, 4, 6, 0, -1, -1, -1, -1},
615  { 3, 1, 0, 3, 0, 9, 3, 9, 7, 2, 8, 6, -1, -1, -1, -1},
616  { 9, 4, 2, 2, 4, 6, 4, 9, 7, 7, 3, 1, 7, 1, 4, -1},
617  { 8, 6, 2, 11, 7, 3, 4, 1, 10, -1, -1, -1, -1, -1, -1, -1},
618  { 2, 0, 1, 6, 2, 1, 10, 6, 1, 11, 7, 3, -1, -1, -1, -1},
619  { 5, 0, 9, 4, 1, 10, 8, 6, 2, 11, 7, 3, -1, -1, -1, -1},
620  { 11, 7, 3, 5, 2, 9, 5, 6, 2, 5, 1, 6, 1, 10, 6, -1},
621  { 4, 5, 7, 4, 7, 3, 4, 3, 10, 6, 2, 8, -1, -1, -1, -1},
622  { 10, 5, 3, 3, 5, 7, 5, 10, 6, 6, 2, 0, 6, 0, 5, -1},
623  { 8, 6, 2, 4, 3, 10, 4, 7, 3, 4, 0, 7, 0, 9, 7, -1},
624  { 9, 7, 10, 10, 7, 3, 10, 6, 9, 6, 2, 9, -1, -1, -1, -1},
625  { 3, 11, 9, 2, 3, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
626  { 4, 8, 0, 2, 3, 11, 2, 11, 9, -1, -1, -1, -1, -1, -1, -1},
627  { 0, 2, 3, 0, 3, 11, 0, 11, 5, -1, -1, -1, -1, -1, -1, -1},
628  { 2, 3, 8, 8, 3, 11, 8, 11, 4, 4, 11, 5, -1, -1, -1, -1},
629  { 2, 3, 1, 2, 1, 5, 2, 5, 9, -1, -1, -1, -1, -1, -1, -1},
630  { 2, 3, 1, 2, 1, 5, 2, 5, 9, 0, 4, 8, -1, -1, -1, -1},
631  { 0, 2, 3, 0, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
632  { 2, 3, 8, 8, 3, 4, 1, 4, 3, -1, -1, -1, -1, -1, -1, -1},
633  { 1, 10, 4, 9, 2, 3, 11, 9, 3, -1, -1, -1, -1, -1, -1, -1},
634  { 10, 8, 0, 10, 0, 1, 3, 11, 9, 2, 3, 9, -1, -1, -1, -1},
635  { 0, 2, 3, 0, 3, 11, 0, 11, 5, 1, 10, 4, -1, -1, -1, -1},
636  { 5, 2, 11, 11, 2, 3, 2, 5, 1, 1, 10, 8, 1, 8, 2, -1},
637  { 10, 2, 3, 9, 2, 10, 4, 9, 10, 5, 9, 4, -1, -1, -1, -1},
638  { 5, 10, 0, 0, 10, 8, 10, 5, 9, 9, 2, 3, 9, 3, 10, -1},
639  { 0, 2, 4, 4, 2, 10, 3, 10, 2, -1, -1, -1, -1, -1, -1, -1},
640  { 10, 8, 2, 10, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
641  { 11, 9, 8, 3, 11, 8, 6, 3, 8, -1, -1, -1, -1, -1, -1, -1},
642  { 0, 11, 9, 3, 11, 0, 4, 3, 0, 6, 3, 4, -1, -1, -1, -1},
643  { 11, 5, 3, 5, 0, 3, 0, 6, 3, 0, 8, 6, -1, -1, -1, -1},
644  { 3, 4, 6, 11, 4, 3, 4, 11, 5, -1, -1, -1, -1, -1, -1, -1},
645  { 3, 1, 6, 6, 1, 5, 6, 5, 8, 8, 5, 9, -1, -1, -1, -1},
646  { 0, 6, 9, 4, 6, 0, 5, 9, 6, 3, 1, 5, 6, 3, 5, -1},
647  { 3, 1, 6, 6, 1, 8, 0, 8, 1, -1, -1, -1, -1, -1, -1, -1},
648  { 3, 1, 4, 3, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
649  { 11, 9, 8, 3, 11, 8, 6, 3, 8, 4, 1, 10, -1, -1, -1, -1},
650  { 3, 9, 6, 11, 9, 3, 10, 6, 9, 0, 1, 10, 9, 0, 10, -1},
651  { 4, 1, 10, 11, 5, 3, 5, 0, 3, 0, 6, 3, 0, 8, 6, -1},
652  { 5, 10, 6, 1, 10, 5, 6, 11, 5, 6, 3, 11, -1, -1, -1, -1},
653  { 10, 5, 3, 4, 5, 10, 6, 3, 5, 9, 8, 6, 5, 9, 6, -1},
654  { 6, 3, 10, 9, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
655  { 3, 10, 0, 0, 10, 4, 0, 8, 3, 8, 6, 3, -1, -1, -1, -1},
656  { 6, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
657  { 10, 3, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
658  { 3, 6, 10, 0, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
659  { 5, 0, 9, 10, 3, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
660  { 3, 6, 10, 8, 9, 5, 8, 5, 4, -1, -1, -1, -1, -1, -1, -1},
661  { 11, 1, 5, 10, 3, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
662  { 0, 4, 8, 1, 5, 11, 10, 3, 6, -1, -1, -1, -1, -1, -1, -1},
663  { 10, 3, 6, 0, 9, 11, 1, 0, 11, -1, -1, -1, -1, -1, -1, -1},
664  { 8, 9, 11, 8, 11, 1, 8, 1, 4, 10, 3, 6, -1, -1, -1, -1},
665  { 4, 1, 3, 6, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
666  { 0, 1, 3, 8, 0, 3, 6, 8, 3, -1, -1, -1, -1, -1, -1, -1},
667  { 5, 0, 9, 3, 6, 4, 1, 3, 4, -1, -1, -1, -1, -1, -1, -1},
668  { 8, 9, 6, 6, 9, 5, 6, 5, 3, 3, 5, 1, -1, -1, -1, -1},
669  { 6, 4, 5, 6, 5, 11, 6, 11, 3, -1, -1, -1, -1, -1, -1, -1},
670  { 0, 6, 8, 0, 3, 6, 0, 5, 3, 5, 11, 3, -1, -1, -1, -1},
671  { 3, 9, 11, 0, 9, 3, 6, 0, 3, 4, 0, 6, -1, -1, -1, -1},
672  { 8, 9, 6, 6, 9, 3, 11, 3, 9, -1, -1, -1, -1, -1, -1, -1},
673  { 2, 8, 10, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
674  { 3, 2, 0, 10, 3, 0, 4, 10, 0, -1, -1, -1, -1, -1, -1, -1},
675  { 5, 0, 9, 8, 10, 3, 8, 3, 2, -1, -1, -1, -1, -1, -1, -1},
676  { 9, 3, 2, 10, 3, 9, 5, 10, 9, 4, 10, 5, -1, -1, -1, -1},
677  { 11, 1, 5, 2, 8, 10, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1},
678  { 3, 2, 0, 10, 3, 0, 4, 10, 0, 5, 11, 1, -1, -1, -1, -1},
679  { 9, 11, 1, 9, 1, 0, 2, 8, 10, 3, 2, 10, -1, -1, -1, -1},
680  { 10, 2, 4, 3, 2, 10, 1, 4, 2, 9, 11, 1, 2, 9, 1, -1},
681  { 1, 3, 2, 4, 1, 2, 8, 4, 2, -1, -1, -1, -1, -1, -1, -1},
682  { 0, 1, 3, 2, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
683  { 1, 3, 2, 4, 1, 2, 8, 4, 2, 9, 5, 0, -1, -1, -1, -1},
684  { 9, 3, 2, 5, 3, 9, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
685  { 3, 2, 11, 11, 2, 8, 11, 8, 5, 5, 8, 4, -1, -1, -1, -1},
686  { 5, 2, 0, 11, 2, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1},
687  { 4, 3, 8, 8, 3, 2, 3, 4, 0, 0, 9, 11, 0, 11, 3, -1},
688  { 9, 11, 3, 9, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
689  { 10, 3, 6, 9, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
690  { 9, 2, 7, 10, 3, 6, 0, 4, 8, -1, -1, -1, -1, -1, -1, -1},
691  { 10, 3, 6, 7, 5, 0, 7, 0, 2, -1, -1, -1, -1, -1, -1, -1},
692  { 7, 5, 4, 2, 7, 4, 8, 2, 4, 10, 3, 6, -1, -1, -1, -1},
693  { 10, 3, 6, 9, 2, 7, 1, 5, 11, -1, -1, -1, -1, -1, -1, -1},
694  { 10, 3, 6, 9, 2, 7, 1, 5, 11, 0, 4, 8, -1, -1, -1, -1},
695  { 1, 0, 2, 1, 2, 7, 1, 7, 11, 3, 6, 10, -1, -1, -1, -1},
696  { 10, 3, 6, 1, 7, 11, 1, 2, 7, 1, 4, 2, 4, 8, 2, -1},
697  { 9, 2, 7, 6, 4, 1, 6, 1, 3, -1, -1, -1, -1, -1, -1, -1},
698  { 0, 1, 3, 8, 0, 3, 6, 8, 3, 7, 9, 2, -1, -1, -1, -1},
699  { 0, 2, 7, 0, 7, 5, 4, 1, 3, 6, 4, 3, -1, -1, -1, -1},
700  { 2, 5, 8, 7, 5, 2, 6, 8, 5, 1, 3, 6, 5, 1, 6, -1},
701  { 6, 4, 5, 6, 5, 11, 6, 11, 3, 7, 9, 2, -1, -1, -1, -1},
702  { 9, 2, 7, 0, 6, 8, 0, 3, 6, 0, 5, 3, 5, 11, 3, -1},
703  { 3, 4, 11, 6, 4, 3, 7, 11, 4, 0, 2, 7, 4, 0, 7, -1},
704  { 11, 3, 8, 8, 3, 6, 8, 2, 11, 2, 7, 11, -1, -1, -1, -1},
705  { 9, 8, 10, 7, 9, 10, 3, 7, 10, -1, -1, -1, -1, -1, -1, -1},
706  { 9, 0, 7, 0, 4, 7, 4, 3, 7, 4, 10, 3, -1, -1, -1, -1},
707  { 8, 10, 0, 0, 10, 3, 0, 3, 5, 5, 3, 7, -1, -1, -1, -1},
708  { 10, 5, 4, 3, 5, 10, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
709  { 9, 8, 10, 7, 9, 10, 3, 7, 10, 1, 5, 11, -1, -1, -1, -1},
710  { 1, 5, 11, 9, 0, 7, 0, 4, 7, 4, 3, 7, 4, 10, 3, -1},
711  { 11, 0, 7, 1, 0, 11, 3, 7, 0, 8, 10, 3, 0, 8, 3, -1},
712  { 7, 1, 4, 11, 1, 7, 4, 3, 7, 4, 10, 3, -1, -1, -1, -1},
713  { 4, 9, 8, 7, 9, 4, 1, 7, 4, 3, 7, 1, -1, -1, -1, -1},
714  { 7, 1, 3, 9, 1, 7, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
715  { 8, 7, 0, 0, 7, 5, 7, 8, 4, 4, 1, 3, 4, 3, 7, -1},
716  { 5, 1, 3, 7, 5, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
717  { 3, 4, 11, 11, 4, 5, 4, 3, 7, 7, 9, 8, 7, 8, 4, -1},
718  { 3, 9, 0, 7, 9, 3, 0, 11, 3, 0, 5, 11, -1, -1, -1, -1},
719  { 3, 7, 11, 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
720  { 3, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
721  { 6, 10, 11, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
722  { 0, 4, 8, 10, 11, 7, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1},
723  { 9, 5, 0, 6, 10, 11, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
724  { 8, 9, 5, 8, 5, 4, 6, 10, 11, 7, 6, 11, -1, -1, -1, -1},
725  { 5, 7, 6, 5, 6, 10, 5, 10, 1, -1, -1, -1, -1, -1, -1, -1},
726  { 5, 7, 6, 5, 6, 10, 5, 10, 1, 4, 8, 0, -1, -1, -1, -1},
727  { 1, 0, 10, 10, 0, 9, 10, 9, 6, 6, 9, 7, -1, -1, -1, -1},
728  { 1, 7, 10, 10, 7, 6, 7, 1, 4, 4, 8, 9, 4, 9, 7, -1},
729  { 7, 6, 4, 7, 4, 1, 7, 1, 11, -1, -1, -1, -1, -1, -1, -1},
730  { 11, 0, 1, 8, 0, 11, 7, 8, 11, 6, 8, 7, -1, -1, -1, -1},
731  { 7, 6, 4, 7, 4, 1, 7, 1, 11, 5, 0, 9, -1, -1, -1, -1},
732  { 11, 6, 1, 7, 6, 11, 5, 1, 6, 8, 9, 5, 6, 8, 5, -1},
733  { 4, 5, 7, 4, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
734  { 5, 7, 0, 0, 7, 8, 6, 8, 7, -1, -1, -1, -1, -1, -1, -1},
735  { 7, 6, 9, 9, 6, 0, 4, 0, 6, -1, -1, -1, -1, -1, -1, -1},
736  { 8, 9, 7, 8, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
737  { 8, 10, 11, 2, 8, 11, 7, 2, 11, -1, -1, -1, -1, -1, -1, -1},
738  { 10, 11, 4, 4, 11, 7, 4, 7, 0, 0, 7, 2, -1, -1, -1, -1},
739  { 8, 10, 11, 2, 8, 11, 7, 2, 11, 5, 0, 9, -1, -1, -1, -1},
740  { 9, 4, 2, 5, 4, 9, 7, 2, 4, 10, 11, 7, 4, 10, 7, -1},
741  { 1, 8, 10, 2, 8, 1, 5, 2, 1, 7, 2, 5, -1, -1, -1, -1},
742  { 1, 7, 10, 5, 7, 1, 4, 10, 7, 2, 0, 4, 7, 2, 4, -1},
743  { 7, 1, 9, 9, 1, 0, 1, 7, 2, 2, 8, 10, 2, 10, 1, -1},
744  { 7, 2, 9, 10, 1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
745  { 8, 4, 2, 4, 1, 2, 1, 7, 2, 1, 11, 7, -1, -1, -1, -1},
746  { 11, 0, 1, 7, 0, 11, 0, 7, 2, -1, -1, -1, -1, -1, -1, -1},
747  { 5, 0, 9, 8, 4, 2, 4, 1, 2, 1, 7, 2, 1, 11, 7, -1},
748  { 2, 5, 1, 9, 5, 2, 1, 7, 2, 1, 11, 7, -1, -1, -1, -1},
749  { 4, 5, 8, 8, 5, 2, 7, 2, 5, -1, -1, -1, -1, -1, -1, -1},
750  { 7, 2, 0, 5, 7, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
751  { 7, 2, 4, 4, 2, 8, 4, 0, 7, 0, 9, 7, -1, -1, -1, -1},
752  { 7, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
753  { 10, 11, 9, 6, 10, 9, 2, 6, 9, -1, -1, -1, -1, -1, -1, -1},
754  { 10, 11, 9, 6, 10, 9, 2, 6, 9, 0, 4, 8, -1, -1, -1, -1},
755  { 5, 10, 11, 6, 10, 5, 0, 6, 5, 2, 6, 0, -1, -1, -1, -1},
756  { 2, 5, 8, 8, 5, 4, 5, 2, 6, 6, 10, 11, 6, 11, 5, -1},
757  { 10, 1, 6, 1, 5, 6, 5, 2, 6, 5, 9, 2, -1, -1, -1, -1},
758  { 0, 4, 8, 10, 1, 6, 1, 5, 6, 5, 2, 6, 5, 9, 2, -1},
759  { 1, 0, 10, 10, 0, 6, 2, 6, 0, -1, -1, -1, -1, -1, -1, -1},
760  { 2, 6, 1, 1, 6, 10, 1, 4, 2, 4, 8, 2, -1, -1, -1, -1},
761  { 11, 9, 1, 1, 9, 2, 1, 2, 4, 4, 2, 6, -1, -1, -1, -1},
762  { 8, 1, 6, 0, 1, 8, 2, 6, 1, 11, 9, 2, 1, 11, 2, -1},
763  { 11, 6, 1, 1, 6, 4, 6, 11, 5, 5, 0, 2, 5, 2, 6, -1},
764  { 2, 6, 8, 11, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
765  { 6, 4, 2, 2, 4, 9, 5, 9, 4, -1, -1, -1, -1, -1, -1, -1},
766  { 5, 9, 6, 6, 9, 2, 6, 8, 5, 8, 0, 5, -1, -1, -1, -1},
767  { 0, 2, 6, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
768  { 2, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
769  { 8, 10, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
770  { 0, 11, 9, 4, 11, 0, 11, 4, 10, -1, -1, -1, -1, -1, -1, -1},
771  { 5, 10, 11, 0, 10, 5, 10, 0, 8, -1, -1, -1, -1, -1, -1, -1},
772  { 4, 10, 11, 5, 4, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
773  { 1, 8, 10, 5, 8, 1, 8, 5, 9, -1, -1, -1, -1, -1, -1, -1},
774  { 9, 4, 10, 0, 4, 9, 10, 5, 9, 10, 1, 5, -1, -1, -1, -1},
775  { 0, 8, 10, 1, 0, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
776  { 10, 1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
777  { 4, 9, 8, 1, 9, 4, 9, 1, 11, -1, -1, -1, -1, -1, -1, -1},
778  { 1, 11, 9, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
779  { 11, 0, 8, 5, 0, 11, 8, 1, 11, 8, 4, 1, -1, -1, -1, -1},
780  { 11, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
781  { 5, 9, 8, 4, 5, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
782  { 9, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
783  { 8, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
784  { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
785 };
786 const int MarchingCubes::cornerMap[Cube::CORNERS]={0,1,3,2,4,5,7,6};
788 
789 unsigned char MarchingCubes::GetIndex(const double v[Cube::CORNERS],double iso)
790 {
791  unsigned char idx=0;
792  if (v[Cube::CornerIndex(0,0,0)] < iso) idx |= 1;
793  if (v[Cube::CornerIndex(1,0,0)] < iso) idx |= 2;
794  if (v[Cube::CornerIndex(1,1,0)] < iso) idx |= 4;
795  if (v[Cube::CornerIndex(0,1,0)] < iso) idx |= 8;
796  if (v[Cube::CornerIndex(0,0,1)] < iso) idx |= 16;
797  if (v[Cube::CornerIndex(1,0,1)] < iso) idx |= 32;
798  if (v[Cube::CornerIndex(1,1,1)] < iso) idx |= 64;
799  if (v[Cube::CornerIndex(0,1,1)] < iso) idx |= 128;
800  return idx;
801 }
802 unsigned char MarchingCubes::GetFaceIndex( const double values[Cube::CORNERS] , double iso , int faceIndex )
803 {
804  int i,j,x,y,z;
805  unsigned char idx=0;
806  double v[2][2];
807  Cube::FactorFaceIndex(faceIndex,x,y,z);
808  if (x<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(0,i,j)];}}}
809  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)];}}}
810  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)];}}}
811  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)];}}}
812  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)];}}}
813  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)];}}}
814  if (v[0][0] < iso) idx |= 1;
815  if (v[1][0] < iso) idx |= 2;
816  if (v[1][1] < iso) idx |= 4;
817  if (v[0][1] < iso) idx |= 8;
818  return idx;
819 }
820 bool MarchingCubes::IsAmbiguous( const double v[Cube::CORNERS] , double isoValue , int faceIndex ){ return MarchingSquares::IsAmbiguous( GetFaceIndex( v , isoValue , faceIndex ) ); }
821 bool MarchingCubes::HasRoots( const double v[Cube::CORNERS] , double isoValue , int faceIndex ){ return MarchingSquares::HasRoots( GetFaceIndex( v , isoValue , faceIndex ) ); }
822 bool MarchingCubes::HasRoots( const double v[Cube::CORNERS] , double isoValue ){ return HasRoots( GetIndex( v , isoValue ) ); }
823 bool MarchingCubes::HasRoots( unsigned char mcIndex ){ return !(mcIndex==0 || mcIndex==255); }
824 int MarchingCubes::AddTriangles( const double v[Cube::CORNERS] , double iso , Triangle* isoTriangles )
825 {
826  unsigned char idx;
827  int ntriang=0;
828  Triangle tri;
829 
830  idx=GetIndex(v,iso);
831 
832  /* Cube is entirely in/out of the surface */
833  if (!edgeMask[idx]) return 0;
834 
835  /* Find the vertices where the surface intersects the cube */
836  int i,j,ii=1;
837  for(i=0;i<12;i++){
838  if(edgeMask[idx] & ii){SetVertex(i,v,iso);}
839  ii<<=1;
840  }
841  /* Create the triangle */
842  for( i=0 ; triangles[idx][i]!=-1 ; i+=3 )
843  {
844  for(j=0;j<3;j++){
845  tri.p[0][j]=vertexList[triangles[idx][i+0]][j];
846  tri.p[1][j]=vertexList[triangles[idx][i+1]][j];
847  tri.p[2][j]=vertexList[triangles[idx][i+2]][j];
848  }
849  isoTriangles[ntriang++]=tri;
850  }
851  return ntriang;
852 }
853 
854 int MarchingCubes::AddTriangleIndices(const double v[Cube::CORNERS],double iso,int* isoIndices){
855  unsigned char idx;
856  int ntriang=0;
857 
858  idx=GetIndex(v,iso);
859 
860  /* Cube is entirely in/out of the surface */
861  if (!edgeMask[idx]) return 0;
862 
863  /* Create the triangle */
864  for(int i=0;triangles[idx][i]!=-1;i+=3){
865  for(int j=0;j<3;j++){isoIndices[i+j]=triangles[idx][i+j];}
866  ntriang++;
867  }
868  return ntriang;
869 }
870 
871 void MarchingCubes::SetVertex( int e , const double values[Cube::CORNERS] , double iso )
872 {
873  double t;
874  int o , i1 , i2;
875  Cube::FactorEdgeIndex( e , o , i1 , i2 );
876  switch( o )
877  {
878  case 0:
879  t = Interpolate( values[ Cube::CornerIndex( 0 , i1 , i2 ) ] - iso , values[ Cube::CornerIndex( 1 , i1 , i2 ) ] - iso );
880  vertexList[e][0] = t , vertexList[e][1] = i1 , vertexList[e][2] = i2;
881  break;
882  case 1:
883  t = Interpolate( values[ Cube::CornerIndex( i1 , 0 , i2 ) ] - iso , values[ Cube::CornerIndex( i1 , 1 , i2 ) ] - iso );
884  vertexList[e][0] = i1 , vertexList[e][1] = t , vertexList[e][2] = i2;
885  break;
886  case 2:
887  t = Interpolate( values[ Cube::CornerIndex( i1 , i2 , 0 ) ] - iso , values[ Cube::CornerIndex( i1 , i2 , 1 ) ] - iso );
888  vertexList[e][0] = i1 , vertexList[e][1] = i2 , vertexList[e][2] = t;
889  break;
890  }
891 }
892 double MarchingCubes::Interpolate( double v1 , double v2 ) { return v1/(v1-v2); }
893 
894 
896 unsigned char MarchingCubes::GetIndex(const float v[Cube::CORNERS],float iso){
897  unsigned char idx=0;
898  if (v[Cube::CornerIndex(0,0,0)] < iso) idx |= 1;
899  if (v[Cube::CornerIndex(1,0,0)] < iso) idx |= 2;
900  if (v[Cube::CornerIndex(1,1,0)] < iso) idx |= 4;
901  if (v[Cube::CornerIndex(0,1,0)] < iso) idx |= 8;
902  if (v[Cube::CornerIndex(0,0,1)] < iso) idx |= 16;
903  if (v[Cube::CornerIndex(1,0,1)] < iso) idx |= 32;
904  if (v[Cube::CornerIndex(1,1,1)] < iso) idx |= 64;
905  if (v[Cube::CornerIndex(0,1,1)] < iso) idx |= 128;
906  return idx;
907 }
908 unsigned char MarchingCubes::GetFaceIndex( const float values[Cube::CORNERS] , float iso , int faceIndex )
909 {
910  int i,j,x,y,z;
911  unsigned char idx=0;
912  double v[2][2];
913  Cube::FactorFaceIndex(faceIndex,x,y,z);
914  if (x<0){for(i=0;i<2;i++){for(j=0;j<2;j++){v[i][j]=values[Cube::CornerIndex(0,i,j)];}}}
915  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)];}}}
916  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)];}}}
917  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)];}}}
918  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)];}}}
919  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)];}}}
920  if (v[0][0] < iso) idx |= 1;
921  if (v[1][0] < iso) idx |= 2;
922  if (v[1][1] < iso) idx |= 4;
923  if (v[0][1] < iso) idx |= 8;
924  return idx;
925 }
926 unsigned char MarchingCubes::GetFaceIndex( unsigned char mcIndex , int faceIndex )
927 {
928  int i,j,x,y,z;
929  unsigned char idx=0;
930  int v[2][2];
931  Cube::FactorFaceIndex(faceIndex,x,y,z);
932  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)]);}}}
933  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)]);}}}
934  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)]);}}}
935  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)]);}}}
936  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)]);}}}
937  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)]);}}}
938  if (v[0][0]) idx |= 1;
939  if (v[1][0]) idx |= 2;
940  if (v[1][1]) idx |= 4;
941  if (v[0][1]) idx |= 8;
942  return idx;
943 }
944 bool MarchingCubes::IsAmbiguous( const float v[Cube::CORNERS] , float isoValue , int faceIndex ){ return MarchingSquares::IsAmbiguous( GetFaceIndex( v , isoValue , faceIndex ) ); }
945 bool MarchingCubes::IsAmbiguous( unsigned char mcIndex , int faceIndex ){ return MarchingSquares::IsAmbiguous( GetFaceIndex( mcIndex , faceIndex ) ); }
946 bool MarchingCubes::HasRoots( const float v[Cube::CORNERS] , float isoValue ){ return HasRoots( GetIndex( v , isoValue ) ); }
947 bool MarchingCubes::HasRoots( const float v[Cube::CORNERS] , float isoValue , int faceIndex){ return MarchingSquares::HasRoots( GetFaceIndex( v , isoValue , faceIndex ) ); }
948 bool MarchingCubes::HasFaceRoots( unsigned char mcIndex , int faceIndex ){ return MarchingSquares::HasRoots( GetFaceIndex( mcIndex , faceIndex ) ); }
949 bool MarchingCubes::HasEdgeRoots( unsigned char mcIndex , int edgeIndex )
950 {
951  int c1 , c2;
952  Cube::EdgeCorners( edgeIndex , c1 , c2 );
953  return !(
954  ( ( mcIndex&(1<<MarchingCubes::cornerMap[c1]) ) && ( mcIndex&(1<<MarchingCubes::cornerMap[c2])) )
955  ||
956  (!( mcIndex&(1<<MarchingCubes::cornerMap[c1]) ) && !( mcIndex&(1<<MarchingCubes::cornerMap[c2])) )
957  );
958 }
959 int MarchingCubes::AddTriangles(const float v[Cube::CORNERS],float iso,Triangle* isoTriangles){
960  unsigned char idx;
961  int ntriang=0;
962  Triangle tri;
963 
964  idx = GetIndex( v , iso );
965 
966  /* Cube is entirely in/out of the surface */
967  if( !edgeMask[idx] ) return 0;
968 
969  /* Find the vertices where the surface intersects the cube */
970  int i,j,ii=1;
971  for( i=0 ; i<12 ; i++ )
972  {
973  if( edgeMask[idx] & ii ) SetVertex( i , v , iso );
974  ii<<=1;
975  }
976  /* Create the triangle */
977  for (i=0;triangles[idx][i]!=-1;i+=3) {
978  for(j=0;j<3;j++){
979  tri.p[0][j]=vertexList[triangles[idx][i+0]][j];
980  tri.p[1][j]=vertexList[triangles[idx][i+1]][j];
981  tri.p[2][j]=vertexList[triangles[idx][i+2]][j];
982  }
983  isoTriangles[ntriang++]=tri;
984  }
985  return ntriang;
986 }
987 
988 int MarchingCubes::AddTriangleIndices( const float v[Cube::CORNERS] , float iso , int* isoIndices ){ return AddTriangleIndices( GetIndex( v , iso ) , isoIndices ); }
989 int MarchingCubes::AddTriangleIndices( int idx , int* isoIndices )
990 {
991  int ntriang=0;
992 
993  /* Cube is entirely in/out of the surface */
994  if (!edgeMask[idx]) return 0;
995 
996  /* Create the triangle */
997  for(int i=0;triangles[idx][i]!=-1;i+=3){
998  for(int j=0;j<3;j++){isoIndices[i+j]=triangles[idx][i+j];}
999  ntriang++;
1000  }
1001  return ntriang;
1002 }
1003 
1004 void MarchingCubes::SetVertex( int e , const float values[Cube::CORNERS] , float iso )
1005 {
1006  double t;
1007  int o , i1 , i2;
1008  Cube::FactorEdgeIndex( e , o , i1 , i2 );
1009  switch( o )
1010  {
1011  case 0:
1012  t = Interpolate( values[ Cube::CornerIndex( 0 , i1 , i2 ) ] - iso , values[ Cube::CornerIndex( 1 , i1 , i2 ) ] - iso );
1013  vertexList[e][0] = t , vertexList[e][1] = i1 , vertexList[e][2] = i2;
1014  break;
1015  case 1:
1016  t = Interpolate( values[ Cube::CornerIndex( i1 , 0 , i2 ) ] - iso , values[ Cube::CornerIndex( i1 , 1 , i2 ) ] - iso );
1017  vertexList[e][0] = i1 , vertexList[e][1] = t , vertexList[e][2] = i2;
1018  break;
1019  case 2:
1020  t = Interpolate( values[ Cube::CornerIndex( i1 , i2 , 0 ) ] - iso , values[ Cube::CornerIndex( i1 , i2 , 1 ) ] - iso );
1021  vertexList[e][0] = i1 , vertexList[e][1] = i2 , vertexList[e][2] = t;
1022  break;
1023  }
1024 }
1025 float MarchingCubes::Interpolate( float v1 , float v2 ){ return v1/(v1-v2); }
static bool IsEdgeCorner(int cIndex, int e)
static int CornerIndex(int x, int y, int z)
static int FaceReflectEdgeIndex(int idx, int faceIndex)
static bool IsFaceCorner(int cIndex, int f)
static const unsigned int EDGES
Definition: MarchingCubes.h:54
static int FaceReflectCornerIndex(int idx, int faceIndex)
static int FaceAdjacentToEdges(int eIndex1, int eIndex2)
static int FaceReflectFaceIndex(int idx, int faceIndex)
static int AntipodalCornerIndex(int idx)
static int EdgeIndex(int orientation, int i, int j)
static int EdgeReflectCornerIndex(int idx, int edgeIndex)
static const unsigned int CORNERS
Definition: MarchingCubes.h:54
static void FactorEdgeIndex(int idx, int &orientation, int &i, int &j)
static int EdgeReflectEdgeIndex(int edgeIndex)
static void FacesAdjacentToEdge(int eIndex, int &f1Index, int &f2Index)
static void FactorFaceIndex(int idx, int &x, int &y, int &z)
static void FaceCorners(int idx, int &c1, int &c2, int &c3, int &c4)
static void EdgeCorners(int idx, int &c1, int &c2)
static int FaceIndex(int dir, int offSet)
static void FactorCornerIndex(int idx, int &x, int &y, int &z)
static bool IsAmbiguous(const double v[Cube::CORNERS], double isoValue, int faceIndex)
static const int cornerMap[Cube::CORNERS]
static const int triangles[1<< Cube::CORNERS][3 *MAX_TRIANGLES+1]
static bool HasEdgeRoots(unsigned char mcIndex, int edgeIndex)
static double vertexList[Cube::EDGES][3]
static unsigned char GetIndex(const double values[Cube::CORNERS], double iso)
static bool HasRoots(const double v[Cube::CORNERS], double isoValue)
static bool HasFaceRoots(unsigned char mcIndex, int faceIndex)
static double Interpolate(double v1, double v2)
static int AddTriangles(const double v[Cube::CORNERS], double isoValue, Triangle *triangles)
static int AddTriangleIndices(int mcIndex, int *triangles)
static const int edgeMask[1<< Cube::CORNERS]
static bool HasEdgeRoots(unsigned char mcIndex, int edgeIndex)
static bool IsAmbiguous(const double v[Square::CORNERS], double isoValue)
static double vertexList[Square::EDGES][2]
Definition: MarchingCubes.h:90
static unsigned char GetIndex(const float values[Square::CORNERS], float iso)
static bool HasRoots(unsigned char mcIndex)
static const int cornerMap[Square::CORNERS]
Definition: MarchingCubes.h:92
static const int edges[1<< Square::CORNERS][2 *MAX_EDGES+1]
Definition: MarchingCubes.h:89
static const int edgeMask[1<< Square::CORNERS]
Definition: MarchingCubes.h:88
static int AddEdges(const double v[Square::CORNERS], double isoValue, Edge *edges)
static int AddEdgeIndices(const double v[Square::CORNERS], double isoValue, int *edges)
static int ReflectCornerIndex(int idx, int edgeIndex)
static int AntipodalCornerIndex(int idx)
static void FactorCornerIndex(int idx, int &x, int &y)
static void FactorEdgeIndex(int idx, int &orientation, int &i)
static int ReflectEdgeIndex(int idx, int edgeIndex)
static void EdgeCorners(int idx, int &c1, int &c2)
static int EdgeIndex(int orientation, int i)
static const unsigned int CORNERS
Definition: MarchingCubes.h:39
static const unsigned int EDGES
Definition: MarchingCubes.h:39
static int CornerIndex(int x, int y)
double p[3][3]
Definition: Geometry.h:205
double p[2][2]
Definition: Geometry.h:194