isosurface.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                         isosurface.cpp  -  description
00003                              -------------------
00004     begin                : Fri Mar 11 2005
00005     copyright            : (C) 2005-2006 by Ben Swerts
00006     email                : bswerts@users.sourceforge.net
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00019 
00031 
00032 
00033 
00035 // C++ header files
00036 #include <cassert>
00037 #include <iostream>
00038 
00039 // Xbrabo header files
00040 #include "isosurface.h"
00041 #include "vector3d.h"
00042 
00046 
00048 IsoSurface::IsoSurface()
00050 {
00051 
00052 }
00053 
00055 IsoSurface::~IsoSurface()
00057 {
00058   clearSurfaces();
00059 }
00060 
00062 void IsoSurface::setParameters(const std::vector<double>* values, const Point3D<unsigned int>& pointDimension, const Point3D<float>& pointDelta, const Point3D<float>& pointOrigin)
00068 {
00069   clearParameters();
00070 
00071   // make a copy of the density values
00072   densityValues.assign(values->begin(), values->end());
00073   // assign the other values
00074   numPoints = pointDimension;
00075   delta = pointDelta;
00076   origin = pointOrigin;
00077 }
00078 
00080 void IsoSurface::addSurface(const double isoDensity)
00083 {
00084   isoLevels.push_back(isoDensity);
00085   calculateSurface(isoDensity);
00086 
00087   // renaming
00088   vector<Point3D<float> >* singleVerticesList = new vector<Point3D<float> >;
00089   vector<unsigned int>* singleTriangleIndices = new vector<unsigned int>;
00090   renameVerticesAndTriangles(singleVerticesList, singleTriangleIndices);
00091   verticesList.push_back(singleVerticesList);
00092   triangleIndices.push_back(singleTriangleIndices);
00093 
00094   // normals
00095   vector<float>* singleNormals = new vector<float>;
00096   calculateNormals(singleNormals, numSurfaces() - 1);
00097   normals.push_back(singleNormals);
00098 }
00099 
00101 void IsoSurface::changeSurface(const unsigned int surface, const double isoDensity)
00103 {
00104   if(surface >= numSurfaces())
00105     return;
00106 
00107   isoLevels[surface] = isoDensity;
00108   calculateSurface(isoDensity);
00109   renameVerticesAndTriangles(verticesList[surface], triangleIndices[surface]);
00110   calculateNormals(normals[surface], surface);
00111 }
00112 
00114 bool IsoSurface::densityPresent() const
00116 {
00117   return densityValues.size() != 0;
00118 }
00119 
00121 unsigned int IsoSurface::numSurfaces() const
00123 {
00124   return isoLevels.size();
00125 }
00126 
00128 unsigned int IsoSurface::numTriangles(const unsigned int surface) const
00130 {
00131   if(surface >= numSurfaces())
00132     return 0;
00133 
00134   return triangleIndices[surface]->size()/3;
00135 }
00136 
00138 unsigned int IsoSurface::numVertices(const unsigned int surface) const
00140 {
00141   if(surface >= numSurfaces())
00142     return 0;
00143  
00144   return verticesList[surface]->size();
00145 }
00146 
00148 void IsoSurface::getTriangle(const unsigned int surface, const unsigned int index, Point3D<float>& point1, Point3D<float>& point2, Point3D<float>& point3, Point3D<float>& normal1, Point3D<float>& normal2, Point3D<float>& normal3) const
00154 {
00155   if(surface >= numSurfaces() || index >= triangleIndices[surface]->size()/3)
00156   {
00157     point1.setValues(0.0, 0.0, 0.0);
00158     point2.setValues(0.0, 0.0, 0.0);
00159     point3.setValues(0.0, 0.0, 0.0);
00160     normal1.setValues(0.0, 0.0, 0.0);
00161     normal2.setValues(0.0, 0.0, 0.0);
00162     normal3.setValues(0.0, 0.0, 0.0);
00163     return;
00164   }
00165 
00166   unsigned int id1, id2, id3;
00167   if(isoLevels[surface] < 0.0)
00168   {
00169     id1 = triangleIndices[surface]->at(index*3);
00170     id2 = triangleIndices[surface]->at(index*3 + 1);
00171     id3 = triangleIndices[surface]->at(index*3 + 2);
00172   }
00173   else
00174   {
00175     id2 = triangleIndices[surface]->at(index*3);
00176     id1 = triangleIndices[surface]->at(index*3 + 1);
00177     id3 = triangleIndices[surface]->at(index*3 + 2);
00178   }
00179   point1 = verticesList[surface]->at(id1);
00180   point2 = verticesList[surface]->at(id2);
00181   point3 = verticesList[surface]->at(id3);
00182   point1.add(origin);
00183   point2.add(origin);
00184   point3.add(origin);
00185   if(isoLevels[surface] < 0.0)
00186   {
00187     normal1.setValues(-normals[surface]->at(id1*3), -normals[surface]->at(id1*3 + 1), -normals[surface]->at(id1*3 + 2));
00188     normal2.setValues(-normals[surface]->at(id2*3), -normals[surface]->at(id2*3 + 1), -normals[surface]->at(id2*3 + 2));
00189     normal3.setValues(-normals[surface]->at(id3*3), -normals[surface]->at(id3*3 + 1), -normals[surface]->at(id3*3 + 2));
00190   }
00191   else
00192   {
00193     normal1.setValues(normals[surface]->at(id1*3), normals[surface]->at(id1*3 + 1), normals[surface]->at(id1*3 + 2));
00194     normal2.setValues(normals[surface]->at(id2*3), normals[surface]->at(id2*3 + 1), normals[surface]->at(id2*3 + 2));
00195     normal3.setValues(normals[surface]->at(id3*3), normals[surface]->at(id3*3 + 1), normals[surface]->at(id3*3 + 2));
00196   }
00197 }
00198 
00200 Point3D<float> IsoSurface::getPoint(const unsigned int surface, const unsigned int index) const
00202 {
00203   if(surface >= numSurfaces() || index >= verticesList[surface]->size())
00204     return Point3D<float>(0.0f, 0.0f, 0.0f);
00205   
00206   Point3D<float> result = verticesList[surface]->at(index);
00207   result.add(origin);
00208   return result;
00209 }
00210 
00212 void IsoSurface::clearParameters()
00214 {
00215   clearSurfaces();
00216   densityValues.clear();
00217 }
00218 
00220 void IsoSurface::clearSurfaces()
00222 {
00223   for(unsigned int i = 0; i < numSurfaces(); i++)
00224   {
00225     delete verticesList[i];
00226     delete triangleIndices[i];
00227     delete normals[i];
00228   }
00229   isoLevels.clear();
00230   verticesList.clear();
00231   triangleIndices.clear();
00232   normals.clear();
00233 }
00234 
00236 void IsoSurface::removeSurface(const unsigned int surface)
00238 {
00239   if(surface >= numSurfaces())
00240     return;
00241 
00242   delete verticesList[surface];
00243   delete triangleIndices[surface];
00244   delete normals[surface];
00245   vector< vector<Point3D<float> >* >::iterator itv = verticesList.begin();
00246   itv += surface;
00247   verticesList.erase(itv);
00248   vector< vector<unsigned int>* >::iterator itt = triangleIndices.begin();
00249   itt += surface;
00250   triangleIndices.erase(itt);
00251   vector< vector<float>* >::iterator itn = normals.begin();
00252   itn += surface;
00253   normals.erase(itn);
00254   vector<double>::iterator iti = isoLevels.begin();
00255   iti += surface;
00256   isoLevels.erase(iti);
00257 }
00258 
00260 Point3D<float> IsoSurface::getOrigin() const
00262 {
00263   return origin;
00264 }
00265 
00267 Point3D<float> IsoSurface::getDelta() const
00269 {
00270   return delta;
00271 }
00272 
00274 Point3D<unsigned int> IsoSurface::getNumPoints() const
00276 {
00277   return numPoints;
00278 }
00279 
00283 
00285 void IsoSurface::calculateSurface(const double isoDensity)
00287 {
00288   currentIsoLevel = isoDensity;
00289   vertices.clear();
00290   triangles.clear();
00291 
00292   for(unsigned int z = 0; z < numPoints.z() - 1; z++)
00293     for(unsigned int y = 0; y < numPoints.y() -1; y++)
00294             for(unsigned int x = 0; x < numPoints.x() - 1; x++)
00295       {
00297         unsigned int tableIndex = 0;
00298                     if(densityValues[getArrayIndex(x, y, z)] < currentIsoLevel)
00299                       tableIndex |= 1;
00300         if(densityValues[getArrayIndex(x, y+1, z)] < currentIsoLevel)
00301                       tableIndex |= 2;
00302                     if(densityValues[getArrayIndex(x+1, y+1, z)] < currentIsoLevel)
00303                       tableIndex |= 4;
00304                     if(densityValues[getArrayIndex(x+1, y, z)] < currentIsoLevel)
00305                       tableIndex |= 8;
00306                     if(densityValues[getArrayIndex(x, y, z+1)] < currentIsoLevel)
00307                       tableIndex |= 16;
00308                     if(densityValues[getArrayIndex(x, y+1, z+1)] < currentIsoLevel)
00309                       tableIndex |= 32;
00310                     if(densityValues[getArrayIndex(x+1, y+1, z+1)] < currentIsoLevel)
00311                       tableIndex |= 64;
00312                     if(densityValues[getArrayIndex(x+1, y, z+1)] < currentIsoLevel)
00313                       tableIndex |= 128;
00314 
00316                     if(edgeTable[tableIndex] != 0)
00317                     {
00318           if(edgeTable[tableIndex] & 8)
00319               {
00320             Point3D<float> point = intersection(x, y, z, 3);
00321                               unsigned int id = getEdgeID(x, y, z, 3);
00322                               vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00323                       }
00324           if(edgeTable[tableIndex] & 1)
00325                       {
00326             Point3D<float> point = intersection(x, y, z, 0);
00327                               unsigned int id = getEdgeID(x, y, z, 0);
00328                               vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00329                       }
00330           if(edgeTable[tableIndex] & 256)
00331                       {
00332             Point3D<float> point = intersection(x, y, z, 8);
00333                               unsigned int id = getEdgeID(x, y, z, 8);
00334                               vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00335                       }
00336                 
00337                       if(x == numPoints.x() - 2)
00338                       {
00339             if(edgeTable[tableIndex] & 4)
00340                               {
00341               Point3D<float> point = intersection(x, y, z, 2);
00342                                 unsigned int id = getEdgeID(x, y, z, 2);
00343                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00344                         }
00345             if(edgeTable[tableIndex] & 2048)
00346                               {
00347               Point3D<float> point = intersection(x, y, z, 11);
00348                                 unsigned int id = getEdgeID(x, y, z, 11);
00349                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00350                               }
00351                       }
00352                       if(y == numPoints.y() - 2)
00353                       {
00354             if(edgeTable[tableIndex] & 2)
00355                               {
00356               Point3D<float> point = intersection(x, y, z, 1);
00357                                 unsigned int id = getEdgeID(x, y, z, 1);
00358                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00359                         }
00360             if(edgeTable[tableIndex] & 512)
00361                               {
00362               Point3D<float> point = intersection(x, y, z, 9);
00363                                 unsigned int id = getEdgeID(x, y, z, 9);
00364                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00365                               }
00366                       }
00367                       if(z == numPoints.z() - 2)
00368                       {
00369             if(edgeTable[tableIndex] & 16)
00370                               {
00371               Point3D<float> point = intersection(x, y, z, 4);
00372                                 unsigned int id = getEdgeID(x, y, z, 4);
00373                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00374                         }
00375             if(edgeTable[tableIndex] & 128)
00376                               {
00377               Point3D<float> point = intersection(x, y, z, 7);
00378                                 unsigned int id = getEdgeID(x, y, z, 7);
00379                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00380                               }
00381                       }
00382           if((x == numPoints.x() - 2) && (y == numPoints.y() - 2))
00383                       {
00384             if(edgeTable[tableIndex] & 1024)
00385                               {
00386               Point3D<float> point = intersection(x, y, z, 10);
00387                                 unsigned int id = getEdgeID(x, y, z, 10);
00388                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00389                               }
00390                       }
00391           if((x == numPoints.x() - 2) && (z == numPoints.z() - 2))
00392                       {
00393             if(edgeTable[tableIndex] & 64)
00394                               {
00395               Point3D<float> point = intersection(x, y, z, 6);
00396                                 unsigned int id = getEdgeID(x, y, z, 6);
00397                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00398                               }
00399                       }
00400           if((y == numPoints.y() - 2) && (z == numPoints.z() - 2))
00401                       {
00402             if(edgeTable[tableIndex] & 32)
00403                               {
00404               Point3D<float> point = intersection(x, y, z, 5);
00405                                 unsigned int id = getEdgeID(x, y, z, 5);
00406                                 vertices.insert(std::map<unsigned int, Point3D<float> >::value_type(id, point));
00407                               }
00408                       }
00409 
00410                       for(unsigned int i = 0; triTable[tableIndex][i] != -1; i += 3)
00411                       {
00412             Triangle triangle;
00413                               triangle.pointID[0] = getEdgeID(x, y, z, triTable[tableIndex][i]);
00414                               triangle.pointID[1] = getEdgeID(x, y, z, triTable[tableIndex][i+1]);
00415                               triangle.pointID[2] = getEdgeID(x, y, z, triTable[tableIndex][i+2]);
00416                               triangles.push_back(triangle);
00417                       }
00418                     }
00419             }
00420 }
00421 
00423 Point3D<float> IsoSurface::intersection(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int edge)
00425 {
00426   unsigned int v1x = x, v1y = y, v1z = z;
00427   unsigned int v2x = x, v2y = y, v2z = z;
00428 
00429   switch(edge)
00430   {
00431     case 0:  v2y += 1;
00432                          break;
00433           case 1:  v1y += 1;
00434                          v2x += 1;
00435                                v2y += 1;
00436                                break;
00437           case 2:  v1x += 1;
00438                          v1y += 1;
00439                                v2x += 1;
00440                    break;
00441           case 3:  v1x += 1;
00442                          break;
00443           case 4:  v1z += 1;
00444                          v2y += 1;
00445                                v2z += 1;
00446                                break;
00447           case 5:  v1y += 1;
00448                          v1z += 1;
00449              v2x += 1;
00450              v2y += 1;
00451              v2z += 1;
00452              break;
00453           case 6:  v1x += 1;
00454                    v1y += 1;
00455              v1z += 1;
00456              v2x += 1;
00457              v2z += 1;
00458              break;
00459           case 7:  v1x += 1;
00460                                v1z += 1;
00461                                v2z += 1;
00462                                break;
00463           case 8:  v2z += 1;
00464                          break;
00465     case 9:  v1y += 1;
00466              v2y += 1;
00467              v2z += 1;
00468              break;
00469     case 10: v1x += 1;
00470              v1y += 1;
00471              v2x += 1;
00472              v2y += 1;
00473              v2z += 1;
00474              break;
00475           case 11: v1x += 1;
00476                          v2x += 1;
00477                                v2z += 1;
00478                                break;
00479   }
00480   Point3D<float> point1(v1x * delta.x(), v1y * delta.y(), v1z * delta.z());
00481   Point3D<float> point2(v2x * delta.y(), v2y * delta.y(), v2z * delta.z());
00482 
00483   double var1 = densityValues[getArrayIndex(v1x, v1y, v1z)];
00484   double var2 = densityValues[getArrayIndex(v2x, v2y, v2z)];
00485   return interpolate(point1, point2, var1, var2);
00486 }
00487 
00489 Point3D<float> IsoSurface::interpolate(const Point3D<float> point1, const Point3D<float> point2, const double var1, const double var2)
00491 {
00492   const float mu = static_cast<float>((currentIsoLevel - var1)/(var2 - var1));
00493   const float x = point1.x() + mu*(point2.x() - point1.x());
00494   const float y = point1.y() + mu*(point2.y() - point1.y());
00495   const float z = point1.z() + mu*(point2.z() - point1.z());
00496 
00497   return Point3D<float>(x, y, z);
00498 }
00499 
00501 unsigned int IsoSurface::getEdgeID(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int edge)
00503 {
00504   switch(edge)
00505   {
00506     case 0:  return getVertexID(x, y, z) + 1;
00507     case 1:  return getVertexID(x, y+1, z);
00508     case 2:  return getVertexID(x+1, y, z) + 1;
00509     case 3:  return getVertexID(x, y, z);
00510     case 4:  return getVertexID(x, y, z+1) + 1;
00511     case 5:  return getVertexID(x, y+1, z+1);
00512     case 6:  return getVertexID(x+1, y, z+1) + 1;
00513     case 7:  return getVertexID(x, y, z+1);
00514     case 8:  return getVertexID(x, y, z) + 2;
00515     case 9:  return getVertexID(x, y+1, z) + 2;
00516     case 10: return getVertexID(x+1, y+1, z) + 2;
00517     case 11: return getVertexID(x+1, y, z) + 2;
00518     default: return static_cast<unsigned int>(-1); // should be a very large positive number 
00519   }
00520 }
00521 
00523 unsigned int IsoSurface::getVertexID(const unsigned int x, const unsigned int y, const unsigned int z)
00525 {
00526   return 3*getArrayIndex(x, y, z);
00527 }
00528 
00530 void IsoSurface::renameVerticesAndTriangles(vector<Point3D<float> >* singleVerticesList, vector<unsigned int>* singleTriangleIndices)
00532 {
00533   unsigned int nextID = 0;
00534   std::map<unsigned int, Point3D<float> >::iterator itVertices = vertices.begin();
00535   std::vector<Triangle>::iterator itTriangles = triangles.begin();
00536 
00538   while(itVertices != vertices.end())
00539   {
00540     (*itVertices).second.setID(nextID++);
00541           itVertices++;
00542   }
00543 
00545   while(itTriangles != triangles.end())
00546   {
00547     for(unsigned int i = 0; i < 3; i++)
00548           {
00549       unsigned int newID = vertices[(*itTriangles).pointID[i]].id();
00550             (*itTriangles).pointID[i] = newID;
00551           }
00552           itTriangles++;
00553   }
00554 
00557   singleVerticesList->clear();
00558   singleVerticesList->reserve(vertices.size());
00559   singleTriangleIndices->clear();
00560   singleTriangleIndices->reserve(triangles.size()*3);
00561 
00562   // copy the vertices
00563   itVertices = vertices.begin();
00564   for(unsigned int i = 0; i < vertices.size(); i++, itVertices++)
00565     singleVerticesList->push_back((*itVertices).second);
00566   vertices.clear();
00567   // copy vertex indices which make triangles
00568   itTriangles = triangles.begin();
00569   for(unsigned int i = 0; i < triangles.size(); i++, itTriangles++)
00570   {
00571     singleTriangleIndices->push_back((*itTriangles).pointID[0]);
00572     singleTriangleIndices->push_back((*itTriangles).pointID[1]);
00573     singleTriangleIndices->push_back((*itTriangles).pointID[2]);
00574   }
00575   triangles.clear();
00576 }
00577 
00579 void IsoSurface::calculateNormals(vector<float>* singleNormals, const unsigned int surface)
00581 {
00582   singleNormals->clear();
00583   singleNormals->reserve(triangleIndices[surface]->size());
00584 
00585   for(unsigned int i = 0; i < triangleIndices[surface]->size(); i++)
00586     singleNormals->push_back(0.0f);
00587 
00588   for(unsigned int i = 0; i < triangleIndices[surface]->size()/3; i++)
00589   {
00590     unsigned int id1 = triangleIndices[surface]->at(i*3);
00591     unsigned int id2 = triangleIndices[surface]->at(i*3 + 1);
00592     unsigned int id3 = triangleIndices[surface]->at(i*3 + 2);
00593           Vector3D<float> vector1(verticesList[surface]->at(id1), verticesList[surface]->at(id2));
00594           Vector3D<float> vector2(verticesList[surface]->at(id1), verticesList[surface]->at(id3));
00595           Vector3D<float> normal = vector2.cross(vector1);
00596           normal.normalize();
00597           singleNormals->at(id1*3)     += normal.x();
00598           singleNormals->at(id1*3 + 1) += normal.y();
00599           singleNormals->at(id1*3 + 2) += normal.z();
00600           singleNormals->at(id2*3)     += normal.x();
00601           singleNormals->at(id2*3 + 1) += normal.y();
00602           singleNormals->at(id2*3 + 2) += normal.z();
00603           singleNormals->at(id3*3)     += normal.x();
00604           singleNormals->at(id3*3 + 1) += normal.y();
00605           singleNormals->at(id3*3 + 2) += normal.z();
00606   }
00607 }
00608 
00610 unsigned int IsoSurface::getArrayIndex(const unsigned int x, const unsigned int y, const unsigned int z) const
00612 {
00613   return x*numPoints.y()*numPoints.z() + y*numPoints.z() + z;
00614 }
00615 
00619 
00620 const unsigned int IsoSurface::edgeTable[256] = 
00621 {
00622         0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
00623         0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
00624         0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
00625         0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
00626         0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
00627         0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
00628         0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
00629         0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
00630         0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
00631         0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
00632         0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
00633         0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
00634         0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
00635         0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
00636         0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
00637         0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
00638         0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
00639         0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
00640         0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
00641         0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
00642         0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
00643         0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
00644         0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
00645         0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
00646         0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
00647         0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
00648         0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
00649         0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
00650         0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
00651         0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
00652         0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
00653         0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 
00654 };
00655 
00656 const int IsoSurface::triTable[256][16] =
00657 {
00658   {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00659   {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00660   {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00661   {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00662   {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00663   {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00664   {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00665   {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
00666   {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00667   {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00668   {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00669   {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
00670   {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00671   {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
00672   {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
00673   {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00674   {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00675   {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00676   {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00677   {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
00678   {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00679   {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
00680   {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
00681   {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
00682   {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00683   {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
00684   {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
00685   {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
00686   {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
00687   {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
00688   {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
00689   {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
00690   {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00691   {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00692   {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00693   {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
00694   {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00695   {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
00696   {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
00697   {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
00698   {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00699   {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
00700   {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
00701   {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
00702   {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
00703   {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
00704   {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
00705   {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
00706   {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00707   {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
00708   {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
00709   {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00710   {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
00711   {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
00712   {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
00713   {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
00714   {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
00715   {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
00716   {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
00717   {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
00718   {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
00719   {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
00720   {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
00721   {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00722   {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00723   {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00724   {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00725   {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
00726   {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00727   {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
00728   {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
00729   {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
00730   {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00731   {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
00732   {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
00733   {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
00734   {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
00735   {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
00736   {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
00737   {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
00738   {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00739   {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
00740   {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
00741   {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
00742   {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
00743   {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
00744   {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
00745   {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
00746   {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
00747   {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
00748   {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
00749   {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
00750   {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
00751   {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
00752   {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
00753   {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
00754   {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00755   {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
00756   {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
00757   {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
00758   {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
00759   {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
00760   {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00761   {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
00762   {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
00763   {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
00764   {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
00765   {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
00766   {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
00767   {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
00768   {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
00769   {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00770   {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
00771   {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
00772   {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
00773   {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
00774   {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
00775   {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
00776   {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
00777   {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00778   {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
00779   {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
00780   {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
00781   {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
00782   {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
00783   {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00784   {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
00785   {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00786   {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00787   {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00788   {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00789   {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
00790   {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00791   {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
00792   {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
00793   {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
00794   {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00795   {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
00796   {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
00797   {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
00798   {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
00799   {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
00800   {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
00801   {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
00802   {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00803   {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
00804   {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
00805   {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
00806   {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
00807   {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
00808   {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
00809   {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
00810   {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
00811   {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00812   {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
00813   {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
00814   {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
00815   {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
00816   {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
00817   {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00818   {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00819   {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
00820   {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
00821   {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
00822   {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
00823   {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
00824   {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
00825   {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
00826   {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
00827   {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
00828   {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
00829   {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
00830   {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
00831   {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
00832   {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
00833   {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
00834   {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
00835   {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
00836   {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
00837   {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
00838   {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
00839   {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
00840   {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
00841   {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
00842   {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
00843   {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
00844   {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
00845   {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00846   {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
00847   {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
00848   {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00849   {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00850   {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00851   {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
00852   {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
00853   {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
00854   {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
00855   {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
00856   {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
00857   {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
00858   {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
00859   {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
00860   {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
00861   {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
00862   {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00863   {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
00864   {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
00865   {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00866   {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
00867   {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
00868   {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
00869   {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
00870   {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
00871   {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
00872   {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
00873   {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00874   {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
00875   {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
00876   {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
00877   {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
00878   {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
00879   {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00880   {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
00881   {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00882   {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
00883   {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
00884   {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
00885   {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
00886   {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
00887   {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
00888   {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
00889   {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
00890   {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
00891   {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
00892   {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
00893   {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00894   {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
00895   {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
00896   {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00897   {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00898   {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00899   {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
00900   {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
00901   {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00902   {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
00903   {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
00904   {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00905   {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00906   {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
00907   {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00908   {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
00909   {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00910   {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00911   {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00912   {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
00913   {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
00914 };
00915 

Generated on Fri May 19 14:31:55 2006 for Brabosphere by  doxygen 1.4.6-NO