diff --git a/applications/utilities/mesh/generation/cvMesh/Allwmake b/applications/utilities/mesh/generation/cvMesh/Allwmake index 688b3be475..f059754bab 100755 --- a/applications/utilities/mesh/generation/cvMesh/Allwmake +++ b/applications/utilities/mesh/generation/cvMesh/Allwmake @@ -4,5 +4,6 @@ set -x wmake libso conformalVoronoiMesh wmake +wmake cvMeshSurfaceSimplify # ----------------------------------------------------------------- end-of-file diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/Make/files b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/Make/files new file mode 100644 index 0000000000..a0fcd8f0bf --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/Make/files @@ -0,0 +1,6 @@ +cvMeshSurfaceSimplify.C + +MarchingCubes/MarchingCubes.cpp +MarchingCubes/ply.c + +EXE = $(FOAM_APPBIN)/cvMeshSurfaceSimplify diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/Make/options b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/Make/options new file mode 100644 index 0000000000..1711b9ba61 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/Make/options @@ -0,0 +1,17 @@ +include $(GENERAL_RULES)/CGAL + +EXE_INC = \ + -IMarchingCubes \ + -I../conformalVoronoiMesh/lnInclude \ + -I$(LIB_SRC)/edgeMesh/lnInclude \ + -I$(LIB_SRC)/triSurface/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + $(CGAL_LIBS) \ + -lconformalVoronoiMesh \ + -ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lscotchDecomp \ + -ledgeMesh \ + -ltriSurface \ + -lmeshTools \ + -ldynamicMesh diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/LookUpTable.h b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/LookUpTable.h new file mode 100755 index 0000000000..5529346954 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/LookUpTable.h @@ -0,0 +1,2322 @@ +/** + * @file LookUpTable.h + * @author Thomas Lewiner + * @author Math Dept, PUC-Rio + * @version 0.2 + * @date 12/08/2002 + * + * @brief LookUpTable for the MarchingCubes 33 Algorithm + */ +//________________________________________________ + + + +#ifndef _LOOKUPTABLE_H_ +#define _LOOKUPTABLE_H_ + + + + + +//_____________________________________________________________________________ +/** + * \brief case mapping + * For each of the possible vertex states listed in this table there is a + * specific triangulation of the edge intersection points. The table lists + * all of them in the form of 0-5 edge triples with the list terminated by + * the invalid value -1. For example: case[3] list the 2 triangles + * formed when cube[0] and cube[1] are inside of the surface, but the rest of + * the cube is not. + * + * Cube description: + * 7 ________ 6 _____6__ ________ + * /| /| 7/| /| /| /| + * / | / | / | /5 | / 6 / | + * 4 /_______ / | /__4____ / 10 /_______3/ | + * | | |5 | | 11 | | | | | 2 | + * | 3|__|_____|2 | |__|__2__| | 4 |__|_____| + * | / | / 8 3/ 9 / | / | / + * | / | / | / | /1 | / 5 / + * |/_______|/ |/___0___|/ |/_1_____|/ + * 0 1 0 1 + */ +//----------------------------------------------------------------------------- +static const char cases[256][2] = { +/* 0: */ { 0, -1 }, +/* 1: 0, */ { 1, 0 }, +/* 2: 1, */ { 1, 1 }, +/* 3: 0, 1, */ { 2, 0 }, +/* 4: 2, */ { 1, 2 }, +/* 5: 0, 2, */ { 3, 0 }, +/* 6: 1, 2, */ { 2, 3 }, +/* 7: 0, 1, 2, */ { 5, 0 }, +/* 8: 3, */ { 1, 3 }, +/* 9: 0, 3, */ { 2, 1 }, +/* 10: 1, 3, */ { 3, 3 }, +/* 11: 0, 1, 3, */ { 5, 1 }, +/* 12: 2, 3, */ { 2, 5 }, +/* 13: 0, 2, 3, */ { 5, 4 }, +/* 14: 1, 2, 3, */ { 5, 9 }, +/* 15: 0, 1, 2, 3, */ { 8, 0 }, +/* 16: 4, */ { 1, 4 }, +/* 17: 0, 4, */ { 2, 2 }, +/* 18: 1, 4, */ { 3, 4 }, +/* 19: 0, 1, 4, */ { 5, 2 }, +/* 20: 2, 4, */ { 4, 2 }, +/* 21: 0, 2, 4, */ { 6, 2 }, +/* 22: 1, 2, 4, */ { 6, 9 }, +/* 23: 0, 1, 2, 4, */ { 11, 0 }, +/* 24: 3, 4, */ { 3, 8 }, +/* 25: 0, 3, 4, */ { 5, 5 }, +/* 26: 1, 3, 4, */ { 7, 3 }, +/* 27: 0, 1, 3, 4, */ { 9, 1 }, +/* 28: 2, 3, 4, */ { 6, 16 }, +/* 29: 0, 2, 3, 4, */ { 14, 3 }, +/* 30: 1, 2, 3, 4, */ { 12, 12 }, +/* 31: 0, 1, 2, 3, 4, */ { 5, 24 }, +/* 32: 5, */ { 1, 5 }, +/* 33: 0, 5, */ { 3, 1 }, +/* 34: 1, 5, */ { 2, 4 }, +/* 35: 0, 1, 5, */ { 5, 3 }, +/* 36: 2, 5, */ { 3, 6 }, +/* 37: 0, 2, 5, */ { 7, 0 }, +/* 38: 1, 2, 5, */ { 5, 10 }, +/* 39: 0, 1, 2, 5, */ { 9, 0 }, +/* 40: 3, 5, */ { 4, 3 }, +/* 41: 0, 3, 5, */ { 6, 4 }, +/* 42: 1, 3, 5, */ { 6, 11 }, +/* 43: 0, 1, 3, 5, */ { 14, 1 }, +/* 44: 2, 3, 5, */ { 6, 17 }, +/* 45: 0, 2, 3, 5, */ { 12, 4 }, +/* 46: 1, 2, 3, 5, */ { 11, 6 }, +/* 47: 0, 1, 2, 3, 5, */ { 5, 25 }, +/* 48: 4, 5, */ { 2, 8 }, +/* 49: 0, 4, 5, */ { 5, 7 }, +/* 50: 1, 4, 5, */ { 5, 12 }, +/* 51: 0, 1, 4, 5, */ { 8, 1 }, +/* 52: 2, 4, 5, */ { 6, 18 }, +/* 53: 0, 2, 4, 5, */ { 12, 5 }, +/* 54: 1, 2, 4, 5, */ { 14, 7 }, +/* 55: 0, 1, 2, 4, 5, */ { 5, 28 }, +/* 56: 3, 4, 5, */ { 6, 21 }, +/* 57: 0, 3, 4, 5, */ { 11, 4 }, +/* 58: 1, 3, 4, 5, */ { 12, 15 }, +/* 59: 0, 1, 3, 4, 5, */ { 5, 30 }, +/* 60: 2, 3, 4, 5, */ { 10, 5 }, +/* 61: 0, 2, 3, 4, 5, */ { 6, 32 }, +/* 62: 1, 2, 3, 4, 5, */ { 6, 39 }, +/* 63: 0, 1, 2, 3, 4, 5, */ { 2, 12 }, +/* 64: 6, */ { 1, 6 }, +/* 65: 0, 6, */ { 4, 0 }, +/* 66: 1, 6, */ { 3, 5 }, +/* 67: 0, 1, 6, */ { 6, 0 }, +/* 68: 2, 6, */ { 2, 6 }, +/* 69: 0, 2, 6, */ { 6, 3 }, +/* 70: 1, 2, 6, */ { 5, 11 }, +/* 71: 0, 1, 2, 6, */ { 14, 0 }, +/* 72: 3, 6, */ { 3, 9 }, +/* 73: 0, 3, 6, */ { 6, 5 }, +/* 74: 1, 3, 6, */ { 7, 4 }, +/* 75: 0, 1, 3, 6, */ { 12, 1 }, +/* 76: 2, 3, 6, */ { 5, 14 }, +/* 77: 0, 2, 3, 6, */ { 11, 3 }, +/* 78: 1, 2, 3, 6, */ { 9, 4 }, +/* 79: 0, 1, 2, 3, 6, */ { 5, 26 }, +/* 80: 4, 6, */ { 3, 10 }, +/* 81: 0, 4, 6, */ { 6, 6 }, +/* 82: 1, 4, 6, */ { 7, 5 }, +/* 83: 0, 1, 4, 6, */ { 12, 2 }, +/* 84: 2, 4, 6, */ { 6, 19 }, +/* 85: 0, 2, 4, 6, */ { 10, 1 }, +/* 86: 1, 2, 4, 6, */ { 12, 13 }, +/* 87: 0, 1, 2, 4, 6, */ { 6, 24 }, +/* 88: 3, 4, 6, */ { 7, 7 }, +/* 89: 0, 3, 4, 6, */ { 12, 9 }, +/* 90: 1, 3, 4, 6, */ { 13, 1 }, +/* 91: 0, 1, 3, 4, 6, */ { 7, 9 }, +/* 92: 2, 3, 4, 6, */ { 12, 20 }, +/* 93: 0, 2, 3, 4, 6, */ { 6, 33 }, +/* 94: 1, 2, 3, 4, 6, */ { 7, 13 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 3, 12 }, +/* 96: 5, 6, */ { 2, 10 }, +/* 97: 0, 5, 6, */ { 6, 7 }, +/* 98: 1, 5, 6, */ { 5, 13 }, +/* 99: 0, 1, 5, 6, */ { 11, 2 }, +/* 100: 2, 5, 6, */ { 5, 16 }, +/* 101: 0, 2, 5, 6, */ { 12, 7 }, +/* 102: 1, 2, 5, 6, */ { 8, 3 }, +/* 103: 0, 1, 2, 5, 6, */ { 5, 29 }, +/* 104: 3, 5, 6, */ { 6, 22 }, +/* 105: 0, 3, 5, 6, */ { 10, 2 }, +/* 106: 1, 3, 5, 6, */ { 12, 17 }, +/* 107: 0, 1, 3, 5, 6, */ { 6, 27 }, +/* 108: 2, 3, 5, 6, */ { 14, 9 }, +/* 109: 0, 2, 3, 5, 6, */ { 6, 34 }, +/* 110: 1, 2, 3, 5, 6, */ { 5, 39 }, +/* 111: 0, 1, 2, 3, 5, 6, */ { 2, 14 }, +/* 112: 4, 5, 6, */ { 5, 20 }, +/* 113: 0, 4, 5, 6, */ { 14, 5 }, +/* 114: 1, 4, 5, 6, */ { 9, 5 }, +/* 115: 0, 1, 4, 5, 6, */ { 5, 32 }, +/* 116: 2, 4, 5, 6, */ { 11, 10 }, +/* 117: 0, 2, 4, 5, 6, */ { 6, 35 }, +/* 118: 1, 2, 4, 5, 6, */ { 5, 41 }, +/* 119: 0, 1, 2, 4, 5, 6, */ { 2, 16 }, +/* 120: 3, 4, 5, 6, */ { 12, 23 }, +/* 121: 0, 3, 4, 5, 6, */ { 6, 37 }, +/* 122: 1, 3, 4, 5, 6, */ { 7, 14 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 3, 16 }, +/* 124: 2, 3, 4, 5, 6, */ { 6, 46 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 4, 6 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 3, 21 }, +/* 127: 0, 1, 2, 3, 4, 5, 6, */ { 1, 8 }, +/* 128: 7, */ { 1, 7 }, +/* 129: 0, 7, */ { 3, 2 }, +/* 130: 1, 7, */ { 4, 1 }, +/* 131: 0, 1, 7, */ { 6, 1 }, +/* 132: 2, 7, */ { 3, 7 }, +/* 133: 0, 2, 7, */ { 7, 1 }, +/* 134: 1, 2, 7, */ { 6, 10 }, +/* 135: 0, 1, 2, 7, */ { 12, 0 }, +/* 136: 3, 7, */ { 2, 7 }, +/* 137: 0, 3, 7, */ { 5, 6 }, +/* 138: 1, 3, 7, */ { 6, 12 }, +/* 139: 0, 1, 3, 7, */ { 11, 1 }, +/* 140: 2, 3, 7, */ { 5, 15 }, +/* 141: 0, 2, 3, 7, */ { 9, 2 }, +/* 142: 1, 2, 3, 7, */ { 14, 6 }, +/* 143: 0, 1, 2, 3, 7, */ { 5, 27 }, +/* 144: 4, 7, */ { 2, 9 }, +/* 145: 0, 4, 7, */ { 5, 8 }, +/* 146: 1, 4, 7, */ { 6, 13 }, +/* 147: 0, 1, 4, 7, */ { 14, 2 }, +/* 148: 2, 4, 7, */ { 6, 20 }, +/* 149: 0, 2, 4, 7, */ { 12, 6 }, +/* 150: 1, 2, 4, 7, */ { 10, 3 }, +/* 151: 0, 1, 2, 4, 7, */ { 6, 25 }, +/* 152: 3, 4, 7, */ { 5, 18 }, +/* 153: 0, 3, 4, 7, */ { 8, 2 }, +/* 154: 1, 3, 4, 7, */ { 12, 16 }, +/* 155: 0, 1, 3, 4, 7, */ { 5, 31 }, +/* 156: 2, 3, 4, 7, */ { 11, 9 }, +/* 157: 0, 2, 3, 4, 7, */ { 5, 34 }, +/* 158: 1, 2, 3, 4, 7, */ { 6, 40 }, +/* 159: 0, 1, 2, 3, 4, 7, */ { 2, 13 }, +/* 160: 5, 7, */ { 3, 11 }, +/* 161: 0, 5, 7, */ { 7, 2 }, +/* 162: 1, 5, 7, */ { 6, 14 }, +/* 163: 0, 1, 5, 7, */ { 12, 3 }, +/* 164: 2, 5, 7, */ { 7, 6 }, +/* 165: 0, 2, 5, 7, */ { 13, 0 }, +/* 166: 1, 2, 5, 7, */ { 12, 14 }, +/* 167: 0, 1, 2, 5, 7, */ { 7, 8 }, +/* 168: 3, 5, 7, */ { 6, 23 }, +/* 169: 0, 3, 5, 7, */ { 12, 10 }, +/* 170: 1, 3, 5, 7, */ { 10, 4 }, +/* 171: 0, 1, 3, 5, 7, */ { 6, 28 }, +/* 172: 2, 3, 5, 7, */ { 12, 21 }, +/* 173: 0, 2, 3, 5, 7, */ { 7, 10 }, +/* 174: 1, 2, 3, 5, 7, */ { 6, 41 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 3, 13 }, +/* 176: 4, 5, 7, */ { 5, 21 }, +/* 177: 0, 4, 5, 7, */ { 9, 3 }, +/* 178: 1, 4, 5, 7, */ { 11, 8 }, +/* 179: 0, 1, 4, 5, 7, */ { 5, 33 }, +/* 180: 2, 4, 5, 7, */ { 12, 22 }, +/* 181: 0, 2, 4, 5, 7, */ { 7, 11 }, +/* 182: 1, 2, 4, 5, 7, */ { 6, 42 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 3, 14 }, +/* 184: 3, 4, 5, 7, */ { 14, 11 }, +/* 185: 0, 3, 4, 5, 7, */ { 5, 36 }, +/* 186: 1, 3, 4, 5, 7, */ { 6, 44 }, +/* 187: 0, 1, 3, 4, 5, 7, */ { 2, 17 }, +/* 188: 2, 3, 4, 5, 7, */ { 6, 47 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 3, 18 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 4, 7 }, +/* 191: 0, 1, 2, 3, 4, 5, 7, */ { 1, 9 }, +/* 192: 6, 7, */ { 2, 11 }, +/* 193: 0, 6, 7, */ { 6, 8 }, +/* 194: 1, 6, 7, */ { 6, 15 }, +/* 195: 0, 1, 6, 7, */ { 10, 0 }, +/* 196: 2, 6, 7, */ { 5, 17 }, +/* 197: 0, 2, 6, 7, */ { 12, 8 }, +/* 198: 1, 2, 6, 7, */ { 11, 7 }, +/* 199: 0, 1, 2, 6, 7, */ { 6, 26 }, +/* 200: 3, 6, 7, */ { 5, 19 }, +/* 201: 0, 3, 6, 7, */ { 14, 4 }, +/* 202: 1, 3, 6, 7, */ { 12, 18 }, +/* 203: 0, 1, 3, 6, 7, */ { 6, 29 }, +/* 204: 2, 3, 6, 7, */ { 8, 4 }, +/* 205: 0, 2, 3, 6, 7, */ { 5, 35 }, +/* 206: 1, 2, 3, 6, 7, */ { 5, 40 }, +/* 207: 0, 1, 2, 3, 6, 7, */ { 2, 15 }, +/* 208: 4, 6, 7, */ { 5, 22 }, +/* 209: 0, 4, 6, 7, */ { 11, 5 }, +/* 210: 1, 4, 6, 7, */ { 12, 19 }, +/* 211: 0, 1, 4, 6, 7, */ { 6, 30 }, +/* 212: 2, 4, 6, 7, */ { 14, 10 }, +/* 213: 0, 2, 4, 6, 7, */ { 6, 36 }, +/* 214: 1, 2, 4, 6, 7, */ { 6, 43 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 4, 4 }, +/* 216: 3, 4, 6, 7, */ { 9, 7 }, +/* 217: 0, 3, 4, 6, 7, */ { 5, 37 }, +/* 218: 1, 3, 4, 6, 7, */ { 7, 15 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 3, 17 }, +/* 220: 2, 3, 4, 6, 7, */ { 5, 44 }, +/* 221: 0, 2, 3, 4, 6, 7, */ { 2, 19 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 3, 22 }, +/* 223: 0, 1, 2, 3, 4, 6, 7, */ { 1, 10 }, +/* 224: 5, 6, 7, */ { 5, 23 }, +/* 225: 0, 5, 6, 7, */ { 12, 11 }, +/* 226: 1, 5, 6, 7, */ { 14, 8 }, +/* 227: 0, 1, 5, 6, 7, */ { 6, 31 }, +/* 228: 2, 5, 6, 7, */ { 9, 6 }, +/* 229: 0, 2, 5, 6, 7, */ { 7, 12 }, +/* 230: 1, 2, 5, 6, 7, */ { 5, 42 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 3, 15 }, +/* 232: 3, 5, 6, 7, */ { 11, 11 }, +/* 233: 0, 3, 5, 6, 7, */ { 6, 38 }, +/* 234: 1, 3, 5, 6, 7, */ { 6, 45 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 4, 5 }, +/* 236: 2, 3, 5, 6, 7, */ { 5, 45 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 3, 19 }, +/* 238: 1, 2, 3, 5, 6, 7, */ { 2, 21 }, +/* 239: 0, 1, 2, 3, 5, 6, 7, */ { 1, 11 }, +/* 240: 4, 5, 6, 7, */ { 8, 5 }, +/* 241: 0, 4, 5, 6, 7, */ { 5, 38 }, +/* 242: 1, 4, 5, 6, 7, */ { 5, 43 }, +/* 243: 0, 1, 4, 5, 6, 7, */ { 2, 18 }, +/* 244: 2, 4, 5, 6, 7, */ { 5, 46 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 3, 20 }, +/* 246: 1, 2, 4, 5, 6, 7, */ { 2, 22 }, +/* 247: 0, 1, 2, 4, 5, 6, 7, */ { 1, 12 }, +/* 248: 3, 4, 5, 6, 7, */ { 5, 47 }, +/* 249: 0, 3, 4, 5, 6, 7, */ { 2, 20 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 3, 23 }, +/* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 13 }, +/* 252: 2, 3, 4, 5, 6, 7, */ { 2, 23 }, +/* 253: 0, 2, 3, 4, 5, 6, 7, */ { 1, 14 }, +/* 254: 1, 2, 3, 4, 5, 6, 7, */ { 1, 15 }, +/* 255: 0, 1, 2, 3, 4, 5, 6, 7, */ { 0, -1 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling1[16][3] = { +/* 1: 0, */ { 0, 8, 3 }, +/* 2: 1, */ { 0, 1, 9 }, +/* 4: 2, */ { 1, 2, 10 }, +/* 8: 3, */ { 3, 11, 2 }, +/* 16: 4, */ { 4, 7, 8 }, +/* 32: 5, */ { 9, 5, 4 }, +/* 64: 6, */ { 10, 6, 5 }, +/* 128: 7, */ { 7, 6, 11 }, +/* 127: 0, 1, 2, 3, 4, 5, 6, */ { 7, 11, 6 }, +/* 191: 0, 1, 2, 3, 4, 5, 7, */ { 10, 5, 6 }, +/* 223: 0, 1, 2, 3, 4, 6, 7, */ { 9, 4, 5 }, +/* 239: 0, 1, 2, 3, 5, 6, 7, */ { 4, 8, 7 }, +/* 247: 0, 1, 2, 4, 5, 6, 7, */ { 3, 2, 11 }, +/* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 10, 2 }, +/* 253: 0, 2, 3, 4, 5, 6, 7, */ { 0, 9, 1 }, +/* 254: 1, 2, 3, 4, 5, 6, 7, */ { 0, 3, 8 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling2[24][6] = { +/* 3: 0, 1, */ { 1, 8, 3, 9, 8, 1 }, +/* 9: 0, 3, */ { 0, 11, 2, 8, 11, 0 }, +/* 17: 0, 4, */ { 4, 3, 0, 7, 3, 4 }, +/* 6: 1, 2, */ { 9, 2, 10, 0, 2, 9 }, +/* 34: 1, 5, */ { 0, 5, 4, 1, 5, 0 }, +/* 12: 2, 3, */ { 3, 10, 1, 11, 10, 3 }, +/* 68: 2, 6, */ { 1, 6, 5, 2, 6, 1 }, +/* 136: 3, 7, */ { 7, 2, 3, 6, 2, 7 }, +/* 48: 4, 5, */ { 9, 7, 8, 5, 7, 9 }, +/* 144: 4, 7, */ { 6, 8, 4, 11, 8, 6 }, +/* 96: 5, 6, */ { 10, 4, 9, 6, 4, 10 }, +/* 192: 6, 7, */ { 11, 5, 10, 7, 5, 11 }, +/* 63: 0, 1, 2, 3, 4, 5, */ { 11, 10, 5, 7, 11, 5 }, +/* 159: 0, 1, 2, 3, 4, 7, */ { 10, 9, 4, 6, 10, 4 }, +/* 111: 0, 1, 2, 3, 5, 6, */ { 6, 4, 8, 11, 6, 8 }, +/* 207: 0, 1, 2, 3, 6, 7, */ { 9, 8, 7, 5, 9, 7 }, +/* 119: 0, 1, 2, 4, 5, 6, */ { 7, 3, 2, 6, 7, 2 }, +/* 187: 0, 1, 3, 4, 5, 7, */ { 1, 5, 6, 2, 1, 6 }, +/* 243: 0, 1, 4, 5, 6, 7, */ { 3, 1, 10, 11, 3, 10 }, +/* 221: 0, 2, 3, 4, 6, 7, */ { 0, 4, 5, 1, 0, 5 }, +/* 249: 0, 3, 4, 5, 6, 7, */ { 9, 10, 2, 0, 9, 2 }, +/* 238: 1, 2, 3, 5, 6, 7, */ { 4, 0, 3, 7, 4, 3 }, +/* 246: 1, 2, 4, 5, 6, 7, */ { 0, 2, 11, 8, 0, 11 }, +/* 252: 2, 3, 4, 5, 6, 7, */ { 1, 3, 8, 9, 1, 8 } +}; +//_____________________________________________________________________________ + +//_____________________________________________________________________________ +/** + * \brief test table for case 3 + * One face to test + * When the test on the specified face is positive : 4 first triangles + * When the test on the specified face is negative : 2 last triangles + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test3[24] = { +/* 5: 0, 2, */ 5, +/* 33: 0, 5, */ 1, +/* 129: 0, 7, */ 4, +/* 10: 1, 3, */ 5, +/* 18: 1, 4, */ 1, +/* 66: 1, 6, */ 2, +/* 36: 2, 5, */ 2, +/* 132: 2, 7, */ 3, +/* 24: 3, 4, */ 4, +/* 72: 3, 6, */ 3, +/* 80: 4, 6, */ 6, +/* 160: 5, 7, */ 6, +/* 95: 0, 1, 2, 3, 4, 6, */ -6, +/* 175: 0, 1, 2, 3, 5, 7, */ -6, +/* 183: 0, 1, 2, 4, 5, 7, */ -3, +/* 231: 0, 1, 2, 5, 6, 7, */ -4, +/* 123: 0, 1, 3, 4, 5, 6, */ -3, +/* 219: 0, 1, 3, 4, 6, 7, */ -2, +/* 189: 0, 2, 3, 4, 5, 7, */ -2, +/* 237: 0, 2, 3, 5, 6, 7, */ -1, +/* 245: 0, 2, 4, 5, 6, 7, */ -5, +/* 126: 1, 2, 3, 4, 5, 6, */ -4, +/* 222: 1, 2, 3, 4, 6, 7, */ -1, +/* 250: 1, 3, 4, 5, 6, 7, */ -5 +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 3.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling3_1[24][6] = { +/* 5: 0, 2, */ { 0, 8, 3, 1, 2, 10 }, +/* 33: 0, 5, */ { 9, 5, 4, 0, 8, 3 }, +/* 129: 0, 7, */ { 3, 0, 8, 11, 7, 6 }, +/* 10: 1, 3, */ { 1, 9, 0, 2, 3, 11 }, +/* 18: 1, 4, */ { 0, 1, 9, 8, 4, 7 }, +/* 66: 1, 6, */ { 9, 0, 1, 5, 10, 6 }, +/* 36: 2, 5, */ { 1, 2, 10, 9, 5, 4 }, +/* 132: 2, 7, */ { 10, 1, 2, 6, 11, 7 }, +/* 24: 3, 4, */ { 8, 4, 7, 3, 11, 2 }, +/* 72: 3, 6, */ { 2, 3, 11, 10, 6, 5 }, +/* 80: 4, 6, */ { 5, 10, 6, 4, 7, 8 }, +/* 160: 5, 7, */ { 4, 9, 5, 7, 6, 11 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 5, 9, 4, 11, 6, 7 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 6, 10, 5, 8, 7, 4 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 11, 3, 2, 5, 6, 10 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 7, 4, 8, 2, 11, 3 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 2, 1, 10, 7, 11, 6 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 10, 2, 1, 4, 5, 9 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 1, 0, 9, 6, 10, 5 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 9, 1, 0, 7, 4, 8 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 0, 9, 1, 11, 3, 2 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 8, 0, 3, 6, 7, 11 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 4, 5, 9, 3, 8, 0 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 3, 8, 0, 10, 2, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 3.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling3_2[24][12] = { +/* 5: 0, 2, */ { 10, 3, 2, 10, 8, 3, 10, 1, 0, 8, 10, 0 }, +/* 33: 0, 5, */ { 3, 4, 8, 3, 5, 4, 3, 0, 9, 5, 3, 9 }, +/* 129: 0, 7, */ { 6, 8, 7, 6, 0, 8, 6, 11, 3, 0, 6, 3 }, +/* 10: 1, 3, */ { 11, 0, 3, 11, 9, 0, 11, 2, 1, 9, 11, 1 }, +/* 18: 1, 4, */ { 7, 9, 4, 7, 1, 9, 7, 8, 0, 1, 7, 0 }, +/* 66: 1, 6, */ { 6, 1, 10, 6, 0, 1, 9, 0, 6, 9, 6, 5 }, +/* 36: 2, 5, */ { 4, 10, 5, 4, 2, 10, 4, 9, 1, 2, 4, 1 }, +/* 132: 2, 7, */ { 7, 2, 11, 7, 1, 2, 7, 6, 10, 1, 7, 10 }, +/* 24: 3, 4, */ { 2, 7, 11, 2, 4, 7, 2, 3, 8, 4, 2, 8 }, +/* 72: 3, 6, */ { 5, 11, 6, 5, 3, 11, 5, 10, 2, 3, 5, 2 }, +/* 80: 4, 6, */ { 8, 6, 7, 8, 10, 6, 8, 4, 5, 10, 8, 5 }, +/* 160: 5, 7, */ { 11, 5, 6, 11, 9, 5, 11, 7, 4, 9, 11, 4 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 6, 5, 11, 5, 9, 11, 4, 7, 11, 4, 11, 9 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 7, 6, 8, 6, 10, 8, 5, 4, 8, 5, 8, 10 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 6, 11, 5, 11, 3, 5, 2, 10, 5, 2, 5, 3 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 11, 7, 2, 7, 4, 2, 8, 3, 2, 8, 2, 4 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 11, 2, 7, 2, 1, 7, 10, 6, 7, 10, 7, 1 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 5, 10, 4, 10, 2, 4, 1, 9, 4, 1, 4, 2 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 10, 1, 6, 1, 0, 6, 6, 0, 9, 5, 6, 9 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 4, 9, 7, 9, 1, 7, 0, 8, 7, 0, 7, 1 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 3, 0, 11, 0, 9, 11, 1, 2, 11, 1, 11, 9 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 7, 8, 6, 8, 0, 6, 3, 11, 6, 3, 6, 0 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 8, 4, 3, 4, 5, 3, 9, 0, 3, 9, 3, 5 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 2, 3, 10, 3, 8, 10, 0, 1, 10, 0, 10, 8 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 4 + * Interior to test + * When the test on the interior is negative : 2 first triangles + * When the test on the interior is positive : 6 last triangles + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test4[8] = { +/* 65: 0, 6, */ 7, +/* 130: 1, 7, */ 7, +/* 20: 2, 4, */ 7, +/* 40: 3, 5, */ 7, +/* 215: 0, 1, 2, 4, 6, 7, */ -7, +/* 235: 0, 1, 3, 5, 6, 7, */ -7, +/* 125: 0, 2, 3, 4, 5, 6, */ -7, +/* 190: 1, 2, 3, 4, 5, 7, */ -7 +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 4.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling4_1[8][6] = { +/* 65: 0, 6, */ { 0, 8, 3, 5, 10, 6 }, +/* 130: 1, 7, */ { 0, 1, 9, 11, 7, 6 }, +/* 20: 2, 4, */ { 1, 2, 10, 8, 4, 7 }, +/* 40: 3, 5, */ { 9, 5, 4, 2, 3, 11 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 4, 5, 9, 11, 3, 2 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 10, 2, 1, 7, 4, 8 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 9, 1, 0, 6, 7, 11 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 3, 8, 0, 6, 10, 5 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 4.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling4_2[8][18] = { +/* 65: 0, 6, */ { 8, 5, 0, 5, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 5 }, +/* 130: 1, 7, */ { 9, 6, 1, 6, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 6 }, +/* 20: 2, 4, */ { 10, 7, 2, 7, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 7 }, +/* 40: 3, 5, */ { 11, 4, 3, 4, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 4 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 3, 4, 11, 5, 11, 4, 11, 5, 2, 9, 2, 5, 2, 9, 3, 4, 3, 9 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 2, 7, 10, 4, 10, 7, 10, 4, 1, 8, 1, 4, 1, 8, 2, 7, 2, 8 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 1, 6, 9, 7, 9, 6, 9, 7, 0, 11, 0, 7, 0, 11, 1, 6, 1, 11 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 0, 5, 8, 6, 8, 5, 8, 6, 3, 10, 3, 6, 3, 10, 0, 5, 0, 10 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 5 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling5[48][9] = { +/* 7: 0, 1, 2, */ { 2, 8, 3, 2, 10, 8, 10, 9, 8 }, +/* 11: 0, 1, 3, */ { 1, 11, 2, 1, 9, 11, 9, 8, 11 }, +/* 19: 0, 1, 4, */ { 4, 1, 9, 4, 7, 1, 7, 3, 1 }, +/* 35: 0, 1, 5, */ { 8, 5, 4, 8, 3, 5, 3, 1, 5 }, +/* 13: 0, 2, 3, */ { 0, 10, 1, 0, 8, 10, 8, 11, 10 }, +/* 25: 0, 3, 4, */ { 11, 4, 7, 11, 2, 4, 2, 0, 4 }, +/* 137: 0, 3, 7, */ { 7, 0, 8, 7, 6, 0, 6, 2, 0 }, +/* 49: 0, 4, 5, */ { 9, 3, 0, 9, 5, 3, 5, 7, 3 }, +/* 145: 0, 4, 7, */ { 3, 6, 11, 3, 0, 6, 0, 4, 6 }, +/* 14: 1, 2, 3, */ { 3, 9, 0, 3, 11, 9, 11, 10, 9 }, +/* 38: 1, 2, 5, */ { 5, 2, 10, 5, 4, 2, 4, 0, 2 }, +/* 70: 1, 2, 6, */ { 9, 6, 5, 9, 0, 6, 0, 2, 6 }, +/* 50: 1, 4, 5, */ { 0, 7, 8, 0, 1, 7, 1, 5, 7 }, +/* 98: 1, 5, 6, */ { 10, 0, 1, 10, 6, 0, 6, 4, 0 }, +/* 76: 2, 3, 6, */ { 6, 3, 11, 6, 5, 3, 5, 1, 3 }, +/* 140: 2, 3, 7, */ { 10, 7, 6, 10, 1, 7, 1, 3, 7 }, +/* 100: 2, 5, 6, */ { 1, 4, 9, 1, 2, 4, 2, 6, 4 }, +/* 196: 2, 6, 7, */ { 11, 1, 2, 11, 7, 1, 7, 5, 1 }, +/* 152: 3, 4, 7, */ { 8, 2, 3, 8, 4, 2, 4, 6, 2 }, +/* 200: 3, 6, 7, */ { 2, 5, 10, 2, 3, 5, 3, 7, 5 }, +/* 112: 4, 5, 6, */ { 7, 10, 6, 7, 8, 10, 8, 9, 10 }, +/* 176: 4, 5, 7, */ { 6, 9, 5, 6, 11, 9, 11, 8, 9 }, +/* 208: 4, 6, 7, */ { 5, 8, 4, 5, 10, 8, 10, 11, 8 }, +/* 224: 5, 6, 7, */ { 4, 11, 7, 4, 9, 11, 9, 10, 11 }, +/* 31: 0, 1, 2, 3, 4, */ { 4, 7, 11, 4, 11, 9, 9, 11, 10 }, +/* 47: 0, 1, 2, 3, 5, */ { 5, 4, 8, 5, 8, 10, 10, 8, 11 }, +/* 79: 0, 1, 2, 3, 6, */ { 6, 5, 9, 6, 9, 11, 11, 9, 8 }, +/* 143: 0, 1, 2, 3, 7, */ { 7, 6, 10, 7, 10, 8, 8, 10, 9 }, +/* 55: 0, 1, 2, 4, 5, */ { 2, 10, 5, 2, 5, 3, 3, 5, 7 }, +/* 103: 0, 1, 2, 5, 6, */ { 8, 3, 2, 8, 2, 4, 4, 2, 6 }, +/* 59: 0, 1, 3, 4, 5, */ { 11, 2, 1, 11, 1, 7, 7, 1, 5 }, +/* 155: 0, 1, 3, 4, 7, */ { 1, 9, 4, 1, 4, 2, 2, 4, 6 }, +/* 115: 0, 1, 4, 5, 6, */ { 10, 6, 7, 10, 7, 1, 1, 7, 3 }, +/* 179: 0, 1, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 5, 3, 1 }, +/* 157: 0, 2, 3, 4, 7, */ { 10, 1, 0, 10, 0, 6, 6, 0, 4 }, +/* 205: 0, 2, 3, 6, 7, */ { 0, 8, 7, 0, 7, 1, 1, 7, 5 }, +/* 185: 0, 3, 4, 5, 7, */ { 9, 5, 6, 9, 6, 0, 0, 6, 2 }, +/* 217: 0, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 4, 2, 0 }, +/* 241: 0, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 11, 9, 10 }, +/* 110: 1, 2, 3, 5, 6, */ { 3, 11, 6, 3, 6, 0, 0, 6, 4 }, +/* 206: 1, 2, 3, 6, 7, */ { 9, 0, 3, 9, 3, 5, 5, 3, 7 }, +/* 118: 1, 2, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 6, 0, 2 }, +/* 230: 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 2, 4, 0 }, +/* 242: 1, 4, 5, 6, 7, */ { 0, 1, 10, 0, 10, 8, 8, 10, 11 }, +/* 220: 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 3, 5, 1 }, +/* 236: 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 7, 1, 3 }, +/* 244: 2, 4, 5, 6, 7, */ { 1, 2, 11, 1, 11, 9, 9, 11, 8 }, +/* 248: 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 10, 8, 9 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief test table for case 6 + * 1 face to test + eventually the interior + * When the test on the specified face is positive : 5 first triangles + * When the test on the specified face is negative : + * - if the test on the interior is negative : 3 middle triangles + * - if the test on the interior is positive : 8 last triangles + * The support edge for the interior test is marked as the 3rd column. + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test6[48][3] = { +/* 67: 0, 1, 6, */ { 2, 7, 10 }, +/* 131: 0, 1, 7, */ { 4, 7, 11 }, +/* 21: 0, 2, 4, */ { 5, 7, 1 }, +/* 69: 0, 2, 6, */ { 5, 7, 3 }, +/* 41: 0, 3, 5, */ { 1, 7, 9 }, +/* 73: 0, 3, 6, */ { 3, 7, 10 }, +/* 81: 0, 4, 6, */ { 6, 7, 5 }, +/* 97: 0, 5, 6, */ { 1, 7, 8 }, +/* 193: 0, 6, 7, */ { 4, 7, 8 }, +/* 22: 1, 2, 4, */ { 1, 7, 8 }, +/* 134: 1, 2, 7, */ { 3, 7, 11 }, +/* 42: 1, 3, 5, */ { 5, 7, 2 }, +/* 138: 1, 3, 7, */ { 5, 7, 0 }, +/* 146: 1, 4, 7, */ { 1, 7, 9 }, +/* 162: 1, 5, 7, */ { 6, 7, 6 }, +/* 194: 1, 6, 7, */ { 2, 7, 9 }, +/* 28: 2, 3, 4, */ { 4, 7, 8 }, +/* 44: 2, 3, 5, */ { 2, 7, 9 }, +/* 52: 2, 4, 5, */ { 2, 7, 10 }, +/* 84: 2, 4, 6, */ { 6, 7, 7 }, +/* 148: 2, 4, 7, */ { 3, 7, 10 }, +/* 56: 3, 4, 5, */ { 4, 7, 11 }, +/* 104: 3, 5, 6, */ { 3, 7, 11 }, +/* 168: 3, 5, 7, */ { 6, 7, 4 }, +/* 87: 0, 1, 2, 4, 6, */ { -6, -7, 4 }, +/* 151: 0, 1, 2, 4, 7, */ { -3, -7, 11 }, +/* 199: 0, 1, 2, 6, 7, */ { -4, -7, 11 }, +/* 107: 0, 1, 3, 5, 6, */ { -3, -7, 10 }, +/* 171: 0, 1, 3, 5, 7, */ { -6, -7, 7 }, +/* 203: 0, 1, 3, 6, 7, */ { -2, -7, 10 }, +/* 211: 0, 1, 4, 6, 7, */ { -2, -7, 9 }, +/* 227: 0, 1, 5, 6, 7, */ { -4, -7, 8 }, +/* 61: 0, 2, 3, 4, 5, */ { -2, -7, 9 }, +/* 93: 0, 2, 3, 4, 6, */ { -6, -7, 6 }, +/* 109: 0, 2, 3, 5, 6, */ { -1, -7, 9 }, +/* 117: 0, 2, 4, 5, 6, */ { -5, -7, 0 }, +/* 213: 0, 2, 4, 6, 7, */ { -5, -7, 2 }, +/* 121: 0, 3, 4, 5, 6, */ { -3, -7, 11 }, +/* 233: 0, 3, 5, 6, 7, */ { -1, -7, 8 }, +/* 62: 1, 2, 3, 4, 5, */ { -4, -7, 8 }, +/* 158: 1, 2, 3, 4, 7, */ { -1, -7, 8 }, +/* 174: 1, 2, 3, 5, 7, */ { -6, -7, 5 }, +/* 182: 1, 2, 4, 5, 7, */ { -3, -7, 10 }, +/* 214: 1, 2, 4, 6, 7, */ { -1, -7, 9 }, +/* 186: 1, 3, 4, 5, 7, */ { -5, -7, 3 }, +/* 234: 1, 3, 5, 6, 7, */ { -5, -7, 1 }, +/* 124: 2, 3, 4, 5, 6, */ { -4, -7, 11 }, +/* 188: 2, 3, 4, 5, 7, */ { -2, -7, 10 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 6.1.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling6_1_1[48][9] = { +/* 67: 0, 1, 6, */ { 6, 5, 10, 3, 1, 8, 9, 8, 1 }, +/* 131: 0, 1, 7, */ { 11, 7, 6, 9, 3, 1, 3, 9, 8 }, +/* 21: 0, 2, 4, */ { 1, 2, 10, 7, 0, 4, 0, 7, 3 }, +/* 69: 0, 2, 6, */ { 3, 0, 8, 5, 2, 6, 2, 5, 1 }, +/* 41: 0, 3, 5, */ { 5, 4, 9, 2, 0, 11, 8, 11, 0 }, +/* 73: 0, 3, 6, */ { 10, 6, 5, 8, 2, 0, 2, 8, 11 }, +/* 81: 0, 4, 6, */ { 10, 6, 5, 0, 4, 3, 7, 3, 4 }, +/* 97: 0, 5, 6, */ { 3, 0, 8, 6, 4, 10, 9, 10, 4 }, +/* 193: 0, 6, 7, */ { 8, 3, 0, 10, 7, 5, 7, 10, 11 }, +/* 22: 1, 2, 4, */ { 8, 4, 7, 10, 0, 2, 0, 10, 9 }, +/* 134: 1, 2, 7, */ { 7, 6, 11, 0, 2, 9, 10, 9, 2 }, +/* 42: 1, 3, 5, */ { 2, 3, 11, 4, 1, 5, 1, 4, 0 }, +/* 138: 1, 3, 7, */ { 0, 1, 9, 6, 3, 7, 3, 6, 2 }, +/* 146: 1, 4, 7, */ { 9, 0, 1, 11, 4, 6, 4, 11, 8 }, +/* 162: 1, 5, 7, */ { 11, 7, 6, 1, 5, 0, 4, 0, 5 }, +/* 194: 1, 6, 7, */ { 0, 1, 9, 7, 5, 11, 10, 11, 5 }, +/* 28: 2, 3, 4, */ { 4, 7, 8, 1, 3, 10, 11, 10, 3 }, +/* 44: 2, 3, 5, */ { 9, 5, 4, 11, 1, 3, 1, 11, 10 }, +/* 52: 2, 4, 5, */ { 10, 1, 2, 8, 5, 7, 5, 8, 9 }, +/* 84: 2, 4, 6, */ { 8, 4, 7, 2, 6, 1, 5, 1, 6 }, +/* 148: 2, 4, 7, */ { 1, 2, 10, 4, 6, 8, 11, 8, 6 }, +/* 56: 3, 4, 5, */ { 2, 3, 11, 5, 7, 9, 8, 9, 7 }, +/* 104: 3, 5, 6, */ { 11, 2, 3, 9, 6, 4, 6, 9, 10 }, +/* 168: 3, 5, 7, */ { 9, 5, 4, 3, 7, 2, 6, 2, 7 }, +/* 87: 0, 1, 2, 4, 6, */ { 4, 5, 9, 2, 7, 3, 7, 2, 6 }, +/* 151: 0, 1, 2, 4, 7, */ { 3, 2, 11, 4, 6, 9, 10, 9, 6 }, +/* 199: 0, 1, 2, 6, 7, */ { 11, 3, 2, 9, 7, 5, 7, 9, 8 }, +/* 107: 0, 1, 3, 5, 6, */ { 10, 2, 1, 8, 6, 4, 6, 8, 11 }, +/* 171: 0, 1, 3, 5, 7, */ { 7, 4, 8, 1, 6, 2, 6, 1, 5 }, +/* 203: 0, 1, 3, 6, 7, */ { 2, 1, 10, 7, 5, 8, 9, 8, 5 }, +/* 211: 0, 1, 4, 6, 7, */ { 4, 5, 9, 3, 1, 11, 10, 11, 1 }, +/* 227: 0, 1, 5, 6, 7, */ { 8, 7, 4, 10, 3, 1, 3, 10, 11 }, +/* 61: 0, 2, 3, 4, 5, */ { 9, 1, 0, 11, 5, 7, 5, 11, 10 }, +/* 93: 0, 2, 3, 4, 6, */ { 6, 7, 11, 0, 5, 1, 5, 0, 4 }, +/* 109: 0, 2, 3, 5, 6, */ { 1, 0, 9, 6, 4, 11, 8, 11, 4 }, +/* 117: 0, 2, 4, 5, 6, */ { 9, 1, 0, 7, 3, 6, 2, 6, 3 }, +/* 213: 0, 2, 4, 6, 7, */ { 11, 3, 2, 5, 1, 4, 0, 4, 1 }, +/* 121: 0, 3, 4, 5, 6, */ { 11, 6, 7, 9, 2, 0, 2, 9, 10 }, +/* 233: 0, 3, 5, 6, 7, */ { 7, 4, 8, 2, 0, 10, 9, 10, 0 }, +/* 62: 1, 2, 3, 4, 5, */ { 0, 3, 8, 5, 7, 10, 11, 10, 7 }, +/* 158: 1, 2, 3, 4, 7, */ { 8, 0, 3, 10, 4, 6, 4, 10, 9 }, +/* 174: 1, 2, 3, 5, 7, */ { 5, 6, 10, 3, 4, 0, 4, 3, 7 }, +/* 182: 1, 2, 4, 5, 7, */ { 5, 6, 10, 0, 2, 8, 11, 8, 2 }, +/* 214: 1, 2, 4, 6, 7, */ { 9, 4, 5, 11, 0, 2, 0, 11, 8 }, +/* 186: 1, 3, 4, 5, 7, */ { 8, 0, 3, 6, 2, 5, 1, 5, 2 }, +/* 234: 1, 3, 5, 6, 7, */ { 10, 2, 1, 4, 0, 7, 3, 7, 0 }, +/* 124: 2, 3, 4, 5, 6, */ { 6, 7, 11, 1, 3, 9, 8, 9, 3 }, +/* 188: 2, 3, 4, 5, 7, */ { 10, 5, 6, 8, 1, 3, 1, 8, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 6.1.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling6_1_2[48][27] = { + /* 67: 0, 1, 6, */ { 1, 12, 3, 12, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 12, 12, 9, 8, 1, 9, 12, 12, 5, 10 }, + /* 131: 0, 1, 7, */ { 1, 12, 3, 1, 11, 12, 11, 1, 6, 9, 6, 1, 6, 9, 7, 12, 7, 9, 9, 8, 12, 12, 8, 3, 11, 7, 12 }, + /* 21: 0, 2, 4, */ { 4, 12, 0, 4, 1, 12, 1, 4, 10, 7, 10, 4, 10, 7, 2, 12, 2, 7, 7, 3, 12, 12, 3, 0, 1, 2, 12 }, + /* 69: 0, 2, 6, */ { 6, 12, 2, 6, 3, 12, 3, 6, 8, 5, 8, 6, 8, 5, 0, 12, 0, 5, 5, 1, 12, 12, 1, 2, 3, 0, 12 }, + /* 41: 0, 3, 5, */ { 0, 12, 2, 12, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 12, 12, 8, 11, 0, 8, 12, 12, 4, 9 }, + /* 73: 0, 3, 6, */ { 0, 12, 2, 0, 10, 12, 10, 0, 5, 8, 5, 0, 5, 8, 6, 12, 6, 8, 8, 11, 12, 12, 11, 2, 10, 6, 12 }, + /* 81: 0, 4, 6, */ { 4, 12, 0, 12, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 12, 12, 7, 3, 4, 7, 12, 12, 6, 5 }, + /* 97: 0, 5, 6, */ { 4, 12, 6, 12, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 12, 12, 9, 10, 4, 9, 12, 12, 0, 8 }, + /* 193: 0, 6, 7, */ { 5, 12, 7, 5, 8, 12, 8, 5, 0, 10, 0, 5, 0, 10, 3, 12, 3, 10, 10, 11, 12, 12, 11, 7, 8, 3, 12 }, + /* 22: 1, 2, 4, */ { 2, 12, 0, 2, 8, 12, 8, 2, 7, 10, 7, 2, 7, 10, 4, 12, 4, 10, 10, 9, 12, 12, 9, 0, 8, 4, 12 }, + /* 134: 1, 2, 7, */ { 2, 12, 0, 12, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 12, 12, 10, 9, 2, 10, 12, 12, 6, 11 }, + /* 42: 1, 3, 5, */ { 5, 12, 1, 5, 2, 12, 2, 5, 11, 4, 11, 5, 11, 4, 3, 12, 3, 4, 4, 0, 12, 12, 0, 1, 2, 3, 12 }, + /* 138: 1, 3, 7, */ { 7, 12, 3, 7, 0, 12, 0, 7, 9, 6, 9, 7, 9, 6, 1, 12, 1, 6, 6, 2, 12, 12, 2, 3, 0, 1, 12 }, + /* 146: 1, 4, 7, */ { 6, 12, 4, 6, 9, 12, 9, 6, 1, 11, 1, 6, 1, 11, 0, 12, 0, 11, 11, 8, 12, 12, 8, 4, 9, 0, 12 }, + /* 162: 1, 5, 7, */ { 5, 12, 1, 12, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 12, 12, 4, 0, 5, 4, 12, 12, 7, 6 }, + /* 194: 1, 6, 7, */ { 5, 12, 7, 12, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 12, 12, 10, 11, 5, 10, 12, 12, 1, 9 }, + /* 28: 2, 3, 4, */ { 3, 12, 1, 12, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 12, 12, 11, 10, 3, 11, 12, 12, 7, 8 }, + /* 44: 2, 3, 5, */ { 3, 12, 1, 3, 9, 12, 9, 3, 4, 11, 4, 3, 4, 11, 5, 12, 5, 11, 11, 10, 12, 12, 10, 1, 9, 5, 12 }, + /* 52: 2, 4, 5, */ { 7, 12, 5, 7, 10, 12, 10, 7, 2, 8, 2, 7, 2, 8, 1, 12, 1, 8, 8, 9, 12, 12, 9, 5, 10, 1, 12 }, + /* 84: 2, 4, 6, */ { 6, 12, 2, 12, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 12, 12, 5, 1, 6, 5, 12, 12, 4, 7 }, + /* 148: 2, 4, 7, */ { 6, 12, 4, 12, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 12, 12, 11, 8, 6, 11, 12, 12, 2, 10 }, + /* 56: 3, 4, 5, */ { 7, 12, 5, 12, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 12, 12, 8, 9, 7, 8, 12, 12, 3, 11 }, + /* 104: 3, 5, 6, */ { 4, 12, 6, 4, 11, 12, 11, 4, 3, 9, 3, 4, 3, 9, 2, 12, 2, 9, 9, 10, 12, 12, 10, 6, 11, 2, 12 }, + /* 168: 3, 5, 7, */ { 7, 12, 3, 12, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 12, 12, 6, 2, 7, 6, 12, 12, 5, 4 }, + /* 87: 0, 1, 2, 4, 6, */ { 3, 12, 7, 3, 4, 12, 4, 3, 9, 2, 9, 3, 9, 2, 5, 12, 5, 2, 2, 6, 12, 12, 6, 7, 4, 5, 12 }, + /* 151: 0, 1, 2, 4, 7, */ { 6, 12, 4, 12, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 12, 12, 10, 9, 6, 10, 12, 12, 2, 11 }, + /* 199: 0, 1, 2, 6, 7, */ { 5, 12, 7, 5, 11, 12, 11, 5, 2, 9, 2, 5, 2, 9, 3, 12, 3, 9, 9, 8, 12, 12, 8, 7, 11, 3, 12 }, + /* 107: 0, 1, 3, 5, 6, */ { 4, 12, 6, 4, 10, 12, 10, 4, 1, 8, 1, 4, 1, 8, 2, 12, 2, 8, 8, 11, 12, 12, 11, 6, 10, 2, 12 }, + /* 171: 0, 1, 3, 5, 7, */ { 2, 12, 6, 2, 7, 12, 7, 2, 8, 1, 8, 2, 8, 1, 4, 12, 4, 1, 1, 5, 12, 12, 5, 6, 7, 4, 12 }, + /* 203: 0, 1, 3, 6, 7, */ { 5, 12, 7, 12, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 12, 12, 9, 8, 5, 9, 12, 12, 1, 10 }, + /* 211: 0, 1, 4, 6, 7, */ { 1, 12, 3, 12, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 12, 12, 10, 11, 1, 10, 12, 12, 5, 9 }, + /* 227: 0, 1, 5, 6, 7, */ { 1, 12, 3, 1, 8, 12, 8, 1, 4, 10, 4, 1, 4, 10, 7, 12, 7, 10, 10, 11, 12, 12, 11, 3, 8, 7, 12 }, + /* 61: 0, 2, 3, 4, 5, */ { 7, 12, 5, 7, 9, 12, 9, 7, 0, 11, 0, 7, 0, 11, 1, 12, 1, 11, 11, 10, 12, 12, 10, 5, 9, 1, 12 }, + /* 93: 0, 2, 3, 4, 6, */ { 1, 12, 5, 1, 6, 12, 6, 1, 11, 0, 11, 1, 11, 0, 7, 12, 7, 0, 0, 4, 12, 12, 4, 5, 6, 7, 12 }, + /* 109: 0, 2, 3, 5, 6, */ { 4, 12, 6, 12, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 12, 12, 8, 11, 4, 8, 12, 12, 0, 9 }, + /* 117: 0, 2, 4, 5, 6, */ { 3, 12, 7, 12, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 12, 12, 2, 6, 3, 2, 12, 12, 1, 0 }, + /* 213: 0, 2, 4, 6, 7, */ { 1, 12, 5, 12, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 12, 12, 0, 4, 1, 0, 12, 12, 3, 2 }, + /* 121: 0, 3, 4, 5, 6, */ { 0, 12, 2, 0, 11, 12, 11, 0, 7, 9, 7, 0, 7, 9, 6, 12, 6, 9, 9, 10, 12, 12, 10, 2, 11, 6, 12 }, + /* 233: 0, 3, 5, 6, 7, */ { 0, 12, 2, 12, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 12, 12, 9, 10, 0, 9, 12, 12, 4, 8 }, + /* 62: 1, 2, 3, 4, 5, */ { 7, 12, 5, 12, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 12, 12, 11, 10, 7, 11, 12, 12, 3, 8 }, + /* 158: 1, 2, 3, 4, 7, */ { 6, 12, 4, 6, 8, 12, 8, 6, 3, 10, 3, 6, 3, 10, 0, 12, 0, 10, 10, 9, 12, 12, 9, 4, 8, 0, 12 }, + /* 174: 1, 2, 3, 5, 7, */ { 0, 12, 4, 0, 5, 12, 5, 0, 10, 3, 10, 0, 10, 3, 6, 12, 6, 3, 3, 7, 12, 12, 7, 4, 5, 6, 12 }, + /* 182: 1, 2, 4, 5, 7, */ { 2, 12, 0, 12, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 12, 12, 11, 8, 2, 11, 12, 12, 6, 10 }, + /* 214: 1, 2, 4, 6, 7, */ { 2, 12, 0, 2, 9, 12, 9, 2, 5, 11, 5, 2, 5, 11, 4, 12, 4, 11, 11, 8, 12, 12, 8, 0, 9, 4, 12 }, + /* 186: 1, 3, 4, 5, 7, */ { 2, 12, 6, 12, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 12, 12, 1, 5, 2, 1, 12, 12, 0, 3 }, + /* 234: 1, 3, 5, 6, 7, */ { 0, 12, 4, 12, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 12, 12, 3, 7, 0, 3, 12, 12, 2, 1 }, + /* 124: 2, 3, 4, 5, 6, */ { 3, 12, 1, 12, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 12, 12, 8, 9, 3, 8, 12, 12, 7, 11 }, + /* 188: 2, 3, 4, 5, 7, */ { 3, 12, 1, 3, 10, 12, 10, 3, 6, 8, 6, 3, 6, 8, 5, 12, 5, 8, 8, 9, 12, 12, 9, 1, 10, 5, 12 }, +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 6.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling6_2[48][15] = { +/* 67: 0, 1, 6, */ { 1, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 9 }, +/* 131: 0, 1, 7, */ { 1, 11, 3, 11, 1, 6, 9, 6, 1, 6, 9, 7, 8, 7, 9 }, +/* 21: 0, 2, 4, */ { 4, 1, 0, 1, 4, 10, 7, 10, 4, 10, 7, 2, 3, 2, 7 }, +/* 69: 0, 2, 6, */ { 6, 3, 2, 3, 6, 8, 5, 8, 6, 8, 5, 0, 1, 0, 5 }, +/* 41: 0, 3, 5, */ { 0, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 8 }, +/* 73: 0, 3, 6, */ { 0, 10, 2, 10, 0, 5, 8, 5, 0, 5, 8, 6, 11, 6, 8 }, +/* 81: 0, 4, 6, */ { 4, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 7 }, +/* 97: 0, 5, 6, */ { 4, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 9 }, +/* 193: 0, 6, 7, */ { 5, 8, 7, 8, 5, 0, 10, 0, 5, 0, 10, 3, 11, 3, 10 }, +/* 22: 1, 2, 4, */ { 2, 8, 0, 8, 2, 7, 10, 7, 2, 7, 10, 4, 9, 4, 10 }, +/* 134: 1, 2, 7, */ { 2, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 10 }, +/* 42: 1, 3, 5, */ { 5, 2, 1, 2, 5, 11, 4, 11, 5, 11, 4, 3, 0, 3, 4 }, +/* 138: 1, 3, 7, */ { 7, 0, 3, 0, 7, 9, 6, 9, 7, 9, 6, 1, 2, 1, 6 }, +/* 146: 1, 4, 7, */ { 6, 9, 4, 9, 6, 1, 11, 1, 6, 1, 11, 0, 8, 0, 11 }, +/* 162: 1, 5, 7, */ { 5, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 4 }, +/* 194: 1, 6, 7, */ { 5, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 10 }, +/* 28: 2, 3, 4, */ { 3, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 11 }, +/* 44: 2, 3, 5, */ { 3, 9, 1, 9, 3, 4, 11, 4, 3, 4, 11, 5, 10, 5, 11 }, +/* 52: 2, 4, 5, */ { 7, 10, 5, 10, 7, 2, 8, 2, 7, 2, 8, 1, 9, 1, 8 }, +/* 84: 2, 4, 6, */ { 6, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 5 }, +/* 148: 2, 4, 7, */ { 6, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 11 }, +/* 56: 3, 4, 5, */ { 7, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 8 }, +/* 104: 3, 5, 6, */ { 4, 11, 6, 11, 4, 3, 9, 3, 4, 3, 9, 2, 10, 2, 9 }, +/* 168: 3, 5, 7, */ { 7, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 6 }, +/* 87: 0, 1, 2, 4, 6, */ { 3, 4, 7, 4, 3, 9, 2, 9, 3, 9, 2, 5, 6, 5, 2 }, +/* 151: 0, 1, 2, 4, 7, */ { 6, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 10 }, +/* 199: 0, 1, 2, 6, 7, */ { 5, 11, 7, 11, 5, 2, 9, 2, 5, 2, 9, 3, 8, 3, 9 }, +/* 107: 0, 1, 3, 5, 6, */ { 4, 10, 6, 10, 4, 1, 8, 1, 4, 1, 8, 2, 11, 2, 8 }, +/* 171: 0, 1, 3, 5, 7, */ { 2, 7, 6, 7, 2, 8, 1, 8, 2, 8, 1, 4, 5, 4, 1 }, +/* 203: 0, 1, 3, 6, 7, */ { 5, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 9 }, +/* 211: 0, 1, 4, 6, 7, */ { 1, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 10 }, +/* 227: 0, 1, 5, 6, 7, */ { 1, 8, 3, 8, 1, 4, 10, 4, 1, 4, 10, 7, 11, 7, 10 }, +/* 61: 0, 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 0, 11, 0, 7, 0, 11, 1, 10, 1, 11 }, +/* 93: 0, 2, 3, 4, 6, */ { 1, 6, 5, 6, 1, 11, 0, 11, 1, 11, 0, 7, 4, 7, 0 }, +/* 109: 0, 2, 3, 5, 6, */ { 4, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 8 }, +/* 117: 0, 2, 4, 5, 6, */ { 3, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 2 }, +/* 213: 0, 2, 4, 6, 7, */ { 1, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 0 }, +/* 121: 0, 3, 4, 5, 6, */ { 0, 11, 2, 11, 0, 7, 9, 7, 0, 7, 9, 6, 10, 6, 9 }, +/* 233: 0, 3, 5, 6, 7, */ { 0, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 9 }, +/* 62: 1, 2, 3, 4, 5, */ { 7, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 11 }, +/* 158: 1, 2, 3, 4, 7, */ { 6, 8, 4, 8, 6, 3, 10, 3, 6, 3, 10, 0, 9, 0, 10 }, +/* 174: 1, 2, 3, 5, 7, */ { 0, 5, 4, 5, 0, 10, 3, 10, 0, 10, 3, 6, 7, 6, 3 }, +/* 182: 1, 2, 4, 5, 7, */ { 2, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 11 }, +/* 214: 1, 2, 4, 6, 7, */ { 2, 9, 0, 9, 2, 5, 11, 5, 2, 5, 11, 4, 8, 4, 11 }, +/* 186: 1, 3, 4, 5, 7, */ { 2, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 1 }, +/* 234: 1, 3, 5, 6, 7, */ { 0, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 3 }, +/* 124: 2, 3, 4, 5, 6, */ { 3, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 8 }, +/* 188: 2, 3, 4, 5, 7, */ { 3, 10, 1, 10, 3, 6, 8, 6, 3, 6, 8, 5, 9, 5, 8 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 7 + * 3 faces to test + eventually the interior + * When the tests on the 3 specified faces are positive : + * - if the test on the interior is positive : 5 first triangles + * - if the test on the interior is negative : 9 next triangles + * When the tests on the first and the second specified faces are positive : 9 next triangles + * When the tests on the first and the third specified faces are positive : 9 next triangles + * When the tests on the second and the third specified faces are positive : 9 next triangles + * When the test on the first specified face is positive : 5 next triangles + * When the test on the second specified face is positive : 5 next triangles + * When the test on the third specified face is positive : 5 next triangles + * When the tests on the 3 specified faces are negative : 3 last triangles + * The support edge for the interior test is marked as the 5th column. + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test7[16][5] = { +/* 37: 0, 2, 5, */ { 1, 2, 5, 7, 1 }, +/* 133: 0, 2, 7, */ { 3, 4, 5, 7, 3 }, +/* 161: 0, 5, 7, */ { 4, 1, 6, 7, 4 }, +/* 26: 1, 3, 4, */ { 4, 1, 5, 7, 0 }, +/* 74: 1, 3, 6, */ { 2, 3, 5, 7, 2 }, +/* 82: 1, 4, 6, */ { 1, 2, 6, 7, 5 }, +/* 164: 2, 5, 7, */ { 2, 3, 6, 7, 6 }, +/* 88: 3, 4, 6, */ { 3, 4, 6, 7, 7 }, +/* 167: 0, 1, 2, 5, 7, */ { -3, -4, -6, -7, 7 }, +/* 91: 0, 1, 3, 4, 6, */ { -2, -3, -6, -7, 6 }, +/* 173: 0, 2, 3, 5, 7, */ { -1, -2, -6, -7, 5 }, +/* 181: 0, 2, 4, 5, 7, */ { -2, -3, -5, -7, 2 }, +/* 229: 0, 2, 5, 6, 7, */ { -4, -1, -5, -7, 0 }, +/* 94: 1, 2, 3, 4, 6, */ { -4, -1, -6, -7, 4 }, +/* 122: 1, 3, 4, 5, 6, */ { -3, -4, -5, -7, 3 }, +/* 218: 1, 3, 4, 6, 7, */ { -1, -2, -5, -7, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_1[16][9] = { +/* 37: 0, 2, 5, */ { 9, 5, 4, 10, 1, 2, 8, 3, 0 }, +/* 133: 0, 2, 7, */ { 11, 7, 6, 8, 3, 0, 10, 1, 2 }, +/* 161: 0, 5, 7, */ { 3, 0, 8, 5, 4, 9, 7, 6, 11 }, +/* 26: 1, 3, 4, */ { 8, 4, 7, 9, 0, 1, 11, 2, 3 }, +/* 74: 1, 3, 6, */ { 10, 6, 5, 11, 2, 3, 9, 0, 1 }, +/* 82: 1, 4, 6, */ { 0, 1, 9, 6, 5, 10, 4, 7, 8 }, +/* 164: 2, 5, 7, */ { 1, 2, 10, 7, 6, 11, 5, 4, 9 }, +/* 88: 3, 4, 6, */ { 2, 3, 11, 4, 7, 8, 6, 5, 10 }, +/* 167: 0, 1, 2, 5, 7, */ { 11, 3, 2, 8, 7, 4, 10, 5, 6 }, +/* 91: 0, 1, 3, 4, 6, */ { 10, 2, 1, 11, 6, 7, 9, 4, 5 }, +/* 173: 0, 2, 3, 5, 7, */ { 9, 1, 0, 10, 5, 6, 8, 7, 4 }, +/* 181: 0, 2, 4, 5, 7, */ { 5, 6, 10, 3, 2, 11, 1, 0, 9 }, +/* 229: 0, 2, 5, 6, 7, */ { 7, 4, 8, 1, 0, 9, 3, 2, 11 }, +/* 94: 1, 2, 3, 4, 6, */ { 8, 0, 3, 9, 4, 5, 11, 6, 7 }, +/* 122: 1, 3, 4, 5, 6, */ { 6, 7, 11, 0, 3, 8, 2, 1, 10 }, +/* 218: 1, 3, 4, 6, 7, */ { 4, 5, 9, 2, 1, 10, 0, 3, 8 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_2[16][3][15] = { +/* 37: 0, 2, 5, */ { + /* 1,0 */ { 1, 2, 10, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, + /* 0,1 */ { 3, 0, 8, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, + /* 1,1 */ { 9, 5, 4, 0, 10, 1, 10, 0, 8, 10, 8, 2, 3, 2, 8 } +}, +/* 133: 0, 2, 7, */ { + /* 1,0 */ { 3, 0, 8, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, + /* 0,1 */ { 1, 2, 10, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, + /* 1,1 */ { 11, 7, 6, 2, 8, 3, 8, 2, 10, 8, 10, 0, 1, 0, 10 } +}, +/* 161: 0, 5, 7, */ { + /* 1,0 */ { 9, 5, 4, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, + /* 0,1 */ { 11, 7, 6, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, + /* 1,1 */ { 3, 0, 8, 4, 9, 7, 11, 7, 9, 5, 11, 9, 11, 5, 6 } +}, +/* 26: 1, 3, 4, */ { + /* 1,0 */ { 0, 1, 9, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, + /* 0,1 */ { 2, 3, 11, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, + /* 1,1 */ { 8, 4, 7, 3, 9, 0, 9, 3, 11, 9, 11, 1, 2, 1, 11 } +}, +/* 74: 1, 3, 6, */ { + /* 1,0 */ { 2, 3, 11, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, + /* 0,1 */ { 0, 1, 9, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, + /* 1,1 */ { 6, 5, 10, 1, 11, 2, 11, 1, 9, 11, 9, 3, 0, 3, 9 } +}, +/* 82: 1, 4, 6, */ { + /* 1,0 */ { 6, 5, 10, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, + /* 0,1 */ { 8, 4, 7, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, + /* 1,1 */ { 0, 1, 9, 5, 10, 4, 8, 4, 10, 6, 8, 10, 8, 6, 7 } +}, +/* 164: 2, 5, 7, */ { + /* 1,0 */ { 11, 7, 6, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, + /* 0,1 */ { 9, 5, 4, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, + /* 1,1 */ { 1, 2, 10, 6, 11, 5, 9, 5, 11, 7, 9, 11, 9, 7, 4 } +}, +/* 88: 3, 4, 6, */ { + /* 1,0 */ { 8, 4, 7, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, + /* 0,1 */ { 6, 5, 10, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, + /* 1,1 */ { 2, 3, 11, 7, 8, 6, 10, 6, 8, 4, 10, 8, 10, 4, 5 } +}, +/* 167: 0, 1, 2, 5, 7, */ { + /* 1,0 */ { 7, 4, 8, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, + /* 0,1 */ { 10, 5, 6, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, + /* 1,1 */ { 11, 3, 2, 6, 8, 7, 8, 6, 10, 8, 10, 4, 5, 4, 10 } +}, +/* 91: 0, 1, 3, 4, 6, */ { + /* 1,0 */ { 6, 7, 11, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, + /* 0,1 */ { 4, 5, 9, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, + /* 1,1 */ { 10, 2, 1, 5, 11, 6, 11, 5, 9, 11, 9, 7, 4, 7, 9 } +}, +/* 173: 0, 2, 3, 5, 7, */ { + /* 1,0 */ { 10, 5, 6, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, + /* 0,1 */ { 7, 4, 8, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, + /* 1,1 */ { 9, 1, 0, 4, 10, 5, 10, 4, 8, 10, 8, 6, 7, 6, 8 } +}, +/* 181: 0, 2, 4, 5, 7, */ { + /* 1,0 */ { 11, 3, 2, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, + /* 0,1 */ { 9, 1, 0, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, + /* 1,1 */ { 10, 5, 6, 2, 11, 1, 9, 1, 11, 3, 9, 11, 9, 3, 0 } +}, +/* 229: 0, 2, 5, 6, 7, */ { + /* 1,0 */ { 9, 1, 0, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, + /* 0,1 */ { 11, 3, 2, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, + /* 1,1 */ { 7, 4, 8, 0, 9, 3, 11, 3, 9, 1, 11, 9, 11, 1, 2 } +}, +/* 94: 1, 2, 3, 4, 6, */ { + /* 1,0 */ { 4, 5, 9, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, + /* 0,1 */ { 6, 7, 11, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, + /* 1,1 */ { 8, 0, 3, 7, 9, 4, 9, 7, 11, 9, 11, 5, 6, 5, 11 } +}, +/* 122: 1, 3, 4, 5, 6, */ { + /* 1,0 */ { 8, 0, 3, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, + /* 0,1 */ { 10, 2, 1, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, + /* 1,1 */ { 6, 7, 11, 3, 8, 2, 10, 2, 8, 0, 10, 8, 10, 0, 1 } +}, +/* 218: 1, 3, 4, 6, 7, */ { + /* 1,0 */ { 10, 2, 1, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, + /* 0,1 */ { 8, 0, 3, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, + /* 1,1 */ { 4, 5, 9, 1, 10, 0, 8, 0, 10, 2, 8, 10, 8, 2, 3 } } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.3 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_3[16][3][27] = { +/* 37: 0, 2, 5, */ { + /* 1,0 */ { 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, + /* 0,1 */ { 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, + /* 1,1 */ { 5, 4, 12, 10, 5, 12, 2, 10, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 } +}, +/* 133: 0, 2, 7, */ { + /* 1,0 */ { 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 }, + /* 0,1 */ { 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, + /* 1,1 */ { 7, 6, 12, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 } +}, +/* 161: 0, 5, 7, */ { + /* 1,0 */ { 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12 }, + /* 0,1 */ { 3, 0, 12, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12, 8, 7, 12, 0, 8, 12 }, + /* 1,1 */ { 12, 3, 0, 12, 0, 9, 12, 9, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 } +}, +/* 26: 1, 3, 4, */ { + /* 1,0 */ { 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 }, + /* 0,1 */ { 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 8, 12, 8, 4 }, + /* 1,1 */ { 4, 7, 12, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 8, 0, 12, 7, 8, 12 } +}, +/* 74: 1, 3, 6, */ { + /* 1,0 */ { 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, + /* 0,1 */ { 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 10, 12, 10, 6 }, + /* 1,1 */ { 6, 5, 12, 11, 6, 12, 3, 11, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12 } +}, +/* 82: 1, 4, 6, */ { + /* 1,0 */ { 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12 }, + /* 0,1 */ { 0, 1, 12, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12, 9, 4, 12, 1, 9, 12 }, + /* 1,1 */ { 12, 0, 1, 12, 1, 10, 12, 10, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 } +}, +/* 164: 2, 5, 7, */ { + /* 1,0 */ { 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12 }, + /* 0,1 */ { 1, 2, 12, 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 6, 11, 12, 5, 6, 12, 10, 5, 12, 2, 10, 12 }, + /* 1,1 */ { 12, 1, 2, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 } +}, +/* 88: 3, 4, 6, */ { + /* 1,0 */ { 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12 }, + /* 0,1 */ { 2, 3, 12, 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 7, 8, 12, 6, 7, 12, 11, 6, 12, 3, 11, 12 }, + /* 1,1 */ { 12, 2, 3, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 } +}, +/* 167: 0, 1, 2, 5, 7, */ { + /* 1,0 */ { 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4 }, + /* 0,1 */ { 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 7, 12, 7, 6, 12, 6, 11, 12, 11, 3 }, + /* 1,1 */ { 3, 2, 12, 8, 3, 12, 4, 8, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 } +}, +/* 91: 0, 1, 3, 4, 6, */ { + /* 1,0 */ { 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7 }, + /* 0,1 */ { 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 6, 12, 6, 5, 12, 5, 10, 12, 10, 2 }, + /* 1,1 */ { 2, 1, 12, 11, 2, 12, 7, 11, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 } +}, +/* 173: 0, 2, 3, 5, 7, */ { + /* 1,0 */ { 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6 }, + /* 0,1 */ { 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 5, 12, 5, 4, 12, 4, 9, 12, 9, 1 }, + /* 1,1 */ { 1, 0, 12, 10, 1, 12, 6, 10, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 } +}, +/* 181: 0, 2, 4, 5, 7, */ { + /* 1,0 */ { 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, + /* 0,1 */ { 5, 6, 12, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 10, 1, 12, 6, 10, 12 }, + /* 1,1 */ { 12, 5, 6, 12, 6, 11, 12, 11, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5 } +}, +/* 229: 0, 2, 5, 6, 7, */ { + /* 1,0 */ { 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 2, 11, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12 }, + /* 0,1 */ { 7, 4, 12, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 8, 3, 12, 4, 8, 12 }, + /* 1,1 */ { 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 8, 12, 8, 7 } +}, +/* 94: 1, 2, 3, 4, 6, */ { + /* 1,0 */ { 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5 }, + /* 0,1 */ { 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 4, 12, 4, 7, 12, 7, 8, 12, 8, 0 }, + /* 1,1 */ { 0, 3, 12, 9, 0, 12, 5, 9, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 } +}, +/* 122: 1, 3, 4, 5, 6, */ { + /* 1,0 */ { 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, + /* 0,1 */ { 6, 7, 12, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, + /* 1,1 */ { 12, 6, 7, 12, 7, 8, 12, 8, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 } +}, +/* 218: 1, 3, 4, 6, 7, */ { + /* 1,0 */ { 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12 }, + /* 0,1 */ { 4, 5, 12, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, + /* 1,1 */ { 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 } } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.4.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_4_1[16][15] = { +/* 37: 0, 2, 5, */ { 3, 4, 8, 4, 3, 10, 2, 10, 3, 4, 10, 5, 9, 1, 0 }, +/* 133: 0, 2, 7, */ { 1, 6, 10, 6, 1, 8, 0, 8, 1, 6, 8, 7, 11, 3, 2 }, +/* 161: 0, 5, 7, */ { 11, 3, 6, 9, 6, 3, 6, 9, 5, 0, 9, 3, 7, 4, 8 }, +/* 26: 1, 3, 4, */ { 2, 7, 11, 7, 2, 9, 1, 9, 2, 7, 9, 4, 8, 0, 3 }, +/* 74: 1, 3, 6, */ { 0, 5, 9, 5, 0, 11, 3, 11, 0, 5, 11, 6, 10, 2, 1 }, +/* 82: 1, 4, 6, */ { 8, 0, 7, 10, 7, 0, 7, 10, 6, 1, 10, 0, 4, 5, 9 }, +/* 164: 2, 5, 7, */ { 9, 1, 4, 11, 4, 1, 4, 11, 7, 2, 11, 1, 5, 6, 10 }, +/* 88: 3, 4, 6, */ { 10, 2, 5, 8, 5, 2, 5, 8, 4, 3, 8, 2, 6, 7, 11 }, +/* 167: 0, 1, 2, 5, 7, */ { 5, 2, 10, 2, 5, 8, 4, 8, 5, 2, 8, 3, 11, 7, 6 }, +/* 91: 0, 1, 3, 4, 6, */ { 4, 1, 9, 1, 4, 11, 7, 11, 4, 1, 11, 2, 10, 6, 5 }, +/* 173: 0, 2, 3, 5, 7, */ { 7, 0, 8, 0, 7, 10, 6, 10, 7, 0, 10, 1, 9, 5, 4 }, +/* 181: 0, 2, 4, 5, 7, */ { 9, 5, 0, 11, 0, 5, 0, 11, 3, 6, 11, 5, 1, 2, 10 }, +/* 229: 0, 2, 5, 6, 7, */ { 11, 7, 2, 9, 2, 7, 2, 9, 1, 4, 9, 7, 3, 0, 8 }, +/* 94: 1, 2, 3, 4, 6, */ { 6, 3, 11, 3, 6, 9, 5, 9, 6, 3, 9, 0, 8, 4, 7 }, +/* 122: 1, 3, 4, 5, 6, */ { 10, 6, 1, 8, 1, 6, 1, 8, 0, 7, 8, 6, 2, 3, 11 }, +/* 218: 1, 3, 4, 6, 7, */ { 8, 4, 3, 10, 3, 4, 3, 10, 2, 5, 10, 4, 0, 1, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.4.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_4_2[16][27] = { +/* 37: 0, 2, 5, */ { 9, 4, 8, 4, 9, 5, 10, 5, 9, 1, 10, 9, 10, 1, 2, 0, 2, 1, 2, 0, 3, 8, 3, 0, 9, 8, 0 }, +/* 133: 0, 2, 7, */ { 11, 6, 10, 6, 11, 7, 8, 7, 11, 3, 8, 11, 8, 3, 0, 2, 0, 3, 0, 2, 1, 10, 1, 2, 11, 10, 2 }, +/* 161: 0, 5, 7, */ { 11, 3, 8, 0, 8, 3, 8, 0, 9, 8, 9, 4, 5, 4, 9, 4, 5, 7, 6, 7, 5, 7, 6, 11, 7, 11, 8 }, +/* 26: 1, 3, 4, */ { 8, 7, 11, 7, 8, 4, 9, 4, 8, 0, 9, 8, 9, 0, 1, 3, 1, 0, 1, 3, 2, 11, 2, 3, 8, 11, 3 }, +/* 74: 1, 3, 6, */ { 10, 5, 9, 5, 10, 6, 11, 6, 10, 2, 11, 10, 11, 2, 3, 1, 3, 2, 3, 1, 0, 9, 0, 1, 10, 9, 1 }, +/* 82: 1, 4, 6, */ { 8, 0, 9, 1, 9, 0, 9, 1, 10, 9, 10, 5, 6, 5, 10, 5, 6, 4, 7, 4, 6, 4, 7, 8, 4, 8, 9 }, +/* 164: 2, 5, 7, */ { 9, 1, 10, 2, 10, 1, 10, 2, 11, 10, 11, 6, 7, 6, 11, 6, 7, 5, 4, 5, 7, 5, 4, 9, 5, 9, 10 }, +/* 88: 3, 4, 6, */ { 10, 2, 11, 3, 11, 2, 11, 3, 8, 11, 8, 7, 4, 7, 8, 7, 4, 6, 5, 6, 4, 6, 5, 10, 6, 10, 11 }, +/* 167: 0, 1, 2, 5, 7, */ { 11, 2, 10, 2, 11, 3, 8, 3, 11, 7, 8, 11, 8, 7, 4, 6, 4, 7, 4, 6, 5, 10, 5, 6, 11, 10, 6 }, +/* 91: 0, 1, 3, 4, 6, */ { 10, 1, 9, 1, 10, 2, 11, 2, 10, 6, 11, 10, 11, 6, 7, 5, 7, 6, 7, 5, 4, 9, 4, 5, 10, 9, 5 }, +/* 173: 0, 2, 3, 5, 7, */ { 9, 0, 8, 0, 9, 1, 10, 1, 9, 5, 10, 9, 10, 5, 6, 4, 6, 5, 6, 4, 7, 8, 7, 4, 9, 8, 4 }, +/* 181: 0, 2, 4, 5, 7, */ { 9, 5, 10, 6, 10, 5, 10, 6, 11, 10, 11, 2, 3, 2, 11, 2, 3, 1, 0, 1, 3, 1, 0, 9, 1, 9, 10 }, +/* 229: 0, 2, 5, 6, 7, */ { 11, 7, 8, 4, 8, 7, 8, 4, 9, 8, 9, 0, 1, 0, 9, 0, 1, 3, 2, 3, 1, 3, 2, 11, 3, 11, 8 }, +/* 94: 1, 2, 3, 4, 6, */ { 8, 3, 11, 3, 8, 0, 9, 0, 8, 4, 9, 8, 9, 4, 5, 7, 5, 4, 5, 7, 6, 11, 6, 7, 8, 11, 7 }, +/* 122: 1, 3, 4, 5, 6, */ { 10, 6, 11, 7, 11, 6, 11, 7, 8, 11, 8, 3, 0, 3, 8, 3, 0, 2, 1, 2, 0, 2, 1, 10, 2, 10, 11 }, +/* 218: 1, 3, 4, 6, 7, */ { 8, 4, 9, 5, 9, 4, 9, 5, 10, 9, 10, 1, 2, 1, 10, 1, 2, 0, 3, 0, 2, 0, 3, 8, 0, 8, 9 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 8 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling8[6][6] = { +/* 15: 0, 1, 2, 3, */ { 9, 8, 10, 10, 8, 11 }, +/* 51: 0, 1, 4, 5, */ { 1, 5, 3, 3, 5, 7 }, +/* 153: 0, 3, 4, 7, */ { 0, 4, 2, 4, 6, 2 }, +/* 102: 1, 2, 5, 6, */ { 0, 2, 4, 4, 2, 6 }, +/* 204: 2, 3, 6, 7, */ { 1, 3, 5, 3, 7, 5 }, +/* 240: 4, 5, 6, 7, */ { 9, 10, 8, 10, 11, 8 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 9 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling9[8][12] = { +/* 39: 0, 1, 2, 5, */ { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8 }, +/* 27: 0, 1, 3, 4, */ { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1 }, +/* 141: 0, 2, 3, 7, */ { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8 }, +/* 177: 0, 4, 5, 7, */ { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5 }, +/* 78: 1, 2, 3, 6, */ { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9 }, +/* 114: 1, 4, 5, 6, */ { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0 }, +/* 228: 2, 5, 6, 7, */ { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2 }, +/* 216: 3, 4, 6, 7, */ { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 10 + * 2 faces to test + eventually the interior + * When the tests on both specified faces are positive : 4 middle triangles (1) + * When the test on the first specified face is positive : 8 first triangles + * When the test on the second specified face is positive : 8 next triangles + * When the tests on both specified faces are negative : + * - if the test on the interior is negative : 4 middle triangles + * - if the test on the interior is positive : 8 last triangles + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test10[6][3] = { +/* 195: 0, 1, 6, 7, */ { 2, 4, 7 }, +/* 85: 0, 2, 4, 6, */ { 5, 6, 7 }, +/* 105: 0, 3, 5, 6, */ { 1, 3, 7 }, +/* 150: 1, 2, 4, 7, */ { 1, 3, 7 }, +/* 170: 1, 3, 5, 7, */ { 5, 6, 7 }, +/* 60: 2, 3, 4, 5, */ { 2, 4, 7 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.1.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_1_1[6][12] = { +/* 195: 0, 1, 6, 7, */ { 5, 10, 7, 11, 7, 10, 8, 1, 9, 1, 8, 3 }, +/* 85: 0, 2, 4, 6, */ { 1, 2, 5, 6, 5, 2, 4, 3, 0, 3, 4, 7 }, +/* 105: 0, 3, 5, 6, */ { 11, 0, 8, 0, 11, 2, 4, 9, 6, 10, 6, 9 }, +/* 150: 1, 2, 4, 7, */ { 9, 0, 10, 2, 10, 0, 6, 8, 4, 8, 6, 11 }, +/* 170: 1, 3, 5, 7, */ { 7, 2, 3, 2, 7, 6, 0, 1, 4, 5, 4, 1 }, +/* 60: 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 8, 10, 1, 11, 3, 11, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.1.1 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_1_1_[6][12] = { +/* 195: 0, 1, 6, 7, */ { 5, 9, 7, 8, 7, 9, 11, 1, 10, 1, 11, 3 }, +/* 85: 0, 2, 4, 6, */ { 3, 2, 7, 6, 7, 2, 4, 1, 0, 1, 4, 5 }, +/* 105: 0, 3, 5, 6, */ { 10, 0, 9, 0, 10, 2, 4, 8, 6, 11, 6, 8 }, +/* 150: 1, 2, 4, 7, */ { 8, 0, 11, 2, 11, 0, 6, 9, 4, 9, 6, 10 }, +/* 170: 1, 3, 5, 7, */ { 5, 2, 1, 2, 5, 6, 0, 3, 4, 7, 4, 3 }, +/* 60: 2, 3, 4, 5, */ { 7, 10, 5, 10, 7, 11, 9, 1, 8, 3, 8, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.1.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_1_2[6][24] = { +/* 195: 0, 1, 6, 7, */ { 3, 11, 7, 3, 7, 8, 9, 8, 7, 5, 9, 7, 9, 5, 10, 9, 10, 1, 3, 1, 10, 11, 3, 10 }, +/* 85: 0, 2, 4, 6, */ { 7, 6, 5, 7, 5, 4, 0, 4, 5, 1, 0, 5, 0, 1, 2, 0, 2, 3, 7, 3, 2, 6, 7, 2 }, +/* 105: 0, 3, 5, 6, */ { 11, 2, 10, 6, 11, 10, 11, 6, 4, 11, 4, 8, 0, 8, 4, 9, 0, 4, 0, 9, 10, 0, 10, 2 }, +/* 150: 1, 2, 4, 7, */ { 11, 2, 10, 11, 10, 6, 4, 6, 10, 9, 4, 10, 4, 9, 0, 4, 0, 8, 11, 8, 0, 2, 11, 0 }, +/* 170: 1, 3, 5, 7, */ { 7, 6, 5, 4, 7, 5, 7, 4, 0, 7, 0, 3, 2, 3, 0, 1, 2, 0, 2, 1, 5, 2, 5, 6 }, +/* 60: 2, 3, 4, 5, */ { 7, 8, 3, 11, 7, 3, 7, 11, 10, 7, 10, 5, 9, 5, 10, 1, 9, 10, 9, 1, 3, 9, 3, 8 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_2[6][24] = { +/* 195: 0, 1, 6, 7, */ { 12, 5, 9, 12, 9, 8, 12, 8, 3, 12, 3, 1, 12, 1, 10, 12, 10, 11, 12, 11, 7, 12, 7, 5 }, +/* 85: 0, 2, 4, 6, */ { 12, 1, 0, 12, 0, 4, 12, 4, 7, 12, 7, 3, 12, 3, 2, 12, 2, 6, 12, 6, 5, 12, 5, 1 }, +/* 105: 0, 3, 5, 6, */ { 4, 8, 12, 6, 4, 12, 10, 6, 12, 9, 10, 12, 0, 9, 12, 2, 0, 12, 11, 2, 12, 8, 11, 12 }, +/* 150: 1, 2, 4, 7, */ { 12, 9, 4, 12, 4, 6, 12, 6, 11, 12, 11, 8, 12, 8, 0, 12, 0, 2, 12, 2, 10, 12, 10, 9 }, +/* 170: 1, 3, 5, 7, */ { 0, 3, 12, 4, 0, 12, 5, 4, 12, 1, 5, 12, 2, 1, 12, 6, 2, 12, 7, 6, 12, 3, 7, 12 }, +/* 60: 2, 3, 4, 5, */ { 10, 5, 12, 11, 10, 12, 3, 11, 12, 1, 3, 12, 9, 1, 12, 8, 9, 12, 7, 8, 12, 5, 7, 12 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.2 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_2_[6][24] = { +/* 195: 0, 1, 6, 7, */ { 8, 7, 12, 9, 8, 12, 1, 9, 12, 3, 1, 12, 11, 3, 12, 10, 11, 12, 5, 10, 12, 7, 5, 12 }, +/* 85: 0, 2, 4, 6, */ { 4, 5, 12, 0, 4, 12, 3, 0, 12, 7, 3, 12, 6, 7, 12, 2, 6, 12, 1, 2, 12, 5, 1, 12 }, +/* 105: 0, 3, 5, 6, */ { 12, 11, 6, 12, 6, 4, 12, 4, 9, 12, 9, 10, 12, 10, 2, 12, 2, 0, 12, 0, 8, 12, 8, 11 }, +/* 150: 1, 2, 4, 7, */ { 6, 10, 12, 4, 6, 12, 8, 4, 12, 11, 8, 12, 2, 11, 12, 0, 2, 12, 9, 0, 12, 10, 9, 12 }, +/* 170: 1, 3, 5, 7, */ { 12, 7, 4, 12, 4, 0, 12, 0, 1, 12, 1, 5, 12, 5, 6, 12, 6, 2, 12, 2, 3, 12, 3, 7 }, +/* 60: 2, 3, 4, 5, */ { 12, 7, 11, 12, 11, 10, 12, 10, 1, 12, 1, 3, 12, 3, 8, 12, 8, 9, 12, 9, 5, 12, 5, 7 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 11 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling11[12][12] = { +/* 23: 0, 1, 2, 4, */ { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4 }, +/* 139: 0, 1, 3, 7, */ { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6 }, +/* 99: 0, 1, 5, 6, */ { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10 }, +/* 77: 0, 2, 3, 6, */ { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6 }, +/* 57: 0, 3, 4, 5, */ { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11 }, +/* 209: 0, 4, 6, 7, */ { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0 }, +/* 46: 1, 2, 3, 5, */ { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3 }, +/* 198: 1, 2, 6, 7, */ { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7 }, +/* 178: 1, 4, 5, 7, */ { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11 }, +/* 156: 2, 3, 4, 7, */ { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1 }, +/* 116: 2, 4, 5, 6, */ { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7 }, +/* 232: 3, 5, 6, 7, */ { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief test table for case 12 + * 2 faces to test + eventually the interior + * When the tests on both specified faces are positive : 4 middle triangles (1) + * When the test on the first specified face is positive : 8 first triangles + * When the test on the second specified face is positive : 8 next triangles + * When the tests on both specified faces are negative : + * - if the test on the interior is negative : 4 middle triangles + * - if the test on the interior is positive : 8 last triangles + * The support edge for the interior test is marked as the 4th column. + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test12[24][4] = { +/* 135: 0, 1, 2, 7, */ { 4, 3, 7, 11 }, +/* 75: 0, 1, 3, 6, */ { 3, 2, 7, 10 }, +/* 83: 0, 1, 4, 6, */ { 2, 6, 7, 5 }, +/* 163: 0, 1, 5, 7, */ { 6, 4, 7, 7 }, +/* 45: 0, 2, 3, 5, */ { 2, 1, 7, 9 }, +/* 53: 0, 2, 4, 5, */ { 5, 2, 7, 1 }, +/* 149: 0, 2, 4, 7, */ { 5, 3, 7, 2 }, +/* 101: 0, 2, 5, 6, */ { 5, 1, 7, 0 }, +/* 197: 0, 2, 6, 7, */ { 5, 4, 7, 3 }, +/* 89: 0, 3, 4, 6, */ { 6, 3, 7, 6 }, +/* 169: 0, 3, 5, 7, */ { 1, 6, 7, 4 }, +/* 225: 0, 5, 6, 7, */ { 1, 4, 7, 8 }, +/* 30: 1, 2, 3, 4, */ { 4, 1, 7, 8 }, +/* 86: 1, 2, 4, 6, */ { 6, 1, 7, 4 }, +/* 166: 1, 2, 5, 7, */ { 3, 6, 7, 6 }, +/* 58: 1, 3, 4, 5, */ { 4, 5, 7, 3 }, +/* 154: 1, 3, 4, 7, */ { 1, 5, 7, 0 }, +/* 106: 1, 3, 5, 6, */ { 3, 5, 7, 2 }, +/* 202: 1, 3, 6, 7, */ { 2, 5, 7, 1 }, +/* 210: 1, 4, 6, 7, */ { 1, 2, 7, 9 }, +/* 92: 2, 3, 4, 6, */ { 4, 6, 7, 7 }, +/* 172: 2, 3, 5, 7, */ { 6, 2, 7, 5 }, +/* 180: 2, 4, 5, 7, */ { 2, 3, 7, 10 }, +/* 120: 3, 4, 5, 6, */ { 3, 4, 7, 11 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.1.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_1_1[24][12] = { +/* 135: 0, 1, 2, 7, */ { 7, 6, 11, 10, 3, 2, 3, 10, 8, 9, 8, 10 }, +/* 75: 0, 1, 3, 6, */ { 6, 5, 10, 9, 2, 1, 2, 9, 11, 8, 11, 9 }, +/* 83: 0, 1, 4, 6, */ { 10, 6, 5, 7, 9, 4, 9, 7, 1, 3, 1, 7 }, +/* 163: 0, 1, 5, 7, */ { 7, 6, 11, 4, 8, 5, 3, 5, 8, 5, 3, 1 }, +/* 45: 0, 2, 3, 5, */ { 5, 4, 9, 8, 1, 0, 1, 8, 10, 11, 10, 8 }, +/* 53: 0, 2, 4, 5, */ { 1, 2, 10, 0, 9, 3, 5, 3, 9, 3, 5, 7 }, +/* 149: 0, 2, 4, 7, */ { 10, 1, 2, 0, 11, 3, 11, 0, 6, 4, 6, 0 }, +/* 101: 0, 2, 5, 6, */ { 8, 3, 0, 2, 9, 1, 9, 2, 4, 6, 4, 2 }, +/* 197: 0, 2, 6, 7, */ { 3, 0, 8, 2, 11, 1, 7, 1, 11, 1, 7, 5 }, +/* 89: 0, 3, 4, 6, */ { 6, 5, 10, 7, 11, 4, 2, 4, 11, 4, 2, 0 }, +/* 169: 0, 3, 5, 7, */ { 9, 5, 4, 6, 8, 7, 8, 6, 0, 2, 0, 6 }, +/* 225: 0, 5, 6, 7, */ { 8, 3, 0, 7, 4, 11, 9, 11, 4, 11, 9, 10 }, +/* 30: 1, 2, 3, 4, */ { 4, 7, 8, 11, 0, 3, 0, 11, 9, 10, 9, 11 }, +/* 86: 1, 2, 4, 6, */ { 4, 7, 8, 5, 9, 6, 0, 6, 9, 6, 0, 2 }, +/* 166: 1, 2, 5, 7, */ { 11, 7, 6, 4, 10, 5, 10, 4, 2, 0, 2, 4 }, +/* 58: 1, 3, 4, 5, */ { 11, 2, 3, 1, 8, 0, 8, 1, 7, 5, 7, 1 }, +/* 154: 1, 3, 4, 7, */ { 0, 1, 9, 3, 8, 2, 4, 2, 8, 2, 4, 6 }, +/* 106: 1, 3, 5, 6, */ { 2, 3, 11, 1, 10, 0, 6, 0, 10, 0, 6, 4 }, +/* 202: 1, 3, 6, 7, */ { 9, 0, 1, 3, 10, 2, 10, 3, 5, 7, 5, 3 }, +/* 210: 1, 4, 6, 7, */ { 9, 0, 1, 4, 5, 8, 10, 8, 5, 8, 10, 11 }, +/* 92: 2, 3, 4, 6, */ { 8, 4, 7, 5, 11, 6, 11, 5, 3, 1, 3, 5 }, +/* 172: 2, 3, 5, 7, */ { 5, 4, 9, 6, 10, 7, 1, 7, 10, 7, 1, 3 }, +/* 180: 2, 4, 5, 7, */ { 10, 1, 2, 5, 6, 9, 11, 9, 6, 9, 11, 8 }, +/* 120: 3, 4, 5, 6, */ { 11, 2, 3, 6, 7, 10, 8, 10, 7, 10, 8, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.1.1 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_1_1_[24][12] = { +/* 135: 0, 1, 2, 7, */ { 3, 2, 11, 10, 7, 6, 7, 10, 8, 9, 8, 10 }, +/* 75: 0, 1, 3, 6, */ { 2, 1, 10, 9, 6, 5, 6, 9, 11, 8, 11, 9 }, +/* 83: 0, 1, 4, 6, */ { 9, 4, 5, 7, 10, 6, 10, 7, 1, 3, 1, 7 }, +/* 163: 0, 1, 5, 7, */ { 7, 4, 8, 6, 11, 5, 3, 5, 11, 5, 3, 1 }, +/* 45: 0, 2, 3, 5, */ { 1, 0, 9, 8, 5, 4, 5, 8, 10, 11, 10, 8 }, +/* 53: 0, 2, 4, 5, */ { 1, 0, 9, 2, 10, 3, 5, 3, 10, 3, 5, 7 }, +/* 149: 0, 2, 4, 7, */ { 11, 3, 2, 0, 10, 1, 10, 0, 6, 4, 6, 0 }, +/* 101: 0, 2, 5, 6, */ { 9, 1, 0, 2, 8, 3, 8, 2, 4, 6, 4, 2 }, +/* 197: 0, 2, 6, 7, */ { 3, 2, 11, 0, 8, 1, 7, 1, 8, 1, 7, 5 }, +/* 89: 0, 3, 4, 6, */ { 6, 7, 11, 5, 10, 4, 2, 4, 10, 4, 2, 0 }, +/* 169: 0, 3, 5, 7, */ { 8, 7, 4, 6, 9, 5, 9, 6, 0, 2, 0, 6 }, +/* 225: 0, 5, 6, 7, */ { 8, 7, 4, 3, 0, 11, 9, 11, 0, 11, 9, 10 }, +/* 30: 1, 2, 3, 4, */ { 0, 3, 8, 11, 4, 7, 4, 11, 9, 10, 9, 11 }, +/* 86: 1, 2, 4, 6, */ { 4, 5, 9, 7, 8, 6, 0, 6, 8, 6, 0, 2 }, +/* 166: 1, 2, 5, 7, */ { 10, 5, 6, 4, 11, 7, 11, 4, 2, 0, 2, 4 }, +/* 58: 1, 3, 4, 5, */ { 8, 0, 3, 1, 11, 2, 11, 1, 7, 5, 7, 1 }, +/* 154: 1, 3, 4, 7, */ { 0, 3, 8, 1, 9, 2, 4, 2, 9, 2, 4, 6 }, +/* 106: 1, 3, 5, 6, */ { 2, 1, 10, 3, 11, 0, 6, 0, 11, 0, 6, 4 }, +/* 202: 1, 3, 6, 7, */ { 10, 2, 1, 3, 9, 0, 9, 3, 5, 7, 5, 3 }, +/* 210: 1, 4, 6, 7, */ { 9, 4, 5, 0, 1, 8, 10, 8, 1, 8, 10, 11 }, +/* 92: 2, 3, 4, 6, */ { 11, 6, 7, 5, 8, 4, 8, 5, 3, 1, 3, 5 }, +/* 172: 2, 3, 5, 7, */ { 5, 6, 10, 4, 9, 7, 1, 7, 9, 7, 1, 3 }, +/* 180: 2, 4, 5, 7, */ { 10, 5, 6, 1, 2, 9, 11, 9, 2, 9, 11, 8 }, +/* 120: 3, 4, 5, 6, */ { 11, 6, 7, 2, 3, 10, 8, 10, 3, 10, 8, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.1.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_1_2[24][24] = { +/* 135: 0, 1, 2, 7, */ { 7, 3, 11, 3, 7, 8, 9, 8, 7, 6, 9, 7, 9, 6, 10, 2, 10, 6, 11, 2, 6, 2, 11, 3 }, +/* 75: 0, 1, 3, 6, */ { 6, 2, 10, 2, 6, 11, 8, 11, 6, 5, 8, 6, 8, 5, 9, 1, 9, 5, 10, 1, 5, 1, 10, 2 }, +/* 83: 0, 1, 4, 6, */ { 10, 9, 5, 9, 10, 1, 3, 1, 10, 6, 3, 10, 3, 6, 7, 4, 7, 6, 5, 4, 6, 4, 5, 9 }, +/* 163: 0, 1, 5, 7, */ { 7, 8, 11, 3, 11, 8, 11, 3, 1, 11, 1, 6, 5, 6, 1, 6, 5, 4, 6, 4, 7, 8, 7, 4 }, +/* 45: 0, 2, 3, 5, */ { 5, 1, 9, 1, 5, 10, 11, 10, 5, 4, 11, 5, 11, 4, 8, 0, 8, 4, 9, 0, 4, 0, 9, 1 }, +/* 53: 0, 2, 4, 5, */ { 1, 9, 10, 5, 10, 9, 10, 5, 7, 10, 7, 2, 3, 2, 7, 2, 3, 0, 2, 0, 1, 9, 1, 0 }, +/* 149: 0, 2, 4, 7, */ { 10, 11, 2, 11, 10, 6, 4, 6, 10, 1, 4, 10, 4, 1, 0, 3, 0, 1, 2, 3, 1, 3, 2, 11 }, +/* 101: 0, 2, 5, 6, */ { 8, 9, 0, 9, 8, 4, 6, 4, 8, 3, 6, 8, 6, 3, 2, 1, 2, 3, 0, 1, 3, 1, 0, 9 }, +/* 197: 0, 2, 6, 7, */ { 3, 11, 8, 7, 8, 11, 8, 7, 5, 8, 5, 0, 1, 0, 5, 0, 1, 2, 0, 2, 3, 11, 3, 2 }, +/* 89: 0, 3, 4, 6, */ { 6, 11, 10, 2, 10, 11, 10, 2, 0, 10, 0, 5, 4, 5, 0, 5, 4, 7, 5, 7, 6, 11, 6, 7 }, +/* 169: 0, 3, 5, 7, */ { 9, 8, 4, 8, 9, 0, 2, 0, 9, 5, 2, 9, 2, 5, 6, 7, 6, 5, 4, 7, 5, 7, 4, 8 }, +/* 225: 0, 5, 6, 7, */ { 8, 4, 0, 9, 0, 4, 0, 9, 10, 0, 10, 3, 11, 3, 10, 3, 11, 7, 3, 7, 8, 4, 8, 7 }, +/* 30: 1, 2, 3, 4, */ { 4, 0, 8, 0, 4, 9, 10, 9, 4, 7, 10, 4, 10, 7, 11, 3, 11, 7, 8, 3, 7, 3, 8, 0 }, +/* 86: 1, 2, 4, 6, */ { 4, 9, 8, 0, 8, 9, 8, 0, 2, 8, 2, 7, 6, 7, 2, 7, 6, 5, 7, 5, 4, 9, 4, 5 }, +/* 166: 1, 2, 5, 7, */ { 11, 10, 6, 10, 11, 2, 0, 2, 11, 7, 0, 11, 0, 7, 4, 5, 4, 7, 6, 5, 7, 5, 6, 10 }, +/* 58: 1, 3, 4, 5, */ { 11, 8, 3, 8, 11, 7, 5, 7, 11, 2, 5, 11, 5, 2, 1, 0, 1, 2, 3, 0, 2, 0, 3, 8 }, +/* 154: 1, 3, 4, 7, */ { 0, 8, 9, 4, 9, 8, 9, 4, 6, 9, 6, 1, 2, 1, 6, 1, 2, 3, 1, 3, 0, 8, 0, 3 }, +/* 106: 1, 3, 5, 6, */ { 2, 10, 11, 6, 11, 10, 11, 6, 4, 11, 4, 3, 0, 3, 4, 3, 0, 1, 3, 1, 2, 10, 2, 1 }, +/* 202: 1, 3, 6, 7, */ { 9, 10, 1, 10, 9, 5, 7, 5, 9, 0, 7, 9, 7, 0, 3, 2, 3, 0, 1, 2, 0, 2, 1, 10 }, +/* 210: 1, 4, 6, 7, */ { 9, 5, 1, 10, 1, 5, 1, 10, 11, 1, 11, 0, 8, 0, 11, 0, 8, 4, 0, 4, 9, 5, 9, 4 }, +/* 92: 2, 3, 4, 6, */ { 8, 11, 7, 11, 8, 3, 1, 3, 8, 4, 1, 8, 1, 4, 5, 6, 5, 4, 7, 6, 4, 6, 7, 11 }, +/* 172: 2, 3, 5, 7, */ { 5, 10, 9, 1, 9, 10, 9, 1, 3, 9, 3, 4, 7, 4, 3, 4, 7, 6, 4, 6, 5, 10, 5, 6 }, +/* 180: 2, 4, 5, 7, */ { 10, 6, 2, 11, 2, 6, 2, 11, 8, 2, 8, 1, 9, 1, 8, 1, 9, 5, 1, 5, 10, 6, 10, 5 }, +/* 120: 3, 4, 5, 6, */ { 11, 7, 3, 8, 3, 7, 3, 8, 9, 3, 9, 2, 10, 2, 9, 2, 10, 6, 2, 6, 11, 7, 11, 6 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_2[24][24] = { +/* 135: 0, 1, 2, 7, */ { 9, 8, 12, 10, 9, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12 }, +/* 75: 0, 1, 3, 6, */ { 8, 11, 12, 9, 8, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12 }, +/* 83: 0, 1, 4, 6, */ { 3, 1, 12, 7, 3, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 }, +/* 163: 0, 1, 5, 7, */ { 12, 3, 1, 12, 1, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 }, +/* 45: 0, 2, 3, 5, */ { 11, 10, 12, 8, 11, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12 }, +/* 53: 0, 2, 4, 5, */ { 12, 5, 7, 12, 7, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, +/* 149: 0, 2, 4, 7, */ { 4, 6, 12, 0, 4, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 }, +/* 101: 0, 2, 5, 6, */ { 6, 4, 12, 2, 6, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 }, +/* 197: 0, 2, 6, 7, */ { 12, 7, 5, 12, 5, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, +/* 89: 0, 3, 4, 6, */ { 12, 2, 0, 12, 0, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 }, +/* 169: 0, 3, 5, 7, */ { 2, 0, 12, 6, 2, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 }, +/* 225: 0, 5, 6, 7, */ { 12, 9, 10, 12, 10, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9 }, +/* 30: 1, 2, 3, 4, */ { 10, 9, 12, 11, 10, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12 }, +/* 86: 1, 2, 4, 6, */ { 12, 0, 2, 12, 2, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 }, +/* 166: 1, 2, 5, 7, */ { 0, 2, 12, 4, 0, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 }, +/* 58: 1, 3, 4, 5, */ { 5, 7, 12, 1, 5, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, +/* 154: 1, 3, 4, 7, */ { 12, 4, 6, 12, 6, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 }, +/* 106: 1, 3, 5, 6, */ { 12, 6, 4, 12, 4, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 }, +/* 202: 1, 3, 6, 7, */ { 7, 5, 12, 3, 7, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, +/* 210: 1, 4, 6, 7, */ { 12, 10, 11, 12, 11, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10 }, +/* 92: 2, 3, 4, 6, */ { 1, 3, 12, 5, 1, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 }, +/* 172: 2, 3, 5, 7, */ { 12, 1, 3, 12, 3, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 }, +/* 180: 2, 4, 5, 7, */ { 12, 11, 8, 12, 8, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11 }, +/* 120: 3, 4, 5, 6, */ { 12, 8, 9, 12, 9, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.2 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_2_[24][24] = { +/* 135: 0, 1, 2, 7, */ { 12, 2, 11, 12, 11, 7, 12, 7, 6, 12, 6, 10, 12, 10, 9, 12, 9, 8, 12, 8, 3, 12, 3, 2 }, +/* 75: 0, 1, 3, 6, */ { 12, 1, 10, 12, 10, 6, 12, 6, 5, 12, 5, 9, 12, 9, 8, 12, 8, 11, 12, 11, 2, 12, 2, 1 }, +/* 83: 0, 1, 4, 6, */ { 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 3, 12, 3, 1, 12, 1, 9, 12, 9, 4 }, +/* 163: 0, 1, 5, 7, */ { 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 1, 5, 12, 3, 1, 12, 11, 3, 12, 6, 11, 12 }, +/* 45: 0, 2, 3, 5, */ { 12, 0, 9, 12, 9, 5, 12, 5, 4, 12, 4, 8, 12, 8, 11, 12, 11, 10, 12, 10, 1, 12, 1, 0 }, +/* 53: 0, 2, 4, 5, */ { 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 7, 3, 12, 5, 7, 12, 10, 5, 12, 2, 10, 12 }, +/* 149: 0, 2, 4, 7, */ { 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 4, 12, 4, 6, 12, 6, 10, 12, 10, 1 }, +/* 101: 0, 2, 5, 6, */ { 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 6, 12, 6, 4, 12, 4, 8, 12, 8, 3 }, +/* 197: 0, 2, 6, 7, */ { 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 5, 1, 12, 7, 5, 12, 8, 7, 12, 0, 8, 12 }, +/* 89: 0, 3, 4, 6, */ { 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 0, 4, 12, 2, 0, 12, 10, 2, 12, 5, 10, 12 }, +/* 169: 0, 3, 5, 7, */ { 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 2, 12, 2, 0, 12, 0, 8, 12, 8, 7 }, +/* 225: 0, 5, 6, 7, */ { 8, 7, 12, 0, 8, 12, 3, 0, 12, 11, 3, 12, 10, 11, 12, 9, 10, 12, 4, 9, 12, 7, 4, 12 }, +/* 30: 1, 2, 3, 4, */ { 12, 7, 8, 12, 8, 0, 12, 0, 3, 12, 3, 11, 12, 11, 10, 12, 10, 9, 12, 9, 4, 12, 4, 7 }, +/* 86: 1, 2, 4, 6, */ { 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 2, 6, 12, 0, 2, 12, 8, 0, 12, 7, 8, 12 }, +/* 166: 1, 2, 5, 7, */ { 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 0, 12, 0, 2, 12, 2, 10, 12, 10, 5 }, +/* 58: 1, 3, 4, 5, */ { 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 5, 12, 5, 7, 12, 7, 8, 12, 8, 0 }, +/* 154: 1, 3, 4, 7, */ { 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 6, 2, 12, 4, 6, 12, 8, 4, 12, 3, 8, 12 }, +/* 106: 1, 3, 5, 6, */ { 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 4, 0, 12, 6, 4, 12, 10, 6, 12, 1, 10, 12 }, +/* 202: 1, 3, 6, 7, */ { 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 7, 12, 7, 5, 12, 5, 10, 12, 10, 2 }, +/* 210: 1, 4, 6, 7, */ { 9, 0, 12, 5, 9, 12, 4, 5, 12, 8, 4, 12, 11, 8, 12, 10, 11, 12, 1, 10, 12, 0, 1, 12 }, +/* 92: 2, 3, 4, 6, */ { 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 1, 12, 1, 3, 12, 3, 11, 12, 11, 6 }, +/* 172: 2, 3, 5, 7, */ { 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 3, 7, 12, 1, 3, 12, 9, 1, 12, 4, 9, 12 }, +/* 180: 2, 4, 5, 7, */ { 10, 1, 12, 6, 10, 12, 5, 6, 12, 9, 5, 12, 8, 9, 12, 11, 8, 12, 2, 11, 12, 1, 2, 12 }, +/* 120: 3, 4, 5, 6, */ { 11, 2, 12, 7, 11, 12, 6, 7, 12, 10, 6, 12, 9, 10, 12, 8, 9, 12, 3, 8, 12, 2, 3, 12 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 13 + * All faces are to be tested + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13: face test */ +static const char test13[2][7] = { +/* 165: 0, 2, 5, 7, */ { 1,2,3,4,5,6,7 }, +/* 90: 1, 3, 4, 6, */ { 2,3,4,1,5,6,7 }, +}; + + + +//_____________________________________________________________________________ +/** + * \brief subconfiguration table for case 13 + * Hard-coded tests for the subconfiguration determination + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13: sub configs */ +static const char subconfig13[64] = { +/* 0: 0,0,0,0,0,0 */ 0, +/* 1: 1,0,0,0,0,0 */ 1, +/* 2: 0,1,0,0,0,0 */ 2, +/* 3: 1,1,0,0,0,0 */ 7, +/* 4: 0,0,1,0,0,0 */ 3, +/* 5: 1,0,1,0,0,0 */ -1, +/* 6: 0,1,1,0,0,0 */ 11, +/* 7: 1,1,1,0,0,0 */ -1, +/* 8: 0,0,0,1,0,0 */ 4, +/* 9: 1,0,0,1,0,0 */ 8, +/* 10: 0,1,0,1,0,0 */ -1, +/* 11: 1,1,0,1,0,0 */ -1, +/* 12: 0,0,1,1,0,0 */ 14, +/* 13: 1,0,1,1,0,0 */ -1, +/* 14: 0,1,1,1,0,0 */ -1, +/* 15: 1,1,1,1,0,0 */ -1, +/* 16: 0,0,0,0,1,0 */ 5, +/* 17: 1,0,0,0,1,0 */ 9, +/* 18: 0,1,0,0,1,0 */ 12, +/* 19: 1,1,0,0,1,0 */ 23, +/* 20: 0,0,1,0,1,0 */ 15, +/* 21: 1,0,1,0,1,0 */ -1, +/* 22: 0,1,1,0,1,0 */ 21, +/* 23: 1,1,1,0,1,0 */ 38, +/* 24: 0,0,0,1,1,0 */ 17, +/* 25: 1,0,0,1,1,0 */ 20, +/* 26: 0,1,0,1,1,0 */ -1, +/* 27: 1,1,0,1,1,0 */ 36, +/* 28: 0,0,1,1,1,0 */ 26, +/* 29: 1,0,1,1,1,0 */ 33, +/* 30: 0,1,1,1,1,0 */ 30, +/* 31: 1,1,1,1,1,0 */ 44, +/* 32: 0,0,0,0,0,1 */ 6, +/* 33: 1,0,0,0,0,1 */ 10, +/* 34: 0,1,0,0,0,1 */ 13, +/* 35: 1,1,0,0,0,1 */ 19, +/* 36: 0,0,1,0,0,1 */ 16, +/* 37: 1,0,1,0,0,1 */ -1, +/* 38: 0,1,1,0,0,1 */ 25, +/* 39: 1,1,1,0,0,1 */ 37, +/* 40: 0,0,0,1,0,1 */ 18, +/* 41: 1,0,0,1,0,1 */ 24, +/* 42: 0,1,0,1,0,1 */ -1, +/* 43: 1,1,0,1,0,1 */ 35, +/* 44: 0,0,1,1,0,1 */ 22, +/* 45: 1,0,1,1,0,1 */ 32, +/* 46: 0,1,1,1,0,1 */ 29, +/* 47: 1,1,1,1,0,1 */ 43, +/* 48: 0,0,0,0,1,1 */ -1, +/* 49: 1,0,0,0,1,1 */ -1, +/* 50: 0,1,0,0,1,1 */ -1, +/* 51: 1,1,0,0,1,1 */ 34, +/* 52: 0,0,1,0,1,1 */ -1, +/* 53: 1,0,1,0,1,1 */ -1, +/* 54: 0,1,1,0,1,1 */ 28, +/* 55: 1,1,1,0,1,1 */ 42, +/* 56: 0,0,0,1,1,1 */ -1, +/* 57: 1,0,0,1,1,1 */ 31, +/* 58: 0,1,0,1,1,1 */ -1, +/* 59: 1,1,0,1,1,1 */ 41, +/* 60: 0,0,1,1,1,1 */ 27, +/* 61: 1,0,1,1,1,1 */ 40, +/* 62: 0,1,1,1,1,1 */ 39, +/* 63: 1,1,1,1,1,1 */ 45, +}; + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.1 */ +static const char tiling13_1[2][12] = { +/* 165: 0, 2, 5, 7, */ { 11, 7, 6, 1, 2, 10, 8, 3, 0, 9, 5, 4 }, +/* 90: 1, 3, 4, 6, */ { 8, 4, 7, 2, 3, 11, 9, 0, 1, 10, 6, 5 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.1 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.1 */ +static const char tiling13_1_[2][12] = { +/* 165: 0, 2, 5, 7, */ { 7, 4, 8, 11, 3, 2, 1, 0, 9, 5, 6, 10 }, +/* 90: 1, 3, 4, 6, */ { 6, 7, 11, 10, 2, 1, 0, 3, 8, 4, 5, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.2 */ +static const char tiling13_2[2][6][18] = { +/* 165: 0, 2, 5, 7, */ { + /* 1 */ { 1, 2, 10, 11, 7, 6, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, + /* 2 */ { 8, 3, 0, 11, 7, 6, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, + /* 3 */ { 9, 5, 4, 8, 3, 0, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, + /* 4 */ { 9, 5, 4, 1, 2, 10, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, + /* 5 */ { 9, 5, 4, 11, 7, 6, 0, 10, 1, 10, 0, 8, 10, 8, 2, 3, 2, 8 }, + /* 6 */ { 1, 2, 10, 3, 0, 8, 4, 9, 7, 11, 7, 9, 5, 11, 9, 11, 5, 6 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1 */ { 2, 3, 11, 8, 4, 7, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, + /* 2 */ { 9, 0, 1, 8, 4, 7, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, + /* 3 */ { 6, 5, 10, 9, 0, 1, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, + /* 4 */ { 6, 5, 10, 2, 3, 11, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, + /* 5 */ { 6, 5, 10, 8, 4, 7, 1, 11, 2, 11, 1, 9, 11, 9, 3, 0, 3, 9 }, + /* 6 */ { 2, 3, 11, 0, 1, 9, 5, 10, 4, 8, 4, 10, 6, 8, 10, 8, 6, 7 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.2 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.2 */ +static const char tiling13_2_[2][6][18] = { +/* 165: 0, 2, 5, 7, */ { + /* 1 */ { 10, 5, 6, 11, 3, 2, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, + /* 2 */ { 11, 3, 2, 7, 4, 8, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, + /* 3 */ { 1, 0, 9, 7, 4, 8, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, + /* 4 */ { 10, 5, 6, 1, 0, 9, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, + /* 5 */ { 10, 5, 6, 7, 4, 8, 2, 11, 1, 9, 1, 11, 3, 9, 11, 9, 3, 0 }, + /* 6 */ { 11, 3, 2, 9, 1, 0, 4, 10, 5, 10, 4, 8, 10, 8, 6, 7, 6, 8 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1 */ { 6, 7, 11, 8, 0, 3, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, + /* 2 */ { 8, 0, 3, 4, 5, 9, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, + /* 3 */ { 2, 1, 10, 4, 5, 9, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, + /* 4 */ { 6, 7, 11, 2, 1, 10, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, + /* 5 */ { 6, 7, 11, 4, 5, 9, 3, 8, 2, 10, 2, 8, 0, 10, 8, 10, 0, 1 }, + /* 6 */ { 8, 0, 3, 10, 2, 1, 5, 11, 6, 11, 5, 9, 11, 9, 7, 4, 7, 9 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.3 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.3 */ +static const char tiling13_3[2][12][30] = { +/* 165: 0, 2, 5, 7, */ { + /* 1,2 */ { 11, 7, 6, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, + /* 1,4 */ { 1, 2, 10, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12 }, + /* 1,5 */ { 11, 7, 6, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, + /* 1,6 */ { 1, 2, 10, 12, 3, 0, 12, 0, 9, 12, 9, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 }, + /* 2,3 */ { 8, 3, 0, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12 }, + /* 2,5 */ { 11, 7, 6, 5, 4, 12, 10, 5, 12, 2, 10, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 }, + /* 2,6 */ { 8, 3, 0, 1, 2, 12, 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 6, 11, 12, 5, 6, 12, 10, 5, 12, 2, 10, 12 }, + /* 3,4 */ { 9, 5, 4, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 }, + /* 3,5 */ { 9, 5, 4, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, + /* 3,6 */ { 8, 3, 0, 12, 1, 2, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 }, + /* 4,5 */ { 9, 5, 4, 7, 6, 12, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 }, + /* 4,6 */ { 1, 2, 10, 3, 0, 12, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12, 8, 7, 12, 0, 8, 12 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1,2 */ { 8, 4, 7, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, + /* 1,4 */ { 2, 3, 11, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12 }, + /* 1,5 */ { 8, 4, 7, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 10, 12, 10, 6 }, + /* 1,6 */ { 2, 3, 11, 12, 0, 1, 12, 1, 10, 12, 10, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 }, + /* 2,3 */ { 0, 1, 9, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12 }, + /* 2,5 */ { 8, 4, 7, 6, 5, 12, 11, 6, 12, 3, 11, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12 }, + /* 2,6 */ { 9, 0, 1, 2, 3, 12, 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 7, 8, 12, 6, 7, 12, 11, 6, 12, 3, 11, 12 }, + /* 3,4 */ { 6, 5, 10, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 }, + /* 3,5 */ { 6, 5, 10, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 8, 12, 8, 4 }, + /* 3,6 */ { 9, 0, 1, 12, 2, 3, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 }, + /* 4,5 */ { 6, 5, 10, 4, 7, 12, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 8, 0, 12, 7, 8, 12 }, + /* 4,6 */ { 2, 3, 11, 0, 1, 12, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12, 9, 4, 12, 1, 9, 12 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.3, inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.3 */ +static const char tiling13_3_[2][12][30] = { +/* 165: 0, 2, 5, 7, */ { + /* 1,2 */ { 3, 2, 11, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 6, 10, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12 }, + /* 1,4 */ { 5, 6, 10, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2 }, + /* 1,5 */ { 10, 5, 6, 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 8, 12, 8, 7 }, + /* 1,6 */ { 11, 3, 2, 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 5, 12, 5, 4, 12, 4, 9, 12, 9, 1 }, + /* 2,3 */ { 7, 4, 8, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, + /* 2,5 */ { 7, 4, 8, 5, 6, 12, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 10, 1, 12, 6, 10, 12 }, + /* 2,6 */ { 11, 3, 2, 1, 0, 12, 10, 1, 12, 6, 10, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 }, + /* 3,4 */ { 1, 0, 9, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4 }, + /* 3,5 */ { 7, 4, 8, 12, 5, 6, 12, 6, 11, 12, 11, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5 }, + /* 3,6 */ { 1, 0, 9, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 7, 12, 7, 6, 12, 6, 11, 12, 11, 3 }, + /* 4,5 */ { 10, 5, 6, 7, 4, 12, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 8, 3, 12, 4, 8, 12 }, + /* 4,6 */ { 9, 1, 0, 3, 2, 12, 8, 3, 12, 4, 8, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1,2 */ { 0, 3, 8, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 7, 11, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12 }, + /* 1,4 */ { 11, 6, 7, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3 }, + /* 1,5 */ { 6, 7, 11, 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 }, + /* 1,6 */ { 8, 0, 3, 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 6, 12, 6, 5, 12, 5, 10, 12, 10, 2 }, + /* 2,3 */ { 4, 5, 9, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, + /* 2,5 */ { 4, 5, 9, 6, 7, 12, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, + /* 2,6 */ { 8, 0, 3, 2, 1, 12, 11, 2, 12, 7, 11, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 }, + /* 3,4 */ { 2, 1, 10, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5 }, + /* 3,5 */ { 4, 5, 9, 12, 6, 7, 12, 7, 8, 12, 8, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 }, + /* 3,6 */ { 2, 1, 10, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 4, 12, 4, 7, 12, 7, 8, 12, 8, 0 }, + /* 4,5 */ { 6, 7, 11, 4, 5, 12, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, + /* 4,6 */ { 10, 2, 1, 0, 3, 12, 9, 0, 12, 5, 9, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.4 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.4 */ +static const char tiling13_4[2][4][36] = { +/* 165: 0, 2, 5, 7, */ { +/* 1,2,6 */ { 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, +/* 1,4,5 */ { 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, +/* 2,3,5 */ { 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12 }, +/* 3,4,6 */ { 12, 0, 8, 12, 8, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 } +}, +/* 90: 1, 3, 4, 6, */ { +/* 1,2,6 */ { 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, +/* 1,4,5 */ { 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, +/* 2,3,5 */ { 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12 }, +/* 3,4,6 */ { 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.5.1 + * The support edge for the interior test is marked as the 1st column. + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.5.1 */ +static const char tiling13_5_1[2][4][18] = { +/* 165: 0, 2, 5, 7, */ { +/* 1,2,5 */ { 7, 6, 11, 1, 0, 9, 10, 3, 2, 3, 10, 5, 3, 5, 8, 4, 8, 5 }, +/* 1,4,6 */ { 1, 2, 10, 7, 4, 8, 3, 0, 11, 6, 11, 0, 9, 6, 0, 6, 9, 5 }, +/* 2,3,6 */ { 3, 0, 8, 5, 6, 10, 1, 2, 9, 4, 9, 2, 11, 4, 2, 4, 11, 7 }, +/* 3,4,5 */ { 5, 4, 9, 3, 2, 11, 8, 1, 0, 1, 8, 7, 1, 7, 10, 6, 10, 7 } +}, +/* 90: 1, 3, 4, 6, */ { +/* 1,2,5 */ { 4, 7, 8, 2, 1, 10, 11, 0, 3, 0, 11, 6, 0, 6, 9, 5, 9, 6 }, +/* 1,4,6 */ { 2, 3, 11, 4, 5, 9, 0, 1, 8, 7, 8, 1, 10, 7, 1, 7, 10, 6 }, +/* 2,3,6 */ { 0, 1, 9, 6, 7, 11, 2, 3, 10, 5, 10, 3, 8, 5, 3, 5, 8, 4 }, +/* 3,4,5 */ { 6, 5, 10, 0, 3, 8, 9, 2, 1, 2, 9, 4, 2, 4, 11, 7, 11, 4 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.5.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.5.2 */ +static const char tiling13_5_2[2][4][30] = { +/* 165: 0, 2, 5, 7, */ { +/* 1,2,5 */ { 1, 0, 9, 7, 4, 8, 7, 8, 3, 7, 3, 11, 2, 11, 3, 11, 2, 10, 11, 10, 6, 5, 6, 10, 6, 5, 7, 4, 7, 5 }, +/* 1,4,6 */ { 7, 4, 8, 11, 3, 2, 6, 11, 2, 10, 6, 2, 6, 10, 5, 9, 5, 10, 1, 9, 10, 9, 1, 0, 2, 0, 1, 0, 2, 3 }, +/* 2,3,6 */ { 5, 6, 10, 9, 1, 0, 4, 9, 0, 8, 4, 0, 4, 8, 7, 11, 7, 8, 3, 11, 8, 11, 3, 2, 0, 2, 3, 2, 0, 1 }, +/* 3,4,5 */ { 3, 2, 11, 5, 6, 10, 5, 10, 1, 5, 1, 9, 0, 9, 1, 9, 0, 8, 9, 8, 4, 4, 8, 7, 4, 7, 5, 6, 5, 7 } +}, +/* 90: 1, 3, 4, 6, */ { +/* 1,2,5 */ { 2, 1, 10, 4, 5, 9, 4, 9, 0, 4, 0, 8, 3, 8, 0, 8, 3, 11, 8, 11, 7, 6, 7, 11, 7, 6, 4, 5, 4, 6 }, +/* 1,4,6 */ { 4, 5, 9, 8, 0, 3, 7, 8, 3, 11, 7, 3, 7, 11, 6, 10, 6, 11, 2, 10, 11, 10, 2, 1, 3, 1, 2, 1, 3, 0 }, +/* 2,3,6 */ { 6, 7, 11, 10, 2, 1, 5, 10, 1, 9, 5, 1, 5, 9, 4, 8, 4, 9, 0, 8, 9, 8, 0, 3, 1, 3, 0, 3, 1, 2 }, +/* 3,4,5 */ { 0, 3, 8, 6, 7, 11, 6, 11, 2, 6, 2, 10, 1, 10, 2, 10, 1, 9, 10, 9, 5, 5, 9, 4, 5, 4, 6, 7, 6, 4 } +} }; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 14 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling14[12][12] = { +/* 71: 0, 1, 2, 6, */ { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8 }, +/* 43: 0, 1, 3, 5, */ { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5 }, +/* 147: 0, 1, 4, 7, */ { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6 }, +/* 29: 0, 2, 3, 4, */ { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4 }, +/* 201: 0, 3, 6, 7, */ { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5 }, +/* 113: 0, 4, 5, 6, */ { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10 }, +/* 142: 1, 2, 3, 7, */ { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7 }, +/* 54: 1, 2, 4, 5, */ { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2 }, +/* 226: 1, 5, 6, 7, */ { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11 }, +/* 108: 2, 3, 5, 6, */ { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3 }, +/* 212: 2, 4, 6, 7, */ { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8 }, +/* 184: 3, 4, 5, 7, */ { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief original Marching Cubes implementation + * For each of the possible vertex states listed in this table there is a + * specific triangulation of the edge intersection points. The table lists + * all of them in the form of 0-5 edge triples with the list terminated by + * the invalid value -1. For example: casesClassic[3] list the 2 triangles + * formed when cube[0] and cube[1] are inside of the surface, but the rest of + * the cube is not. + */ +//----------------------------------------------------------------------------- +static const char casesClassic[256][16] = { +/* 0: */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 1: 0, */ { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 2: 1, */ { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 3: 0, 1, */ { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 4: 2, */ { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 5: 0, 2, */ { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 6: 1, 2, */ { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 7: 0, 1, 2, */ { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 8: 3, */ { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 9: 0, 3, */ { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 10: 1, 3, */ { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 11: 0, 1, 3, */ { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 12: 2, 3, */ { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 13: 0, 2, 3, */ { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 14: 1, 2, 3, */ { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 15: 0, 1, 2, 3, */ { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 16: 4, */ { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 17: 0, 4, */ { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 18: 1, 4, */ { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 19: 0, 1, 4, */ { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 20: 2, 4, */ { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 21: 0, 2, 4, */ { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 22: 1, 2, 4, */ { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 23: 0, 1, 2, 4, */ { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, +/* 24: 3, 4, */ { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 25: 0, 3, 4, */ { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 26: 1, 3, 4, */ { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 27: 0, 1, 3, 4, */ { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, +/* 28: 2, 3, 4, */ { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 29: 0, 2, 3, 4, */ { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, +/* 30: 1, 2, 3, 4, */ { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, +/* 31: 0, 1, 2, 3, 4, */ { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 32: 5, */ { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 33: 0, 5, */ { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 34: 1, 5, */ { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 35: 0, 1, 5, */ { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 36: 2, 5, */ { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 37: 0, 2, 5, */ { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 38: 1, 2, 5, */ { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 39: 0, 1, 2, 5, */ { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, +/* 40: 3, 5, */ { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 41: 0, 3, 5, */ { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 42: 1, 3, 5, */ { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 43: 0, 1, 3, 5, */ { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, +/* 44: 2, 3, 5, */ { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 45: 0, 2, 3, 5, */ { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, +/* 46: 1, 2, 3, 5, */ { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, +/* 47: 0, 1, 2, 3, 5, */ { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 48: 4, 5, */ { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 49: 0, 4, 5, */ { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 50: 1, 4, 5, */ { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 51: 0, 1, 4, 5, */ { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 52: 2, 4, 5, */ { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 53: 0, 2, 4, 5, */ { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, +/* 54: 1, 2, 4, 5, */ { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, +/* 55: 0, 1, 2, 4, 5, */ { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 56: 3, 4, 5, */ { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 57: 0, 3, 4, 5, */ { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, +/* 58: 1, 3, 4, 5, */ { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, +/* 59: 0, 1, 3, 4, 5, */ { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 60: 2, 3, 4, 5, */ { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, +/* 61: 0, 2, 3, 4, 5, */ { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, +/* 62: 1, 2, 3, 4, 5, */ { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, +/* 63: 0, 1, 2, 3, 4, 5, */ { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 64: 6, */ { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 65: 0, 6, */ { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 66: 1, 6, */ { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 67: 0, 1, 6, */ { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 68: 2, 6, */ { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 69: 0, 2, 6, */ { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 70: 1, 2, 6, */ { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 71: 0, 1, 2, 6, */ { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, +/* 72: 3, 6, */ { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 73: 0, 3, 6, */ { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 74: 1, 3, 6, */ { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 75: 0, 1, 3, 6, */ { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, +/* 76: 2, 3, 6, */ { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 77: 0, 2, 3, 6, */ { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, +/* 78: 1, 2, 3, 6, */ { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, +/* 79: 0, 1, 2, 3, 6, */ { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 80: 4, 6, */ { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 81: 0, 4, 6, */ { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 82: 1, 4, 6, */ { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 83: 0, 1, 4, 6, */ { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, +/* 84: 2, 4, 6, */ { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 85: 0, 2, 4, 6, */ { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, +/* 86: 1, 2, 4, 6, */ { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, +/* 87: 0, 1, 2, 4, 6, */ { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, +/* 88: 3, 4, 6, */ { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 89: 0, 3, 4, 6, */ { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, +/* 90: 1, 3, 4, 6, */ { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, +/* 91: 0, 1, 3, 4, 6, */ { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, +/* 92: 2, 3, 4, 6, */ { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, +/* 93: 0, 2, 3, 4, 6, */ { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, +/* 94: 1, 2, 3, 4, 6, */ { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, +/* 96: 5, 6, */ { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 97: 0, 5, 6, */ { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 98: 1, 5, 6, */ { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 99: 0, 1, 5, 6, */ { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, +/* 100: 2, 5, 6, */ { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 101: 0, 2, 5, 6, */ { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, +/* 102: 1, 2, 5, 6, */ { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 103: 0, 1, 2, 5, 6, */ { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 104: 3, 5, 6, */ { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 105: 0, 3, 5, 6, */ { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, +/* 106: 1, 3, 5, 6, */ { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, +/* 107: 0, 1, 3, 5, 6, */ { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, +/* 108: 2, 3, 5, 6, */ { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, +/* 109: 0, 2, 3, 5, 6, */ { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, +/* 110: 1, 2, 3, 5, 6, */ { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 111: 0, 1, 2, 3, 5, 6, */ { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 112: 4, 5, 6, */ { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 113: 0, 4, 5, 6, */ { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, +/* 114: 1, 4, 5, 6, */ { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, +/* 115: 0, 1, 4, 5, 6, */ { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 116: 2, 4, 5, 6, */ { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, +/* 117: 0, 2, 4, 5, 6, */ { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, +/* 118: 1, 2, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 119: 0, 1, 2, 4, 5, 6, */ { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 120: 3, 4, 5, 6, */ { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, +/* 121: 0, 3, 4, 5, 6, */ { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, +/* 122: 1, 3, 4, 5, 6, */ { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, +/* 124: 2, 3, 4, 5, 6, */ { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, +/* 127: 0, 1, 2, 3, 4, 5, 6, */ { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 128: 7, */ { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 129: 0, 7, */ { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 130: 1, 7, */ { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 131: 0, 1, 7, */ { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 132: 2, 7, */ { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 133: 0, 2, 7, */ { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 134: 1, 2, 7, */ { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 135: 0, 1, 2, 7, */ { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, +/* 136: 3, 7, */ { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 137: 0, 3, 7, */ { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 138: 1, 3, 7, */ { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 139: 0, 1, 3, 7, */ { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, +/* 140: 2, 3, 7, */ { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 141: 0, 2, 3, 7, */ { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, +/* 142: 1, 2, 3, 7, */ { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, +/* 143: 0, 1, 2, 3, 7, */ { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 144: 4, 7, */ { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 145: 0, 4, 7, */ { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 146: 1, 4, 7, */ { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 147: 0, 1, 4, 7, */ { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, +/* 148: 2, 4, 7, */ { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 149: 0, 2, 4, 7, */ { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, +/* 150: 1, 2, 4, 7, */ { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, +/* 151: 0, 1, 2, 4, 7, */ { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, +/* 152: 3, 4, 7, */ { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 153: 0, 3, 4, 7, */ { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 154: 1, 3, 4, 7, */ { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, +/* 155: 0, 1, 3, 4, 7, */ { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 156: 2, 3, 4, 7, */ { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, +/* 157: 0, 2, 3, 4, 7, */ { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 158: 1, 2, 3, 4, 7, */ { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, +/* 159: 0, 1, 2, 3, 4, 7, */ { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 160: 5, 7, */ { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 161: 0, 5, 7, */ { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 162: 1, 5, 7, */ { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 163: 0, 1, 5, 7, */ { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, +/* 164: 2, 5, 7, */ { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 165: 0, 2, 5, 7, */ { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, +/* 166: 1, 2, 5, 7, */ { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, +/* 167: 0, 1, 2, 5, 7, */ { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, +/* 168: 3, 5, 7, */ { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 169: 0, 3, 5, 7, */ { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, +/* 170: 1, 3, 5, 7, */ { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, +/* 171: 0, 1, 3, 5, 7, */ { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, +/* 172: 2, 3, 5, 7, */ { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, +/* 173: 0, 2, 3, 5, 7, */ { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, +/* 174: 1, 2, 3, 5, 7, */ { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, +/* 176: 4, 5, 7, */ { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 177: 0, 4, 5, 7, */ { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, +/* 178: 1, 4, 5, 7, */ { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, +/* 179: 0, 1, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 180: 2, 4, 5, 7, */ { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, +/* 181: 0, 2, 4, 5, 7, */ { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, +/* 182: 1, 2, 4, 5, 7, */ { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, +/* 184: 3, 4, 5, 7, */ { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, +/* 185: 0, 3, 4, 5, 7, */ { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 186: 1, 3, 4, 5, 7, */ { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, +/* 187: 0, 1, 3, 4, 5, 7, */ { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 188: 2, 3, 4, 5, 7, */ { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 191: 0, 1, 2, 3, 4, 5, 7, */ { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 192: 6, 7, */ { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 193: 0, 6, 7, */ { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 194: 1, 6, 7, */ { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 195: 0, 1, 6, 7, */ { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, +/* 196: 2, 6, 7, */ { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 197: 0, 2, 6, 7, */ { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, +/* 198: 1, 2, 6, 7, */ { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, +/* 199: 0, 1, 2, 6, 7, */ { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, +/* 200: 3, 6, 7, */ { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 201: 0, 3, 6, 7, */ { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, +/* 202: 1, 3, 6, 7, */ { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, +/* 203: 0, 1, 3, 6, 7, */ { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, +/* 204: 2, 3, 6, 7, */ { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 205: 0, 2, 3, 6, 7, */ { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 206: 1, 2, 3, 6, 7, */ { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 207: 0, 1, 2, 3, 6, 7, */ { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 208: 4, 6, 7, */ { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 209: 0, 4, 6, 7, */ { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, +/* 210: 1, 4, 6, 7, */ { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, +/* 211: 0, 1, 4, 6, 7, */ { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, +/* 212: 2, 4, 6, 7, */ { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, +/* 213: 0, 2, 4, 6, 7, */ { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, +/* 214: 1, 2, 4, 6, 7, */ { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 216: 3, 4, 6, 7, */ { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, +/* 217: 0, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 218: 1, 3, 4, 6, 7, */ { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, +/* 220: 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 221: 0, 2, 3, 4, 6, 7, */ { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, +/* 223: 0, 1, 2, 3, 4, 6, 7, */ { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 224: 5, 6, 7, */ { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 225: 0, 5, 6, 7, */ { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, +/* 226: 1, 5, 6, 7, */ { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, +/* 227: 0, 1, 5, 6, 7, */ { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, +/* 228: 2, 5, 6, 7, */ { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, +/* 229: 0, 2, 5, 6, 7, */ { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, +/* 230: 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, +/* 232: 3, 5, 6, 7, */ { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, +/* 233: 0, 3, 5, 6, 7, */ { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, +/* 234: 1, 3, 5, 6, 7, */ { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 236: 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, +/* 238: 1, 2, 3, 5, 6, 7, */ { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 239: 0, 1, 2, 3, 5, 6, 7, */ { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 240: 4, 5, 6, 7, */ { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 241: 0, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 242: 1, 4, 5, 6, 7, */ { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 243: 0, 1, 4, 5, 6, 7, */ { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 244: 2, 4, 5, 6, 7, */ { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, +/* 246: 1, 2, 4, 5, 6, 7, */ { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 247: 0, 1, 2, 4, 5, 6, 7, */ { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 248: 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 249: 0, 3, 4, 5, 6, 7, */ { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, +/* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 252: 2, 3, 4, 5, 6, 7, */ { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 253: 0, 2, 3, 4, 5, 6, 7, */ { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 254: 1, 2, 3, 4, 5, 6, 7, */ { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 255: 0, 1, 2, 3, 4, 5, 6, 7, */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } +}; +//_____________________________________________________________________________ + + + +#endif // _LOOKUPTABLE_H_ diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/MarchingCubes.cpp b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/MarchingCubes.cpp new file mode 100755 index 0000000000..d9012f0405 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/MarchingCubes.cpp @@ -0,0 +1,1302 @@ +/** + * @file MarchingCubes.cpp + * @author Thomas Lewiner + * @author Math Dept, PUC-Rio + * @version 0.2 + * @date 12/08/2002 + * + * @brief MarchingCubes Algorithm + */ +//________________________________________________ + + +#if !defined(WIN32) || defined(__CYGWIN__) +#pragma implementation +#endif // WIN32 + +#include +#include +#include +#include +#include +#include "MarchingCubes.h" +#include "ply.h" +#include "LookUpTable.h" + +// step size of the arrays of vertices and triangles +#define ALLOC_SIZE 65536 + +//_____________________________________________________________________________ +// print cube for debug +void MarchingCubes::print_cube() { printf( "\t%f %f %f %f %f %f %f %f\n", _cube[0], _cube[1], _cube[2], _cube[3], _cube[4], _cube[5], _cube[6], _cube[7]) ; } +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// Constructor +MarchingCubes::MarchingCubes( const int size_x /*= -1*/, const int size_y /*= -1*/, const int size_z /*= -1*/ ) : +//----------------------------------------------------------------------------- + _originalMC(false), + _ext_data (false), + _size_x (size_x), + _size_y (size_y), + _size_z (size_z), + _data ((real *)NULL), + _x_verts (( int *)NULL), + _y_verts (( int *)NULL), + _z_verts (( int *)NULL), + _nverts (0), + _ntrigs (0), + _Nverts (0), + _Ntrigs (0), + _vertices (( Vertex *)NULL), + _triangles ((Triangle*)NULL) +{} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// Destructor +MarchingCubes::~MarchingCubes() +//----------------------------------------------------------------------------- +{ + clean_all() ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// main algorithm +void MarchingCubes::run( real iso ) +//----------------------------------------------------------------------------- +{ + clock_t time = clock() ; + + compute_intersection_points( iso ) ; + + for( _k = 0 ; _k < _size_z-1 ; _k++ ) + for( _j = 0 ; _j < _size_y-1 ; _j++ ) + for( _i = 0 ; _i < _size_x-1 ; _i++ ) + { + _lut_entry = 0 ; + for( int p = 0 ; p < 8 ; ++p ) + { + _cube[p] = get_data( _i+((p^(p>>1))&1), _j+((p>>1)&1), _k+((p>>2)&1) ) - iso ; + if( fabs( _cube[p] ) < FLT_EPSILON ) _cube[p] = FLT_EPSILON ; + if( _cube[p] > 0 ) _lut_entry += 1 << p ; + } +/* + if( ( _cube[0] = get_data( _i , _j , _k ) ) > 0 ) _lut_entry += 1 ; + if( ( _cube[1] = get_data(_i+1, _j , _k ) ) > 0 ) _lut_entry += 2 ; + if( ( _cube[2] = get_data(_i+1,_j+1, _k ) ) > 0 ) _lut_entry += 4 ; + if( ( _cube[3] = get_data( _i ,_j+1, _k ) ) > 0 ) _lut_entry += 8 ; + if( ( _cube[4] = get_data( _i , _j ,_k+1) ) > 0 ) _lut_entry += 16 ; + if( ( _cube[5] = get_data(_i+1, _j ,_k+1) ) > 0 ) _lut_entry += 32 ; + if( ( _cube[6] = get_data(_i+1,_j+1,_k+1) ) > 0 ) _lut_entry += 64 ; + if( ( _cube[7] = get_data( _i ,_j+1,_k+1) ) > 0 ) _lut_entry += 128 ; +*/ + process_cube( ) ; + } + + printf("Marching Cubes ran in %lf secs.\n", (double)(clock() - time)/CLOCKS_PER_SEC) ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// init temporary structures (must set sizes before call) +void MarchingCubes::init_temps() +//----------------------------------------------------------------------------- +{ + if( !_ext_data ) + _data = new real [_size_x * _size_y * _size_z] ; + _x_verts = new int [_size_x * _size_y * _size_z] ; + _y_verts = new int [_size_x * _size_y * _size_z] ; + _z_verts = new int [_size_x * _size_y * _size_z] ; + + memset( _x_verts, -1, _size_x * _size_y * _size_z * sizeof( int ) ) ; + memset( _y_verts, -1, _size_x * _size_y * _size_z * sizeof( int ) ) ; + memset( _z_verts, -1, _size_x * _size_y * _size_z * sizeof( int ) ) ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// init all structures (must set sizes before call) +void MarchingCubes::init_all () +//----------------------------------------------------------------------------- +{ + init_temps() ; + + _nverts = _ntrigs = 0 ; + _Nverts = _Ntrigs = ALLOC_SIZE ; + _vertices = new Vertex [_Nverts] ; + _triangles = new Triangle[_Ntrigs] ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// clean temporary structures +void MarchingCubes::clean_temps() +//----------------------------------------------------------------------------- +{ + if( !_ext_data ) + delete [] _data; + delete [] _x_verts; + delete [] _y_verts; + delete [] _z_verts; + + if( !_ext_data ) + _data = (real*)NULL ; + _x_verts = (int*)NULL ; + _y_verts = (int*)NULL ; + _z_verts = (int*)NULL ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// clean all structures +void MarchingCubes::clean_all() +//----------------------------------------------------------------------------- +{ + clean_temps() ; + delete [] _vertices ; + delete [] _triangles ; + _vertices = (Vertex *)NULL ; + _triangles = (Triangle *)NULL ; + _nverts = _ntrigs = 0 ; + _Nverts = _Ntrigs = 0 ; + + _size_x = _size_y = _size_z = -1 ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +// Compute the intersection points +void MarchingCubes::compute_intersection_points( real iso ) +//----------------------------------------------------------------------------- +{ + for( _k = 0 ; _k < _size_z ; _k++ ) + for( _j = 0 ; _j < _size_y ; _j++ ) + for( _i = 0 ; _i < _size_x ; _i++ ) + { + _cube[0] = get_data( _i, _j, _k ) - iso ; + if( _i < _size_x - 1 ) _cube[1] = get_data(_i+1, _j , _k ) - iso ; + else _cube[1] = _cube[0] ; + + if( _j < _size_y - 1 ) _cube[3] = get_data( _i ,_j+1, _k ) - iso ; + else _cube[3] = _cube[0] ; + + if( _k < _size_z - 1 ) _cube[4] = get_data( _i , _j ,_k+1) - iso ; + else _cube[4] = _cube[0] ; + + if( fabs( _cube[0] ) < FLT_EPSILON ) _cube[0] = FLT_EPSILON ; + if( fabs( _cube[1] ) < FLT_EPSILON ) _cube[1] = FLT_EPSILON ; + if( fabs( _cube[3] ) < FLT_EPSILON ) _cube[3] = FLT_EPSILON ; + if( fabs( _cube[4] ) < FLT_EPSILON ) _cube[4] = FLT_EPSILON ; + + if( _cube[0] < 0 ) + { + if( _cube[1] > 0 ) set_x_vert( add_x_vertex( ), _i,_j,_k ) ; + if( _cube[3] > 0 ) set_y_vert( add_y_vertex( ), _i,_j,_k ) ; + if( _cube[4] > 0 ) set_z_vert( add_z_vertex( ), _i,_j,_k ) ; + } + else + { + if( _cube[1] < 0 ) set_x_vert( add_x_vertex( ), _i,_j,_k ) ; + if( _cube[3] < 0 ) set_y_vert( add_y_vertex( ), _i,_j,_k ) ; + if( _cube[4] < 0 ) set_z_vert( add_z_vertex( ), _i,_j,_k ) ; + } + } +} +//_____________________________________________________________________________ + + + + + +//_____________________________________________________________________________ +// Test a face +// if face>0 return true if the face contains a part of the surface +bool MarchingCubes::test_face( schar face ) +//----------------------------------------------------------------------------- +{ + real A,B,C,D ; + + switch( face ) + { + case -1 : case 1 : A = _cube[0] ; B = _cube[4] ; C = _cube[5] ; D = _cube[1] ; break ; + case -2 : case 2 : A = _cube[1] ; B = _cube[5] ; C = _cube[6] ; D = _cube[2] ; break ; + case -3 : case 3 : A = _cube[2] ; B = _cube[6] ; C = _cube[7] ; D = _cube[3] ; break ; + case -4 : case 4 : A = _cube[3] ; B = _cube[7] ; C = _cube[4] ; D = _cube[0] ; break ; + case -5 : case 5 : A = _cube[0] ; B = _cube[3] ; C = _cube[2] ; D = _cube[1] ; break ; + case -6 : case 6 : A = _cube[4] ; B = _cube[7] ; C = _cube[6] ; D = _cube[5] ; break ; + default : printf( "Invalid face code %d\n", face ) ; print_cube() ; A = B = C = D = 0 ; + }; + + if( fabs( A*C - B*D ) < FLT_EPSILON ) + return face >= 0 ; + return face * A * ( A*C - B*D ) >= 0 ; // face and A invert signs +} +//_____________________________________________________________________________ + + + + + +//_____________________________________________________________________________ +// Test the interior of a cube +// if s == 7, return true if the interior is empty +// if s ==-7, return false if the interior is empty +bool MarchingCubes::test_interior( schar s ) +//----------------------------------------------------------------------------- +{ + real t, At=0, Bt=0, Ct=0, Dt=0, a, b ; + char test = 0 ; + char edge = -1 ; // reference edge of the triangulation + + switch( _case ) + { + case 4 : + case 10 : + a = ( _cube[4] - _cube[0] ) * ( _cube[6] - _cube[2] ) - ( _cube[7] - _cube[3] ) * ( _cube[5] - _cube[1] ) ; + b = _cube[2] * ( _cube[4] - _cube[0] ) + _cube[0] * ( _cube[6] - _cube[2] ) + - _cube[1] * ( _cube[7] - _cube[3] ) - _cube[3] * ( _cube[5] - _cube[1] ) ; + t = - b / (2*a) ; + if( t<0 || t>1 ) return s>0 ; + + At = _cube[0] + ( _cube[4] - _cube[0] ) * t ; + Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ; + Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ; + Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ; + break ; + + case 6 : + case 7 : + case 12 : + case 13 : + switch( _case ) + { + case 6 : edge = test6 [_config][2] ; break ; + case 7 : edge = test7 [_config][4] ; break ; + case 12 : edge = test12[_config][3] ; break ; + case 13 : edge = tiling13_5_1[_config][_subconfig][0] ; break ; + } + switch( edge ) + { + case 0 : + t = _cube[0] / ( _cube[0] - _cube[1] ) ; + At = 0 ; + Bt = _cube[3] + ( _cube[2] - _cube[3] ) * t ; + Ct = _cube[7] + ( _cube[6] - _cube[7] ) * t ; + Dt = _cube[4] + ( _cube[5] - _cube[4] ) * t ; + break ; + case 1 : + t = _cube[1] / ( _cube[1] - _cube[2] ) ; + At = 0 ; + Bt = _cube[0] + ( _cube[3] - _cube[0] ) * t ; + Ct = _cube[4] + ( _cube[7] - _cube[4] ) * t ; + Dt = _cube[5] + ( _cube[6] - _cube[5] ) * t ; + break ; + case 2 : + t = _cube[2] / ( _cube[2] - _cube[3] ) ; + At = 0 ; + Bt = _cube[1] + ( _cube[0] - _cube[1] ) * t ; + Ct = _cube[5] + ( _cube[4] - _cube[5] ) * t ; + Dt = _cube[6] + ( _cube[7] - _cube[6] ) * t ; + break ; + case 3 : + t = _cube[3] / ( _cube[3] - _cube[0] ) ; + At = 0 ; + Bt = _cube[2] + ( _cube[1] - _cube[2] ) * t ; + Ct = _cube[6] + ( _cube[5] - _cube[6] ) * t ; + Dt = _cube[7] + ( _cube[4] - _cube[7] ) * t ; + break ; + case 4 : + t = _cube[4] / ( _cube[4] - _cube[5] ) ; + At = 0 ; + Bt = _cube[7] + ( _cube[6] - _cube[7] ) * t ; + Ct = _cube[3] + ( _cube[2] - _cube[3] ) * t ; + Dt = _cube[0] + ( _cube[1] - _cube[0] ) * t ; + break ; + case 5 : + t = _cube[5] / ( _cube[5] - _cube[6] ) ; + At = 0 ; + Bt = _cube[4] + ( _cube[7] - _cube[4] ) * t ; + Ct = _cube[0] + ( _cube[3] - _cube[0] ) * t ; + Dt = _cube[1] + ( _cube[2] - _cube[1] ) * t ; + break ; + case 6 : + t = _cube[6] / ( _cube[6] - _cube[7] ) ; + At = 0 ; + Bt = _cube[5] + ( _cube[4] - _cube[5] ) * t ; + Ct = _cube[1] + ( _cube[0] - _cube[1] ) * t ; + Dt = _cube[2] + ( _cube[3] - _cube[2] ) * t ; + break ; + case 7 : + t = _cube[7] / ( _cube[7] - _cube[4] ) ; + At = 0 ; + Bt = _cube[6] + ( _cube[5] - _cube[6] ) * t ; + Ct = _cube[2] + ( _cube[1] - _cube[2] ) * t ; + Dt = _cube[3] + ( _cube[0] - _cube[3] ) * t ; + break ; + case 8 : + t = _cube[0] / ( _cube[0] - _cube[4] ) ; + At = 0 ; + Bt = _cube[3] + ( _cube[7] - _cube[3] ) * t ; + Ct = _cube[2] + ( _cube[6] - _cube[2] ) * t ; + Dt = _cube[1] + ( _cube[5] - _cube[1] ) * t ; + break ; + case 9 : + t = _cube[1] / ( _cube[1] - _cube[5] ) ; + At = 0 ; + Bt = _cube[0] + ( _cube[4] - _cube[0] ) * t ; + Ct = _cube[3] + ( _cube[7] - _cube[3] ) * t ; + Dt = _cube[2] + ( _cube[6] - _cube[2] ) * t ; + break ; + case 10 : + t = _cube[2] / ( _cube[2] - _cube[6] ) ; + At = 0 ; + Bt = _cube[1] + ( _cube[5] - _cube[1] ) * t ; + Ct = _cube[0] + ( _cube[4] - _cube[0] ) * t ; + Dt = _cube[3] + ( _cube[7] - _cube[3] ) * t ; + break ; + case 11 : + t = _cube[3] / ( _cube[3] - _cube[7] ) ; + At = 0 ; + Bt = _cube[2] + ( _cube[6] - _cube[2] ) * t ; + Ct = _cube[1] + ( _cube[5] - _cube[1] ) * t ; + Dt = _cube[0] + ( _cube[4] - _cube[0] ) * t ; + break ; + default : printf( "Invalid edge %d\n", edge ) ; print_cube() ; break ; + } + break ; + + default : printf( "Invalid ambiguous case %d\n", _case ) ; print_cube() ; break ; + } + + if( At >= 0 ) test ++ ; + if( Bt >= 0 ) test += 2 ; + if( Ct >= 0 ) test += 4 ; + if( Dt >= 0 ) test += 8 ; + switch( test ) + { + case 0 : return s>0 ; + case 1 : return s>0 ; + case 2 : return s>0 ; + case 3 : return s>0 ; + case 4 : return s>0 ; + case 5 : if( At * Ct - Bt * Dt < FLT_EPSILON ) return s>0 ; break ; + case 6 : return s>0 ; + case 7 : return s<0 ; + case 8 : return s>0 ; + case 9 : return s>0 ; + case 10 : if( At * Ct - Bt * Dt >= FLT_EPSILON ) return s>0 ; break ; + case 11 : return s<0 ; + case 12 : return s>0 ; + case 13 : return s<0 ; + case 14 : return s<0 ; + case 15 : return s<0 ; + } + + return s<0 ; +} +//_____________________________________________________________________________ + + + + +//_____________________________________________________________________________ +// Process a unit cube +void MarchingCubes::process_cube( ) +//----------------------------------------------------------------------------- +{ + if( _originalMC ) + { + char nt = 0 ; + while( casesClassic[_lut_entry][3*nt] != -1 ) nt++ ; + add_triangle( casesClassic[_lut_entry], nt ) ; + return ; + } + + int v12 = -1 ; + _case = cases[_lut_entry][0] ; + _config = cases[_lut_entry][1] ; + _subconfig = 0 ; + + switch( _case ) + { + case 0 : + break ; + + case 1 : + add_triangle( tiling1[_config], 1 ) ; + break ; + + case 2 : + add_triangle( tiling2[_config], 2 ) ; + break ; + + case 3 : + if( test_face( test3[_config]) ) + add_triangle( tiling3_2[_config], 4 ) ; // 3.2 + else + add_triangle( tiling3_1[_config], 2 ) ; // 3.1 + break ; + + case 4 : + if( test_interior( test4[_config]) ) + add_triangle( tiling4_1[_config], 2 ) ; // 4.1.1 + else + add_triangle( tiling4_2[_config], 6 ) ; // 4.1.2 + break ; + + case 5 : + add_triangle( tiling5[_config], 3 ) ; + break ; + + case 6 : + if( test_face( test6[_config][0]) ) + add_triangle( tiling6_2[_config], 5 ) ; // 6.2 + else + { + if( test_interior( test6[_config][1]) ) + add_triangle( tiling6_1_1[_config], 3 ) ; // 6.1.1 + else + { + v12 = add_c_vertex() ; + add_triangle( tiling6_1_2[_config], 9 , v12) ; // 6.1.2 + } + } + break ; + + case 7 : + if( test_face( test7[_config][0] ) ) _subconfig += 1 ; + if( test_face( test7[_config][1] ) ) _subconfig += 2 ; + if( test_face( test7[_config][2] ) ) _subconfig += 4 ; + switch( _subconfig ) + { + case 0 : + add_triangle( tiling7_1[_config], 3 ) ; break ; + case 1 : + add_triangle( tiling7_2[_config][0], 5 ) ; break ; + case 2 : + add_triangle( tiling7_2[_config][1], 5 ) ; break ; + case 3 : + v12 = add_c_vertex() ; + add_triangle( tiling7_3[_config][0], 9, v12 ) ; break ; + case 4 : + add_triangle( tiling7_2[_config][2], 5 ) ; break ; + case 5 : + v12 = add_c_vertex() ; + add_triangle( tiling7_3[_config][1], 9, v12 ) ; break ; + case 6 : + v12 = add_c_vertex() ; + add_triangle( tiling7_3[_config][2], 9, v12 ) ; break ; + case 7 : + if( test_interior( test7[_config][3]) ) + add_triangle( tiling7_4_2[_config], 9 ) ; + else + add_triangle( tiling7_4_1[_config], 5 ) ; + break ; + }; + break ; + + case 8 : + add_triangle( tiling8[_config], 2 ) ; + break ; + + case 9 : + add_triangle( tiling9[_config], 4 ) ; + break ; + + case 10 : + if( test_face( test10[_config][0]) ) + { + if( test_face( test10[_config][1]) ) + add_triangle( tiling10_1_1_[_config], 4 ) ; // 10.1.1 + else + { + v12 = add_c_vertex() ; + add_triangle( tiling10_2[_config], 8, v12 ) ; // 10.2 + } + } + else + { + if( test_face( test10[_config][1]) ) + { + v12 = add_c_vertex() ; + add_triangle( tiling10_2_[_config], 8, v12 ) ; // 10.2 + } + else + { + if( test_interior( test10[_config][2]) ) + add_triangle( tiling10_1_1[_config], 4 ) ; // 10.1.1 + else + add_triangle( tiling10_1_2[_config], 8 ) ; // 10.1.2 + } + } + break ; + + case 11 : + add_triangle( tiling11[_config], 4 ) ; + break ; + + case 12 : + if( test_face( test12[_config][0]) ) + { + if( test_face( test12[_config][1]) ) + add_triangle( tiling12_1_1_[_config], 4 ) ; // 12.1.1 + else + { + v12 = add_c_vertex() ; + add_triangle( tiling12_2[_config], 8, v12 ) ; // 12.2 + } + } + else + { + if( test_face( test12[_config][1]) ) + { + v12 = add_c_vertex() ; + add_triangle( tiling12_2_[_config], 8, v12 ) ; // 12.2 + } + else + { + if( test_interior( test12[_config][2]) ) + add_triangle( tiling12_1_1[_config], 4 ) ; // 12.1.1 + else + add_triangle( tiling12_1_2[_config], 8 ) ; // 12.1.2 + } + } + break ; + + case 13 : + if( test_face( test13[_config][0] ) ) _subconfig += 1 ; + if( test_face( test13[_config][1] ) ) _subconfig += 2 ; + if( test_face( test13[_config][2] ) ) _subconfig += 4 ; + if( test_face( test13[_config][3] ) ) _subconfig += 8 ; + if( test_face( test13[_config][4] ) ) _subconfig += 16 ; + if( test_face( test13[_config][5] ) ) _subconfig += 32 ; + switch( subconfig13[_subconfig] ) + { + case 0 :/* 13.1 */ + add_triangle( tiling13_1[_config], 4 ) ; break ; + + case 1 :/* 13.2 */ + add_triangle( tiling13_2[_config][0], 6 ) ; break ; + case 2 :/* 13.2 */ + add_triangle( tiling13_2[_config][1], 6 ) ; break ; + case 3 :/* 13.2 */ + add_triangle( tiling13_2[_config][2], 6 ) ; break ; + case 4 :/* 13.2 */ + add_triangle( tiling13_2[_config][3], 6 ) ; break ; + case 5 :/* 13.2 */ + add_triangle( tiling13_2[_config][4], 6 ) ; break ; + case 6 :/* 13.2 */ + add_triangle( tiling13_2[_config][5], 6 ) ; break ; + + case 7 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][0], 10, v12 ) ; break ; + case 8 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][1], 10, v12 ) ; break ; + case 9 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][2], 10, v12 ) ; break ; + case 10 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][3], 10, v12 ) ; break ; + case 11 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][4], 10, v12 ) ; break ; + case 12 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][5], 10, v12 ) ; break ; + case 13 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][6], 10, v12 ) ; break ; + case 14 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][7], 10, v12 ) ; break ; + case 15 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][8], 10, v12 ) ; break ; + case 16 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][9], 10, v12 ) ; break ; + case 17 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][10], 10, v12 ) ; break ; + case 18 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3[_config][11], 10, v12 ) ; break ; + + case 19 :/* 13.4 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_4[_config][0], 12, v12 ) ; break ; + case 20 :/* 13.4 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_4[_config][1], 12, v12 ) ; break ; + case 21 :/* 13.4 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_4[_config][2], 12, v12 ) ; break ; + case 22 :/* 13.4 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_4[_config][3], 12, v12 ) ; break ; + + case 23 :/* 13.5 */ + _subconfig = 0 ; + if( test_interior( test13[_config][6] ) ) + add_triangle( tiling13_5_1[_config][0], 6 ) ; + else + add_triangle( tiling13_5_2[_config][0], 10 ) ; + break ; + case 24 :/* 13.5 */ + _subconfig = 1 ; + if( test_interior( test13[_config][6] ) ) + add_triangle( tiling13_5_1[_config][1], 6 ) ; + else + add_triangle( tiling13_5_2[_config][1], 10 ) ; + break ; + case 25 :/* 13.5 */ + _subconfig = 2 ; + if( test_interior( test13[_config][6] ) ) + add_triangle( tiling13_5_1[_config][2], 6 ) ; + else + add_triangle( tiling13_5_2[_config][2], 10 ) ; + break ; + case 26 :/* 13.5 */ + _subconfig = 3 ; + if( test_interior( test13[_config][6] ) ) + add_triangle( tiling13_5_1[_config][3], 6 ) ; + else + add_triangle( tiling13_5_2[_config][3], 10 ) ; + break ; + + case 27 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][0], 10, v12 ) ; break ; + case 28 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][1], 10, v12 ) ; break ; + case 29 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][2], 10, v12 ) ; break ; + case 30 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][3], 10, v12 ) ; break ; + case 31 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][4], 10, v12 ) ; break ; + case 32 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][5], 10, v12 ) ; break ; + case 33 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][6], 10, v12 ) ; break ; + case 34 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][7], 10, v12 ) ; break ; + case 35 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][8], 10, v12 ) ; break ; + case 36 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][9], 10, v12 ) ; break ; + case 37 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][10], 10, v12 ) ; break ; + case 38 :/* 13.3 */ + v12 = add_c_vertex() ; + add_triangle( tiling13_3_[_config][11], 10, v12 ) ; break ; + + case 39 :/* 13.2 */ + add_triangle( tiling13_2_[_config][0], 6 ) ; break ; + case 40 :/* 13.2 */ + add_triangle( tiling13_2_[_config][1], 6 ) ; break ; + case 41 :/* 13.2 */ + add_triangle( tiling13_2_[_config][2], 6 ) ; break ; + case 42 :/* 13.2 */ + add_triangle( tiling13_2_[_config][3], 6 ) ; break ; + case 43 :/* 13.2 */ + add_triangle( tiling13_2_[_config][4], 6 ) ; break ; + case 44 :/* 13.2 */ + add_triangle( tiling13_2_[_config][5], 6 ) ; break ; + + case 45 :/* 13.1 */ + add_triangle( tiling13_1_[_config], 4 ) ; break ; + + default : + printf("Marching Cubes: Impossible case 13?\n" ) ; print_cube() ; + } + break ; + + case 14 : + add_triangle( tiling14[_config], 4 ) ; + break ; + }; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// Adding triangles +void MarchingCubes::add_triangle( const char* trig, char n, int v12 ) +//----------------------------------------------------------------------------- +{ + int tv[3] ; + + for( int t = 0 ; t < 3*n ; t++ ) + { + switch( trig[t] ) + { + case 0 : tv[ t % 3 ] = get_x_vert( _i , _j , _k ) ; break ; + case 1 : tv[ t % 3 ] = get_y_vert(_i+1, _j , _k ) ; break ; + case 2 : tv[ t % 3 ] = get_x_vert( _i ,_j+1, _k ) ; break ; + case 3 : tv[ t % 3 ] = get_y_vert( _i , _j , _k ) ; break ; + case 4 : tv[ t % 3 ] = get_x_vert( _i , _j ,_k+1) ; break ; + case 5 : tv[ t % 3 ] = get_y_vert(_i+1, _j ,_k+1) ; break ; + case 6 : tv[ t % 3 ] = get_x_vert( _i ,_j+1,_k+1) ; break ; + case 7 : tv[ t % 3 ] = get_y_vert( _i , _j ,_k+1) ; break ; + case 8 : tv[ t % 3 ] = get_z_vert( _i , _j , _k ) ; break ; + case 9 : tv[ t % 3 ] = get_z_vert(_i+1, _j , _k ) ; break ; + case 10 : tv[ t % 3 ] = get_z_vert(_i+1,_j+1, _k ) ; break ; + case 11 : tv[ t % 3 ] = get_z_vert( _i ,_j+1, _k ) ; break ; + case 12 : tv[ t % 3 ] = v12 ; break ; + default : break ; + } + + if( tv[t%3] == -1 ) + { + printf("Marching Cubes: invalid triangle %d\n", _ntrigs+1) ; + print_cube() ; + } + + if( t%3 == 2 ) + { + if( _ntrigs >= _Ntrigs ) + { + Triangle *temp = _triangles ; + _triangles = new Triangle[ 2*_Ntrigs ] ; + memcpy( _triangles, temp, _Ntrigs*sizeof(Triangle) ) ; + delete[] temp ; + printf("%d allocated triangles\n", _Ntrigs) ; + _Ntrigs *= 2 ; + } + + Triangle *T = _triangles + _ntrigs++ ; + T->v1 = tv[0] ; + T->v2 = tv[1] ; + T->v3 = tv[2] ; + } + } +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// Calculating gradient + +real MarchingCubes::get_x_grad( const int i, const int j, const int k ) const +//----------------------------------------------------------------------------- +{ + if( i > 0 ) + { + if ( i < _size_x - 1 ) + return ( get_data( i+1, j, k ) - get_data( i-1, j, k ) ) / 2 ; + else + return get_data( i, j, k ) - get_data( i-1, j, k ) ; + } + else + return get_data( i+1, j, k ) - get_data( i, j, k ) ; +} +//----------------------------------------------------------------------------- + +real MarchingCubes::get_y_grad( const int i, const int j, const int k ) const +//----------------------------------------------------------------------------- +{ + if( j > 0 ) + { + if ( j < _size_y - 1 ) + return ( get_data( i, j+1, k ) - get_data( i, j-1, k ) ) / 2 ; + else + return get_data( i, j, k ) - get_data( i, j-1, k ) ; + } + else + return get_data( i, j+1, k ) - get_data( i, j, k ) ; +} +//----------------------------------------------------------------------------- + +real MarchingCubes::get_z_grad( const int i, const int j, const int k ) const +//----------------------------------------------------------------------------- +{ + if( k > 0 ) + { + if ( k < _size_z - 1 ) + return ( get_data( i, j, k+1 ) - get_data( i, j, k-1 ) ) / 2 ; + else + return get_data( i, j, k ) - get_data( i, j, k-1 ) ; + } + else + return get_data( i, j, k+1 ) - get_data( i, j, k ) ; +} +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +// Adding vertices + +void MarchingCubes::test_vertex_addition() +{ + if( _nverts >= _Nverts ) + { + Vertex *temp = _vertices ; + _vertices = new Vertex[ _Nverts*2 ] ; + memcpy( _vertices, temp, _Nverts*sizeof(Vertex) ) ; + delete[] temp ; + printf("%d allocated vertices\n", _Nverts) ; + _Nverts *= 2 ; + } +} + + +int MarchingCubes::add_x_vertex( ) +//----------------------------------------------------------------------------- +{ + test_vertex_addition() ; + Vertex *vert = _vertices + _nverts++ ; + + real u = ( _cube[0] ) / ( _cube[0] - _cube[1] ) ; + + vert->x = (real)_i+u; + vert->y = (real) _j ; + vert->z = (real) _k ; + + vert->nx = (1-u)*get_x_grad(_i,_j,_k) + u*get_x_grad(_i+1,_j,_k) ; + vert->ny = (1-u)*get_y_grad(_i,_j,_k) + u*get_y_grad(_i+1,_j,_k) ; + vert->nz = (1-u)*get_z_grad(_i,_j,_k) + u*get_z_grad(_i+1,_j,_k) ; + + u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ; + if( u > 0 ) + { + vert->nx /= u ; + vert->ny /= u ; + vert->nz /= u ; + } + + + return _nverts-1 ; +} +//----------------------------------------------------------------------------- + +int MarchingCubes::add_y_vertex( ) +//----------------------------------------------------------------------------- +{ + test_vertex_addition() ; + Vertex *vert = _vertices + _nverts++ ; + + real u = ( _cube[0] ) / ( _cube[0] - _cube[3] ) ; + + vert->x = (real) _i ; + vert->y = (real)_j+u; + vert->z = (real) _k ; + + vert->nx = (1-u)*get_x_grad(_i,_j,_k) + u*get_x_grad(_i,_j+1,_k) ; + vert->ny = (1-u)*get_y_grad(_i,_j,_k) + u*get_y_grad(_i,_j+1,_k) ; + vert->nz = (1-u)*get_z_grad(_i,_j,_k) + u*get_z_grad(_i,_j+1,_k) ; + + u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ; + if( u > 0 ) + { + vert->nx /= u ; + vert->ny /= u ; + vert->nz /= u ; + } + + return _nverts-1 ; +} +//----------------------------------------------------------------------------- + +int MarchingCubes::add_z_vertex( ) +//----------------------------------------------------------------------------- +{ + test_vertex_addition() ; + Vertex *vert = _vertices + _nverts++ ; + + real u = ( _cube[0] ) / ( _cube[0] - _cube[4] ) ; + + vert->x = (real) _i ; + vert->y = (real) _j ; + vert->z = (real)_k+u; + + vert->nx = (1-u)*get_x_grad(_i,_j,_k) + u*get_x_grad(_i,_j,_k+1) ; + vert->ny = (1-u)*get_y_grad(_i,_j,_k) + u*get_y_grad(_i,_j,_k+1) ; + vert->nz = (1-u)*get_z_grad(_i,_j,_k) + u*get_z_grad(_i,_j,_k+1) ; + + u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ; + if( u > 0 ) + { + vert->nx /= u ; + vert->ny /= u ; + vert->nz /= u ; + } + + return _nverts-1 ; +} + + +int MarchingCubes::add_c_vertex( ) +//----------------------------------------------------------------------------- +{ + test_vertex_addition() ; + Vertex *vert = _vertices + _nverts++ ; + + real u = 0 ; + int vid ; + + vert->x = vert->y = vert->z = vert->nx = vert->ny = vert->nz = 0 ; + + // Computes the average of the intersection points of the cube + vid = get_x_vert( _i , _j , _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_y_vert(_i+1, _j , _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_x_vert( _i ,_j+1, _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_y_vert( _i , _j , _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_x_vert( _i , _j ,_k+1) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_y_vert(_i+1, _j ,_k+1) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_x_vert( _i ,_j+1,_k+1) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_y_vert( _i , _j ,_k+1) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_z_vert( _i , _j , _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_z_vert(_i+1, _j , _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_z_vert(_i+1,_j+1, _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + vid = get_z_vert( _i ,_j+1, _k ) ; + if( vid != -1 ) { ++u ; const Vertex &v = _vertices[vid] ; vert->x += v.x ; vert->y += v.y ; vert->z += v.z ; vert->nx += v.nx ; vert->ny += v.ny ; vert->nz += v.nz ; } + + vert->x /= u ; + vert->y /= u ; + vert->z /= u ; + + u = (real) sqrt( vert->nx * vert->nx + vert->ny * vert->ny +vert->nz * vert->nz ) ; + if( u > 0 ) + { + vert->nx /= u ; + vert->ny /= u ; + vert->nz /= u ; + } + + return _nverts-1 ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +//_____________________________________________________________________________ + + + + +//_____________________________________________________________________________ +// Grid exportation +void MarchingCubes::writeISO(const char *fn ) +//----------------------------------------------------------------------------- +{ + unsigned char buf[sizeof(float)] ; + + FILE *fp = fopen( fn, "wb" ) ; + + // header + * (int*) buf = _size_x ; + fwrite(buf, sizeof(float), 1, fp); + * (int*) buf = _size_y ; + fwrite(buf, sizeof(float), 1, fp); + * (int*) buf = _size_z ; + fwrite(buf, sizeof(float), 1, fp); + + * (float*) buf = -1.0f ; + fwrite(buf, sizeof(float), 1, fp); + * (float*) buf = 1.0f ; + fwrite(buf, sizeof(float), 1, fp); + * (float*) buf = -1.0f ; + fwrite(buf, sizeof(float), 1, fp); + * (float*) buf = 1.0f ; + fwrite(buf, sizeof(float), 1, fp); + * (float*) buf = -1.0f ; + fwrite(buf, sizeof(float), 1, fp); + * (float*) buf = 1.0f ; + fwrite(buf, sizeof(float), 1, fp); + + for( int i = 0 ; i < _size_x ; i++ ) + { + for( int j = 0 ; j < _size_y ; j++ ) + { + for( int k = 0 ; k < _size_z ; k++ ) + { + * (float*) buf = (float)get_data( i,j,k ) ; + fwrite(buf, sizeof(float), 1, fp); + } + } + } + + fclose(fp) ; +} +//_____________________________________________________________________________ + + + + + +//_____________________________________________________________________________ +// PLY exportation +void MarchingCubes::writePLY(const char *fn, bool bin ) +//----------------------------------------------------------------------------- +{ + + typedef struct PlyFace { + unsigned char nverts; /* number of Vertex indices in list */ + int *verts; /* Vertex index list */ + } PlyFace; + + + PlyProperty vert_props[] = { /* list of property information for a PlyVertex */ + {"x", Float32, Float32, offsetof( Vertex,x ), 0, 0, 0, 0}, + {"y", Float32, Float32, offsetof( Vertex,y ), 0, 0, 0, 0}, + {"z", Float32, Float32, offsetof( Vertex,z ), 0, 0, 0, 0}, + {"nx", Float32, Float32, offsetof( Vertex,nx ), 0, 0, 0, 0}, + {"ny", Float32, Float32, offsetof( Vertex,ny ), 0, 0, 0, 0}, + {"nz", Float32, Float32, offsetof( Vertex,nz ), 0, 0, 0, 0} + }; + + PlyProperty face_props[] = { /* list of property information for a PlyFace */ + {"vertex_indices", Int32, Int32, offsetof( PlyFace,verts ), + 1, Uint8, Uint8, offsetof( PlyFace,nverts )}, + }; + + + PlyFile *ply; + FILE *fp = fopen( fn, "w" ); + + int i ; + PlyFace face ; + int verts[3] ; + char *elem_names[] = { "vertex", "face" }; + printf("Marching Cubes::writePLY(%s)...", fn ) ; + ply = write_ply ( fp, 2, elem_names, bin? PLY_BINARY_LE : PLY_ASCII ); + + /* describe what properties go into the PlyVertex elements */ + describe_element_ply ( ply, "vertex", _nverts ); + describe_property_ply ( ply, &vert_props[0] ); + describe_property_ply ( ply, &vert_props[1] ); + describe_property_ply ( ply, &vert_props[2] ); + describe_property_ply ( ply, &vert_props[3] ); + describe_property_ply ( ply, &vert_props[4] ); + describe_property_ply ( ply, &vert_props[5] ); + + /* describe PlyFace properties (just list of PlyVertex indices) */ + describe_element_ply ( ply, "face", _ntrigs ); + describe_property_ply ( ply, &face_props[0] ); + + header_complete_ply ( ply ); + + /* set up and write the PlyVertex elements */ + put_element_setup_ply ( ply, "vertex" ); + for ( i = 0; i < _nverts; i++ ) + put_element_ply ( ply, ( void * ) &(_vertices[i]) ); + printf(" %d vertices written\n", _nverts ) ; + + /* set up and write the PlyFace elements */ + put_element_setup_ply ( ply, "face" ); + face.nverts = 3 ; + face.verts = verts ; + for ( i = 0; i < _ntrigs; i++ ) + { + face.verts[0] = _triangles[i].v1 ; + face.verts[1] = _triangles[i].v2 ; + face.verts[2] = _triangles[i].v3 ; + put_element_ply ( ply, ( void * ) &face ); + } + printf(" %d triangles written\n", _ntrigs ) ; + + close_ply ( ply ); + free_ply ( ply ); + fclose( fp ) ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// PLY importation +void MarchingCubes::readPLY(const char *fn ) +//----------------------------------------------------------------------------- +{ + typedef struct PlyFace { + unsigned char nverts; /* number of Vertex indices in list */ + int *verts; /* Vertex index list */ + } PlyFace; + + + PlyProperty vert_props[] = { /* list of property information for a PlyVertex */ + {"x", Float32, Float32, offsetof( Vertex,x ), 0, 0, 0, 0}, + {"y", Float32, Float32, offsetof( Vertex,y ), 0, 0, 0, 0}, + {"z", Float32, Float32, offsetof( Vertex,z ), 0, 0, 0, 0}, + {"nx", Float32, Float32, offsetof( Vertex,nx ), 0, 0, 0, 0}, + {"ny", Float32, Float32, offsetof( Vertex,ny ), 0, 0, 0, 0}, + {"nz", Float32, Float32, offsetof( Vertex,nz ), 0, 0, 0, 0} + }; + + PlyProperty face_props[] = { /* list of property information for a PlyFace */ + {"vertex_indices", Int32, Int32, offsetof( PlyFace,verts ), + 1, Uint8, Uint8, offsetof( PlyFace,nverts )}, + }; + + + FILE *fp = fopen( fn, "r" ); + if( !fp ) return ; + PlyFile *ply = read_ply ( fp ); + printf("Marching Cubes::readPLY(%s)...", fn ) ; + + //----------------------------------------------------------------------------- + + // gets the number of faces and vertices + for ( int i = 0; i < ply->num_elem_types; ++i ) + { + int elem_count ; + char *elem_name = setup_element_read_ply ( ply, i, &elem_count ); + if ( equal_strings ( "vertex", elem_name ) ) + _Nverts = _nverts = elem_count; + if ( equal_strings ( "face", elem_name ) ) + _Ntrigs = _ntrigs = elem_count; + } + delete [] _vertices ; + _vertices = new Vertex [_Nverts] ; + delete [] _triangles ; + _triangles = new Triangle[_Ntrigs] ; + + //----------------------------------------------------------------------------- + + /* examine each element type that is in the file (PlyVertex, PlyFace) */ + + for ( int i = 0; i < ply->num_elem_types; ++i ) + { + /* prepare to read the i'th list of elements */ + int elem_count ; + char *elem_name = setup_element_read_ply ( ply, i, &elem_count ); + + //----------------------------------------------------------------------------- + if ( equal_strings ( "vertex", elem_name ) ) + { + /* set up for getting PlyVertex elements */ + setup_property_ply ( ply, &vert_props[0] ); + setup_property_ply ( ply, &vert_props[1] ); + setup_property_ply ( ply, &vert_props[2] ); + setup_property_ply ( ply, &vert_props[3] ); + setup_property_ply ( ply, &vert_props[4] ); + setup_property_ply ( ply, &vert_props[5] ); + + for ( int j = 0; j < _nverts; ++j ) + { + get_element_ply ( ply, ( void * ) (_vertices + j) ); + } + printf(" %d vertices read\n", _nverts ) ; + } + + //----------------------------------------------------------------------------- + else if ( equal_strings ( "face", elem_name ) ) + { + /* set up for getting PlyFace elements */ + /* (all we need are PlyVertex indices) */ + + setup_property_ply ( ply, &face_props[0] ) ; + PlyFace face ; + for ( int j = 0; j < _ntrigs; ++j ) + { + get_element_ply ( ply, ( void * ) &face ); + if( face.nverts != 3 ) + { + printf( "not a triangulated surface: polygon %d has %d sides\n", j, face.nverts ) ; + return ; + } + + _triangles[j].v1 = face.verts[0] ; + _triangles[j].v2 = face.verts[1] ; + _triangles[j].v3 = face.verts[2] ; + + free( face.verts ) ; + } + printf(" %d triangles read\n", _ntrigs ) ; + } + //----------------------------------------------------------------------------- + + //----------------------------------------------------------------------------- + else /* all non-PlyVertex and non-PlyFace elements are grabbed here */ + get_other_element_ply ( ply ); + //----------------------------------------------------------------------------- + } + + close_ply ( ply ); + free_ply ( ply ); + +// fit_to_bbox() ; + fclose( fp ) ; +} +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +// Open Inventor / VRML 1.0 ascii exportation +void MarchingCubes::writeIV(const char *fn ) +//----------------------------------------------------------------------------- +{ + FILE *fp = fopen( fn, "w" ) ; + int i ; + + printf("Marching Cubes::exportIV(%s)...", fn) ; + + fprintf( fp, "#Inventor V2.1 ascii \n\nSeparator { \n ShapeHints {\n vertexOrdering COUNTERCLOCKWISE\n shapeType UNKNOWN_SHAPE_TYPE\n creaseAngle 0.0\n }\n Coordinate3 { \n point [ \n" ) ; + for ( i = 0; i < _nverts; i++ ) + fprintf( fp, " %f %f %f,\n", _vertices[i].x, _vertices[i].y, _vertices[i].z ) ; + printf(" %d vertices written\n", _nverts ) ; + + fprintf( fp, "\n ] \n} \nNormal { \nvector [ \n" ) ; + for ( i = 0; i < _nverts; i++ ) + fprintf( fp, " %f %f %f,\n", _vertices[i].nx, _vertices[i].ny, _vertices[i].nz ) ; + + fprintf( fp, "\n ] \n} \nIndexedFaceSet { \ncoordIndex [ \n" ) ; + for ( i = 0; i < _ntrigs; i++ ) + fprintf( fp, "%d, %d, %d, -1,\n", _triangles[i].v1, _triangles[i].v2, _triangles[i].v3 ) ; + + fprintf( fp, " ] \n } \n } \n" ) ; + fclose( fp ) ; + printf(" %d triangles written\n", _ntrigs ) ; +} +//_____________________________________________________________________________ diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/MarchingCubes.h b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/MarchingCubes.h new file mode 100755 index 0000000000..c589bffb7f --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/MarchingCubes.h @@ -0,0 +1,343 @@ +/** + * @file MarchingCubes.h + * @author Thomas Lewiner + * @author Math Dept, PUC-Rio + * @version 0.2 + * @date 12/08/2002 + * + * @brief MarchingCubes Algorithm + */ +//________________________________________________ + + +#ifndef _MARCHINGCUBES_H_ +#define _MARCHINGCUBES_H_ + +#if !defined(WIN32) || defined(__CYGWIN__) +#pragma interface +#endif // WIN32 + + +//_____________________________________________________________________________ +// types +/** unsigned char alias */ +typedef unsigned char uchar ; +/** signed char alias */ +typedef signed char schar ; +/** isovalue alias */ +typedef float real ; + +//----------------------------------------------------------------------------- +// Vertex structure +/** \struct Vertex "MarchingCubes.h" MarchingCubes + * Position and normal of a vertex + * \brief vertex structure + * \param x X coordinate + * \param y Y coordinate + * \param z Z coordinate + * \param nx X component of the normal + * \param ny Y component of the normal + * \param nz Z component of the normal + */ +typedef struct +{ + real x, y, z ; /**< Vertex coordinates */ + real nx, ny, nz ; /**< Vertex normal */ +} Vertex ; + +//----------------------------------------------------------------------------- +// Triangle structure +/** \struct Triangle "MarchingCubes.h" MarchingCubes + * Indices of the oriented triange vertices + * \brief triangle structure + * \param v1 First vertex index + * \param v2 Second vertex index + * \param v3 Third vertex index + */ +typedef struct +{ + int v1,v2,v3 ; /**< Triangle vertices */ +} Triangle ; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** Marching Cubes algorithm wrapper */ +/** \class MarchingCubes + * \brief Marching Cubes algorithm. + */ +class MarchingCubes +//----------------------------------------------------------------------------- +{ +// Constructors +public : + /** + * Main and default constructor + * \brief constructor + * \param size_x width of the grid + * \param size_y depth of the grid + * \param size_z height of the grid + */ + MarchingCubes ( const int size_x = -1, const int size_y = -1, const int size_z = -1 ) ; + /** Destructor */ + ~MarchingCubes() ; + +//----------------------------------------------------------------------------- +// Accessors +public : + /** accesses the number of vertices of the generated mesh */ + inline const int nverts() const { return _nverts ; } + /** accesses the number of triangles of the generated mesh */ + inline const int ntrigs() const { return _ntrigs ; } + /** accesses a specific vertex of the generated mesh */ + inline Vertex * vert( const int i ) const { if( i < 0 || i >= _nverts ) return ( Vertex *)NULL ; return _vertices + i ; } + /** accesses a specific triangle of the generated mesh */ + inline Triangle * trig( const int i ) const { if( i < 0 || i >= _ntrigs ) return (Triangle*)NULL ; return _triangles + i ; } + + /** accesses the vertex buffer of the generated mesh */ + inline Vertex *vertices () { return _vertices ; } + /** accesses the triangle buffer of the generated mesh */ + inline Triangle *triangles() { return _triangles ; } + + /** accesses the width of the grid */ + inline const int size_x() const { return _size_x ; } + /** accesses the depth of the grid */ + inline const int size_y() const { return _size_y ; } + /** accesses the height of the grid */ + inline const int size_z() const { return _size_z ; } + + /** + * changes the size of the grid + * \param size_x width of the grid + * \param size_y depth of the grid + * \param size_z height of the grid + */ + inline void set_resolution( const int size_x, const int size_y, const int size_z ) { _size_x = size_x ; _size_y = size_y ; _size_z = size_z ; } + /** + * selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes + * \param originalMC true for the original Marching Cubes + */ + inline void set_method ( const bool originalMC = false ) { _originalMC = originalMC ; } + /** + * selects to use data from another class + * \param data is the pointer to the external data, allocated as a size_x*size_y*size_z vector running in x first + */ + inline void set_ext_data ( real *data ) + { if( !_ext_data ) delete [] _data ; _ext_data = data != NULL ; if( _ext_data ) _data = data ; } + /** + * selects to allocate data + */ + inline void set_int_data () { _ext_data = false ; _data = NULL ; } + + // Data access + /** + * accesses a specific cube of the grid + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline const real get_data ( const int i, const int j, const int k ) const { return _data[ i + j*_size_x + k*_size_x*_size_y] ; } + /** + * sets a specific cube of the grid + * \param val new value for the cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline void set_data ( const real val, const int i, const int j, const int k ) { _data[ i + j*_size_x + k*_size_x*_size_y] = val ; } + + // Data initialization + /** inits temporary structures (must set sizes before call) : the grid and the vertex index per cube */ + void init_temps () ; + /** inits all structures (must set sizes before call) : the temporary structures and the mesh buffers */ + void init_all () ; + /** clears temporary structures : the grid and the main */ + void clean_temps() ; + /** clears all structures : the temporary structures and the mesh buffers */ + void clean_all () ; + + +//----------------------------------------------------------------------------- +// Exportation +public : + /** + * PLY exportation of the generated mesh + * \param fn name of the PLY file to create + * \param bin if true, the PLY will be written in binary mode + */ + void writePLY( const char *fn, bool bin = false ) ; + + /** + * PLY importation of a mesh + * \param fn name of the PLY file to read from + */ + void readPLY( const char *fn ) ; + + /** + * VRML / Open Inventor exportation of the generated mesh + * \param fn name of the IV file to create + */ + void writeIV ( const char *fn ) ; + + /** + * ISO exportation of the input grid + * \param fn name of the ISO file to create + */ + void writeISO( const char *fn ) ; + + +//----------------------------------------------------------------------------- +// Algorithm +public : + /** + * Main algorithm : must be called after init_all + * \param iso isovalue + */ + void run( real iso = (real)0.0 ) ; + +protected : + /** tesselates one cube */ + void process_cube () ; + /** tests if the components of the tesselation of the cube should be connected by the interior of an ambiguous face */ + bool test_face ( schar face ) ; + /** tests if the components of the tesselation of the cube should be connected through the interior of the cube */ + bool test_interior( schar s ) ; + + +//----------------------------------------------------------------------------- +// Operations +protected : + /** + * computes almost all the vertices of the mesh by interpolation along the cubes edges + * \param iso isovalue + */ + void compute_intersection_points( real iso ) ; + + /** + * routine to add a triangle to the mesh + * \param trig the code for the triangle as a sequence of edges index + * \param n the number of triangles to produce + * \param v12 the index of the interior vertex to use, if necessary + */ + void add_triangle ( const char* trig, char n, int v12 = -1 ) ; + + /** tests and eventually doubles the vertex buffer capacity for a new vertex insertion */ + void test_vertex_addition() ; + /** adds a vertex on the current horizontal edge */ + int add_x_vertex() ; + /** adds a vertex on the current longitudinal edge */ + int add_y_vertex() ; + /** adds a vertex on the current vertical edge */ + int add_z_vertex() ; + /** adds a vertex inside the current cube */ + int add_c_vertex() ; + + /** + * interpolates the horizontal gradient of the implicit function at the lower vertex of the specified cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + real get_x_grad( const int i, const int j, const int k ) const ; + /** + * interpolates the longitudinal gradient of the implicit function at the lower vertex of the specified cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + real get_y_grad( const int i, const int j, const int k ) const ; + /** + * interpolates the vertical gradient of the implicit function at the lower vertex of the specified cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + real get_z_grad( const int i, const int j, const int k ) const ; + + /** + * accesses the pre-computed vertex index on the lower horizontal edge of a specific cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline int get_x_vert( const int i, const int j, const int k ) const { return _x_verts[ i + j*_size_x + k*_size_x*_size_y] ; } + /** + * accesses the pre-computed vertex index on the lower longitudinal edge of a specific cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline int get_y_vert( const int i, const int j, const int k ) const { return _y_verts[ i + j*_size_x + k*_size_x*_size_y] ; } + /** + * accesses the pre-computed vertex index on the lower vertical edge of a specific cube + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline int get_z_vert( const int i, const int j, const int k ) const { return _z_verts[ i + j*_size_x + k*_size_x*_size_y] ; } + + /** + * sets the pre-computed vertex index on the lower horizontal edge of a specific cube + * \param val the index of the new vertex + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline void set_x_vert( const int val, const int i, const int j, const int k ) { _x_verts[ i + j*_size_x + k*_size_x*_size_y] = val ; } + /** + * sets the pre-computed vertex index on the lower longitudinal edge of a specific cube + * \param val the index of the new vertex + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline void set_y_vert( const int val, const int i, const int j, const int k ) { _y_verts[ i + j*_size_x + k*_size_x*_size_y] = val ; } + /** + * sets the pre-computed vertex index on the lower vertical edge of a specific cube + * \param val the index of the new vertex + * \param i abscisse of the cube + * \param j ordinate of the cube + * \param k height of the cube + */ + inline void set_z_vert( const int val, const int i, const int j, const int k ) { _z_verts[ i + j*_size_x + k*_size_x*_size_y] = val ; } + + /** prints cube for debug */ + void print_cube() ; + +//----------------------------------------------------------------------------- +// Elements +protected : + bool _originalMC ; /**< selects wether the algorithm will use the enhanced topologically controlled lookup table or the original MarchingCubes */ + bool _ext_data ; /**< selects wether to allocate data or use data from another class */ + + int _size_x ; /**< width of the grid */ + int _size_y ; /**< depth of the grid */ + int _size_z ; /**< height of the grid */ + real *_data ; /**< implicit function values sampled on the grid */ + + int *_x_verts ; /**< pre-computed vertex indices on the lower horizontal edge of each cube */ + int *_y_verts ; /**< pre-computed vertex indices on the lower longitudinal edge of each cube */ + int *_z_verts ; /**< pre-computed vertex indices on the lower vertical edge of each cube */ + + int _nverts ; /**< number of allocated vertices in the vertex buffer */ + int _ntrigs ; /**< number of allocated triangles in the triangle buffer */ + int _Nverts ; /**< size of the vertex buffer */ + int _Ntrigs ; /**< size of the triangle buffer */ + Vertex *_vertices ; /**< vertex buffer */ + Triangle *_triangles ; /**< triangle buffer */ + + int _i ; /**< abscisse of the active cube */ + int _j ; /**< height of the active cube */ + int _k ; /**< ordinate of the active cube */ + + real _cube[8] ; /**< values of the implicit function on the active cube */ + uchar _lut_entry ; /**< cube sign representation in [0..255] */ + uchar _case ; /**< case of the active cube in [0..15] */ + uchar _config ; /**< configuration of the active cube */ + uchar _subconfig ; /**< subconfiguration of the active cube */ +}; +//_____________________________________________________________________________ + + +#endif // _MARCHINGCUBES_H_ diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/ply.c b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/ply.c new file mode 100755 index 0000000000..06c60f4dbb --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/ply.c @@ -0,0 +1,3325 @@ +/* + +The interface routines for reading and writing PLY polygon files. + +Greg Turk + +--------------------------------------------------------------- + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties the floating-point values x,y,z and the three unsigned +chars representing red, green and blue. + +----------------------------------------------------------------------- + +Copyright (c) 1998 Georgia Institute of Technology. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#include +#include +#include +#include +#include "ply.h" + +char *type_names[] = { /* names of scalar types */ +"invalid", +"int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64", +}; + +char *old_type_names[] = { /* old names of types for backward compatability */ +"invalid", +"char", "short", "int", "uchar", "ushort", "uint", "float", "double", +}; + +int ply_type_size[] = { +0, 1, 2, 4, 1, 2, 4, 4, 8 +}; + +#define NO_OTHER_PROPS -1 + +#define DONT_STORE_PROP 0 +#define STORE_PROP 1 + +#define OTHER_PROP 0 +#define NAMED_PROP 1 + +/* returns 1 if strings are equal, 0 if not */ +int equal_strings( char * , char * ); + +/* find an element in a plyfile's list */ +PlyElement *find_element( PlyFile * , char * ); + +/* find a property in an element's list */ +PlyProperty *find_property( PlyElement * , char * , int * ); + +/* write to a file the word describing a PLY file data type */ +void write_scalar_type( FILE * , int ); + +/* read a line from a file and break it up into separate words */ +char* *get_words( FILE * , int * , char ** ); + +/* write an item to a file */ +void write_binary_item( FILE * , int, unsigned int, double, int ); +void write_ascii_item( FILE * , int, unsigned int, double, int ); + +/* add information to a PLY file descriptor */ +void add_element( PlyFile * , char ** , int ); +void add_property( PlyFile * , char ** , int ); +void add_comment( PlyFile * , char * ); +void add_obj_info( PlyFile * , char * ); + +/* copy a property */ +void copy_property( PlyProperty * , PlyProperty * ); + +/* store a value into where a pointer and a type specify */ +void store_item( char * , int, int, unsigned int, double ); + +/* return the value of a stored item */ +void get_stored_item( void * , int, int * , unsigned int * , double * ); + +/* return the value stored in an item, given ptr to it and its type */ +double get_item_value( char * , int ); + +/* get binary or ascii item and store it according to ptr and type */ +void get_ascii_item( char * , int, int * , unsigned int * , double * ); +void get_binary_item( FILE * , int, int * , unsigned int * , double * ); + +/* get a bunch of elements from a file */ +void ascii_get_element( PlyFile * , char * ); +void binary_get_element( PlyFile * , char * ); + +/* memory allocation */ +static char *my_alloc( int, int, char * ); + + +/*************/ +/* Writing */ +/*************/ + + +/****************************************************************************** +Given a file pointer, get ready to write PLY data to the file. + +Entry: +fp - the given file pointer +nelems - number of elements in object +elem_names - list of element names +file_type - file type, either ascii or binary + +Exit: +returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_write( FILE *fp, int nelems, char **elem_names, int file_type ) +{ + int i; + PlyFile *plyfile; + PlyElement *elem; + + /* check for NULL file pointer */ + if ( fp == NULL ) + return ( NULL ); + + /* create a record for this object */ + + plyfile = ( PlyFile * ) myalloc ( sizeof ( PlyFile ) ); + plyfile->file_type = file_type; + plyfile->num_comments = 0; + plyfile->num_obj_info = 0; + plyfile->num_elem_types = nelems; + plyfile->version = 1.0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + + /* tuck aside the names of the elements */ + + plyfile->elems = ( PlyElement * * ) myalloc ( sizeof ( PlyElement * ) * nelems ); + for ( i = 0; i < nelems; i++ ) + { + elem = ( PlyElement * ) myalloc ( sizeof ( PlyElement ) ); + plyfile->elems[i] = elem; + elem->name = strdup ( elem_names[i] ); + elem->num = 0; + elem->nprops = 0; + } + + /* return pointer to the file descriptor */ + return ( plyfile ); +} + + +/****************************************************************************** +Open a polygon file for writing. + +Entry: +filename - name of file to read from +nelems - number of elements in object +elem_names - list of element names +file_type - file type, either ascii or binary + +Exit: +returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *open_for_writing_ply( char *filename, int nelems, char **elem_names, int file_type ) +{ + PlyFile *plyfile; + char *name; + FILE *fp; + + /* tack on the extension .ply, if necessary */ + + name = ( char * ) myalloc ( sizeof ( char ) * ( strlen ( filename ) + 5 ) ); + strcpy ( name, filename ); + if ( strlen ( name ) < 4 || strcmp ( name + strlen ( name ) - 4, ".ply" ) != 0 ) + strcat ( name, ".ply" ); + + /* open the file for writing */ + + fp = fopen ( name, "w" ); + if ( fp == NULL ) + { + return ( NULL ); + } + + /* create the actual PlyFile structure */ + + plyfile = ply_write ( fp, nelems, elem_names, file_type ); + if ( plyfile == NULL ) + return ( NULL ); + + /* return pointer to the file descriptor */ + return ( plyfile ); +} + + +/****************************************************************************** +Describe an element, including its properties and how many will be written +to the file. + +Entry: +plyfile - file identifier +elem_name - name of element that information is being specified about +nelems - number of elements of this type to be written +nprops - number of properties contained in the element +prop_list - list of properties +******************************************************************************/ + +void element_layout_ply( PlyFile *plyfile, char *elem_name, int nelems, int nprops, PlyProperty *prop_list ) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + { + fprintf( stderr,"element_layout_ply: can't find element '%s'\n",elem_name ); + exit ( -1 ); + } + + elem->num = nelems; + + /* copy the list of properties */ + + elem->nprops = nprops; + elem->props = ( PlyProperty * * ) myalloc ( sizeof ( PlyProperty * ) * nprops ); + elem->store_prop = ( char * ) myalloc ( sizeof ( char ) * nprops ); + + for ( i = 0; i < nprops; i++ ) + { + prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + elem->props[i] = prop; + elem->store_prop[i] = NAMED_PROP; + copy_property ( prop, &prop_list[i] ); + } +} + + +/****************************************************************************** +Describe a property of an element. + +Entry: +plyfile - file identifier +elem_name - name of element that information is being specified about +prop - the new property +******************************************************************************/ + +void ply_describe_property( PlyFile *plyfile, char *elem_name, PlyProperty *prop ) +{ + PlyElement *elem; + PlyProperty *elem_prop; + + /* look for appropriate element */ + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + { + fprintf( stderr, "ply_describe_property: can't find element '%s'\n", + elem_name ); + return; + } + + /* create room for new property */ + + if ( elem->nprops == 0 ) + { + elem->props = ( PlyProperty * * ) myalloc ( sizeof ( PlyProperty * ) ); + elem->store_prop = ( char * ) myalloc ( sizeof ( char ) ); + elem->nprops = 1; + } + else + { + elem->nprops++; + elem->props = ( PlyProperty * * ) + realloc ( elem->props, sizeof ( PlyProperty * ) * elem->nprops ); + elem->store_prop = ( char * ) + realloc ( elem->store_prop, sizeof ( char ) * elem->nprops ); + } + + /* copy the new property */ + + elem_prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + elem->props[elem->nprops - 1] = elem_prop; + elem->store_prop[elem->nprops - 1] = NAMED_PROP; + copy_property ( elem_prop, prop ); +} + + +/****************************************************************************** +State how many of a given element will be written. + +Entry: +plyfile - file identifier +elem_name - name of element that information is being specified about +nelems - number of elements of this type to be written +******************************************************************************/ + +void element_count_ply( PlyFile *plyfile, char *elem_name, int nelems ) +{ + PlyElement *elem; + + /* look for appropriate element */ + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + { + fprintf( stderr,"element_count_ply: can't find element '%s'\n",elem_name ); + exit ( -1 ); + } + + elem->num = nelems; +} + + +/****************************************************************************** +Signal that we've described everything a PLY file's header and that the +header should be written to the file. + +Entry: +plyfile - file identifier +******************************************************************************/ + +void header_complete_ply( PlyFile *plyfile ) +{ + int i,j; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + + fprintf ( fp, "ply\n" ); + + switch ( plyfile->file_type ) + { + case PLY_ASCII: + fprintf ( fp, "format ascii 1.0\n" ); + break; + case PLY_BINARY_BE: + fprintf ( fp, "format binary_big_endian 1.0\n" ); + break; + case PLY_BINARY_LE: + fprintf ( fp, "format binary_little_endian 1.0\n" ); + break; + default: + fprintf ( stderr, "ply_header_complete: bad file type = %d\n", + plyfile->file_type ); + exit ( -1 ); + } + + /* write out the comments */ + + for ( i = 0; i < plyfile->num_comments; i++ ) + fprintf ( fp, "comment %s\n", plyfile->comments[i] ); + + /* write out object information */ + + for ( i = 0; i < plyfile->num_obj_info; i++ ) + fprintf ( fp, "obj_info %s\n", plyfile->obj_info[i] ); + + /* write out information about each element */ + + for ( i = 0; i < plyfile->num_elem_types; i++ ) + { + elem = plyfile->elems[i]; + fprintf ( fp, "element %s %d\n", elem->name, elem->num ); + + /* write out each property */ + for ( j = 0; j < elem->nprops; j++ ) + { + prop = elem->props[j]; + if ( prop->is_list == PLY_LIST ) + { + fprintf ( fp, "property list " ); + write_scalar_type ( fp, prop->count_external ); + fprintf ( fp, " " ); + write_scalar_type ( fp, prop->external_type ); + fprintf ( fp, " %s\n", prop->name ); + } + else if ( prop->is_list == PLY_STRING ) + { + fprintf ( fp, "property string" ); + fprintf ( fp, " %s\n", prop->name ); + } + else + { + fprintf ( fp, "property " ); + write_scalar_type ( fp, prop->external_type ); + fprintf ( fp, " %s\n", prop->name ); + } + } + } + + fprintf ( fp, "end_header\n" ); +} + + +/****************************************************************************** +Specify which elements are going to be written. This should be called +before a call to the routine ply_put_element(). + +Entry: +plyfile - file identifier +elem_name - name of element we're talking about +******************************************************************************/ + +void put_element_setup_ply( PlyFile *plyfile, char *elem_name ) +{ + PlyElement *elem; + + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + { + fprintf( stderr, "put_element_setup_ply: can't find element '%s'\n", elem_name ); + exit ( -1 ); + } + + plyfile->which_elem = elem; +} + + +/****************************************************************************** +Write an element to the file. This routine assumes that we're +writing the type of element specified in the last call to the routine +put_element_setup_ply(). + +Entry: +plyfile - file identifier +elem_ptr - pointer to the element +******************************************************************************/ + +void put_element_ply( PlyFile *plyfile, void *elem_ptr ) +{ + int j,k; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + char *item; + char *elem_data; + char* *item_ptr; + int list_count; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + char* *other_ptr; + + elem = plyfile->which_elem; + elem_data = ( char * ) elem_ptr; + other_ptr = ( char * * ) ( ( ( char * ) elem_ptr ) + elem->other_offset ); + + /* write out either to an ascii or binary file */ + + if ( plyfile->file_type == PLY_ASCII ) + { + /* write an ascii file */ + + /* write out each property of the element */ + for ( j = 0; j < elem->nprops; j++ ) + { + prop = elem->props[j]; + + if ( elem->store_prop[j] == OTHER_PROP ) + elem_data = *other_ptr; + else + elem_data = ( char * ) elem_ptr; + + if ( prop->is_list == PLY_LIST ) + { + /* list */ + item = elem_data + prop->count_offset; + get_stored_item ( ( void * ) item, prop->count_internal, + &int_val, &uint_val, &double_val ); + write_ascii_item ( fp, int_val, uint_val, double_val, + prop->count_external ); + list_count = uint_val; + item_ptr = ( char * * ) ( elem_data + prop->offset ); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for ( k = 0; k < list_count; k++ ) + { + get_stored_item ( ( void * ) item, prop->internal_type, + &int_val, &uint_val, &double_val ); + write_ascii_item ( fp, int_val, uint_val, double_val, + prop->external_type ); + item += item_size; + } + } + else if ( prop->is_list == PLY_STRING ) + { + /* string */ + char* *str; + item = elem_data + prop->offset; + str = ( char * * ) item; + fprintf ( fp, "\"%s\"", *str ); + } + else + { + /* scalar */ + item = elem_data + prop->offset; + get_stored_item ( ( void * ) item, prop->internal_type, + &int_val, &uint_val, &double_val ); + write_ascii_item ( fp, int_val, uint_val, double_val, + prop->external_type ); + } + } + + fprintf ( fp, "\n" ); + } + else + { + /* write a binary file */ + + /* write out each property of the element */ + for ( j = 0; j < elem->nprops; j++ ) + { + prop = elem->props[j]; + if ( elem->store_prop[j] == OTHER_PROP ) + elem_data = *other_ptr; + else + elem_data = ( char * ) elem_ptr; + if ( prop->is_list == PLY_LIST ) + { + /* list */ + item = elem_data + prop->count_offset; + item_size = ply_type_size[prop->count_internal]; + get_stored_item ( ( void * ) item, prop->count_internal, + &int_val, &uint_val, &double_val ); + write_binary_item ( fp, int_val, uint_val, double_val, + prop->count_external ); + list_count = uint_val; + item_ptr = ( char * * ) ( elem_data + prop->offset ); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for ( k = 0; k < list_count; k++ ) + { + get_stored_item ( ( void * ) item, prop->internal_type, + &int_val, &uint_val, &double_val ); + write_binary_item ( fp, int_val, uint_val, double_val, + prop->external_type ); + item += item_size; + } + } + else if ( prop->is_list == PLY_STRING ) + { + /* string */ + int len; + char* *str; + item = elem_data + prop->offset; + str = ( char * * ) item; + + /* write the length */ + len = strlen( *str ) + 1; + fwrite ( &len, sizeof( int ), 1, fp ); + + /* write the string, including the null character */ + fwrite ( *str, len, 1, fp ); + } + else + { + /* scalar */ + item = elem_data + prop->offset; + item_size = ply_type_size[prop->internal_type]; + get_stored_item ( ( void * ) item, prop->internal_type, + &int_val, &uint_val, &double_val ); + write_binary_item ( fp, int_val, uint_val, double_val, + prop->external_type ); + } + } + } +} + + + + + + +/*************/ +/* Reading */ +/*************/ + + + +/****************************************************************************** +Given a file pointer, get ready to read PLY data from the file. + +Entry: +fp - the given file pointer + +Exit: +nelems - number of elements in object +elem_names - list of element names +returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_read( FILE *fp, int *nelems, char ***elem_names ) +{ + int i,j; + PlyFile *plyfile; + int nwords; + char* *words; + int found_format = 0; + char* *elist; + PlyElement *elem; + char *orig_line; + + /* check for NULL file pointer */ + if ( fp == NULL ) + return ( NULL ); + + /* create record for this object */ + + plyfile = ( PlyFile * ) myalloc ( sizeof ( PlyFile ) ); + plyfile->num_elem_types = 0; + plyfile->comments = NULL; + plyfile->num_comments = 0; + plyfile->obj_info = NULL; + plyfile->num_obj_info = 0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + plyfile->rule_list = NULL; + + /* read and parse the file's header */ + + words = get_words ( plyfile->fp, &nwords, &orig_line ); + if ( !words || !equal_strings ( words[0], "ply" ) ) + return ( NULL ); + + while ( words ) + { + /* parse words */ + + if ( equal_strings ( words[0], "format" ) ) + { + if ( nwords != 3 ) + return ( NULL ); + if ( equal_strings ( words[1], "ascii" ) ) + plyfile->file_type = PLY_ASCII; + else if ( equal_strings ( words[1], "binary_big_endian" ) ) + plyfile->file_type = PLY_BINARY_BE; + else if ( equal_strings ( words[1], "binary_little_endian" ) ) + plyfile->file_type = PLY_BINARY_LE; + else + return ( NULL ); + plyfile->version = ( float ) atof ( words[2] ); + found_format = 1; + } + else if ( equal_strings ( words[0], "element" ) ) + add_element ( plyfile, words, nwords ); + else if ( equal_strings ( words[0], "property" ) ) + add_property ( plyfile, words, nwords ); + else if ( equal_strings ( words[0], "comment" ) ) + add_comment ( plyfile, orig_line ); + else if ( equal_strings ( words[0], "obj_info" ) ) + add_obj_info ( plyfile, orig_line ); + else if ( equal_strings ( words[0], "end_header" ) ) + break; + + /* free up words space */ + free ( words ); + + words = get_words ( plyfile->fp, &nwords, &orig_line ); + } + + /* create tags for each property of each element, to be used */ + /* later to say whether or not to store each property for the user */ + + for ( i = 0; i < plyfile->num_elem_types; i++ ) + { + elem = plyfile->elems[i]; + elem->store_prop = ( char * ) myalloc ( sizeof ( char ) * elem->nprops ); + for ( j = 0; j < elem->nprops; j++ ) + elem->store_prop[j] = DONT_STORE_PROP; + elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ + } + + /* set return values about the elements */ + + elist = ( char * * ) myalloc ( sizeof ( char * ) * plyfile->num_elem_types ); + for ( i = 0; i < plyfile->num_elem_types; i++ ) + elist[i] = strdup ( plyfile->elems[i]->name ); + + *elem_names = elist; + *nelems = plyfile->num_elem_types; + + /* return a pointer to the file's information */ + + return ( plyfile ); +} + + +/****************************************************************************** +Open a polygon file for reading. + +Entry: +filename - name of file to read from + +Exit: +nelems - number of elements in object +elem_names - list of element names +file_type - file type, either ascii or binary +version - version number of PLY file +returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *ply_open_for_reading( char *filename, int *nelems, char ***elem_names, int *file_type, float *version ) +{ + FILE *fp; + PlyFile *plyfile; + char *name; + + /* tack on the extension .ply, if necessary */ + + name = ( char * ) myalloc ( sizeof ( char ) * ( strlen ( filename ) + 5 ) ); + strcpy ( name, filename ); + if ( strlen ( name ) < 4 || strcmp ( name + strlen ( name ) - 4, ".ply" ) != 0 ) + strcat ( name, ".ply" ); + + /* open the file for reading */ + + fp = fopen ( name, "r" ); + if ( fp == NULL ) + return ( NULL ); + + /* create the PlyFile data structure */ + + plyfile = ply_read ( fp, nelems, elem_names ); + + /* determine the file type and version */ + + *file_type = plyfile->file_type; + *version = plyfile->version; + + /* return a pointer to the file's information */ + + return ( plyfile ); +} + + +/****************************************************************************** +Get information about a particular element. + +Entry: +plyfile - file identifier +elem_name - name of element to get information about + +Exit: +nelems - number of elements of this type in the file +nprops - number of properties +returns a list of properties, or NULL if the file doesn't contain that elem +******************************************************************************/ + +PlyProperty **get_element_description_ply( PlyFile *plyfile, char *elem_name, int *nelems, int *nprops ) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + PlyProperty* *prop_list; + + /* find information about the element */ + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + return ( NULL ); + + *nelems = elem->num; + *nprops = elem->nprops; + + /* make a copy of the element's property list */ + prop_list = ( PlyProperty * * ) myalloc ( sizeof ( PlyProperty * ) * elem->nprops ); + for ( i = 0; i < elem->nprops; i++ ) + { + prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + copy_property ( prop, elem->props[i] ); + prop_list[i] = prop; + } + + /* return this duplicate property list */ + return ( prop_list ); +} + + +/****************************************************************************** +Specify which properties of an element are to be returned. This should be +called before a call to the routine get_element_ply(). + +Entry: +plyfile - file identifier +elem_name - which element we're talking about +nprops - number of properties +prop_list - list of properties +******************************************************************************/ + +void get_element_setup_ply( PlyFile *plyfile, char *elem_name, int nprops, PlyProperty *prop_list ) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + int index; + + /* find information about the element */ + elem = find_element ( plyfile, elem_name ); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + for ( i = 0; i < nprops; i++ ) + { + /* look for actual property */ + prop = find_property ( elem, prop_list[i].name, &index ); + if ( prop == NULL ) + { + fprintf ( stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop_list[i].name, elem_name ); + continue; + } + + /* store its description */ + prop->internal_type = prop_list[i].internal_type; + prop->offset = prop_list[i].offset; + prop->count_internal = prop_list[i].count_internal; + prop->count_offset = prop_list[i].count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; + } +} + + +/****************************************************************************** +Specify a property of an element that is to be returned. This should be +called (usually multiple times) before a call to the routine ply_get_element(). +This routine should be used in preference to the less flexible old routine +called ply_get_element_setup(). + +Entry: +plyfile - file identifier +elem_name - which element we're talking about +prop - property to add to those that will be returned +******************************************************************************/ + +void ply_get_property( PlyFile *plyfile, char *elem_name, PlyProperty *prop ) +{ + PlyElement *elem; + PlyProperty *prop_ptr; + int index; + + /* find information about the element */ + elem = find_element ( plyfile, elem_name ); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + + prop_ptr = find_property ( elem, prop->name, &index ); + if ( prop_ptr == NULL ) + { + fprintf ( stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop->name, elem_name ); + return; + } + prop_ptr->internal_type = prop->internal_type; + prop_ptr->offset = prop->offset; + prop_ptr->count_internal = prop->count_internal; + prop_ptr->count_offset = prop->count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; +} + + +/****************************************************************************** +Read one element from the file. This routine assumes that we're reading +the type of element specified in the last call to the routine +ply_get_element_setup(). + +Entry: +plyfile - file identifier +elem_ptr - pointer to location where the element information should be put +******************************************************************************/ + +void ply_get_element( PlyFile *plyfile, void *elem_ptr ) +{ + if ( plyfile->file_type == PLY_ASCII ) + ascii_get_element ( plyfile, ( char * ) elem_ptr ); + else + binary_get_element ( plyfile, ( char * ) elem_ptr ); +} + + +/****************************************************************************** +Extract the comments from the header information of a PLY file. + +Entry: +plyfile - file identifier + +Exit: +num_comments - number of comments returned +returns a pointer to a list of comments +******************************************************************************/ + +char **get_comments_ply( PlyFile *plyfile, int *num_comments ) +{ + *num_comments = plyfile->num_comments; + return ( plyfile->comments ); +} + + +/****************************************************************************** +Extract the object information (arbitrary text) from the header information +of a PLY file. + +Entry: +plyfile - file identifier + +Exit: +num_obj_info - number of lines of text information returned +returns a pointer to a list of object info lines +******************************************************************************/ + +char **get_obj_info_ply( PlyFile *plyfile, int *num_obj_info ) +{ + *num_obj_info = plyfile->num_obj_info; + return ( plyfile->obj_info ); +} + + +/****************************************************************************** +ake ready for "other" properties of an element-- those properties that +the user has not explicitly asked for, but that are to be stashed away +in a special structure to be carried along with the element's other +information. + +Entry: +plyfile - file identifier +elem - element for which we want to save away other properties +******************************************************************************/ + +void setup_other_props( PlyFile *plyfile, PlyElement *elem ) +{ + int i; + PlyProperty *prop; + int size = 0; + int type_size; + + /* Examine each property in decreasing order of size. */ + /* We do this so that all data types will be aligned by */ + /* word, half-word, or whatever within the structure. */ + + for ( type_size = 8; type_size > 0; type_size /= 2 ) + { + /* add up the space taken by each property, and save this information */ + /* away in the property descriptor */ + + for ( i = 0; i < elem->nprops; i++ ) + { + /* don't bother with properties we've been asked to store explicitly */ + if ( elem->store_prop[i] ) + continue; + + prop = elem->props[i]; + + /* internal types will be same as external */ + prop->internal_type = prop->external_type; + prop->count_internal = prop->count_external; + + /* list case */ + if ( prop->is_list == PLY_LIST ) + { + /* pointer to list */ + if ( type_size == sizeof ( void * ) ) + { + prop->offset = size; + size += sizeof ( void * ); /* always use size of a pointer here */ + } + + /* count of number of list elements */ + if ( type_size == ply_type_size[prop->count_external] ) + { + prop->count_offset = size; + size += ply_type_size[prop->count_external]; + } + } + /* string */ + else if ( prop->is_list == PLY_STRING ) + { + /* pointer to string */ + if ( type_size == sizeof ( char * ) ) + { + prop->offset = size; + size += sizeof ( char * ); + } + } + /* scalar */ + else if ( type_size == ply_type_size[prop->external_type] ) + { + prop->offset = size; + size += ply_type_size[prop->external_type]; + } + } + } + + /* save the size for the other_props structure */ + elem->other_size = size; +} + + +/****************************************************************************** +Specify that we want the "other" properties of an element to be tucked +away within the user's structure. + +Entry: +plyfile - file identifier +elem - the element that we want to store other_props in +offset - offset to where other_props will be stored inside user's structure + +Exit: +returns pointer to structure containing description of other_props +******************************************************************************/ + +static PlyOtherProp *get_other_properties( PlyFile *plyfile, PlyElement *elem, int offset ) +{ + int i; + PlyOtherProp *other; + PlyProperty *prop; + int nprops; + + /* remember that this is the "current" element */ + plyfile->which_elem = elem; + + /* save the offset to where to store the other_props */ + elem->other_offset = offset; + + /* place the appropriate pointers, etc. in the element's property list */ + setup_other_props ( plyfile, elem ); + + /* create structure for describing other_props */ + other = ( PlyOtherProp * ) myalloc ( sizeof ( PlyOtherProp ) ); + other->name = strdup ( elem->name ); +#if 0 +if (elem->other_offset == NO_OTHER_PROPS) { +other->size = 0; +other->props = NULL; +other->nprops = 0; +return (other); +} +#endif + other->size = elem->other_size; + other->props = ( PlyProperty * * ) myalloc ( sizeof( PlyProperty ) * elem->nprops ); + + /* save descriptions of each "other" property */ + nprops = 0; + for ( i = 0; i < elem->nprops; i++ ) + { + if ( elem->store_prop[i] ) + continue; + prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + copy_property ( prop, elem->props[i] ); + other->props[nprops] = prop; + nprops++; + } + other->nprops = nprops; + + /* set other_offset pointer appropriately if there are NO other properties */ + if ( other->nprops == 0 ) + { + elem->other_offset = NO_OTHER_PROPS; + } + + /* return structure */ + return ( other ); +} + + +/****************************************************************************** +Specify that we want the "other" properties of an element to be tucked +away within the user's structure. The user needn't be concerned for how +these properties are stored. + +Entry: +plyfile - file identifier +elem_name - name of element that we want to store other_props in +offset - offset to where other_props will be stored inside user's structure + +Exit: +returns pointer to structure containing description of other_props +******************************************************************************/ + +PlyOtherProp *ply_get_other_properties( PlyFile *plyfile, char *elem_name, int offset ) +{ + PlyElement *elem; + PlyOtherProp *other; + + /* find information about the element */ + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + { + fprintf ( stderr, "ply_get_other_properties: Can't find element '%s'\n", + elem_name ); + return ( NULL ); + } + + other = get_other_properties ( plyfile, elem, offset ); + return ( other ); +} + + + + +/*************************/ +/* Other Element Stuff */ +/*************************/ + + + + + +/****************************************************************************** +Grab all the data for the current element that a user does not want to +explicitly read in. Stores this in the PLY object's data structure. + +Entry: +plyfile - pointer to file + +Exit: +returns pointer to ALL the "other" element data for this PLY file +******************************************************************************/ + +PlyOtherElems *get_other_element_ply( PlyFile *plyfile ) +{ + int i; + PlyElement *elem; + char *elem_name; + int elem_count; + PlyOtherElems *other_elems; + OtherElem *other; + + elem = plyfile->which_elem; + elem_name = elem->name; + elem_count = elem->num; + + /* create room for the new "other" element, initializing the */ + /* other data structure if necessary */ + + if ( plyfile->other_elems == NULL ) + { + plyfile->other_elems = ( PlyOtherElems * ) myalloc ( sizeof ( PlyOtherElems ) ); + other_elems = plyfile->other_elems; + other_elems->other_list = ( OtherElem * ) myalloc ( sizeof ( OtherElem ) ); + other = &( other_elems->other_list[0] ); + other_elems->num_elems = 1; + } + else + { + other_elems = plyfile->other_elems; + other_elems->other_list = ( OtherElem * ) realloc ( other_elems->other_list, + sizeof ( OtherElem ) * other_elems->num_elems + 1 ); + other = &( other_elems->other_list[other_elems->num_elems] ); + other_elems->num_elems++; + } + + /* count of element instances in file */ + other->elem_count = elem_count; + + /* save name of element */ + other->elem_name = strdup ( elem_name ); + + /* create a list to hold all the current elements */ + other->other_data = ( OtherData * * ) + malloc ( sizeof ( OtherData * ) * other->elem_count ); + + /* set up for getting elements */ + other->other_props = ply_get_other_properties ( plyfile, elem_name, + offsetof( OtherData,other_props ) ); + + /* grab all these elements */ + for ( i = 0; i < other->elem_count; i++ ) + { + /* grab and element from the file */ + other->other_data[i] = ( OtherData * ) malloc ( sizeof ( OtherData ) ); + ply_get_element ( plyfile, ( void * ) other->other_data[i] ); + } + + /* return pointer to the other elements data */ + return ( other_elems ); +} + + +/****************************************************************************** +Write out the "other" elements specified for this PLY file. + +Entry: +plyfile - pointer to PLY file to write out other elements for +******************************************************************************/ + +void put_other_elements_ply( PlyFile *plyfile ) +{ + int i,j; + OtherElem *other; + + /* make sure we have other elements to write */ + if ( plyfile->other_elems == NULL ) + return; + + /* write out the data for each "other" element */ + + for ( i = 0; i < plyfile->other_elems->num_elems; i++ ) + { + other = &( plyfile->other_elems->other_list[i] ); + put_element_setup_ply ( plyfile, other->elem_name ); + + /* write out each instance of the current element */ + for ( j = 0; j < other->elem_count; j++ ) + put_element_ply ( plyfile, ( void * ) other->other_data[j] ); + } +} + + +/****************************************************************************** +Free up storage used by an "other" elements data structure. + +Entry: +other_elems - data structure to free up +******************************************************************************/ + +void free_other_elements_ply( PlyOtherElems *other_elems ) +{ +} + + + +/*******************/ +/* Miscellaneous */ +/*******************/ + + + +/****************************************************************************** +Close a PLY file. + +Entry: +plyfile - identifier of file to close +******************************************************************************/ + +void ply_close( PlyFile *plyfile ) +{ + fclose ( plyfile->fp ); + + /* free up memory associated with the PLY file */ + free ( plyfile ); +} + + +/****************************************************************************** +Get version number and file type of a PlyFile. + +Entry: +ply - pointer to PLY file + +Exit: +version - version of the file +file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE +******************************************************************************/ + +void get_info_ply( PlyFile *ply, float *version, int *file_type ) +{ + if ( ply == NULL ) + return; + + *version = ply->version; + *file_type = ply->file_type; +} + + +/****************************************************************************** +Compare two strings. Returns 1 if they are the same, 0 if not. +******************************************************************************/ + +int equal_strings( char *s1, char *s2 ) +{ + while ( *s1 && *s2 ) + if ( *s1++ != *s2++ ) + return ( 0 ); + + if ( *s1 != *s2 ) + return ( 0 ); + else + return ( 1 ); +} + + +/****************************************************************************** +Re-create the command line that was used to invoke this program. + +Entry: +argc - number of words in argv +argv - array of words in command line +******************************************************************************/ + +char *recreate_command_line( int argc, char *argv[] ) +{ + int i; + char *line; + int len = 0; + + /* count total number of characters needed, including separating spaces */ + for ( i = 0; i < argc; i++ ) + len += strlen( argv[i] ) + 1; + + /* create empty line */ + line = ( char * ) malloc ( sizeof( char ) * len ); + line[0] = '\0'; + + /* repeatedly append argv */ + for ( i = 0; i < argc; i++ ) + { + strcat ( line, argv[i] ); + if ( i != argc - 1 ) + strcat ( line, " " ); + } + + return ( line ); +} + + +/****************************************************************************** +Find an element from the element list of a given PLY object. + +Entry: +plyfile - file id for PLY file +element - name of element we're looking for + +Exit: +returns the element, or NULL if not found +******************************************************************************/ + +PlyElement *find_element( PlyFile *plyfile, char *element ) +{ + int i; + + for ( i = 0; i < plyfile->num_elem_types; i++ ) + if ( equal_strings ( element, plyfile->elems[i]->name ) ) + return ( plyfile->elems[i] ); + + return ( NULL ); +} + + +/****************************************************************************** +Find a property in the list of properties of a given element. + +Entry: +elem - pointer to element in which we want to find the property +prop_name - name of property to find + +Exit: +index - index to position in list +returns a pointer to the property, or NULL if not found +******************************************************************************/ + +PlyProperty *find_property( PlyElement *elem, char *prop_name, int *index ) +{ + int i; + + for ( i = 0; i < elem->nprops; i++ ) + if ( equal_strings ( prop_name, elem->props[i]->name ) ) + { + *index = i; + return ( elem->props[i] ); + } + + *index = -1; + return ( NULL ); +} + + +/****************************************************************************** +Read an element from an ascii file. + +Entry: +plyfile - file identifier +elem_ptr - pointer to element +******************************************************************************/ + +void ascii_get_element( PlyFile *plyfile, char *elem_ptr ) +{ + int j,k; + PlyElement *elem; + PlyProperty *prop; + char* *words; + int nwords; + int which_word; + char *elem_data,*item; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char* *store_array; + char *orig_line; + char *other_data; + int other_flag; + + item = (char*) NULL ; + other_data = (char*) NULL ; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if ( elem->other_offset != NO_OTHER_PROPS ) + { + char* *ptr; + other_flag = 1; + /* make room for other_props */ + other_data = ( char * ) myalloc ( elem->other_size ); + /* store pointer in user's structure to the other_props */ + ptr = ( char * * ) ( elem_ptr + elem->other_offset ); + *ptr = other_data; + } + else + other_flag = 0; + + /* read in the element */ + + words = get_words ( plyfile->fp, &nwords, &orig_line ); + if ( words == NULL ) + { + fprintf ( stderr, "ply_get_element: unexpected end of file\n" ); + exit ( -1 ); + } + + which_word = 0; + + for ( j = 0; j < elem->nprops; j++ ) + { + prop = elem->props[j]; + store_it = ( elem->store_prop[j] | other_flag ); + + /* store either in the user's structure or in other_props */ + if ( elem->store_prop[j] ) + elem_data = elem_ptr; + else + elem_data = other_data; + + if ( prop->is_list == PLY_LIST ) + { + /* a list */ + + /* get and store the number of items in the list */ + get_ascii_item ( words[which_word++], prop->count_external, + &int_val, &uint_val, &double_val ); + if ( store_it ) + { + item = elem_data + prop->count_offset; + store_item( item, prop->count_internal, int_val, uint_val, double_val ); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + item_size = ply_type_size[prop->internal_type]; + store_array = ( char * * ) ( elem_data + prop->offset ); + + if ( list_count == 0 ) + { + if ( store_it ) + *store_array = NULL; + } + else + { + if ( store_it ) + { + item_ptr = ( char * ) myalloc ( sizeof ( char ) * item_size * list_count ); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for ( k = 0; k < list_count; k++ ) + { + get_ascii_item ( words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val ); + if ( store_it ) + { + store_item ( item, prop->internal_type, + int_val, uint_val, double_val ); + item += item_size; + } + } + } + } + else if ( prop->is_list == PLY_STRING ) + { + /* a string */ + if ( store_it ) + { + char *str; + char* *str_ptr; + str = strdup ( words[which_word++] ); + item = elem_data + prop->offset; + str_ptr = ( char * * ) item; + *str_ptr = str; + } + else + { + which_word++; + } + } + else + { + /* a scalar */ + get_ascii_item ( words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val ); + if ( store_it ) + { + item = elem_data + prop->offset; + store_item ( item, prop->internal_type, int_val, uint_val, double_val ); + } + } + } + + free ( words ); +} + + +/****************************************************************************** +Read an element from a binary file. + +Entry: +plyfile - file identifier +elem_ptr - pointer to an element +******************************************************************************/ + +void binary_get_element( PlyFile *plyfile, char *elem_ptr ) +{ + int j,k; + PlyElement *elem; + PlyProperty *prop; + FILE *fp = plyfile->fp; + char *elem_data; + char *item; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char* *store_array; + char *other_data; + int other_flag; + + item = (char*) NULL ; + other_data = (char*) NULL ; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if ( elem->other_offset != NO_OTHER_PROPS ) + { + char* *ptr; + other_flag = 1; + /* make room for other_props */ + other_data = ( char * ) myalloc ( elem->other_size ); + /* store pointer in user's structure to the other_props */ + ptr = ( char * * ) ( elem_ptr + elem->other_offset ); + *ptr = other_data; + } + else + other_flag = 0; + + /* read in a number of elements */ + + for ( j = 0; j < elem->nprops; j++ ) + { + prop = elem->props[j]; + store_it = ( elem->store_prop[j] | other_flag ); + + /* store either in the user's structure or in other_props */ + if ( elem->store_prop[j] ) + elem_data = elem_ptr; + else + elem_data = other_data; + + if ( prop->is_list == PLY_LIST ) + { + /* list */ + + /* get and store the number of items in the list */ + get_binary_item ( fp, prop->count_external, + &int_val, &uint_val, &double_val ); + if ( store_it ) + { + item = elem_data + prop->count_offset; + store_item( item, prop->count_internal, int_val, uint_val, double_val ); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + item_size = ply_type_size[prop->internal_type]; + store_array = ( char * * ) ( elem_data + prop->offset ); + if ( list_count == 0 ) + { + if ( store_it ) + *store_array = NULL; + } + else + { + if ( store_it ) + { + item_ptr = ( char * ) myalloc ( sizeof ( char ) * item_size * list_count ); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for ( k = 0; k < list_count; k++ ) + { + get_binary_item ( fp, prop->external_type, + &int_val, &uint_val, &double_val ); + if ( store_it ) + { + store_item ( item, prop->internal_type, + int_val, uint_val, double_val ); + item += item_size; + } + } + } + } + else if ( prop->is_list == PLY_STRING ) + { + /* string */ + int len; + char *str; + fread ( &len, sizeof( int ), 1, fp ); + str = ( char * ) myalloc ( len ); + fread ( str, len, 1, fp ); + if ( store_it ) + { + char* *str_ptr; + item = elem_data + prop->offset; + str_ptr = ( char * * ) item; + *str_ptr = str; + } + } + else + { + /* scalar */ + get_binary_item ( fp, prop->external_type, + &int_val, &uint_val, &double_val ); + if ( store_it ) + { + item = elem_data + prop->offset; + store_item ( item, prop->internal_type, int_val, uint_val, double_val ); + } + } + } +} + + +/****************************************************************************** +Write to a file the word that represents a PLY data type. + +Entry: +fp - file pointer +code - code for type +******************************************************************************/ + +void write_scalar_type( FILE *fp, int code ) +{ + /* make sure this is a valid code */ + + if ( code <= StartType || code >= EndType ) + { + fprintf ( stderr, "write_scalar_type: bad data code = %d\n", code ); + exit ( -1 ); + } + + /* write the code to a file */ + + fprintf ( fp, "%s", type_names[code] ); +} + + +/****************************************************************************** +Get a text line from a file and break it up into words. + +IMPORTANT: The calling routine should call "free" on the returned pointer once +finished with it. + +Entry: +fp - file to read from + +Exit: +nwords - number of words returned +orig_line - the original line of characters +returns a list of words from the line, or NULL if end-of-file +******************************************************************************/ + +char **get_words( FILE *fp, int *nwords, char **orig_line ) +{ +#define BIG_STRING 4096 + static char str[BIG_STRING]; + static char str_copy[BIG_STRING]; + char* *words; + int max_words = 10; + int num_words = 0; + char *ptr,*ptr2; + char *result; + + words = ( char * * ) myalloc ( sizeof ( char * ) * max_words ); + + /* read in a line */ + result = fgets ( str, BIG_STRING, fp ); + if ( result == NULL ) + { + *nwords = 0; + *orig_line = NULL; + return ( NULL ); + } + + /* convert line-feed and tabs into spaces */ + /* (this guarentees that there will be a space before the */ + /* null character at the end of the string) */ + + str[BIG_STRING - 2] = ' '; + str[BIG_STRING - 1] = '\0'; + + for ( ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++ ) + { + *ptr2 = *ptr; + if ( *ptr == '\t' ) + { + *ptr = ' '; + *ptr2 = ' '; + } + else if ( *ptr == '\n' ) + { + *ptr = ' '; + *ptr2 = ' '; + break; + } + else if ( *ptr == '\r' ) + { + *ptr = ' '; + *ptr2 = '\0'; + } + } + + /* find the words in the line */ + + ptr = str; + while ( *ptr != '\0' ) + { + /* jump over leading spaces */ + while ( *ptr == ' ' ) + ptr++; + + /* break if we reach the end */ + if ( *ptr == '\0' ) + break; + + /* allocate more room for words if necessary */ + if ( num_words >= max_words ) + { + max_words += 10; + words = ( char * * ) realloc ( words, sizeof ( char * ) * max_words ); + } + + if ( *ptr == '\"' ) + { + /* a quote indidicates that we have a string */ + + /* skip over leading quote */ + ptr++; + + /* save pointer to beginning of word */ + words[num_words++] = ptr; + + /* find trailing quote or end of line */ + while ( *ptr != '\"' && *ptr != '\0' ) + ptr++; + + /* replace quote with a null character to mark the end of the word */ + /* if we are not already at the end of the line */ + if ( *ptr != '\0' ) + *ptr++ = '\0'; + } + else + { + /* non-string */ + + /* save pointer to beginning of word */ + words[num_words++] = ptr; + + /* jump over non-spaces */ + while ( *ptr != ' ' ) + ptr++; + + /* place a null character here to mark the end of the word */ + *ptr++ = '\0'; + } + } + + /* return the list of words */ + *nwords = num_words; + *orig_line = str_copy; + return ( words ); +} + + +/****************************************************************************** +Return the value of an item, given a pointer to it and its type. + +Entry: +item - pointer to item +type - data type that "item" points to + +Exit: +returns a double-precision float that contains the value of the item +******************************************************************************/ + +double get_item_value( char *item, int type ) +{ + unsigned char *puchar; + char *pchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + int int_value; + unsigned int uint_value; + double double_value; + + switch ( type ) + { + case Int8: + pchar = ( char * ) item; + int_value = *pchar; + return ( ( double ) int_value ); + case Uint8: + puchar = ( unsigned char * ) item; + int_value = *puchar; + return ( ( double ) int_value ); + case Int16: + pshort = ( short int * ) item; + int_value = *pshort; + return ( ( double ) int_value ); + case Uint16: + pushort = ( unsigned short int * ) item; + int_value = *pushort; + return ( ( double ) int_value ); + case Int32: + pint = ( int * ) item; + int_value = *pint; + return ( ( double ) int_value ); + case Uint32: + puint = ( unsigned int * ) item; + uint_value = *puint; + return ( ( double ) uint_value ); + case Float32: + pfloat = ( float * ) item; + double_value = *pfloat; + return ( double_value ); + case Float64: + pdouble = ( double * ) item; + double_value = *pdouble; + return ( double_value ); + default: + fprintf ( stderr, "get_item_value: bad type = %d\n", type ); + exit ( -1 ); + } + + return ( 0.0 ); /* never actually gets here */ +} + + +/****************************************************************************** +Write out an item to a file as raw binary bytes. + +Entry: +fp - file to write to +int_val - integer version of item +uint_val - unsigned integer version of item +double_val - double-precision float version of item +type - data type to write out +******************************************************************************/ + +void write_binary_item( FILE *fp, int int_val, unsigned int uint_val, double double_val, int type ) +{ + unsigned char uchar_val; + char char_val; + unsigned short ushort_val; + short short_val; + float float_val; + + switch ( type ) + { + case Int8: + char_val = int_val; + fwrite ( &char_val, 1, 1, fp ); + break; + case Int16: + short_val = int_val; + fwrite ( &short_val, 2, 1, fp ); + break; + case Int32: + fwrite ( &int_val, 4, 1, fp ); + break; + case Uint8: + uchar_val = uint_val; + fwrite ( &uchar_val, 1, 1, fp ); + break; + case Uint16: + ushort_val = uint_val; + fwrite ( &ushort_val, 2, 1, fp ); + break; + case Uint32: + fwrite ( &uint_val, 4, 1, fp ); + break; + case Float32: + float_val = ( float ) double_val; + fwrite ( &float_val, 4, 1, fp ); + break; + case Float64: + fwrite ( &double_val, 8, 1, fp ); + break; + default: + fprintf ( stderr, "write_binary_item: bad type = %d\n", type ); + exit ( -1 ); + } +} + + +/****************************************************************************** +Write out an item to a file as ascii characters. + +Entry: +fp - file to write to +int_val - integer version of item +uint_val - unsigned integer version of item +double_val - double-precision float version of item +type - data type to write out +******************************************************************************/ + +void write_ascii_item( FILE *fp, int int_val, unsigned int uint_val, double double_val, int type ) +{ + switch ( type ) + { + case Int8: + case Int16: + case Int32: + fprintf ( fp, "%d ", int_val ); + break; + case Uint8: + case Uint16: + case Uint32: + fprintf ( fp, "%u ", uint_val ); + break; + case Float32: + case Float64: + fprintf ( fp, "%12f ", double_val ); + break; + default: + fprintf ( stderr, "write_ascii_item: bad type = %d\n", type ); + exit ( -1 ); + } +} + + +/****************************************************************************** +Get the value of an item that is in memory, and place the result +into an integer, an unsigned integer and a double. + +Entry: +ptr - pointer to the item +type - data type supposedly in the item + +Exit: +int_val - integer value +uint_val - unsigned integer value +double_val - double-precision floating point value +******************************************************************************/ + +void get_stored_item( void *ptr, int type, int *int_val, unsigned int *uint_val, double *double_val ) +{ + switch ( type ) + { + case Int8: + *int_val = *( ( char * ) ptr ); + *uint_val = *int_val; + *double_val = *int_val; + break; + case Uint8: + *uint_val = *( ( unsigned char * ) ptr ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case Int16: + *int_val = *( ( short int * ) ptr ); + *uint_val = *int_val; + *double_val = *int_val; + break; + case Uint16: + *uint_val = *( ( unsigned short int * ) ptr ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case Int32: + *int_val = *( ( int * ) ptr ); + *uint_val = *int_val; + *double_val = *int_val; + break; + case Uint32: + *uint_val = *( ( unsigned int * ) ptr ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case Float32: + *double_val = *( ( float * ) ptr ); + *int_val = ( int ) *double_val; + *uint_val = ( unsigned int ) *double_val; + break; + case Float64: + *double_val = *( ( double * ) ptr ); + *int_val = ( int ) *double_val; + *uint_val = ( unsigned int ) *double_val; + break; + default: + fprintf ( stderr, "get_stored_item: bad type = %d\n", type ); + exit ( -1 ); + } +} + + +/****************************************************************************** +Get the value of an item from a binary file, and place the result +into an integer, an unsigned integer and a double. + +Entry: +fp - file to get item from +type - data type supposedly in the word + +Exit: +int_val - integer value +uint_val - unsigned integer value +double_val - double-precision floating point value +******************************************************************************/ + +void get_binary_item( FILE *fp, int type, int *int_val, unsigned int *uint_val, double *double_val ) +{ + char c[8]; + void *ptr; + + ptr = ( void * ) c; + + switch ( type ) + { + case Int8: + fread ( ptr, 1, 1, fp ); + *int_val = *( ( char * ) ptr ); + *uint_val = *int_val; + *double_val = *int_val; + break; + case Uint8: + fread ( ptr, 1, 1, fp ); + *uint_val = *( ( unsigned char * ) ptr ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case Int16: + fread ( ptr, 2, 1, fp ); + *int_val = *( ( short int * ) ptr ); + *uint_val = *int_val; + *double_val = *int_val; + break; + case Uint16: + fread ( ptr, 2, 1, fp ); + *uint_val = *( ( unsigned short int * ) ptr ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case Int32: + fread ( ptr, 4, 1, fp ); + *int_val = *( ( int * ) ptr ); + *uint_val = *int_val; + *double_val = *int_val; + break; + case Uint32: + fread ( ptr, 4, 1, fp ); + *uint_val = *( ( unsigned int * ) ptr ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case Float32: + fread ( ptr, 4, 1, fp ); + *double_val = *( ( float * ) ptr ); + *int_val = ( int ) *double_val; + *uint_val = ( unsigned int ) *double_val; + break; + case Float64: + fread ( ptr, 8, 1, fp ); + *double_val = *( ( double * ) ptr ); + *int_val = ( int ) *double_val; + *uint_val = ( unsigned int ) *double_val; + break; + default: + fprintf ( stderr, "get_binary_item: bad type = %d\n", type ); + exit ( -1 ); + } +} + + +/****************************************************************************** +Extract the value of an item from an ascii word, and place the result +into an integer, an unsigned integer and a double. + +Entry: +word - word to extract value from +type - data type supposedly in the word + +Exit: +int_val - integer value +uint_val - unsigned integer value +double_val - double-precision floating point value +******************************************************************************/ + +void get_ascii_item( char *word, int type, int *int_val, unsigned int *uint_val, double *double_val ) +{ + switch ( type ) + { + case Int8: + case Uint8: + case Int16: + case Uint16: + case Int32: + *int_val = atoi ( word ); + *uint_val = *int_val; + *double_val = *int_val; + break; + + case Uint32: + *uint_val = strtoul ( word, ( char * * ) NULL, 10 ); + *int_val = *uint_val; + *double_val = *uint_val; + break; + + case Float32: + case Float64: + *double_val = atof ( word ); + *int_val = ( int ) *double_val; + *uint_val = ( unsigned int ) *double_val; + break; + + default: + fprintf ( stderr, "get_ascii_item: bad type = %d\n", type ); + exit ( -1 ); + } +} + + +/****************************************************************************** +Store a value into a place being pointed to, guided by a data type. + +Entry: +item - place to store value +type - data type +int_val - integer version of value +uint_val - unsigned integer version of value +double_val - double version of value + +Exit: +item - pointer to stored value +******************************************************************************/ + +void store_item( char *item, int type, int int_val, unsigned int uint_val, double double_val ) +{ + unsigned char *puchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + + switch ( type ) + { + case Int8: + *item = int_val; + break; + case Uint8: + puchar = ( unsigned char * ) item; + *puchar = uint_val; + break; + case Int16: + pshort = ( short * ) item; + *pshort = int_val; + break; + case Uint16: + pushort = ( unsigned short * ) item; + *pushort = uint_val; + break; + case Int32: + pint = ( int * ) item; + *pint = int_val; + break; + case Uint32: + puint = ( unsigned int * ) item; + *puint = uint_val; + break; + case Float32: + pfloat = ( float * ) item; + *pfloat = ( float ) double_val; + break; + case Float64: + pdouble = ( double * ) item; + *pdouble = double_val; + break; + default: + fprintf ( stderr, "store_item: bad type = %d\n", type ); + exit ( -1 ); + } +} + + +/****************************************************************************** +Add an element to a PLY file descriptor. + +Entry: +plyfile - PLY file descriptor +words - list of words describing the element +nwords - number of words in the list +******************************************************************************/ + +void add_element( PlyFile *plyfile, char **words, int nwords ) +{ + PlyElement *elem; + + /* create the new element */ + elem = ( PlyElement * ) myalloc ( sizeof ( PlyElement ) ); + elem->name = strdup ( words[1] ); + elem->num = atoi ( words[2] ); + elem->nprops = 0; + + /* make room for new element in the object's list of elements */ + if ( plyfile->num_elem_types == 0 ) + plyfile->elems = ( PlyElement * * ) myalloc ( sizeof ( PlyElement * ) ); + else + plyfile->elems = ( PlyElement * * ) realloc ( plyfile->elems, + sizeof ( PlyElement * ) * ( plyfile->num_elem_types + 1 ) ); + + /* add the new element to the object's list */ + plyfile->elems[plyfile->num_elem_types] = elem; + plyfile->num_elem_types++; +} + + +/****************************************************************************** +Return the type of a property, given the name of the property. + +Entry: +name - name of property type + +Exit: +returns integer code for property, or 0 if not found +******************************************************************************/ + +int get_prop_type( char *type_name ) +{ + int i; + + /* try to match the type name */ + for ( i = StartType + 1; i < EndType; i++ ) + if ( equal_strings ( type_name, type_names[i] ) ) + return ( i ); + + /* see if we can match an old type name */ + for ( i = StartType + 1; i < EndType; i++ ) + if ( equal_strings ( type_name, old_type_names[i] ) ) + return ( i ); + + /* if we get here, we didn't find the type */ + return ( 0 ); +} + + +/****************************************************************************** +Add a property to a PLY file descriptor. + +Entry: +plyfile - PLY file descriptor +words - list of words describing the property +nwords - number of words in the list +******************************************************************************/ + +void add_property( PlyFile *plyfile, char **words, int nwords ) +{ + PlyProperty *prop; + PlyElement *elem; + + /* create the new property */ + + prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + + if ( equal_strings ( words[1], "list" ) ) + { + /* list */ + prop->count_external = get_prop_type ( words[2] ); + prop->external_type = get_prop_type ( words[3] ); + prop->name = strdup ( words[4] ); + prop->is_list = PLY_LIST; + } + else if ( equal_strings ( words[1], "string" ) ) + { + /* string */ + prop->count_external = Int8; + prop->external_type = Int8; + prop->name = strdup ( words[2] ); + prop->is_list = PLY_STRING; + } + else + { + /* scalar */ + prop->external_type = get_prop_type ( words[1] ); + prop->name = strdup ( words[2] ); + prop->is_list = PLY_SCALAR; + } + + /* add this property to the list of properties of the current element */ + + elem = plyfile->elems[plyfile->num_elem_types - 1]; + + if ( elem->nprops == 0 ) + elem->props = ( PlyProperty * * ) myalloc ( sizeof ( PlyProperty * ) ); + else + elem->props = ( PlyProperty * * ) realloc ( elem->props, + sizeof ( PlyProperty * ) * ( elem->nprops + 1 ) ); + + elem->props[elem->nprops] = prop; + elem->nprops++; +} + + +/****************************************************************************** +Add a comment to a PLY file descriptor. + +Entry: +plyfile - PLY file descriptor +line - line containing comment +******************************************************************************/ + +void add_comment( PlyFile *plyfile, char *line ) +{ + int i; + + /* skip over "comment" and leading spaces and tabs */ + i = 7; + while ( line[i] == ' ' || line[i] == '\t' ) + i++; + + append_comment_ply ( plyfile, &line[i] ); +} + + +/****************************************************************************** +Add a some object information to a PLY file descriptor. + +Entry: +plyfile - PLY file descriptor +line - line containing text info +******************************************************************************/ + +void add_obj_info( PlyFile *plyfile, char *line ) +{ + int i; + + /* skip over "obj_info" and leading spaces and tabs */ + i = 8; + while ( line[i] == ' ' || line[i] == '\t' ) + i++; + + append_obj_info_ply ( plyfile, &line[i] ); +} + + +/****************************************************************************** +Copy a property. +******************************************************************************/ + +void copy_property( PlyProperty *dest, PlyProperty *src ) +{ + dest->name = strdup ( src->name ); + dest->external_type = src->external_type; + dest->internal_type = src->internal_type; + dest->offset = src->offset; + + dest->is_list = src->is_list; + dest->count_external = src->count_external; + dest->count_internal = src->count_internal; + dest->count_offset = src->count_offset; +} + + +/****************************************************************************** +Allocate some memory. + +Entry: +size - amount of memory requested (in bytes) +lnum - line number from which memory was requested +fname - file name from which memory was requested +******************************************************************************/ + +static char *my_alloc( int size, int lnum, char *fname ) +{ + char *ptr; + + ptr = ( char * ) malloc ( size ); + + if ( ptr == 0 ) + { + fprintf( stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname ); + } + + return ( ptr ); +} + + +/**** NEW STUFF ****/ +/**** NEW STUFF ****/ +/**** NEW STUFF ****/ +/**** NEW STUFF ****/ + + + +/****************************************************************************** +Given a file pointer, get ready to read PLY data from the file. + +Entry: +fp - the given file pointer + +Exit: +nelems - number of elements in object +elem_names - list of element names +returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *read_ply( FILE *fp ) +{ + PlyFile *ply; + int num_elems; + char* *elem_names; + + ply = ply_read ( fp, &num_elems, &elem_names ); + + return ( ply ); +} + + +/****************************************************************************** +Given a file pointer, get ready to write PLY data to the file. + +Entry: +fp - the given file pointer +nelems - number of elements in object +elem_names - list of element names +file_type - file type, either ascii or binary + +Exit: +returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *write_ply( FILE *fp, int nelems, char **elem_names, int file_type ) +{ + PlyFile *ply; + + ply = ply_write ( fp, nelems, elem_names, file_type ); + + return ( ply ); +} + + +/****************************************************************************** +Return a list of the names of the elements in a particular PLY file. + +Entry: +ply - PLY file whose element name list we want + +Exit: +num_elems - the number of element names in the list +returns the list of names +******************************************************************************/ + +char **get_element_list_ply( PlyFile *ply, int *num_elems ) +{ + int i; + char* *elist; + + /* create the list of element names */ + + elist = ( char * * ) myalloc ( sizeof ( char * ) * ply->num_elem_types ); + for ( i = 0; i < ply->num_elem_types; i++ ) + elist[i] = strdup ( ply->elems[i]->name ); + + /* return the number of elements and the list of element names */ + *num_elems = ply->num_elem_types; + return ( elist ); +} + + +/****************************************************************************** +Append a comment to a PLY file. + +Entry: +ply - file to append comment to +comment - the comment to append +******************************************************************************/ + +void append_comment_ply( PlyFile *ply, char *comment ) +{ + /* (re)allocate space for new comment */ + if ( ply->num_comments == 0 ) + ply->comments = ( char * * ) myalloc ( sizeof ( char * ) ); + else + ply->comments = ( char * * ) realloc ( ply->comments, + sizeof ( char * ) * ( ply->num_comments + 1 ) ); + + /* add comment to list */ + ply->comments[ply->num_comments] = strdup ( comment ); + ply->num_comments++; +} + + +/****************************************************************************** +Copy the comments from one PLY file to another. + +Entry: +out_ply - destination file to copy comments to +in_ply - the source of the comments +******************************************************************************/ + +void copy_comments_ply( PlyFile *out_ply, PlyFile *in_ply ) +{ + int i; + + for ( i = 0; i < in_ply->num_comments; i++ ) + append_comment_ply ( out_ply, in_ply->comments[i] ); +} + + +/****************************************************************************** +Append object information (arbitrary text) to a PLY file. + +Entry: +ply - file to append object info to +obj_info - the object info to append +******************************************************************************/ + +void append_obj_info_ply( PlyFile *ply, char *obj_info ) +{ + /* (re)allocate space for new info */ + if ( ply->num_obj_info == 0 ) + ply->obj_info = ( char * * ) myalloc ( sizeof ( char * ) ); + else + ply->obj_info = ( char * * ) realloc ( ply->obj_info, + sizeof ( char * ) * ( ply->num_obj_info + 1 ) ); + + /* add info to list */ + ply->obj_info[ply->num_obj_info] = strdup ( obj_info ); + ply->num_obj_info++; +} + + +/****************************************************************************** +Copy the object information from one PLY file to another. + +Entry: +out_ply - destination file to copy object information to +in_ply - the source of the object information +******************************************************************************/ + +void copy_obj_info_ply( PlyFile *out_ply, PlyFile *in_ply ) +{ + int i; + + for ( i = 0; i < in_ply->num_obj_info; i++ ) + append_obj_info_ply ( out_ply, in_ply->obj_info[i] ); +} + + +/****************************************************************************** +Close a PLY file. + +Entry: +plyfile - identifier of file to close +******************************************************************************/ + +void close_ply( PlyFile *plyfile ) +{ + fclose ( plyfile->fp ); +} + + +/****************************************************************************** +Free the memory used by a PLY file. + +Entry: +plyfile - identifier of file +******************************************************************************/ + +void free_ply( PlyFile *plyfile ) +{ + /* free up memory associated with the PLY file */ + free ( plyfile ); +} + + +/****************************************************************************** +Specify the index of the next element to be read in from a PLY file. + +Entry: +ply - file to read from +index - index of the element to be read + +Exit: +elem_count - the number of elements in the file +returns pointer to the name of this next element +******************************************************************************/ + +char *setup_element_read_ply( PlyFile *ply, int index, int *elem_count ) +{ + PlyElement *elem; + + if ( index < 0 || index > ply->num_elem_types ) + { + fprintf ( stderr, "Warning: No element with index %d\n", index ); + return ( 0 ); + } + + elem = ply->elems[index]; + + /* set this to be the current element */ + ply->which_elem = elem; + + /* return the number of such elements in the file and the element's name */ + *elem_count = elem->num; + return ( elem->name ); +} + + +/****************************************************************************** +Read one element from the file. This routine assumes that we're reading +the type of element specified in the last call to the routine +setup_element_read_ply(). + +Entry: +plyfile - file identifier +elem_ptr - pointer to location where the element information should be put +******************************************************************************/ + +void get_element_ply( PlyFile *plyfile, void *elem_ptr ) +{ + if ( plyfile->file_type == PLY_ASCII ) + ascii_get_element ( plyfile, ( char * ) elem_ptr ); + else + binary_get_element ( plyfile, ( char * ) elem_ptr ); +} + + +/****************************************************************************** +Specify one of several properties of the current element that is to be +read from a file. This should be called (usually multiple times) before a +call to the routine get_element_ply(). + +Entry: +plyfile - file identifier +prop - property to add to those that will be returned + +Exit: +0 if the property has not been found +1 if the property has been found +******************************************************************************/ + +int setup_property_ply( PlyFile *plyfile, PlyProperty *prop ) +{ + PlyElement *elem; + PlyProperty *prop_ptr; + int index; + + elem = plyfile->which_elem; + + /* deposit the property information into the element's description */ + + prop_ptr = find_property ( elem, prop->name, &index ); + if ( prop_ptr == NULL ) + { + fprintf ( stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop->name, elem->name ); + return 0; + } + prop_ptr->internal_type = prop->internal_type; + prop_ptr->offset = prop->offset; + prop_ptr->count_internal = prop->count_internal; + prop_ptr->count_offset = prop->count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; + return 1 ; +} + + +/****************************************************************************** +Specify that we want the "other" properties of the current element to be tucked +away within the user's structure. + +Entry: +plyfile - file identifier +offset - offset to where other_props will be stored inside user's structure + +Exit: +returns pointer to structure containing description of other_props +******************************************************************************/ + +PlyOtherProp *get_other_properties_ply( PlyFile *plyfile, int offset ) +{ + PlyOtherProp *other; + + other = get_other_properties ( plyfile, plyfile->which_elem, offset ); + return ( other ); +} + + +/****************************************************************************** +Describe which element is to be written next and state how many of them will +be written. + +Entry: +plyfile - file identifier +elem_name - name of element that information is being described +nelems - number of elements of this type to be written +******************************************************************************/ + +void describe_element_ply( PlyFile *plyfile, char *elem_name, int nelems ) +{ + PlyElement *elem; + + /* look for appropriate element */ + elem = find_element ( plyfile, elem_name ); + if ( elem == NULL ) + { + fprintf( stderr,"describe_element_ply: can't find element '%s'\n",elem_name ); + exit ( -1 ); + } + + elem->num = nelems; + + /* now this element is the current element */ + plyfile->which_elem = elem; +} + + +/****************************************************************************** +Describe a property of an element. + +Entry: +plyfile - file identifier +prop - the new property +******************************************************************************/ + +void describe_property_ply( PlyFile *plyfile, PlyProperty *prop ) +{ + PlyElement *elem; + PlyProperty *elem_prop; + + elem = plyfile->which_elem; + + /* create room for new property */ + + if ( elem->nprops == 0 ) + { + elem->props = ( PlyProperty * * ) myalloc ( sizeof ( PlyProperty * ) ); + elem->store_prop = ( char * ) myalloc ( sizeof ( char ) ); + elem->nprops = 1; + } + else + { + elem->nprops++; + elem->props = ( PlyProperty * * ) + realloc ( elem->props, sizeof ( PlyProperty * ) * elem->nprops ); + elem->store_prop = ( char * ) + realloc ( elem->store_prop, sizeof ( char ) * elem->nprops ); + } + + /* copy the new property */ + + elem_prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + elem->props[elem->nprops - 1] = elem_prop; + elem->store_prop[elem->nprops - 1] = NAMED_PROP; + copy_property ( elem_prop, prop ); +} + + +/****************************************************************************** +Describe what the "other" properties are that are to be stored, and where +they are in an element. +******************************************************************************/ + +void describe_other_properties_ply( PlyFile *plyfile, PlyOtherProp *other, int offset ) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element ( plyfile, other->name ); + if ( elem == NULL ) + { + fprintf( stderr, "describe_other_properties_ply: can't find element '%s'\n", + other->name ); + return; + } + + /* create room for other properties */ + + if ( elem->nprops == 0 ) + { + elem->props = ( PlyProperty * * ) + myalloc ( sizeof ( PlyProperty * ) * other->nprops ); + elem->store_prop = ( char * ) myalloc ( sizeof ( char ) * other->nprops ); + elem->nprops = 0; + } + else + { + int newsize; + newsize = elem->nprops + other->nprops; + elem->props = ( PlyProperty * * ) + realloc ( elem->props, sizeof ( PlyProperty * ) * newsize ); + elem->store_prop = ( char * ) + realloc ( elem->store_prop, sizeof ( char ) * newsize ); + } + + /* copy the other properties */ + + for ( i = 0; i < other->nprops; i++ ) + { + prop = ( PlyProperty * ) myalloc ( sizeof ( PlyProperty ) ); + copy_property ( prop, other->props[i] ); + elem->props[elem->nprops] = prop; + elem->store_prop[elem->nprops] = OTHER_PROP; + elem->nprops++; + } + + /* save other info about other properties */ + elem->other_size = other->size; + elem->other_offset = offset; +} + + +/****************************************************************************** +Pass along a pointer to "other" elements that we want to save in a given +PLY file. These other elements were presumably read from another PLY file. + +Entry: +plyfile - file pointer in which to store this other element info +other_elems - info about other elements that we want to store +******************************************************************************/ + +void describe_other_elements_ply( PlyFile *plyfile, PlyOtherElems *other_elems ) +{ + int i; + OtherElem *other; + + /* ignore this call if there is no other element */ + if ( other_elems == NULL ) + return; + + /* save pointer to this information */ + plyfile->other_elems = other_elems; + + /* describe the other properties of this element */ + + for ( i = 0; i < other_elems->num_elems; i++ ) + { + other = &( other_elems->other_list[i] ); + element_count_ply ( plyfile, other->elem_name, other->elem_count ); + describe_other_properties_ply ( plyfile, other->other_props, + offsetof( OtherData,other_props ) ); + } +} + + + +/**** Property Propagation Rules ****/ + + +typedef struct RuleName { +int code; +char *name; +} RuleName; + +RuleName rule_name_list[] = { +{AVERAGE_RULE, "avg"}, +{RANDOM_RULE, "rnd"}, +{MINIMUM_RULE, "max"}, +{MAXIMUM_RULE, "min"}, +{MAJORITY_RULE, "major"}, +{SAME_RULE, "same"}, +{-1, "end_marker"}, +}; + + + +/****************************************************************************** +Initialize the property propagation rules for an element. Default is to +use averaging (AVERAGE_RULE) for creating all new properties. + +Entry: +ply - PLY object that this is for +elem_name - name of the element that we're making the rules for + +Exit: +returns pointer to the default rules +******************************************************************************/ + +PlyPropRules *init_rule_ply( PlyFile *ply, char *elem_name ) +{ + int i,j; + PlyElement *elem; + PlyPropRules *rules; + PlyRuleList *list; + int found_prop; + + elem = find_element ( ply, elem_name ); + if ( elem == NULL ) + { + fprintf ( stderr, "init_rule_ply: Can't find element '%s'\n", elem_name ); + exit ( -1 ); + } + + rules = ( PlyPropRules * ) myalloc ( sizeof ( PlyPropRules ) ); + rules->elem = elem; + rules->rule_list = ( int * ) myalloc ( sizeof( int ) * elem->nprops ); + rules->max_props = 0; + rules->nprops = 0; + + /* default is to use averaging rule */ + for ( i = 0; i < elem->nprops; i++ ) + rules->rule_list[i] = AVERAGE_RULE; + + /* see if there are other rules we should use */ + + if ( ply->rule_list == NULL ) + return ( rules ); + + /* try to match the element, property and rule name */ + + for ( list = ply->rule_list; list != NULL; list = list->next ) + { + if ( !equal_strings ( list->element, elem->name ) ) + continue; + + found_prop = 0; + + for ( i = 0; i < elem->nprops; i++ ) + if ( equal_strings ( list->property, elem->props[i]->name ) ) + { + found_prop = 1; + + /* look for matching rule name */ + for ( j = 0; rule_name_list[j].code != -1; j++ ) + if ( equal_strings ( list->name, rule_name_list[j].name ) ) + { + rules->rule_list[i] = rule_name_list[j].code; + break; + } + } + + if ( !found_prop ) + { + fprintf ( stderr, "Can't find property '%s' for rule '%s'\n", + list->property, list->name ); + continue; + } + } + + return ( rules ); +} + + +/****************************************************************************** +odify a property propagation rule. + +Entry: +rules - rules for the element +prop_name - name of the property whose rule we're modifying +rule_type - type of rule (MAXIMUM_RULE, MINIMUM_RULE, MAJORITY_RULE, etc.) +******************************************************************************/ + +void modify_rule_ply( PlyPropRules *rules, char *prop_name, int rule_type ) +{ + int i; + PlyElement *elem = rules->elem; + + /* find the property and modify its rule type */ + + for ( i = 0; i < elem->nprops; i++ ) + if ( equal_strings ( elem->props[i]->name, prop_name ) ) + { + rules->rule_list[i] = rule_type; + return; + } + + /* we didn't find the property if we get here */ + fprintf ( stderr, "modify_rule_ply: Can't find property '%s'\n", prop_name ); + exit ( -1 ); +} + + +/****************************************************************************** +Begin to create a set of properties from a set of propagation rules. + +Entry: +ply - PLY object whose rules we're preparing to use +rules - rules for the element +******************************************************************************/ + +void start_props_ply( PlyFile *ply, PlyPropRules *rules ) +{ + /* PlyElement *elem = rules->elem; */ + + /* save pointer to the rules in the PLY object */ + ply->current_rules = rules; + + /* get ready for new sets of properties to combine */ + rules->nprops = 0; +} + + +/****************************************************************************** +Remember a set of properties and their weights for creating a new set of +properties. + +Entry: +weight - weights for this set of properties +other_props - the properties to use +******************************************************************************/ + +void weight_props_ply( PlyFile *ply, float weight, void *other_props ) +{ + PlyPropRules *rules = ply->current_rules; + + /* allocate space for properties and weights, if necessary */ + if ( rules->max_props == 0 ) + { + rules->max_props = 6; + rules->props = ( void * * ) myalloc ( sizeof ( void * ) * rules->max_props ); + rules->weights = ( float * ) myalloc ( sizeof ( float ) * rules->max_props ); + } + if ( rules->nprops == rules->max_props ) + { + rules->max_props *= 2; + rules->props = ( void * * ) realloc ( rules->props, + sizeof ( void * ) * rules->max_props ); + rules->weights = ( float * ) realloc ( rules->weights, + sizeof ( float ) * rules->max_props ); + } + + /* remember these new properties and their weights */ + + rules->props[rules->nprops] = other_props; + rules->weights[rules->nprops] = weight; + rules->nprops++; +} + + +/****************************************************************************** +Return a pointer to a new set of properties that have been created using +a specified set of property combination rules and a given collection of +"other" properties. + +Exit: +returns a pointer to the new properties +******************************************************************************/ + +void *get_new_props_ply( PlyFile *ply ) +{ + int i,j; + static double *vals; + static int max_vals = 0; + PlyPropRules *rules = ply->current_rules; + PlyElement *elem = rules->elem; + PlyProperty *prop; + char *data; + char *new_data; + void *ptr; + int offset; + int type; + double double_val; + int int_val; + unsigned int uint_val; + int random_pick; + + /* return NULL if we've got no "other" properties */ + if ( elem->other_size == 0 ) + { + return ( NULL ); + } + + /* create room for combined other properties */ + new_data = ( char * ) myalloc ( sizeof ( char ) * elem->other_size ); + + /* make sure there is enough room to store values we're to combine */ + + if ( max_vals == 0 ) + { + max_vals = rules->nprops; + vals = ( double * ) myalloc ( sizeof ( double ) * rules->nprops ); + } + if ( rules->nprops >= max_vals ) + { + max_vals = rules->nprops; + vals = ( double * ) realloc ( vals, sizeof ( double ) * rules->nprops ); + } + + /* in case we need a random choice */ + random_pick = ( int ) floor ( rules->nprops ); //* drand48()); + + /* calculate the combination for each "other" property of the element */ + + for ( i = 0; i < elem->nprops; i++ ) + { + /* don't bother with properties we've been asked to store explicitly */ + if ( elem->store_prop[i] ) + continue; + + prop = elem->props[i]; + offset = prop->offset; + type = prop->external_type; + + /* collect together all the values we're to combine */ + + for ( j = 0; j < rules->nprops; j++ ) + { + data = ( char * ) rules->props[j]; + ptr = ( void * ) ( data + offset ); + get_stored_item ( ( void * ) ptr, type, &int_val, &uint_val, &double_val ); + vals[j] = double_val; + } + + /* calculate the combined value */ + + switch ( rules->rule_list[i] ) + { + case AVERAGE_RULE: + { + double sum = 0; + double weight_sum = 0; + for ( j = 0; j < rules->nprops; j++ ) + { + sum += vals[j] * rules->weights[j]; + weight_sum += rules->weights[j]; + } + double_val = sum / weight_sum; + break; + } + case MINIMUM_RULE: + { + double_val = vals[0]; + for ( j = 1; j < rules->nprops; j++ ) + if ( double_val > vals[j] ) + double_val = vals[j]; + break; + } + case MAXIMUM_RULE: + { + double_val = vals[0]; + for ( j = 1; j < rules->nprops; j++ ) + if ( double_val < vals[j] ) + double_val = vals[j]; + break; + } + case RANDOM_RULE: + { + double_val = vals[random_pick]; + break; + } + case SAME_RULE: + { + double_val = vals[0]; + for ( j = 1; j < rules->nprops; j++ ) + if ( double_val != vals[j] ) + { + fprintf ( stderr, + "get_new_props_ply: Error combining properties that should be the same.\n" ); + exit ( -1 ); + } + break; + } + default: + fprintf ( stderr, "get_new_props_ply: Bad rule = %d\n", + rules->rule_list[i] ); + exit ( -1 ); + } + + /* store the combined value */ + + int_val = ( int ) double_val; + uint_val = ( unsigned int ) double_val; + ptr = ( void * ) ( new_data + offset ); + store_item ( ( char * ) ptr, type, int_val, uint_val, double_val ); + } + + return ( ( void * ) new_data ); +} + + +/****************************************************************************** +Set the list of user-specified property combination rules. +******************************************************************************/ + +void set_prop_rules_ply( PlyFile *ply, PlyRuleList *prop_rules ) +{ + ply->rule_list = prop_rules; +} + + +/****************************************************************************** +Append a property rule to a growing list of user-specified rules. + +Entry: +rule_list - current rule list +name - name of property combination rule +property - "element.property" says which property the rule affects + +Exit: +returns pointer to the new rule list +******************************************************************************/ + +PlyRuleList *append_prop_rule( PlyRuleList *rule_list, char *name, char *property ) +{ + PlyRuleList *rule; + PlyRuleList *rule_ptr; + char *str,*str2; + char *ptr; + + /* find . */ + str = strdup ( property ); + for ( ptr = str; *ptr != '\0' && *ptr != '.'; ptr++ ) + ; + + /* split string at . */ + if ( *ptr == '.' ) + { + *ptr = '\0'; + str2 = ptr + 1; + } + else + { + fprintf ( stderr, "Can't find property '%s' for rule '%s'\n", + property, name ); + return ( rule_list ); + } + + rule = ( PlyRuleList * ) malloc ( sizeof ( PlyRuleList ) ); + rule->name = name; + rule->element = str; + rule->property = str2; + rule->next = NULL; + + /* either start rule list or append to it */ + + if ( rule_list == NULL ) + rule_list = rule; + else + { + /* append new rule to current list */ + rule_ptr = rule_list; + while ( rule_ptr->next != NULL ) + rule_ptr = rule_ptr->next; + rule_ptr->next = rule; + } + + /* return pointer to list */ + + return ( rule_list ); +} + + +/****************************************************************************** +See if a name matches the name of any property combination rules. + +Entry: +name - name of rule we're trying to match + +Exit: +returns 1 if we find a match, 0 if not +******************************************************************************/ + +int matches_rule_name( char *name ) +{ + int i; + + for ( i = 0; rule_name_list[i].code != -1; i++ ) + if ( equal_strings ( rule_name_list[i].name, name ) ) + return ( 1 ); + + return ( 0 ); +} + diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/ply.h b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/ply.h new file mode 100755 index 0000000000..1925d5e584 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/MarchingCubes/ply.h @@ -0,0 +1,233 @@ +/* + +Header for PLY polygon files. + +- Greg Turk + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties three floating-point values x,y,z and three unsigned +chars for red, green and blue. + +----------------------------------------------------------------------- + +Copyright (c) 1998 Georgia Institute of Technology. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#ifndef __PLY_H__ +#define __PLY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define PLY_ASCII 1 /* ascii PLY file */ +#define PLY_BINARY_BE 2 /* binary PLY file, big endian */ +#define PLY_BINARY_LE 3 /* binary PLY file, little endian */ + +#define PLY_OKAY 0 /* ply routine worked okay */ +#define PLY_ERROR -1 /* error in ply routine */ + +/* scalar data types supported by PLY format */ + +#define StartType 0 +#define Int8 1 +#define Int16 2 +#define Int32 3 +#define Uint8 4 +#define Uint16 5 +#define Uint32 6 +#define Float32 7 +#define Float64 8 +#define EndType 9 + +#define PLY_SCALAR 0 +#define PLY_LIST 1 +#define PLY_STRING 2 + + +typedef struct PlyProperty { /* description of a property */ + +char *name; /* property name */ +int external_type; /* file's data type */ +int internal_type; /* program's data type */ +int offset; /* offset bytes of prop in a struct */ + +int is_list; /* 0 = scalar, 1 = list, 2 = char string */ +int count_external; /* file's count type */ +int count_internal; /* program's count type */ +int count_offset; /* offset byte for list count */ + +} PlyProperty; + +typedef struct PlyElement { /* description of an element */ +char *name; /* element name */ +int num; /* number of elements in this object */ +int size; /* size of element (bytes) or -1 if variable */ +int nprops; /* number of properties for this element */ +PlyProperty **props; /* list of properties in the file */ +char *store_prop; /* flags: property wanted by user? */ +int other_offset; /* offset to un-asked-for props, or -1 if none*/ +int other_size; /* size of other_props structure */ +} PlyElement; + +typedef struct PlyOtherProp { /* describes other properties in an element */ +char *name; /* element name */ +int size; /* size of other_props */ +int nprops; /* number of properties in other_props */ +PlyProperty **props; /* list of properties in other_props */ +} PlyOtherProp; + +typedef struct OtherData { /* for storing other_props for an other element */ +void *other_props; +} OtherData; + +typedef struct OtherElem { /* data for one "other" element */ +char *elem_name; /* names of other elements */ +int elem_count; /* count of instances of each element */ +OtherData **other_data; /* actual property data for the elements */ +PlyOtherProp *other_props; /* description of the property data */ +} OtherElem; + +typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */ +int num_elems; /* number of other elements */ +OtherElem *other_list; /* list of data for other elements */ +} PlyOtherElems; + +#define AVERAGE_RULE 1 +#define MAJORITY_RULE 2 +#define MINIMUM_RULE 3 +#define MAXIMUM_RULE 4 +#define SAME_RULE 5 +#define RANDOM_RULE 6 + +typedef struct PlyPropRules { /* rules for combining "other" properties */ +PlyElement *elem; /* element whose rules we are making */ +int *rule_list; /* types of rules (AVERAGE_PLY, MAJORITY_PLY, etc.) */ +int nprops; /* number of properties we're combining so far */ +int max_props; /* maximum number of properties we have room for now */ +void **props; /* list of properties we're combining */ +float *weights; /* list of weights of the properties */ +} PlyPropRules; + +typedef struct PlyRuleList { +char *name; /* name of the rule */ +char *element; /* name of element that rule applies to */ +char *property; /* name of property that rule applies to */ +struct PlyRuleList *next; /* pointer for linked list of rules */ +} PlyRuleList; + +typedef struct PlyFile { /* description of PLY file */ +FILE *fp; /* file pointer */ +int file_type; /* ascii or binary */ +float version; /* version number of file */ +int num_elem_types; /* number of element types of object */ +PlyElement **elems; /* list of elements */ +int num_comments; /* number of comments */ +char **comments; /* list of comments */ +int num_obj_info; /* number of items of object information */ +char **obj_info; /* list of object info items */ +PlyElement *which_elem; /* element we're currently reading or writing */ +PlyOtherElems *other_elems; /* "other" elements from a PLY file */ +PlyPropRules *current_rules; /* current propagation rules */ +PlyRuleList *rule_list; /* rule list from user */ +} PlyFile; + +/* memory allocation */ +/* +extern char *my_alloc(); +*/ +#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__) + + +/* old routines */ + +#if 0 +extern PlyFile *ply_write(FILE *, int, char **, int); +extern PlyFile *ply_read(FILE *, int *, char ***); +extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *); +extern void ply_close(PlyFile *); +extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int); +#endif + +extern void ply_describe_property( PlyFile * , char * , PlyProperty * ); +extern void ply_get_property( PlyFile * , char * , PlyProperty * ); +extern void ply_get_element( PlyFile * , void * ); + + +/*** delcaration of routines ***/ + +PlyOtherElems *get_other_element_ply( PlyFile * ); + +PlyFile *read_ply( FILE * ); +PlyFile *write_ply( FILE * , int, char ** , int ); +extern PlyFile *open_for_writing_ply( char * , int, char ** , int ); +void close_ply( PlyFile * ); +void free_ply( PlyFile * ); + +void get_info_ply( PlyFile * , float * , int * ); +void free_other_elements_ply( PlyOtherElems * ); + +void append_comment_ply( PlyFile * , char * ); +void append_obj_info_ply( PlyFile * , char * ); +void copy_comments_ply( PlyFile * , PlyFile * ); +void copy_obj_info_ply( PlyFile * , PlyFile * ); +char* *get_comments_ply( PlyFile * , int * ); +char* *get_obj_info_ply( PlyFile * , int * ); + +char* *get_element_list_ply( PlyFile * , int * ); +int setup_property_ply( PlyFile * , PlyProperty * ); +void get_element_ply( PlyFile * , void * ); +char *setup_element_read_ply( PlyFile * , int, int * ); +PlyOtherProp *get_other_properties_ply( PlyFile * , int ); + +void element_count_ply( PlyFile * , char * , int ); +void describe_element_ply( PlyFile * , char * , int ); +void describe_property_ply( PlyFile * , PlyProperty * ); +void describe_other_properties_ply( PlyFile * , PlyOtherProp * , int ); +void describe_other_elements_ply( PlyFile * , PlyOtherElems * ); +void get_element_setup_ply( PlyFile * , char * , int, PlyProperty * ); +PlyProperty* *get_element_description_ply( PlyFile * , char * , int * , int * ); +void element_layout_ply( PlyFile * , char * , int, int, PlyProperty * ); + +void header_complete_ply( PlyFile * ); +void put_element_setup_ply( PlyFile * , char * ); +void put_element_ply( PlyFile * , void * ); +void put_other_elements_ply( PlyFile * ); + +PlyPropRules *init_rule_ply( PlyFile * , char * ); +void modify_rule_ply( PlyPropRules * , char * , int ); +void start_props_ply( PlyFile * , PlyPropRules * ); +void weight_props_ply( PlyFile * , float, void * ); +void *get_new_props_ply( PlyFile * ); +void set_prop_rules_ply( PlyFile * , PlyRuleList * ); +PlyRuleList *append_prop_rule( PlyRuleList * , char * , char * ); +int matches_rule_name( char * ); + +int equal_strings( char * , char * ); +char *recreate_command_line( int, char *argv[] ); + + +#ifdef __cplusplus +} +#endif +#endif /* !__PLY_H__ */ + diff --git a/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/cvMeshSurfaceSimplify.C b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/cvMeshSurfaceSimplify.C new file mode 100644 index 0000000000..adc46f7623 --- /dev/null +++ b/applications/utilities/mesh/generation/cvMesh/cvMeshSurfaceSimplify/cvMeshSurfaceSimplify.C @@ -0,0 +1,350 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Application + cvMeshSurfaceSimplify + +Description + Simplifies surfaces by resampling. + + Uses Thomas Lewiner's topology preserving MarchingCubes. + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "searchableSurfaces.H" +#include "conformationSurfaces.H" +#include "triSurfaceMesh.H" + +#include "MarchingCubes.h" + + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Main program: + +int main(int argc, char *argv[]) +{ + argList::addNote + ( + "Re-sample surfaces used in cvMesh operation" + ); + //argList::validArgs.append("inputFile"); + argList::validArgs.append("(nx ny nz)"); + argList::validArgs.append("outputName"); + + #include "setRootCase.H" + #include "createTime.H" + runTime.functionObjects().off(); + + const Vector