Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /intern/dualcon
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'intern/dualcon')
-rw-r--r--intern/dualcon/CMakeLists.txt36
-rw-r--r--intern/dualcon/dualcon.h34
-rw-r--r--intern/dualcon/intern/GeoCommon.h18
-rw-r--r--intern/dualcon/intern/MemoryAllocator.h289
-rw-r--r--intern/dualcon/intern/ModelReader.h45
-rw-r--r--intern/dualcon/intern/Projections.cpp504
-rw-r--r--intern/dualcon/intern/Projections.h109
-rw-r--r--intern/dualcon/intern/Queue.h143
-rw-r--r--intern/dualcon/intern/cubes.h32
-rw-r--r--intern/dualcon/intern/dualcon_c_api.cpp251
-rw-r--r--intern/dualcon/intern/manifold_table.cpp3586
-rw-r--r--intern/dualcon/intern/manifold_table.h6
-rw-r--r--intern/dualcon/intern/marching_cubes_table.cpp3095
-rw-r--r--intern/dualcon/intern/octree.cpp4852
-rw-r--r--intern/dualcon/intern/octree.h2524
15 files changed, 10296 insertions, 5228 deletions
diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt
index a5c1137bc65..9a0be94fc75 100644
--- a/intern/dualcon/CMakeLists.txt
+++ b/intern/dualcon/CMakeLists.txt
@@ -17,32 +17,32 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- .
- intern
+ .
+ intern
)
set(INC_SYS
- ${EIGEN3_INCLUDE_DIRS}
+ ${EIGEN3_INCLUDE_DIRS}
)
set(SRC
- intern/manifold_table.cpp
- intern/marching_cubes_table.cpp
- intern/octree.cpp
- intern/Projections.cpp
+ intern/manifold_table.cpp
+ intern/marching_cubes_table.cpp
+ intern/octree.cpp
+ intern/Projections.cpp
- intern/cubes.h
- intern/GeoCommon.h
- intern/manifold_table.h
- intern/marching_cubes_table.h
- intern/MemoryAllocator.h
- intern/ModelReader.h
- intern/octree.h
- intern/Projections.h
- intern/Queue.h
+ intern/cubes.h
+ intern/GeoCommon.h
+ intern/manifold_table.h
+ intern/marching_cubes_table.h
+ intern/MemoryAllocator.h
+ intern/ModelReader.h
+ intern/octree.h
+ intern/Projections.h
+ intern/Queue.h
- intern/dualcon_c_api.cpp
- dualcon.h
+ intern/dualcon_c_api.cpp
+ dualcon.h
)
set(LIB
diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
index 4e84e60154d..e9bff72a1ce 100644
--- a/intern/dualcon/dualcon.h
+++ b/intern/dualcon/dualcon.h
@@ -29,22 +29,22 @@ typedef float (*DualConCo)[3];
typedef unsigned int (*DualConTri)[3];
-typedef unsigned int (*DualConLoop);
+typedef unsigned int(*DualConLoop);
typedef struct DualConInput {
- DualConLoop mloop;
+ DualConLoop mloop;
- DualConCo co;
- int co_stride;
- int totco;
+ DualConCo co;
+ int co_stride;
+ int totco;
- DualConTri looptri;
- int tri_stride;
- int tottri;
+ DualConTri looptri;
+ int tri_stride;
+ int tottri;
- int loop_stride;
+ int loop_stride;
- float min[3], max[3];
+ float min[3], max[3];
} DualConInput;
/* callback for allocating memory for output */
@@ -55,16 +55,16 @@ typedef void (*DualConAddVert)(void *output, const float co[3]);
typedef void (*DualConAddQuad)(void *output, const int vert_indices[4]);
typedef enum {
- DUALCON_FLOOD_FILL = 1,
+ DUALCON_FLOOD_FILL = 1,
} DualConFlags;
typedef enum {
- /* blocky */
- DUALCON_CENTROID,
- /* smooth */
- DUALCON_MASS_POINT,
- /* keeps sharp edges */
- DUALCON_SHARP_FEATURES,
+ /* blocky */
+ DUALCON_CENTROID,
+ /* smooth */
+ DUALCON_MASS_POINT,
+ /* keeps sharp edges */
+ DUALCON_SHARP_FEATURES,
} DualConMode;
/* Usage:
diff --git a/intern/dualcon/intern/GeoCommon.h b/intern/dualcon/intern/GeoCommon.h
index 3c21b4c36e8..421e2c5e65e 100644
--- a/intern/dualcon/intern/GeoCommon.h
+++ b/intern/dualcon/intern/GeoCommon.h
@@ -28,31 +28,29 @@
* @author Tao Ju
*/
-
// 3d point with integer coordinates
typedef struct {
- int x, y, z;
+ int x, y, z;
} Point3i;
typedef struct {
- Point3i begin;
- Point3i end;
+ Point3i begin;
+ Point3i end;
} BoundingBox;
// triangle that points to three vertices
typedef struct {
- float vt[3][3];
+ float vt[3][3];
} Triangle;
// 3d point with float coordinates
typedef struct {
- float x, y, z;
+ float x, y, z;
} Point3f;
typedef struct {
- Point3f begin;
- Point3f end;
+ Point3f begin;
+ Point3f end;
} BoundingBoxf;
-
-#endif /* __GEOCOMMON_H__ */
+#endif /* __GEOCOMMON_H__ */
diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h
index 035348483fc..933b9dea197 100644
--- a/intern/dualcon/intern/MemoryAllocator.h
+++ b/intern/dualcon/intern/MemoryAllocator.h
@@ -29,29 +29,27 @@
* @author Tao Ju
*/
-
-
/**
* Base class of memory allocators
*/
-class VirtualMemoryAllocator
-{
-public:
-virtual ~VirtualMemoryAllocator() {}
+class VirtualMemoryAllocator {
+ public:
+ virtual ~VirtualMemoryAllocator()
+ {
+ }
-virtual void *allocate( ) = 0;
-virtual void deallocate(void *obj) = 0;
-virtual void destroy( ) = 0;
-virtual void printInfo( ) = 0;
+ virtual void *allocate() = 0;
+ virtual void deallocate(void *obj) = 0;
+ virtual void destroy() = 0;
+ virtual void printInfo() = 0;
-virtual int getAllocated( ) = 0;
-virtual int getAll( ) = 0;
-virtual int getBytes( ) = 0;
+ virtual int getAllocated() = 0;
+ virtual int getAll() = 0;
+ virtual int getBytes() = 0;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:VirtualMemoryAllocator")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:VirtualMemoryAllocator")
#endif
-
};
/**
@@ -59,167 +57,160 @@ virtual int getBytes( ) = 0;
*
* Note: there are 4 bytes overhead for each allocated yet unused object.
*/
-template < int N >
-class MemoryAllocator : public VirtualMemoryAllocator
-{
-private:
+template<int N> class MemoryAllocator : public VirtualMemoryAllocator {
+ private:
+ /// Constants
+ int HEAP_UNIT, HEAP_MASK;
-/// Constants
-int HEAP_UNIT, HEAP_MASK;
+ /// Data array
+ UCHAR **data;
-/// Data array
-UCHAR **data;
+ /// Allocation stack
+ UCHAR ***stack;
-/// Allocation stack
-UCHAR ***stack;
+ /// Number of data blocks
+ int datablocknum;
-/// Number of data blocks
-int datablocknum;
+ /// Number of stack blocks
+ int stackblocknum;
-/// Number of stack blocks
-int stackblocknum;
+ /// Size of stack
+ int stacksize;
-/// Size of stack
-int stacksize;
+ /// Number of available objects on stack
+ int available;
-/// Number of available objects on stack
-int available;
-
-/**
+ /**
* Allocate a memory block
*/
-void allocateDataBlock( )
-{
- // Allocate a data block
- datablocknum += 1;
- data = ( UCHAR ** )realloc(data, sizeof (UCHAR *) * datablocknum);
- data[datablocknum - 1] = ( UCHAR * )malloc(HEAP_UNIT * N);
-
- // Update allocation stack
- for (int i = 0; i < HEAP_UNIT; i++)
- {
- stack[0][i] = (data[datablocknum - 1] + i * N);
- }
- available = HEAP_UNIT;
-}
-
-/**
+ void allocateDataBlock()
+ {
+ // Allocate a data block
+ datablocknum += 1;
+ data = (UCHAR **)realloc(data, sizeof(UCHAR *) * datablocknum);
+ data[datablocknum - 1] = (UCHAR *)malloc(HEAP_UNIT * N);
+
+ // Update allocation stack
+ for (int i = 0; i < HEAP_UNIT; i++) {
+ stack[0][i] = (data[datablocknum - 1] + i * N);
+ }
+ available = HEAP_UNIT;
+ }
+
+ /**
* Allocate a stack block, to store more deallocated objects
*/
-void allocateStackBlock( )
-{
- // Allocate a stack block
- stackblocknum += 1;
- stacksize += HEAP_UNIT;
- stack = ( UCHAR *** )realloc(stack, sizeof (UCHAR * *) * stackblocknum);
- stack[stackblocknum - 1] = ( UCHAR ** )malloc(HEAP_UNIT * sizeof (UCHAR *) );
-}
-
-
-public:
-/**
+ void allocateStackBlock()
+ {
+ // Allocate a stack block
+ stackblocknum += 1;
+ stacksize += HEAP_UNIT;
+ stack = (UCHAR ***)realloc(stack, sizeof(UCHAR **) * stackblocknum);
+ stack[stackblocknum - 1] = (UCHAR **)malloc(HEAP_UNIT * sizeof(UCHAR *));
+ }
+
+ public:
+ /**
* Constructor
*/
-MemoryAllocator( )
-{
- HEAP_UNIT = 1 << HEAP_BASE;
- HEAP_MASK = (1 << HEAP_BASE) - 1;
-
- data = ( UCHAR ** )malloc(sizeof(UCHAR *) );
- data[0] = ( UCHAR * )malloc(HEAP_UNIT * N);
- datablocknum = 1;
-
- stack = ( UCHAR *** )malloc(sizeof (UCHAR * *) );
- stack[0] = ( UCHAR ** )malloc(HEAP_UNIT * sizeof (UCHAR *) );
- stackblocknum = 1;
- stacksize = HEAP_UNIT;
- available = HEAP_UNIT;
-
- for (int i = 0; i < HEAP_UNIT; i++)
- {
- stack[0][i] = (data[0] + i * N);
- }
-}
-
-/**
+ MemoryAllocator()
+ {
+ HEAP_UNIT = 1 << HEAP_BASE;
+ HEAP_MASK = (1 << HEAP_BASE) - 1;
+
+ data = (UCHAR **)malloc(sizeof(UCHAR *));
+ data[0] = (UCHAR *)malloc(HEAP_UNIT * N);
+ datablocknum = 1;
+
+ stack = (UCHAR ***)malloc(sizeof(UCHAR **));
+ stack[0] = (UCHAR **)malloc(HEAP_UNIT * sizeof(UCHAR *));
+ stackblocknum = 1;
+ stacksize = HEAP_UNIT;
+ available = HEAP_UNIT;
+
+ for (int i = 0; i < HEAP_UNIT; i++) {
+ stack[0][i] = (data[0] + i * N);
+ }
+ }
+
+ /**
* Destructor
*/
-void destroy( )
-{
- int i;
- for (i = 0; i < datablocknum; i++)
- {
- free(data[i]);
- }
- for (i = 0; i < stackblocknum; i++)
- {
- free(stack[i]);
- }
- free(data);
- free(stack);
-}
-
-/**
+ void destroy()
+ {
+ int i;
+ for (i = 0; i < datablocknum; i++) {
+ free(data[i]);
+ }
+ for (i = 0; i < stackblocknum; i++) {
+ free(stack[i]);
+ }
+ free(data);
+ free(stack);
+ }
+
+ /**
* Allocation method
*/
-void *allocate( )
-{
- if (available == 0)
- {
- allocateDataBlock( );
- }
-
- // printf("Allocating %d\n", header[ allocated ]) ;
- available--;
- return (void *)stack[available >> HEAP_BASE][available & HEAP_MASK];
-}
-
-/**
+ void *allocate()
+ {
+ if (available == 0) {
+ allocateDataBlock();
+ }
+
+ // printf("Allocating %d\n", header[ allocated ]) ;
+ available--;
+ return (void *)stack[available >> HEAP_BASE][available & HEAP_MASK];
+ }
+
+ /**
* De-allocation method
*/
-void deallocate(void *obj)
-{
- if (available == stacksize)
- {
- allocateStackBlock( );
- }
-
- // printf("De-allocating %d\n", ( obj - data ) / N ) ;
- stack[available >> HEAP_BASE][available & HEAP_MASK] = (UCHAR *)obj;
- available++;
- // printf("%d %d\n", allocated, header[ allocated ]) ;
-}
-
-/**
+ void deallocate(void *obj)
+ {
+ if (available == stacksize) {
+ allocateStackBlock();
+ }
+
+ // printf("De-allocating %d\n", ( obj - data ) / N ) ;
+ stack[available >> HEAP_BASE][available & HEAP_MASK] = (UCHAR *)obj;
+ available++;
+ // printf("%d %d\n", allocated, header[ allocated ]) ;
+ }
+
+ /**
* Print information
*/
-void printInfo( )
-{
- printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n", getBytes(), getAllocated(), getAll(), stacksize);
-}
-
-/**
+ void printInfo()
+ {
+ printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n",
+ getBytes(),
+ getAllocated(),
+ getAll(),
+ stacksize);
+ }
+
+ /**
* Query methods
*/
-int getAllocated( )
-{
- return HEAP_UNIT * datablocknum - available;
-};
+ int getAllocated()
+ {
+ return HEAP_UNIT * datablocknum - available;
+ };
-int getAll( )
-{
- return HEAP_UNIT * datablocknum;
-};
+ int getAll()
+ {
+ return HEAP_UNIT * datablocknum;
+ };
-int getBytes( )
-{
- return N;
-};
+ int getBytes()
+ {
+ return N;
+ };
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:MemoryAllocator")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:MemoryAllocator")
#endif
-
};
-#endif /* __MEMORYALLOCATOR_H__ */
+#endif /* __MEMORYALLOCATOR_H__ */
diff --git a/intern/dualcon/intern/ModelReader.h b/intern/dualcon/intern/ModelReader.h
index ae735b2f1d0..0f056724a62 100644
--- a/intern/dualcon/intern/ModelReader.h
+++ b/intern/dualcon/intern/ModelReader.h
@@ -24,40 +24,37 @@
*
* @author Tao Ju
*/
-class ModelReader
-{
-public:
-/// Constructor
-ModelReader(){
-};
+class ModelReader {
+ public:
+ /// Constructor
+ ModelReader(){};
-/// Get next triangle
-virtual Triangle *getNextTriangle( ) = 0;
-virtual int getNextTriangle(int t[3]) = 0;
+ /// Get next triangle
+ virtual Triangle *getNextTriangle() = 0;
+ virtual int getNextTriangle(int t[3]) = 0;
-/// Get bounding box
-virtual float getBoundingBox(float origin[3]) = 0;
+ /// Get bounding box
+ virtual float getBoundingBox(float origin[3]) = 0;
-/// Get number of triangles
-virtual int getNumTriangles( ) = 0;
+ /// Get number of triangles
+ virtual int getNumTriangles() = 0;
-/// Get storage size
-virtual int getMemory( ) = 0;
+ /// Get storage size
+ virtual int getMemory() = 0;
-/// Reset file reading location
-virtual void reset( ) = 0;
+ /// Reset file reading location
+ virtual void reset() = 0;
-/// For explicit vertex models
-virtual int getNumVertices( ) = 0;
+ /// For explicit vertex models
+ virtual int getNumVertices() = 0;
-virtual void getNextVertex(float v[3]) = 0;
+ virtual void getNextVertex(float v[3]) = 0;
-virtual void printInfo( ) = 0;
+ virtual void printInfo() = 0;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:ModelReader")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:ModelReader")
#endif
-
};
-#endif /* __MODELREADER_H__ */
+#endif /* __MODELREADER_H__ */
diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp
index 9fc9f5beb14..b065ba95330 100644
--- a/intern/dualcon/intern/Projections.cpp
+++ b/intern/dualcon/intern/Projections.cpp
@@ -22,52 +22,45 @@
#include "Projections.h"
const int vertmap[8][3] = {
- {0, 0, 0},
- {0, 0, 1},
- {0, 1, 0},
- {0, 1, 1},
- {1, 0, 0},
- {1, 0, 1},
- {1, 1, 0},
- {1, 1, 1},
+ {0, 0, 0},
+ {0, 0, 1},
+ {0, 1, 0},
+ {0, 1, 1},
+ {1, 0, 0},
+ {1, 0, 1},
+ {1, 1, 0},
+ {1, 1, 1},
};
const int centmap[3][3][3][2] = {
- {{{0, 0}, {0, 1}, {1, 1}},
- {{0, 2}, {0, 3}, {1, 3}},
- {{2, 2}, {2, 3}, {3, 3}}},
+ {{{0, 0}, {0, 1}, {1, 1}}, {{0, 2}, {0, 3}, {1, 3}}, {{2, 2}, {2, 3}, {3, 3}}},
- {{{0, 4}, {0, 5}, {1, 5}},
- {{0, 6}, {0, 7}, {1, 7}},
- {{2, 6}, {2, 7}, {3, 7}}},
+ {{{0, 4}, {0, 5}, {1, 5}}, {{0, 6}, {0, 7}, {1, 7}}, {{2, 6}, {2, 7}, {3, 7}}},
- {{{4, 4}, {4, 5}, {5, 5}},
- {{4, 6}, {4, 7}, {5, 7}},
- {{6, 6}, {6, 7}, {7, 7}}}
-};
+ {{{4, 4}, {4, 5}, {5, 5}}, {{4, 6}, {4, 7}, {5, 7}}, {{6, 6}, {6, 7}, {7, 7}}}};
const int edgemap[12][2] = {
- {0, 4},
- {1, 5},
- {2, 6},
- {3, 7},
- {0, 2},
- {1, 3},
- {4, 6},
- {5, 7},
- {0, 1},
- {2, 3},
- {4, 5},
- {6, 7},
+ {0, 4},
+ {1, 5},
+ {2, 6},
+ {3, 7},
+ {0, 2},
+ {1, 3},
+ {4, 6},
+ {5, 7},
+ {0, 1},
+ {2, 3},
+ {4, 5},
+ {6, 7},
};
const int facemap[6][4] = {
- {0, 1, 2, 3},
- {4, 5, 6, 7},
- {0, 1, 4, 5},
- {2, 3, 6, 7},
- {0, 2, 4, 6},
- {1, 3, 5, 7},
+ {0, 1, 2, 3},
+ {4, 5, 6, 7},
+ {0, 1, 4, 5},
+ {2, 3, 6, 7},
+ {0, 2, 4, 6},
+ {1, 3, 5, 7},
};
/**
@@ -75,16 +68,16 @@ const int facemap[6][4] = {
*/
static void crossProduct(int64_t res[3], const int64_t a[3], const int64_t b[3])
{
- res[0] = a[1] * b[2] - a[2] * b[1];
- res[1] = a[2] * b[0] - a[0] * b[2];
- res[2] = a[0] * b[1] - a[1] * b[0];
+ res[0] = a[1] * b[2] - a[2] * b[1];
+ res[1] = a[2] * b[0] - a[0] * b[2];
+ res[2] = a[0] * b[1] - a[1] * b[0];
}
static void crossProduct(double res[3], const double a[3], const double b[3])
{
- res[0] = a[1] * b[2] - a[2] * b[1];
- res[1] = a[2] * b[0] - a[0] * b[2];
- res[2] = a[0] * b[1] - a[1] * b[0];
+ res[0] = a[1] * b[2] - a[2] * b[1];
+ res[1] = a[2] * b[0] - a[0] * b[2];
+ res[2] = a[0] * b[1] - a[1] * b[0];
}
/**
@@ -92,18 +85,18 @@ static void crossProduct(double res[3], const double a[3], const double b[3])
*/
static int64_t dotProduct(const int64_t a[3], const int64_t b[3])
{
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
static void normalize(double a[3])
{
- double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
- if (mag > 0) {
- mag = sqrt(mag);
- a[0] /= mag;
- a[1] /= mag;
- a[2] /= mag;
- }
+ double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
+ if (mag > 0) {
+ mag = sqrt(mag);
+ a[0] /= mag;
+ a[1] /= mag;
+ a[2] /= mag;
+ }
}
/* Create projection axes for cube+triangle intersection testing.
@@ -118,114 +111,115 @@ static void normalize(double a[3])
*/
static void create_projection_axes(int64_t axes[NUM_AXES][3], const int64_t tri[3][3])
{
- /* Cube face normals */
- axes[0][0] = 1;
- axes[0][1] = 0;
- axes[0][2] = 0;
- axes[1][0] = 0;
- axes[1][1] = 1;
- axes[1][2] = 0;
- axes[2][0] = 0;
- axes[2][1] = 0;
- axes[2][2] = 1;
-
- /* Get triangle edge vectors */
- int64_t tri_edges[3][3];
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++)
- tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j];
- }
-
- /* Triangle normal */
- crossProduct(axes[3], tri_edges[0], tri_edges[1]);
-
- // Face edges and triangle edges
- int ct = 4;
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- crossProduct(axes[ct], axes[j], tri_edges[i]);
- ct++;
- }
- }
+ /* Cube face normals */
+ axes[0][0] = 1;
+ axes[0][1] = 0;
+ axes[0][2] = 0;
+ axes[1][0] = 0;
+ axes[1][1] = 1;
+ axes[1][2] = 0;
+ axes[2][0] = 0;
+ axes[2][1] = 0;
+ axes[2][2] = 1;
+
+ /* Get triangle edge vectors */
+ int64_t tri_edges[3][3];
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++)
+ tri_edges[i][j] = tri[(i + 1) % 3][j] - tri[i][j];
+ }
+
+ /* Triangle normal */
+ crossProduct(axes[3], tri_edges[0], tri_edges[1]);
+
+ // Face edges and triangle edges
+ int ct = 4;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ crossProduct(axes[ct], axes[j], tri_edges[i]);
+ ct++;
+ }
+ }
}
/**
* Construction from a cube (axes aligned) and triangle
*/
-CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int64_t /*error*/, int triind)
+CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3],
+ int64_t tri[3][3],
+ int64_t /*error*/,
+ int triind)
{
- int i;
- inherit = new TriangleProjection;
- inherit->index = triind;
-
- int64_t axes[NUM_AXES][3];
- create_projection_axes(axes, tri);
-
- /* Normalize face normal and store */
- double dedge1[] = {(double)tri[1][0] - (double)tri[0][0],
- (double)tri[1][1] - (double)tri[0][1],
- (double)tri[1][2] - (double)tri[0][2]};
- double dedge2[] = {(double)tri[2][0] - (double)tri[1][0],
- (double)tri[2][1] - (double)tri[1][1],
- (double)tri[2][2] - (double)tri[1][2]};
- crossProduct(inherit->norm, dedge1, dedge2);
- normalize(inherit->norm);
-
- int64_t cubeedge[3][3];
- for (i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- cubeedge[i][j] = 0;
- }
- cubeedge[i][i] = cube[1][i] - cube[0][i];
- }
-
- /* Project the cube on to each axis */
- for (int axis = 0; axis < NUM_AXES; axis++) {
- CubeProjection &cube_proj = cubeProj[axis];
-
- /* Origin */
- cube_proj.origin = dotProduct(axes[axis], cube[0]);
-
- /* 3 direction vectors */
- for (i = 0; i < 3; i++)
- cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]);
-
- /* Offsets of 2 ends of cube projection */
- int64_t max = 0;
- int64_t min = 0;
- for (i = 1; i < 8; i++) {
- int64_t proj = (vertmap[i][0] * cube_proj.edges[0] +
- vertmap[i][1] * cube_proj.edges[1] +
- vertmap[i][2] * cube_proj.edges[2]);
- if (proj > max) {
- max = proj;
- }
- if (proj < min) {
- min = proj;
- }
- }
- cube_proj.min = min;
- cube_proj.max = max;
-
- }
-
- /* Project the triangle on to each axis */
- for (int axis = 0; axis < NUM_AXES; axis++) {
- const int64_t vts[3] = {dotProduct(axes[axis], tri[0]),
- dotProduct(axes[axis], tri[1]),
- dotProduct(axes[axis], tri[2])};
-
- // Triangle
- inherit->tri_proj[axis][0] = vts[0];
- inherit->tri_proj[axis][1] = vts[0];
- for (i = 1; i < 3; i++) {
- if (vts[i] < inherit->tri_proj[axis][0])
- inherit->tri_proj[axis][0] = vts[i];
-
- if (vts[i] > inherit->tri_proj[axis][1])
- inherit->tri_proj[axis][1] = vts[i];
- }
- }
+ int i;
+ inherit = new TriangleProjection;
+ inherit->index = triind;
+
+ int64_t axes[NUM_AXES][3];
+ create_projection_axes(axes, tri);
+
+ /* Normalize face normal and store */
+ double dedge1[] = {(double)tri[1][0] - (double)tri[0][0],
+ (double)tri[1][1] - (double)tri[0][1],
+ (double)tri[1][2] - (double)tri[0][2]};
+ double dedge2[] = {(double)tri[2][0] - (double)tri[1][0],
+ (double)tri[2][1] - (double)tri[1][1],
+ (double)tri[2][2] - (double)tri[1][2]};
+ crossProduct(inherit->norm, dedge1, dedge2);
+ normalize(inherit->norm);
+
+ int64_t cubeedge[3][3];
+ for (i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ cubeedge[i][j] = 0;
+ }
+ cubeedge[i][i] = cube[1][i] - cube[0][i];
+ }
+
+ /* Project the cube on to each axis */
+ for (int axis = 0; axis < NUM_AXES; axis++) {
+ CubeProjection &cube_proj = cubeProj[axis];
+
+ /* Origin */
+ cube_proj.origin = dotProduct(axes[axis], cube[0]);
+
+ /* 3 direction vectors */
+ for (i = 0; i < 3; i++)
+ cube_proj.edges[i] = dotProduct(axes[axis], cubeedge[i]);
+
+ /* Offsets of 2 ends of cube projection */
+ int64_t max = 0;
+ int64_t min = 0;
+ for (i = 1; i < 8; i++) {
+ int64_t proj = (vertmap[i][0] * cube_proj.edges[0] + vertmap[i][1] * cube_proj.edges[1] +
+ vertmap[i][2] * cube_proj.edges[2]);
+ if (proj > max) {
+ max = proj;
+ }
+ if (proj < min) {
+ min = proj;
+ }
+ }
+ cube_proj.min = min;
+ cube_proj.max = max;
+ }
+
+ /* Project the triangle on to each axis */
+ for (int axis = 0; axis < NUM_AXES; axis++) {
+ const int64_t vts[3] = {dotProduct(axes[axis], tri[0]),
+ dotProduct(axes[axis], tri[1]),
+ dotProduct(axes[axis], tri[2])};
+
+ // Triangle
+ inherit->tri_proj[axis][0] = vts[0];
+ inherit->tri_proj[axis][1] = vts[0];
+ for (i = 1; i < 3; i++) {
+ if (vts[i] < inherit->tri_proj[axis][0])
+ inherit->tri_proj[axis][0] = vts[i];
+
+ if (vts[i] > inherit->tri_proj[axis][1])
+ inherit->tri_proj[axis][1] = vts[i];
+ }
+ }
}
/**
@@ -234,67 +228,64 @@ CubeTriangleIsect::CubeTriangleIsect(int64_t cube[2][3], int64_t tri[3][3], int6
*/
CubeTriangleIsect::CubeTriangleIsect(CubeTriangleIsect *parent)
{
- // Copy inheritable projections
- this->inherit = parent->inherit;
+ // Copy inheritable projections
+ this->inherit = parent->inherit;
- // Shrink cube projections
- for (int i = 0; i < NUM_AXES; i++) {
- cubeProj[i].origin = parent->cubeProj[i].origin;
+ // Shrink cube projections
+ for (int i = 0; i < NUM_AXES; i++) {
+ cubeProj[i].origin = parent->cubeProj[i].origin;
- for (int j = 0; j < 3; j++)
- cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1;
+ for (int j = 0; j < 3; j++)
+ cubeProj[i].edges[j] = parent->cubeProj[i].edges[j] >> 1;
- cubeProj[i].min = parent->cubeProj[i].min >> 1;
- cubeProj[i].max = parent->cubeProj[i].max >> 1;
- }
+ cubeProj[i].min = parent->cubeProj[i].min >> 1;
+ cubeProj[i].max = parent->cubeProj[i].max >> 1;
+ }
}
-unsigned char CubeTriangleIsect::getBoxMask( )
+unsigned char CubeTriangleIsect::getBoxMask()
{
- int i, j, k;
- int bmask[3][2] = {{0, 0}, {0, 0}, {0, 0}};
- unsigned char boxmask = 0;
- int64_t child_len = cubeProj[0].edges[0] >> 1;
-
- for (i = 0; i < 3; i++) {
- int64_t mid = cubeProj[i].origin + child_len;
-
- // Check bounding box
- if (mid >= inherit->tri_proj[i][0]) {
- bmask[i][0] = 1;
- }
- if (mid < inherit->tri_proj[i][1]) {
- bmask[i][1] = 1;
- }
-
- }
-
- // Fill in masks
- int ct = 0;
- for (i = 0; i < 2; i++) {
- for (j = 0; j < 2; j++) {
- for (k = 0; k < 2; k++) {
- boxmask |= ( (bmask[0][i] & bmask[1][j] & bmask[2][k]) << ct);
- ct++;
- }
- }
- }
-
- // Return bounding box masks
- return boxmask;
+ int i, j, k;
+ int bmask[3][2] = {{0, 0}, {0, 0}, {0, 0}};
+ unsigned char boxmask = 0;
+ int64_t child_len = cubeProj[0].edges[0] >> 1;
+
+ for (i = 0; i < 3; i++) {
+ int64_t mid = cubeProj[i].origin + child_len;
+
+ // Check bounding box
+ if (mid >= inherit->tri_proj[i][0]) {
+ bmask[i][0] = 1;
+ }
+ if (mid < inherit->tri_proj[i][1]) {
+ bmask[i][1] = 1;
+ }
+ }
+
+ // Fill in masks
+ int ct = 0;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++) {
+ for (k = 0; k < 2; k++) {
+ boxmask |= ((bmask[0][i] & bmask[1][j] & bmask[2][k]) << ct);
+ ct++;
+ }
+ }
+ }
+
+ // Return bounding box masks
+ return boxmask;
}
-
/**
* Shifting a cube to a new origin
*/
void CubeTriangleIsect::shift(int off[3])
{
- for (int i = 0; i < NUM_AXES; i++) {
- cubeProj[i].origin += (off[0] * cubeProj[i].edges[0] +
- off[1] * cubeProj[i].edges[1] +
- off[2] * cubeProj[i].edges[2]);
- }
+ for (int i = 0; i < NUM_AXES; i++) {
+ cubeProj[i].origin += (off[0] * cubeProj[i].edges[0] + off[1] * cubeProj[i].edges[1] +
+ off[2] * cubeProj[i].edges[2]);
+ }
}
/**
@@ -302,75 +293,70 @@ void CubeTriangleIsect::shift(int off[3])
*/
int CubeTriangleIsect::isIntersecting() const
{
- for (int i = 0; i < NUM_AXES; i++) {
- /*
- int64_t proj0 = cubeProj[i][0] +
- vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
- vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
- vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
- int64_t proj1 = cubeProj[i][0] +
- vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
- vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
- vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
- */
-
- int64_t proj0 = cubeProj[i].origin + cubeProj[i].min;
- int64_t proj1 = cubeProj[i].origin + cubeProj[i].max;
-
- if (proj0 > inherit->tri_proj[i][1] ||
- proj1 < inherit->tri_proj[i][0]) {
- return 0;
- }
- }
-
- return 1;
+ for (int i = 0; i < NUM_AXES; i++) {
+ /*
+ int64_t proj0 = cubeProj[i][0] +
+ vertmap[inherit->cubeEnds[i][0]][0] * cubeProj[i][1] +
+ vertmap[inherit->cubeEnds[i][0]][1] * cubeProj[i][2] +
+ vertmap[inherit->cubeEnds[i][0]][2] * cubeProj[i][3] ;
+ int64_t proj1 = cubeProj[i][0] +
+ vertmap[inherit->cubeEnds[i][1]][0] * cubeProj[i][1] +
+ vertmap[inherit->cubeEnds[i][1]][1] * cubeProj[i][2] +
+ vertmap[inherit->cubeEnds[i][1]][2] * cubeProj[i][3] ;
+ */
+
+ int64_t proj0 = cubeProj[i].origin + cubeProj[i].min;
+ int64_t proj1 = cubeProj[i].origin + cubeProj[i].max;
+
+ if (proj0 > inherit->tri_proj[i][1] || proj1 < inherit->tri_proj[i][0]) {
+ return 0;
+ }
+ }
+
+ return 1;
}
int CubeTriangleIsect::isIntersectingPrimary(int edgeInd) const
{
- for (int i = 0; i < NUM_AXES; i++) {
-
- int64_t proj0 = cubeProj[i].origin;
- int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd];
-
- if (proj0 < proj1) {
- if (proj0 > inherit->tri_proj[i][1] ||
- proj1 < inherit->tri_proj[i][0]) {
- return 0;
- }
- }
- else {
- if (proj1 > inherit->tri_proj[i][1] ||
- proj0 < inherit->tri_proj[i][0]) {
- return 0;
- }
- }
-
- }
-
- // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
- return 1;
+ for (int i = 0; i < NUM_AXES; i++) {
+
+ int64_t proj0 = cubeProj[i].origin;
+ int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd];
+
+ if (proj0 < proj1) {
+ if (proj0 > inherit->tri_proj[i][1] || proj1 < inherit->tri_proj[i][0]) {
+ return 0;
+ }
+ }
+ else {
+ if (proj1 > inherit->tri_proj[i][1] || proj0 < inherit->tri_proj[i][0]) {
+ return 0;
+ }
+ }
+ }
+
+ // printf( "Intersecting: %d %d\n", edgemap[edgeInd][0], edgemap[edgeInd][1] ) ;
+ return 1;
}
float CubeTriangleIsect::getIntersectionPrimary(int edgeInd) const
{
- int i = 3;
-
+ int i = 3;
- int64_t proj0 = cubeProj[i].origin;
- int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd];
- int64_t proj2 = inherit->tri_proj[i][1];
- int64_t d = proj1 - proj0;
- double alpha;
+ int64_t proj0 = cubeProj[i].origin;
+ int64_t proj1 = cubeProj[i].origin + cubeProj[i].edges[edgeInd];
+ int64_t proj2 = inherit->tri_proj[i][1];
+ int64_t d = proj1 - proj0;
+ double alpha;
- if (d == 0)
- alpha = 0.5;
- else {
- alpha = (double)((proj2 - proj0)) / (double)d;
+ if (d == 0)
+ alpha = 0.5;
+ else {
+ alpha = (double)((proj2 - proj0)) / (double)d;
- if (alpha < 0 || alpha > 1)
- alpha = 0.5;
- }
+ if (alpha < 0 || alpha > 1)
+ alpha = 0.5;
+ }
- return (float)alpha;
+ return (float)alpha;
}
diff --git a/intern/dualcon/intern/Projections.h b/intern/dualcon/intern/Projections.h
index e77c234b058..fc650158a0b 100644
--- a/intern/dualcon/intern/Projections.h
+++ b/intern/dualcon/intern/Projections.h
@@ -24,11 +24,11 @@
#define GRID_DIMENSION 20
#if defined(_WIN32) && !(_MSC_VER >= 1900)
-#define isnan(n) _isnan(n)
-#define LONG __int64
-#define int64_t __int64
+# define isnan(n) _isnan(n)
+# define LONG __int64
+# define int64_t __int64
#else
-#include <stdint.h>
+# include <stdint.h>
#endif
/**
@@ -59,71 +59,70 @@ extern const int facemap[6][4];
* Structure for the projections inheritable from parent
*/
struct TriangleProjection {
- /// Projections of triangle (min and max)
- int64_t tri_proj[NUM_AXES][2];
+ /// Projections of triangle (min and max)
+ int64_t tri_proj[NUM_AXES][2];
- /// Normal of the triangle
- double norm[3];
+ /// Normal of the triangle
+ double norm[3];
- /// Index of polygon
- int index;
+ /// Index of polygon
+ int index;
};
/* This is a projection for the cube against a single projection
axis, see CubeTriangleIsect.cubeProj */
struct CubeProjection {
- int64_t origin;
- int64_t edges[3];
- int64_t min, max;
+ int64_t origin;
+ int64_t edges[3];
+ int64_t min, max;
};
-
/**
* Class for projections of cube / triangle vertices on the separating axes
*/
-class CubeTriangleIsect
-{
-public:
- /// Inheritable portion
- TriangleProjection *inherit;
-
- /// Projections of the cube vertices
- CubeProjection cubeProj[NUM_AXES];
-
-public:
- CubeTriangleIsect() {}
-
- /**
- * Construction from a cube (axes aligned) and triangle
- */
- CubeTriangleIsect(int64_t cube[2][3], int64_t trig[3][3], int64_t error, int triind);
-
- /**
- * Construction from a parent CubeTriangleIsect object and the index of
- * the children
- */
- CubeTriangleIsect(CubeTriangleIsect *parent);
-
- unsigned char getBoxMask( );
-
- /**
- * Shifting a cube to a new origin
- */
- void shift(int off[3]);
-
- /**
- * Method to test intersection of the triangle and the cube
- */
- int isIntersecting() const;
-
- int isIntersectingPrimary(int edgeInd) const;
-
- float getIntersectionPrimary(int edgeInd) const;
+class CubeTriangleIsect {
+ public:
+ /// Inheritable portion
+ TriangleProjection *inherit;
+
+ /// Projections of the cube vertices
+ CubeProjection cubeProj[NUM_AXES];
+
+ public:
+ CubeTriangleIsect()
+ {
+ }
+
+ /**
+ * Construction from a cube (axes aligned) and triangle
+ */
+ CubeTriangleIsect(int64_t cube[2][3], int64_t trig[3][3], int64_t error, int triind);
+
+ /**
+ * Construction from a parent CubeTriangleIsect object and the index of
+ * the children
+ */
+ CubeTriangleIsect(CubeTriangleIsect *parent);
+
+ unsigned char getBoxMask();
+
+ /**
+ * Shifting a cube to a new origin
+ */
+ void shift(int off[3]);
+
+ /**
+ * Method to test intersection of the triangle and the cube
+ */
+ int isIntersecting() const;
+
+ int isIntersectingPrimary(int edgeInd) const;
+
+ float getIntersectionPrimary(int edgeInd) const;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:CubeTriangleIsect")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:CubeTriangleIsect")
#endif
-
};
-#endif /* __PROJECTIONS_H__ */
+#endif /* __PROJECTIONS_H__ */
diff --git a/intern/dualcon/intern/Queue.h b/intern/dualcon/intern/Queue.h
index 1a257aa9a85..2620ab6cb32 100644
--- a/intern/dualcon/intern/Queue.h
+++ b/intern/dualcon/intern/Queue.h
@@ -18,85 +18,78 @@
#define __QUEUE_H__
struct gridQueueEle {
- int x, y, z;
- UCHAR dir;
- gridQueueEle *next;
+ int x, y, z;
+ UCHAR dir;
+ gridQueueEle *next;
};
-class GridQueue
-{
-gridQueueEle *head;
-gridQueueEle *tail;
-int numEles;
-
-public:
-
-GridQueue( )
-{
- head = NULL;
- tail = NULL;
- numEles = 0;
-}
-
-gridQueueEle *getHead( )
-{
- return head;
-}
-
-int getNumElements( )
-{
- return numEles;
-}
-
-
-void pushQueue(int st[3], int dir)
-{
- gridQueueEle *ele = new gridQueueEle;
- ele->x = st[0];
- ele->y = st[1];
- ele->z = st[2];
- ele->dir = (UCHAR) dir;
- ele->next = NULL;
- if (head == NULL)
- {
- head = ele;
- }
- else {
- tail->next = ele;
- }
- tail = ele;
- numEles++;
-}
-
-int popQueue(int st[3], int& dir)
-{
- if (head == NULL)
- {
- return 0;
- }
-
- st[0] = head->x;
- st[1] = head->y;
- st[2] = head->z;
- dir = (int) (head->dir);
-
- gridQueueEle *temp = head;
- head = head->next;
- delete temp;
-
- if (head == NULL)
- {
- tail = NULL;
- }
- numEles--;
-
- return 1;
-}
+class GridQueue {
+ gridQueueEle *head;
+ gridQueueEle *tail;
+ int numEles;
+
+ public:
+ GridQueue()
+ {
+ head = NULL;
+ tail = NULL;
+ numEles = 0;
+ }
+
+ gridQueueEle *getHead()
+ {
+ return head;
+ }
+
+ int getNumElements()
+ {
+ return numEles;
+ }
+
+ void pushQueue(int st[3], int dir)
+ {
+ gridQueueEle *ele = new gridQueueEle;
+ ele->x = st[0];
+ ele->y = st[1];
+ ele->z = st[2];
+ ele->dir = (UCHAR)dir;
+ ele->next = NULL;
+ if (head == NULL) {
+ head = ele;
+ }
+ else {
+ tail->next = ele;
+ }
+ tail = ele;
+ numEles++;
+ }
+
+ int popQueue(int st[3], int &dir)
+ {
+ if (head == NULL) {
+ return 0;
+ }
+
+ st[0] = head->x;
+ st[1] = head->y;
+ st[2] = head->z;
+ dir = (int)(head->dir);
+
+ gridQueueEle *temp = head;
+ head = head->next;
+ delete temp;
+
+ if (head == NULL) {
+ tail = NULL;
+ }
+ numEles--;
+
+ return 1;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:GridQueue")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:GridQueue")
#endif
-
};
-#endif /* __QUEUE_H__ */
+#endif /* __QUEUE_H__ */
diff --git a/intern/dualcon/intern/cubes.h b/intern/dualcon/intern/cubes.h
index 1a8413524d4..3561ce008c2 100644
--- a/intern/dualcon/intern/cubes.h
+++ b/intern/dualcon/intern/cubes.h
@@ -20,26 +20,24 @@
#include "marching_cubes_table.h"
/* simple wrapper for auto-generated marching cubes data */
-class Cubes
-{
-public:
-/// Get number of triangles
-int getNumTriangle(int mask)
-{
- return marching_cubes_numtri[mask];
-}
+class Cubes {
+ public:
+ /// Get number of triangles
+ int getNumTriangle(int mask)
+ {
+ return marching_cubes_numtri[mask];
+ }
-/// Get a triangle
-void getTriangle(int mask, int index, int indices[3])
-{
- for (int i = 0; i < 3; i++)
- indices[i] = marching_cubes_tris[mask][index][i];
-}
+ /// Get a triangle
+ void getTriangle(int mask, int index, int indices[3])
+ {
+ for (int i = 0; i < 3; i++)
+ indices[i] = marching_cubes_tris[mask][index][i];
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Cubes")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Cubes")
#endif
-
};
-#endif /* __CUBES_H__ */
+#endif /* __CUBES_H__ */
diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp
index 01aa8a608db..459bb711e13 100644
--- a/intern/dualcon/intern/dualcon_c_api.cpp
+++ b/intern/dualcon/intern/dualcon_c_api.cpp
@@ -23,141 +23,139 @@
#include <float.h>
#if defined(_WIN32)
-#define isnan(n) _isnan(n)
+# define isnan(n) _isnan(n)
#endif
static void veccopy(float dst[3], const float src[3])
{
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
}
#define GET_TRI(_mesh, _n) \
- (*(DualConTri)(((char *)(_mesh)->looptri) + ((_n) * (_mesh)->tri_stride)))
+ (*(DualConTri)(((char *)(_mesh)->looptri) + ((_n) * (_mesh)->tri_stride)))
-#define GET_CO(_mesh, _n) \
- (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
+#define GET_CO(_mesh, _n) (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
#define GET_LOOP(_mesh, _n) \
- (*(DualConLoop)(((char *)(_mesh)->mloop) + ((_n) * (_mesh)->loop_stride)))
-
-class DualConInputReader : public ModelReader
-{
-private:
-const DualConInput *input_mesh;
-int tottri, curtri;
-float min[3], max[3], maxsize;
-float scale;
-public:
-DualConInputReader(const DualConInput *mesh, float _scale)
- : input_mesh(mesh), scale(_scale)
-{
- reset();
-}
-
-void reset()
-{
- curtri = 0;
- maxsize = 0;
- tottri = input_mesh->tottri;
-
- veccopy(min, input_mesh->min);
- veccopy(max, input_mesh->max);
-
- /* initialize maxsize */
- for (int i = 0; i < 3; i++) {
- float d = max[i] - min[i];
- if (d > maxsize)
- maxsize = d;
- }
-
- /* redo the bounds */
- for (int i = 0; i < 3; i++)
- {
- min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
- max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
- }
-
- for (int i = 0; i < 3; i++)
- min[i] -= maxsize * (1 / scale - 1) / 2;
- maxsize *= 1 / scale;
-}
-
-Triangle *getNextTriangle()
-{
- if (curtri == input_mesh->tottri)
- return NULL;
-
- Triangle *t = new Triangle();
-
- unsigned int *tr = GET_TRI(input_mesh, curtri);
- veccopy(t->vt[0], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[0])));
- veccopy(t->vt[1], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[1])));
- veccopy(t->vt[2], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[2])));
-
- curtri++;
-
- /* remove triangle if it contains invalid coords */
- for (int i = 0; i < 3; i++) {
- const float *co = t->vt[i];
- if (isnan(co[0]) || isnan(co[1]) || isnan(co[2])) {
- delete t;
- return getNextTriangle();
- }
- }
-
- return t;
-}
-
-int getNextTriangle(int t[3])
-{
- if (curtri == input_mesh->tottri)
- return 0;
-
- unsigned int *tr = GET_TRI(input_mesh, curtri);
- t[0] = tr[0];
- t[1] = tr[1];
- t[2] = tr[2];
-
- curtri++;
-
- return 1;
-}
-
-int getNumTriangles()
-{
- return tottri;
-}
-
-int getNumVertices()
-{
- return input_mesh->totco;
-}
-
-float getBoundingBox(float origin[3])
-{
- veccopy(origin, min);
- return maxsize;
-}
-
-/* output */
-void getNextVertex(float /*v*/[3])
-{
- /* not used */
-}
-
-/* stubs */
-void printInfo() {
-}
-int getMemory() {
- return sizeof(DualConInputReader);
-}
+ (*(DualConLoop)(((char *)(_mesh)->mloop) + ((_n) * (_mesh)->loop_stride)))
+
+class DualConInputReader : public ModelReader {
+ private:
+ const DualConInput *input_mesh;
+ int tottri, curtri;
+ float min[3], max[3], maxsize;
+ float scale;
+
+ public:
+ DualConInputReader(const DualConInput *mesh, float _scale) : input_mesh(mesh), scale(_scale)
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ curtri = 0;
+ maxsize = 0;
+ tottri = input_mesh->tottri;
+
+ veccopy(min, input_mesh->min);
+ veccopy(max, input_mesh->max);
+
+ /* initialize maxsize */
+ for (int i = 0; i < 3; i++) {
+ float d = max[i] - min[i];
+ if (d > maxsize)
+ maxsize = d;
+ }
+
+ /* redo the bounds */
+ for (int i = 0; i < 3; i++) {
+ min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
+ max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
+ }
+
+ for (int i = 0; i < 3; i++)
+ min[i] -= maxsize * (1 / scale - 1) / 2;
+ maxsize *= 1 / scale;
+ }
+
+ Triangle *getNextTriangle()
+ {
+ if (curtri == input_mesh->tottri)
+ return NULL;
+
+ Triangle *t = new Triangle();
+
+ unsigned int *tr = GET_TRI(input_mesh, curtri);
+ veccopy(t->vt[0], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[0])));
+ veccopy(t->vt[1], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[1])));
+ veccopy(t->vt[2], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[2])));
+
+ curtri++;
+
+ /* remove triangle if it contains invalid coords */
+ for (int i = 0; i < 3; i++) {
+ const float *co = t->vt[i];
+ if (isnan(co[0]) || isnan(co[1]) || isnan(co[2])) {
+ delete t;
+ return getNextTriangle();
+ }
+ }
+
+ return t;
+ }
+
+ int getNextTriangle(int t[3])
+ {
+ if (curtri == input_mesh->tottri)
+ return 0;
+
+ unsigned int *tr = GET_TRI(input_mesh, curtri);
+ t[0] = tr[0];
+ t[1] = tr[1];
+ t[2] = tr[2];
+
+ curtri++;
+
+ return 1;
+ }
+
+ int getNumTriangles()
+ {
+ return tottri;
+ }
+
+ int getNumVertices()
+ {
+ return input_mesh->totco;
+ }
+
+ float getBoundingBox(float origin[3])
+ {
+ veccopy(origin, min);
+ return maxsize;
+ }
+
+ /* output */
+ void getNextVertex(float /*v*/[3])
+ {
+ /* not used */
+ }
+
+ /* stubs */
+ void printInfo()
+ {
+ }
+ int getMemory()
+ {
+ return sizeof(DualConInputReader);
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:DualConInputReader")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:DualConInputReader")
#endif
-
};
void *dualcon(const DualConInput *input_mesh,
@@ -173,9 +171,8 @@ void *dualcon(const DualConInput *input_mesh,
float scale,
int depth)
{
- DualConInputReader r(input_mesh, scale);
- Octree o(&r, alloc_output, add_vert, add_quad,
- flags, mode, depth, threshold, hermite_num);
- o.scanConvert();
- return o.getOutputMesh();
+ DualConInputReader r(input_mesh, scale);
+ Octree o(&r, alloc_output, add_vert, add_quad, flags, mode, depth, threshold, hermite_num);
+ o.scanConvert();
+ return o.getOutputMesh();
}
diff --git a/intern/dualcon/intern/manifold_table.cpp b/intern/dualcon/intern/manifold_table.cpp
index baa6b82a91f..d08e1fd27c0 100644
--- a/intern/dualcon/intern/manifold_table.cpp
+++ b/intern/dualcon/intern/manifold_table.cpp
@@ -16,261 +16,3331 @@
#include "manifold_table.h"
-const ManifoldIndices manifold_table[256] = {
- {0, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
- {3, {{1, 1}, {2, 2}, {3, 3}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {3, 3}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {0, 0}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
- {3, {{1, 1}, {2, 2}, {0, 0}, {3, 3}, {1, 1}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}, {2, 2}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {2, {{0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 2}, {2, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {1, 2}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
- {3, {{1, 1}, {0, 0}, {2, 2}, {3, 3}, {1, 1}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}, {0, 0}, {2, 2}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {1, 1}}},
- {2, {{0, 0}, {1, 2}, {1, 1}, {2, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
- {2, {{2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 2}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {3, {{1, 1}, {2, 2}, {3, 3}, {0, 0}, {1, 1}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {3, 3}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {2, 2}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {1, 1}}},
- {2, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {1, 1}}},
- {2, {{2, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 2}, {1, 1}, {2, 2}}},
- {3, {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {0, 0}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {3, 3}, {1, 1}, {2, 2}}},
- {4, {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 1}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {4, 4}, {2, 2}, {3, 3}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {1, 1}}},
- {2, {{0, 0}, {0, 0}, {0, 0}, {2, 1}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 0}, {2, 2}, {1, 1}}},
- {2, {{1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 2}, {2, 2}, {1, 1}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
- {2, {{0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}}},
- {2, {{1, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}},
- {2, {{0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
- {2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
- {2, {{1, 1}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
- {2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}}},
- {3, {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {2, 2}, {1, 1}, {0, 0}, {3, 3}, {1, 1}, {2, 2}, {0, 0}, {3, 3}}},
- {2, {{1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}}},
- {3, {{1, 1}, {2, 2}, {0, 0}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {3, {{1, 1}, {0, 0}, {2, 2}, {3, 3}, {2, 2}, {0, 0}, {1, 1}, {3, 3}, {0, 0}, {2, 2}, {1, 1}, {3, 3}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {2, 2}}},
- {4, {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {4, 4}, {2, 2}, {3, 3}, {1, 1}, {4, 4}}},
- {2, {{0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {2, 2}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 2}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}}},
- {2, {{1, 1}, {2, 2}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}}},
- {2, {{0, 0}, {1, 2}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {2, 2}}},
- {2, {{0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {2, 2}}},
- {2, {{1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 2}, {2, 2}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {2, {{2, 2}, {1, 1}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 2}, {2, 2}, {0, 0}, {1, 1}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}}},
- {2, {{0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 2}, {2, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {1, 1}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{0, 0}, {2, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 2}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}}},
- {2, {{2, 2}, {1, 2}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 1}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {2, 2}}},
- {2, {{2, 2}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {2, {{1, 2}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 2}, {0, 0}, {2, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {1, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 2}, {2, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {0, 0}, {2, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {1, 2}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 2}, {1, 1}, {0, 0}}},
- {2, {{0, 0}, {1, 1}, {2, 2}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {2, 2}, {2, 2}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{2, 2}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {1, 2}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {2, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {1, 2}, {0, 0}, {0, 0}, {2, 1}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {0, 0}}},
- {2, {{0, 0}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 1}, {1, 2}, {0, 0}, {1, 1}, {2, 2}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {0, 0}, {2, 2}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}, {1, 1}, {2, 2}, {2, 2}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {0, 0}, {2, 2}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}, {0, 0}, {2, 1}, {1, 2}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {2, {{1, 1}, {2, 2}, {0, 0}, {0, 0}, {0, 0}, {1, 2}, {2, 1}, {0, 0}, {1, 1}, {0, 0}, {2, 2}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{1, 2}, {0, 0}, {0, 0}, {2, 1}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {2, {{0, 0}, {1, 2}, {2, 1}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}, {2, 2}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {0, 0}, {1, 1}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {1, {{1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {0, 0}, {0, 0}, {0, 0}}},
- {0, {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}}
-};
+const ManifoldIndices manifold_table[256] = {{0,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {3,
+ {{1, 1},
+ {2, 2},
+ {3, 3},
+ {0, 0},
+ {3, 3},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {3, 3},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {3,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {3, 3},
+ {1, 1},
+ {3, 3},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {3, 3},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 2},
+ {2, 2},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {3,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {3, 3},
+ {1, 1},
+ {3, 3},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {3, 3},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {1, 2},
+ {1, 1},
+ {2, 2},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 2}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {3,
+ {{1, 1},
+ {2, 2},
+ {3, 3},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {3, 3},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {3, 3}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 2},
+ {1, 1},
+ {2, 2}}},
+ {3,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {3, 3},
+ {0, 0},
+ {3, 3},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {3, 3},
+ {1, 1},
+ {2, 2}}},
+ {4,
+ {{1, 1},
+ {2, 2},
+ {3, 3},
+ {4, 4},
+ {1, 1},
+ {4, 4},
+ {3, 3},
+ {2, 2},
+ {1, 1},
+ {4, 4},
+ {2, 2},
+ {3, 3}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {3,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {3, 3},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {3, 3},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {3, 3}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1}}},
+ {3,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {3, 3},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {3, 3},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {3, 3}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {3,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {3, 3},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {3, 3},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {3, 3}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {2, 2}}},
+ {4,
+ {{1, 1},
+ {2, 2},
+ {3, 3},
+ {4, 4},
+ {3, 3},
+ {2, 2},
+ {1, 1},
+ {4, 4},
+ {2, 2},
+ {3, 3},
+ {1, 1},
+ {4, 4}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {1, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {1, 2},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {1, 2},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {2, 2}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {2, 2}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 2},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {2,
+ {{2, 2},
+ {1, 1},
+ {1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {1, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 2},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 2}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1}}},
+ {2,
+ {{2, 2},
+ {1, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2}}},
+ {2,
+ {{2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 2},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {1, 2},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 2},
+ {2, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {1, 2},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {2, 2},
+ {1, 2},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {2, 2},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{2, 2},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {1, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {2, 2},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {2, 2},
+ {1, 1},
+ {1, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {1, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {2,
+ {{1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 2},
+ {2, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {2, 2},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{1, 2},
+ {0, 0},
+ {0, 0},
+ {2, 1},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {2,
+ {{0, 0},
+ {1, 2},
+ {2, 1},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {2, 2},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {1,
+ {{1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0}}},
+ {0,
+ {{0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0}}}};
diff --git a/intern/dualcon/intern/manifold_table.h b/intern/dualcon/intern/manifold_table.h
index 2d60041312a..4f15afefa75 100644
--- a/intern/dualcon/intern/manifold_table.h
+++ b/intern/dualcon/intern/manifold_table.h
@@ -18,10 +18,10 @@
#define __MANIFOLD_TABLE_H__
typedef struct {
- int comps;
- int pairs[12][2];
+ int comps;
+ int pairs[12][2];
} ManifoldIndices;
extern const ManifoldIndices manifold_table[256];
-#endif /* __MANIFOLD_TABLE_H__ */
+#endif /* __MANIFOLD_TABLE_H__ */
diff --git a/intern/dualcon/intern/marching_cubes_table.cpp b/intern/dualcon/intern/marching_cubes_table.cpp
index 85b6813f483..5270be25033 100644
--- a/intern/dualcon/intern/marching_cubes_table.cpp
+++ b/intern/dualcon/intern/marching_cubes_table.cpp
@@ -18,531 +18,2574 @@
/* number of triangles in each configuration */
const int marching_cubes_numtri[TOTCONF] = {
- 0, 1, 1, 2, 1, 2, 4, 3, 1, 4, 2, 3, 2, 3, 3, 2, 1, 2, 4, 3, 4, 3, 5, 4,
- 6, 5, 5, 4, 5, 4, 4, 3, 1, 4, 2, 3, 6, 5, 5, 4, 4, 5, 3, 4, 5, 4, 4, 3,
- 2, 3, 3, 2, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 1, 4, 6, 5, 2, 3, 5, 4,
- 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 2, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
- 4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2,
- 4, 3, 3, 2, 3, 2, 2, 1, 1, 6, 4, 5, 4, 5, 5, 4, 2, 5, 3, 4, 3, 4, 4, 3,
- 4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 2, 5, 3, 4, 5, 4, 4, 3,
- 3, 4, 2, 3, 4, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
- 2, 5, 5, 4, 3, 4, 4, 3, 3, 4, 4, 3, 2, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2,
- 4, 3, 3, 2, 3, 2, 2, 1, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
- 2, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0
-};
+ 0, 1, 1, 2, 1, 2, 4, 3, 1, 4, 2, 3, 2, 3, 3, 2, 1, 2, 4, 3, 4, 3, 5, 4, 6, 5, 5, 4, 5,
+ 4, 4, 3, 1, 4, 2, 3, 6, 5, 5, 4, 4, 5, 3, 4, 5, 4, 4, 3, 2, 3, 3, 2, 5, 4, 4, 3, 5, 4,
+ 4, 3, 4, 3, 3, 2, 1, 4, 6, 5, 2, 3, 5, 4, 4, 5, 5, 4, 3, 4, 4, 3, 2, 3, 5, 4, 3, 2, 4,
+ 3, 5, 4, 4, 3, 4, 3, 3, 2, 4, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 3, 4, 4, 3,
+ 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 1, 6, 4, 5, 4, 5, 5, 4, 2, 5, 3, 4, 3, 4, 4, 3, 4,
+ 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 2, 5, 3, 4, 5, 4, 4, 3, 3, 4, 2, 3, 4, 3,
+ 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 2, 5, 5, 4, 3, 4, 4, 3, 3, 4, 4,
+ 3, 2, 3, 3, 2, 3, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 3, 4, 4, 3, 4, 3, 3, 2,
+ 4, 3, 3, 2, 3, 2, 2, 1, 2, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
/* table of triangles in each configuration */
-const int marching_cubes_tris[TOTCONF][MAX_TRIS][3] = {
- {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 8}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 1, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 1}, {4, 1, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 9, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 8, 9}, {0, 9, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 5, 9}, {1, 9, 2}, {1, 2, 4}, {1, 4, 8}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 1, 5}, {0, 5, 9}, {0, 9, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 3, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 8, 5}, {0, 5, 3}, {0, 3, 9}, {0, 9, 4}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 1, 3}, {8, 3, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 1}, {4, 1, 3}, {4, 3, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 5, 3}, {4, 3, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 8, 5}, {0, 5, 3}, {0, 3, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 1}, {4, 1, 3}, {4, 3, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 1, 3}, {0, 3, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 6, 10}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 4, 6}, {8, 6, 10}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 10, 1}, {6, 1, 5}, {6, 5, 8}, {6, 8, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 6, 10}, {4, 10, 1}, {4, 1, 5}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 4}, {10, 4, 9}, {10, 9, 2}, {10, 2, 6}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 10, 8}, {6, 8, 9}, {6, 9, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {6, 10, 1}, {6, 1, 5}, {6, 5, 9}, {6, 9, 2},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 10, 1}, {6, 1, 5}, {6, 5, 9}, {6, 9, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 5}, {0, 6, 9}, {9, 5, 0}, {6, 10, 3}, {5, 3, 10},
- {3, 9, 6}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 5}, {10, 5, 3}, {9, 4, 6}, {6, 10, 3}, {6, 3, 9},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 3}, {9, 8, 0}, {9, 0, 6}, {6, 10, 3}, {6, 3, 9},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 6, 10}, {4, 10, 1}, {4, 1, 3}, {4, 3, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 4, 5}, {3, 2, 6}, {3, 6, 10}, {10, 0, 5}, {10, 5, 3},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 10, 8}, {6, 8, 5}, {6, 5, 3}, {6, 3, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {6, 10, 1}, {6, 1, 3}, {6, 3, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 10, 1}, {6, 1, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 7, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 10}, {4, 10, 7}, {4, 7, 1}, {4, 1, 8}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 10, 7}, {8, 7, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 10}, {4, 10, 7}, {4, 7, 5}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 2, 4}, {10, 4, 1}, {7, 2, 10}, {1, 9, 7}, {1, 4, 9},
- {9, 2, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 8, 9}, {2, 0, 10}, {2, 10, 7}, {7, 1, 9}, {7, 9, 2},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {7, 5, 9}, {7, 9, 2}, {2, 4, 10}, {2, 10, 7},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 7}, {0, 7, 5}, {0, 5, 9}, {0, 9, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 7, 3}, {10, 3, 9}, {10, 9, 5}, {10, 5, 1}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {4, 0, 10}, {4, 10, 7}, {4, 7, 3}, {4, 3, 9},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 10, 7}, {8, 7, 3}, {8, 3, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 10}, {4, 10, 7}, {4, 7, 3}, {4, 3, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 5, 1}, {4, 1, 10}, {7, 3, 2}, {2, 4, 10}, {2, 10, 7},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {0, 10, 7}, {0, 7, 3}, {0, 3, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {4, 10, 7}, {4, 7, 3}, {4, 3, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 7}, {0, 7, 3}, {0, 3, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 6, 7}, {0, 7, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 4, 6}, {8, 6, 7}, {8, 7, 1}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 6}, {8, 6, 7}, {8, 7, 5}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 6, 7}, {4, 7, 5}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 0, 4}, {1, 4, 9}, {2, 6, 7}, {7, 1, 9}, {7, 9, 2},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 7, 1}, {6, 1, 8}, {6, 8, 9}, {6, 9, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {6, 7, 5}, {6, 5, 9}, {6, 9, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 7, 5}, {6, 5, 9}, {6, 9, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 0}, {6, 7, 3}, {6, 3, 9}, {9, 5, 0}, {9, 0, 6},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {4, 6, 7}, {4, 7, 3}, {4, 3, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 6}, {8, 6, 7}, {8, 7, 3}, {8, 3, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 6, 7}, {4, 7, 3}, {4, 3, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 4, 5}, {0, 5, 1}, {6, 7, 3}, {6, 3, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {6, 7, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {6, 7, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 7, 3}, {6, 3, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 2, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 4, 2}, {8, 2, 11}, {8, 11, 6}, {8, 6, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 1, 6}, {6, 1, 11}, {11, 1, 5}, {2, 11, 5}, {2, 5, 8},
- {6, 2, 8}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {5, 4, 2}, {5, 2, 11}, {11, 6, 1}, {11, 1, 5},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 9}, {6, 9, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 8}, {6, 8, 9}, {6, 9, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 8}, {6, 8, 1}, {5, 9, 11}, {11, 6, 1}, {11, 1, 5},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {6, 1, 5}, {6, 5, 9}, {6, 9, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 2, 9}, {6, 9, 5}, {6, 5, 3}, {6, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 2, 9}, {6, 0, 8}, {6, 8, 5}, {6, 5, 3}, {6, 3, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{2, 9, 8}, {1, 3, 11}, {1, 11, 6}, {6, 2, 8}, {6, 8, 1},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 2, 9}, {6, 0, 1}, {6, 1, 3}, {6, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 5}, {6, 5, 3}, {6, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 8}, {6, 8, 5}, {6, 5, 3}, {6, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 8}, {6, 8, 1}, {6, 1, 3}, {6, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {6, 1, 3}, {6, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 2}, {10, 2, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 4}, {10, 4, 2}, {10, 2, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 2}, {11, 10, 1}, {11, 1, 5}, {5, 8, 2}, {5, 2, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 5}, {10, 5, 4}, {10, 4, 2}, {10, 2, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 4}, {10, 4, 9}, {10, 9, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 9}, {10, 9, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {10, 1, 5}, {10, 5, 9}, {10, 9, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 5}, {10, 5, 9}, {10, 9, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 2, 9}, {0, 9, 5}, {3, 11, 10}, {10, 0, 5}, {10, 5, 3},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 2, 9}, {10, 8, 5}, {10, 5, 3}, {10, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 2}, {8, 2, 9}, {10, 1, 3}, {10, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 2, 9}, {10, 1, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 4}, {10, 4, 5}, {10, 5, 3}, {10, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 5}, {10, 5, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {10, 1, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 3}, {10, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 10, 6}, {1, 6, 2}, {1, 2, 11}, {1, 11, 7}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {7, 1, 8}, {7, 8, 4}, {7, 4, 2}, {7, 2, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 10, 6}, {8, 6, 2}, {11, 7, 5}, {5, 8, 2}, {5, 2, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {7, 5, 4}, {7, 4, 2}, {7, 2, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 6, 4}, {9, 11, 7}, {9, 7, 1}, {1, 10, 4}, {1, 4, 9},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {7, 1, 8}, {7, 8, 9}, {7, 9, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {4, 10, 6}, {7, 5, 9}, {7, 9, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {7, 5, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 10}, {5, 10, 6}, {5, 6, 2}, {5, 2, 9}, {7, 3, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {8, 5, 1}, {4, 2, 9}, {7, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 10, 6}, {8, 6, 2}, {8, 2, 9}, {7, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {4, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 6, 4}, {10, 4, 5}, {10, 5, 1}, {7, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {8, 5, 1}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {4, 10, 6}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 1, 0}, {7, 0, 2}, {7, 2, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 1, 8}, {7, 8, 4}, {7, 4, 2}, {7, 2, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 5, 8}, {7, 8, 0}, {7, 0, 2}, {7, 2, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 5, 4}, {7, 4, 2}, {7, 2, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 1, 0}, {7, 0, 4}, {7, 4, 9}, {7, 9, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 1, 8}, {7, 8, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {7, 5, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 5, 9}, {7, 9, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 0}, {5, 0, 2}, {5, 2, 9}, {7, 3, 11}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {4, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 2}, {8, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 2, 9}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 4, 5}, {0, 5, 1}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 3, 11}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 11, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 11, 0}, {7, 0, 8}, {0, 11, 4}, {8, 3, 7}, {11, 3, 4},
- {3, 8, 4}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 1, 7}, {8, 7, 11}, {8, 11, 3}, {8, 3, 5}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 1, 7}, {0, 7, 11}, {3, 5, 4}, {4, 0, 11}, {4, 11, 3},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 9, 3}, {4, 3, 7}, {4, 7, 11}, {4, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 9, 3}, {8, 3, 7}, {11, 2, 0}, {0, 8, 7}, {0, 7, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 9, 3}, {4, 8, 1}, {4, 1, 7}, {4, 7, 11}, {4, 11, 2},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 9, 3}, {0, 1, 7}, {0, 7, 11}, {0, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 7, 11}, {5, 11, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 7}, {11, 9, 4}, {11, 4, 0}, {0, 8, 7}, {0, 7, 11},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 1, 7}, {8, 7, 11}, {8, 11, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 1}, {4, 1, 7}, {4, 7, 11}, {4, 11, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 5, 7}, {4, 7, 11}, {4, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 8, 5}, {0, 5, 7}, {0, 7, 11}, {0, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 1}, {4, 1, 7}, {4, 7, 11}, {4, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 1, 7}, {0, 7, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 6, 11}, {0, 11, 3}, {0, 3, 7}, {0, 7, 10}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 8}, {4, 6, 11}, {4, 11, 3}, {3, 7, 8}, {3, 8, 4},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {5, 8, 0}, {5, 0, 6}, {5, 6, 11}, {5, 11, 3},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {5, 4, 6}, {5, 6, 11}, {5, 11, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 0}, {7, 0, 4}, {7, 4, 9}, {7, 9, 3}, {6, 11, 2},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 8}, {7, 8, 9}, {7, 9, 3}, {6, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {10, 1, 7}, {5, 9, 3}, {6, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {5, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 7, 10}, {5, 10, 0}, {6, 11, 9}, {9, 5, 0}, {9, 0, 6},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 5}, {10, 5, 7}, {4, 6, 11}, {4, 11, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {8, 0, 6}, {8, 6, 11}, {8, 11, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {4, 6, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 4}, {10, 4, 5}, {10, 5, 7}, {6, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 5}, {10, 5, 7}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {10, 1, 7}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 10, 11}, {1, 11, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 11}, {3, 1, 8}, {3, 8, 4}, {4, 0, 11}, {4, 11, 3},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 8, 10}, {5, 10, 11}, {5, 11, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 4, 0}, {5, 0, 10}, {5, 10, 11}, {5, 11, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{9, 3, 1}, {10, 11, 2}, {10, 2, 4}, {4, 9, 1}, {4, 1, 10},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 8, 9}, {1, 9, 3}, {0, 10, 11}, {0, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 9, 3}, {4, 8, 10}, {4, 10, 11}, {4, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 9, 3}, {0, 10, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 10}, {5, 10, 11}, {5, 11, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {4, 0, 10}, {4, 10, 11}, {4, 11, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 10, 11}, {8, 11, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 0, 10}, {4, 10, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 5, 1}, {4, 1, 10}, {4, 10, 11}, {4, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {0, 10, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {4, 10, 11}, {4, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 11}, {0, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 0, 6}, {1, 6, 11}, {1, 11, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 8, 4}, {1, 4, 6}, {1, 6, 11}, {1, 11, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 8, 0}, {5, 0, 6}, {5, 6, 11}, {5, 11, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 4, 6}, {5, 6, 11}, {5, 11, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 0, 4}, {1, 4, 9}, {1, 9, 3}, {6, 11, 2}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 8, 9}, {1, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {5, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 9, 3}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 0}, {5, 0, 6}, {5, 6, 11}, {5, 11, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {4, 6, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 6}, {8, 6, 11}, {8, 11, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 6, 11}, {4, 11, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 4, 5}, {0, 5, 1}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 11, 2}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 6, 2}, {7, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 6, 0}, {7, 0, 8}, {4, 2, 3}, {3, 7, 8}, {3, 8, 4},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 7, 6}, {2, 3, 5}, {2, 5, 8}, {8, 1, 6}, {8, 6, 2},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {6, 1, 7}, {5, 4, 2}, {5, 2, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 6, 4}, {7, 4, 9}, {7, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 6, 0}, {7, 0, 8}, {7, 8, 9}, {7, 9, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 8}, {6, 8, 1}, {6, 1, 7}, {5, 9, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {6, 1, 7}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 7, 6}, {5, 6, 2}, {5, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 8}, {6, 8, 5}, {6, 5, 7}, {4, 2, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 1, 7}, {8, 7, 6}, {8, 6, 2}, {8, 2, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {6, 1, 7}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 5}, {6, 5, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 8}, {6, 8, 5}, {6, 5, 7}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 4, 8}, {6, 8, 1}, {6, 1, 7}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{6, 0, 1}, {6, 1, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 0}, {7, 0, 2}, {7, 2, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 8}, {7, 8, 4}, {7, 4, 2}, {7, 2, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {5, 8, 0}, {5, 0, 2}, {5, 2, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {5, 4, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 0}, {7, 0, 4}, {7, 4, 9}, {7, 9, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{7, 10, 8}, {7, 8, 9}, {7, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {10, 1, 7}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 7, 10}, {5, 10, 0}, {5, 0, 2}, {5, 2, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 5}, {10, 5, 7}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {8, 0, 2}, {8, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 0, 4}, {10, 4, 5}, {10, 5, 7}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 8, 5}, {10, 5, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {10, 1, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 1, 7}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 10, 6}, {1, 6, 2}, {1, 2, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {1, 8, 4}, {1, 4, 2}, {1, 2, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 8, 10}, {5, 10, 6}, {5, 6, 2}, {5, 2, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {5, 4, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 10, 6}, {1, 6, 4}, {1, 4, 9}, {1, 9, 3}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {1, 8, 9}, {1, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {4, 10, 6}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 10}, {5, 10, 6}, {5, 6, 2}, {5, 2, 9}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {8, 5, 1}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 10, 6}, {8, 6, 2}, {8, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{10, 6, 4}, {10, 4, 5}, {10, 5, 1}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {8, 5, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 10}, {4, 10, 6}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 10, 6}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 0, 2}, {1, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 8, 4}, {1, 4, 2}, {1, 2, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 8, 0}, {5, 0, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 4, 2}, {5, 2, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 0, 4}, {1, 4, 9}, {1, 9, 3}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{1, 8, 9}, {1, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 9, 3}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{5, 1, 0}, {5, 0, 2}, {5, 2, 9}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 0, 2}, {8, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 2, 9}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 4, 5}, {0, 5, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{8, 5, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{4, 8, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}},
- {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}
-};
+const int marching_cubes_tris[TOTCONF][MAX_TRIS][3] = {{{0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 8},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 1, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 1},
+ {4, 1, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 8, 9},
+ {0, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 5, 9},
+ {1, 9, 2},
+ {1, 2, 4},
+ {1, 4, 8},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 1, 5},
+ {0, 5, 9},
+ {0, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 8, 5},
+ {0, 5, 3},
+ {0, 3, 9},
+ {0, 9, 4},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 1, 3},
+ {8, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 1},
+ {4, 1, 3},
+ {4, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 5, 3},
+ {4, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 8, 5},
+ {0, 5, 3},
+ {0, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 1},
+ {4, 1, 3},
+ {4, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 1, 3},
+ {0, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 6, 10},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 4, 6},
+ {8, 6, 10},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 10, 1},
+ {6, 1, 5},
+ {6, 5, 8},
+ {6, 8, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 6, 10},
+ {4, 10, 1},
+ {4, 1, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 4},
+ {10, 4, 9},
+ {10, 9, 2},
+ {10, 2, 6},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 10, 8},
+ {6, 8, 9},
+ {6, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {6, 10, 1},
+ {6, 1, 5},
+ {6, 5, 9},
+ {6, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 10, 1},
+ {6, 1, 5},
+ {6, 5, 9},
+ {6, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 5},
+ {0, 6, 9},
+ {9, 5, 0},
+ {6, 10, 3},
+ {5, 3, 10},
+ {3, 9, 6},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 5},
+ {10, 5, 3},
+ {9, 4, 6},
+ {6, 10, 3},
+ {6, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 3},
+ {9, 8, 0},
+ {9, 0, 6},
+ {6, 10, 3},
+ {6, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 6, 10},
+ {4, 10, 1},
+ {4, 1, 3},
+ {4, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 4, 5},
+ {3, 2, 6},
+ {3, 6, 10},
+ {10, 0, 5},
+ {10, 5, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 10, 8},
+ {6, 8, 5},
+ {6, 5, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {6, 10, 1},
+ {6, 1, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 10, 1},
+ {6, 1, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 7, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 10},
+ {4, 10, 7},
+ {4, 7, 1},
+ {4, 1, 8},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 10, 7},
+ {8, 7, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 10},
+ {4, 10, 7},
+ {4, 7, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 2, 4},
+ {10, 4, 1},
+ {7, 2, 10},
+ {1, 9, 7},
+ {1, 4, 9},
+ {9, 2, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 8, 9},
+ {2, 0, 10},
+ {2, 10, 7},
+ {7, 1, 9},
+ {7, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {7, 5, 9},
+ {7, 9, 2},
+ {2, 4, 10},
+ {2, 10, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 7},
+ {0, 7, 5},
+ {0, 5, 9},
+ {0, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 7, 3},
+ {10, 3, 9},
+ {10, 9, 5},
+ {10, 5, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {4, 0, 10},
+ {4, 10, 7},
+ {4, 7, 3},
+ {4, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 10, 7},
+ {8, 7, 3},
+ {8, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 10},
+ {4, 10, 7},
+ {4, 7, 3},
+ {4, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 5, 1},
+ {4, 1, 10},
+ {7, 3, 2},
+ {2, 4, 10},
+ {2, 10, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {0, 10, 7},
+ {0, 7, 3},
+ {0, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {4, 10, 7},
+ {4, 7, 3},
+ {4, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 7},
+ {0, 7, 3},
+ {0, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 6, 7},
+ {0, 7, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 4, 6},
+ {8, 6, 7},
+ {8, 7, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 6},
+ {8, 6, 7},
+ {8, 7, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 6, 7},
+ {4, 7, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 0, 4},
+ {1, 4, 9},
+ {2, 6, 7},
+ {7, 1, 9},
+ {7, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 7, 1},
+ {6, 1, 8},
+ {6, 8, 9},
+ {6, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {6, 7, 5},
+ {6, 5, 9},
+ {6, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 7, 5},
+ {6, 5, 9},
+ {6, 9, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 0},
+ {6, 7, 3},
+ {6, 3, 9},
+ {9, 5, 0},
+ {9, 0, 6},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {4, 6, 7},
+ {4, 7, 3},
+ {4, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 6},
+ {8, 6, 7},
+ {8, 7, 3},
+ {8, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 6, 7},
+ {4, 7, 3},
+ {4, 3, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 4, 5},
+ {0, 5, 1},
+ {6, 7, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {6, 7, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {6, 7, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 7, 3},
+ {6, 3, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 4, 2},
+ {8, 2, 11},
+ {8, 11, 6},
+ {8, 6, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 1, 6},
+ {6, 1, 11},
+ {11, 1, 5},
+ {2, 11, 5},
+ {2, 5, 8},
+ {6, 2, 8},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {5, 4, 2},
+ {5, 2, 11},
+ {11, 6, 1},
+ {11, 1, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 9},
+ {6, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 8},
+ {6, 8, 9},
+ {6, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 8},
+ {6, 8, 1},
+ {5, 9, 11},
+ {11, 6, 1},
+ {11, 1, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {6, 1, 5},
+ {6, 5, 9},
+ {6, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 2, 9},
+ {6, 9, 5},
+ {6, 5, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 2, 9},
+ {6, 0, 8},
+ {6, 8, 5},
+ {6, 5, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{2, 9, 8},
+ {1, 3, 11},
+ {1, 11, 6},
+ {6, 2, 8},
+ {6, 8, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 2, 9},
+ {6, 0, 1},
+ {6, 1, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 5},
+ {6, 5, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 8},
+ {6, 8, 5},
+ {6, 5, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 8},
+ {6, 8, 1},
+ {6, 1, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {6, 1, 3},
+ {6, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 2},
+ {10, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 4},
+ {10, 4, 2},
+ {10, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 2},
+ {11, 10, 1},
+ {11, 1, 5},
+ {5, 8, 2},
+ {5, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 5},
+ {10, 5, 4},
+ {10, 4, 2},
+ {10, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 4},
+ {10, 4, 9},
+ {10, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 9},
+ {10, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {10, 1, 5},
+ {10, 5, 9},
+ {10, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 5},
+ {10, 5, 9},
+ {10, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 2, 9},
+ {0, 9, 5},
+ {3, 11, 10},
+ {10, 0, 5},
+ {10, 5, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 2, 9},
+ {10, 8, 5},
+ {10, 5, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 2},
+ {8, 2, 9},
+ {10, 1, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 2, 9},
+ {10, 1, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 4},
+ {10, 4, 5},
+ {10, 5, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 5},
+ {10, 5, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {10, 1, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 3},
+ {10, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 10, 6},
+ {1, 6, 2},
+ {1, 2, 11},
+ {1, 11, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {7, 1, 8},
+ {7, 8, 4},
+ {7, 4, 2},
+ {7, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 10, 6},
+ {8, 6, 2},
+ {11, 7, 5},
+ {5, 8, 2},
+ {5, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {7, 5, 4},
+ {7, 4, 2},
+ {7, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 6, 4},
+ {9, 11, 7},
+ {9, 7, 1},
+ {1, 10, 4},
+ {1, 4, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {7, 1, 8},
+ {7, 8, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {4, 10, 6},
+ {7, 5, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {7, 5, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 10},
+ {5, 10, 6},
+ {5, 6, 2},
+ {5, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {8, 5, 1},
+ {4, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 10, 6},
+ {8, 6, 2},
+ {8, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {4, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 6, 4},
+ {10, 4, 5},
+ {10, 5, 1},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {8, 5, 1},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {4, 10, 6},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 1, 0},
+ {7, 0, 2},
+ {7, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 1, 8},
+ {7, 8, 4},
+ {7, 4, 2},
+ {7, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 5, 8},
+ {7, 8, 0},
+ {7, 0, 2},
+ {7, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 5, 4},
+ {7, 4, 2},
+ {7, 2, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 1, 0},
+ {7, 0, 4},
+ {7, 4, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 1, 8},
+ {7, 8, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {7, 5, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 5, 9},
+ {7, 9, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 0},
+ {5, 0, 2},
+ {5, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {4, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 2},
+ {8, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 2, 9},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 4, 5},
+ {0, 5, 1},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 3, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 11, 0},
+ {7, 0, 8},
+ {0, 11, 4},
+ {8, 3, 7},
+ {11, 3, 4},
+ {3, 8, 4},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 1, 7},
+ {8, 7, 11},
+ {8, 11, 3},
+ {8, 3, 5},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 1, 7},
+ {0, 7, 11},
+ {3, 5, 4},
+ {4, 0, 11},
+ {4, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 9, 3},
+ {4, 3, 7},
+ {4, 7, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 9, 3},
+ {8, 3, 7},
+ {11, 2, 0},
+ {0, 8, 7},
+ {0, 7, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 9, 3},
+ {4, 8, 1},
+ {4, 1, 7},
+ {4, 7, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 9, 3},
+ {0, 1, 7},
+ {0, 7, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 7, 11},
+ {5, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 7},
+ {11, 9, 4},
+ {11, 4, 0},
+ {0, 8, 7},
+ {0, 7, 11},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 1, 7},
+ {8, 7, 11},
+ {8, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 1},
+ {4, 1, 7},
+ {4, 7, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 5, 7},
+ {4, 7, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 8, 5},
+ {0, 5, 7},
+ {0, 7, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 1},
+ {4, 1, 7},
+ {4, 7, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 1, 7},
+ {0, 7, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 6, 11},
+ {0, 11, 3},
+ {0, 3, 7},
+ {0, 7, 10},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 8},
+ {4, 6, 11},
+ {4, 11, 3},
+ {3, 7, 8},
+ {3, 8, 4},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {5, 8, 0},
+ {5, 0, 6},
+ {5, 6, 11},
+ {5, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {5, 4, 6},
+ {5, 6, 11},
+ {5, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 0},
+ {7, 0, 4},
+ {7, 4, 9},
+ {7, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 8},
+ {7, 8, 9},
+ {7, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {10, 1, 7},
+ {5, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {5, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 7, 10},
+ {5, 10, 0},
+ {6, 11, 9},
+ {9, 5, 0},
+ {9, 0, 6},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 5},
+ {10, 5, 7},
+ {4, 6, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {8, 0, 6},
+ {8, 6, 11},
+ {8, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {4, 6, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 4},
+ {10, 4, 5},
+ {10, 5, 7},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 5},
+ {10, 5, 7},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {10, 1, 7},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 10, 11},
+ {1, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 11},
+ {3, 1, 8},
+ {3, 8, 4},
+ {4, 0, 11},
+ {4, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 8, 10},
+ {5, 10, 11},
+ {5, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 4, 0},
+ {5, 0, 10},
+ {5, 10, 11},
+ {5, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{9, 3, 1},
+ {10, 11, 2},
+ {10, 2, 4},
+ {4, 9, 1},
+ {4, 1, 10},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 8, 9},
+ {1, 9, 3},
+ {0, 10, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 9, 3},
+ {4, 8, 10},
+ {4, 10, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 9, 3},
+ {0, 10, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 10},
+ {5, 10, 11},
+ {5, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {4, 0, 10},
+ {4, 10, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 10, 11},
+ {8, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 0, 10},
+ {4, 10, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 5, 1},
+ {4, 1, 10},
+ {4, 10, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {0, 10, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {4, 10, 11},
+ {4, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 11},
+ {0, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 0, 6},
+ {1, 6, 11},
+ {1, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 8, 4},
+ {1, 4, 6},
+ {1, 6, 11},
+ {1, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 8, 0},
+ {5, 0, 6},
+ {5, 6, 11},
+ {5, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 4, 6},
+ {5, 6, 11},
+ {5, 11, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 0, 4},
+ {1, 4, 9},
+ {1, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 8, 9},
+ {1, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {5, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 9, 3},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 0},
+ {5, 0, 6},
+ {5, 6, 11},
+ {5, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {4, 6, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 6},
+ {8, 6, 11},
+ {8, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 6, 11},
+ {4, 11, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 4, 5},
+ {0, 5, 1},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 11, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 6, 2},
+ {7, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 6, 0},
+ {7, 0, 8},
+ {4, 2, 3},
+ {3, 7, 8},
+ {3, 8, 4},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 7, 6},
+ {2, 3, 5},
+ {2, 5, 8},
+ {8, 1, 6},
+ {8, 6, 2},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {6, 1, 7},
+ {5, 4, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 6, 4},
+ {7, 4, 9},
+ {7, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 6, 0},
+ {7, 0, 8},
+ {7, 8, 9},
+ {7, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 8},
+ {6, 8, 1},
+ {6, 1, 7},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {6, 1, 7},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 7, 6},
+ {5, 6, 2},
+ {5, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 8},
+ {6, 8, 5},
+ {6, 5, 7},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 1, 7},
+ {8, 7, 6},
+ {8, 6, 2},
+ {8, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {6, 1, 7},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 5},
+ {6, 5, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 8},
+ {6, 8, 5},
+ {6, 5, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 4, 8},
+ {6, 8, 1},
+ {6, 1, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{6, 0, 1},
+ {6, 1, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 0},
+ {7, 0, 2},
+ {7, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 8},
+ {7, 8, 4},
+ {7, 4, 2},
+ {7, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {5, 8, 0},
+ {5, 0, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {5, 4, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 0},
+ {7, 0, 4},
+ {7, 4, 9},
+ {7, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{7, 10, 8},
+ {7, 8, 9},
+ {7, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {10, 1, 7},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 7, 10},
+ {5, 10, 0},
+ {5, 0, 2},
+ {5, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 5},
+ {10, 5, 7},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {8, 0, 2},
+ {8, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 0, 4},
+ {10, 4, 5},
+ {10, 5, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 8, 5},
+ {10, 5, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {10, 1, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 1, 7},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 10, 6},
+ {1, 6, 2},
+ {1, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {1, 8, 4},
+ {1, 4, 2},
+ {1, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 8, 10},
+ {5, 10, 6},
+ {5, 6, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {5, 4, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 10, 6},
+ {1, 6, 4},
+ {1, 4, 9},
+ {1, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {1, 8, 9},
+ {1, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {4, 10, 6},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 10},
+ {5, 10, 6},
+ {5, 6, 2},
+ {5, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {8, 5, 1},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 10, 6},
+ {8, 6, 2},
+ {8, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{10, 6, 4},
+ {10, 4, 5},
+ {10, 5, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {8, 5, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 10},
+ {4, 10, 6},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 10, 6},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 0, 2},
+ {1, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 8, 4},
+ {1, 4, 2},
+ {1, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 8, 0},
+ {5, 0, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 4, 2},
+ {5, 2, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 0, 4},
+ {1, 4, 9},
+ {1, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{1, 8, 9},
+ {1, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 9, 3},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{5, 1, 0},
+ {5, 0, 2},
+ {5, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 0, 2},
+ {8, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 2, 9},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 4, 5},
+ {0, 5, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{8, 5, 1},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{4, 8, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}},
+ {{0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}}};
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
index 878cd2971de..46783176fc1 100644
--- a/intern/dualcon/intern/octree.cpp
+++ b/intern/dualcon/intern/octree.cpp
@@ -34,2063 +34,2085 @@
#if DC_DEBUG
/* enable debug printfs */
-#define dc_printf printf
+# define dc_printf printf
#else
/* disable debug printfs */
-#define dc_printf(...) do {} while (0)
+# define dc_printf(...) \
+ do { \
+ } while (0)
#endif
Octree::Octree(ModelReader *mr,
DualConAllocOutput alloc_output_func,
DualConAddVert add_vert_func,
DualConAddQuad add_quad_func,
- DualConFlags flags, DualConMode dualcon_mode, int depth,
- float threshold, float sharpness)
- : use_flood_fill(flags & DUALCON_FLOOD_FILL),
- /* note on `use_manifold':
-
- After playing around with this option, the only case I could
- find where this option gives different results is on
- relatively thin corners. Sometimes along these corners two
- vertices from separate sides will be placed in the same
- position, so hole gets filled with a 5-sided face, where two
- of those vertices are in the same 3D location. If
- `use_manifold' is disabled, then the modifier doesn't
- generate two separate vertices so the results end up as all
- quads.
-
- Since the results are just as good with all quads, there
- doesn't seem any reason to allow this to be toggled in
- Blender. -nicholasbishop
- */
- use_manifold(false),
- hermite_num(sharpness),
- mode(dualcon_mode),
- alloc_output(alloc_output_func),
- add_vert(add_vert_func),
- add_quad(add_quad_func)
+ DualConFlags flags,
+ DualConMode dualcon_mode,
+ int depth,
+ float threshold,
+ float sharpness)
+ : use_flood_fill(flags & DUALCON_FLOOD_FILL),
+ /* note on `use_manifold':
+
+ After playing around with this option, the only case I could
+ find where this option gives different results is on
+ relatively thin corners. Sometimes along these corners two
+ vertices from separate sides will be placed in the same
+ position, so hole gets filled with a 5-sided face, where two
+ of those vertices are in the same 3D location. If
+ `use_manifold' is disabled, then the modifier doesn't
+ generate two separate vertices so the results end up as all
+ quads.
+
+ Since the results are just as good with all quads, there
+ doesn't seem any reason to allow this to be toggled in
+ Blender. -nicholasbishop
+ */
+ use_manifold(false),
+ hermite_num(sharpness),
+ mode(dualcon_mode),
+ alloc_output(alloc_output_func),
+ add_vert(add_vert_func),
+ add_quad(add_quad_func)
{
- thresh = threshold;
- reader = mr;
- dimen = 1 << GRID_DIMENSION;
- range = reader->getBoundingBox(origin);
- nodeCount = nodeSpace = 0;
- maxDepth = depth;
- mindimen = (dimen >> maxDepth);
- minshift = (GRID_DIMENSION - maxDepth);
- buildTable();
-
- maxTrianglePerCell = 0;
-
- // Initialize memory
+ thresh = threshold;
+ reader = mr;
+ dimen = 1 << GRID_DIMENSION;
+ range = reader->getBoundingBox(origin);
+ nodeCount = nodeSpace = 0;
+ maxDepth = depth;
+ mindimen = (dimen >> maxDepth);
+ minshift = (GRID_DIMENSION - maxDepth);
+ buildTable();
+
+ maxTrianglePerCell = 0;
+
+ // Initialize memory
#ifdef IN_VERBOSE_MODE
- dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2]);
- dc_printf("Initialize memory...\n");
+ dc_printf("Range: %f origin: %f, %f,%f \n", range, origin[0], origin[1], origin[2]);
+ dc_printf("Initialize memory...\n");
#endif
- initMemory();
- root = (Node *)createInternal(0);
+ initMemory();
+ root = (Node *)createInternal(0);
- // Read MC table
+ // Read MC table
#ifdef IN_VERBOSE_MODE
- dc_printf("Reading contour table...\n");
+ dc_printf("Reading contour table...\n");
#endif
- cubes = new Cubes();
-
+ cubes = new Cubes();
}
Octree::~Octree()
{
- delete cubes;
- freeMemory();
+ delete cubes;
+ freeMemory();
}
void Octree::scanConvert()
{
- // Scan triangles
+ // Scan triangles
#if DC_DEBUG
- clock_t start, finish;
- start = clock();
+ clock_t start, finish;
+ start = clock();
#endif
- addAllTriangles();
- resetMinimalEdges();
- preparePrimalEdgesMask(&root->internal);
+ addAllTriangles();
+ resetMinimalEdges();
+ preparePrimalEdgesMask(&root->internal);
#if DC_DEBUG
- finish = clock();
- dc_printf("Time taken: %f seconds \n",
- (double)(finish - start) / CLOCKS_PER_SEC);
+ finish = clock();
+ dc_printf("Time taken: %f seconds \n",
+ (double)(finish - start) / CLOCKS_PER_SEC);
#endif
- // Generate signs
- // Find holes
+ // Generate signs
+ // Find holes
#if DC_DEBUG
- dc_printf("Patching...\n");
- start = clock();
+ dc_printf("Patching...\n");
+ start = clock();
#endif
- trace();
+ trace();
#if DC_DEBUG
- finish = clock();
- dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
-#ifdef IN_VERBOSE_MODE
- dc_printf("Holes: %d Average Length: %f Max Length: %d \n", numRings, (float)totRingLengths / (float) numRings, maxRingLength);
-#endif
+ finish = clock();
+ dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
+# ifdef IN_VERBOSE_MODE
+ dc_printf("Holes: %d Average Length: %f Max Length: %d \n",
+ numRings,
+ (float)totRingLengths / (float)numRings,
+ maxRingLength);
+# endif
#endif
- // Check again
- int tnumRings = numRings;
- trace();
+ // Check again
+ int tnumRings = numRings;
+ trace();
#ifdef IN_VERBOSE_MODE
- dc_printf("Holes after patching: %d \n", numRings);
+ dc_printf("Holes after patching: %d \n", numRings);
#endif
- numRings = tnumRings;
+ numRings = tnumRings;
#if DC_DEBUG
- dc_printf("Building signs...\n");
- start = clock();
+ dc_printf("Building signs...\n");
+ start = clock();
#endif
- buildSigns();
+ buildSigns();
#if DC_DEBUG
- finish = clock();
- dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
+ finish = clock();
+ dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
#endif
- if (use_flood_fill) {
- /*
- start = clock();
- floodFill();
- // Check again
- tnumRings = numRings;
- trace();
- dc_printf("Holes after filling: %d \n", numRings);
- numRings = tnumRings;
- buildSigns();
- finish = clock();
- dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
- */
+ if (use_flood_fill) {
+ /*
+ start = clock();
+ floodFill();
+ // Check again
+ tnumRings = numRings;
+ trace();
+ dc_printf("Holes after filling: %d \n", numRings);
+ numRings = tnumRings;
+ buildSigns();
+ finish = clock();
+ dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
+ */
#if DC_DEBUG
- start = clock();
- dc_printf("Removing components...\n");
+ start = clock();
+ dc_printf("Removing components...\n");
#endif
- floodFill();
- buildSigns();
- // dc_printf("Checking...\n");
- // floodFill();
+ floodFill();
+ buildSigns();
+ // dc_printf("Checking...\n");
+ // floodFill();
#if DC_DEBUG
- finish = clock();
- dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
+ finish = clock();
+ dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
#endif
- }
+ }
- // Output
+ // Output
#if DC_DEBUG
- start = clock();
+ start = clock();
#endif
- writeOut();
+ writeOut();
#if DC_DEBUG
- finish = clock();
+ finish = clock();
#endif
- // dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
+ // dc_printf("Time taken: %f seconds \n", (double)(finish - start) / CLOCKS_PER_SEC);
- // Print info
+ // Print info
#ifdef IN_VERBOSE_MODE
- printMemUsage();
+ printMemUsage();
#endif
}
void Octree::initMemory()
{
- leafalloc[0] = new MemoryAllocator<sizeof(LeafNode)>();
- leafalloc[1] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) *EDGE_FLOATS>();
- leafalloc[2] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) *EDGE_FLOATS * 2>();
- leafalloc[3] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) *EDGE_FLOATS * 3>();
-
- alloc[0] = new MemoryAllocator<sizeof(InternalNode)>();
- alloc[1] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *)>();
- alloc[2] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 2>();
- alloc[3] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 3>();
- alloc[4] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 4>();
- alloc[5] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 5>();
- alloc[6] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 6>();
- alloc[7] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 7>();
- alloc[8] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 8>();
+ leafalloc[0] = new MemoryAllocator<sizeof(LeafNode)>();
+ leafalloc[1] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) * EDGE_FLOATS>();
+ leafalloc[2] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) * EDGE_FLOATS * 2>();
+ leafalloc[3] = new MemoryAllocator<sizeof(LeafNode) + sizeof(float) * EDGE_FLOATS * 3>();
+
+ alloc[0] = new MemoryAllocator<sizeof(InternalNode)>();
+ alloc[1] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *)>();
+ alloc[2] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 2>();
+ alloc[3] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 3>();
+ alloc[4] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 4>();
+ alloc[5] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 5>();
+ alloc[6] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 6>();
+ alloc[7] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 7>();
+ alloc[8] = new MemoryAllocator<sizeof(InternalNode) + sizeof(Node *) * 8>();
}
void Octree::freeMemory()
{
- for (int i = 0; i < 9; i++) {
- alloc[i]->destroy();
- delete alloc[i];
- }
-
- for (int i = 0; i < 4; i++) {
- leafalloc[i]->destroy();
- delete leafalloc[i];
- }
+ for (int i = 0; i < 9; i++) {
+ alloc[i]->destroy();
+ delete alloc[i];
+ }
+
+ for (int i = 0; i < 4; i++) {
+ leafalloc[i]->destroy();
+ delete leafalloc[i];
+ }
}
void Octree::printMemUsage()
{
- int totalbytes = 0;
- dc_printf("********* Internal nodes: \n");
- for (int i = 0; i < 9; i++) {
- alloc[i]->printInfo();
-
- totalbytes += alloc[i]->getAll() * alloc[i]->getBytes();
- }
- dc_printf("********* Leaf nodes: \n");
- int totalLeafs = 0;
- for (int i = 0; i < 4; i++) {
- leafalloc[i]->printInfo();
-
- totalbytes += leafalloc[i]->getAll() * leafalloc[i]->getBytes();
- totalLeafs += leafalloc[i]->getAllocated();
- }
-
- dc_printf("Total allocated bytes on disk: %d \n", totalbytes);
- dc_printf("Total leaf nodes: %d\n", totalLeafs);
+ int totalbytes = 0;
+ dc_printf("********* Internal nodes: \n");
+ for (int i = 0; i < 9; i++) {
+ alloc[i]->printInfo();
+
+ totalbytes += alloc[i]->getAll() * alloc[i]->getBytes();
+ }
+ dc_printf("********* Leaf nodes: \n");
+ int totalLeafs = 0;
+ for (int i = 0; i < 4; i++) {
+ leafalloc[i]->printInfo();
+
+ totalbytes += leafalloc[i]->getAll() * leafalloc[i]->getBytes();
+ totalLeafs += leafalloc[i]->getAllocated();
+ }
+
+ dc_printf("Total allocated bytes on disk: %d \n", totalbytes);
+ dc_printf("Total leaf nodes: %d\n", totalLeafs);
}
void Octree::resetMinimalEdges()
{
- cellProcParity(root, 0, maxDepth);
+ cellProcParity(root, 0, maxDepth);
}
void Octree::addAllTriangles()
{
- Triangle *trian;
- int count = 0;
+ Triangle *trian;
+ int count = 0;
#if DC_DEBUG
- int total = reader->getNumTriangles();
- int unitcount = 1000;
- dc_printf("\nScan converting to depth %d...\n", maxDepth);
+ int total = reader->getNumTriangles();
+ int unitcount = 1000;
+ dc_printf("\nScan converting to depth %d...\n", maxDepth);
#endif
- srand(0);
+ srand(0);
- while ((trian = reader->getNextTriangle()) != NULL) {
- // Drop triangles
- {
- addTriangle(trian, count);
- }
- delete trian;
+ while ((trian = reader->getNextTriangle()) != NULL) {
+ // Drop triangles
+ {
+ addTriangle(trian, count);
+ }
+ delete trian;
- count++;
+ count++;
#if DC_DEBUG
- if (count % unitcount == 0) {
- putchar(13);
-
- switch ((count / unitcount) % 4) {
- case 0: dc_printf("-");
- break;
- case 1: dc_printf("/");
- break;
- case 2: dc_printf("|");
- break;
- case 3: dc_printf("\\");
- break;
- }
-
- float percent = (float) count / total;
-
- /*
- int totbars = 50;
- int bars =(int)(percent * totbars);
- for(int i = 0; i < bars; i ++) {
- putchar(219);
- }
- for(i = bars; i < totbars; i ++) {
- putchar(176);
- }
- */
-
- dc_printf(" %d triangles: ", count);
- dc_printf(" %f%% complete.", 100 * percent);
- }
+ if (count % unitcount == 0) {
+ putchar(13);
+
+ switch ((count / unitcount) % 4) {
+ case 0:
+ dc_printf("-");
+ break;
+ case 1:
+ dc_printf("/");
+ break;
+ case 2:
+ dc_printf("|");
+ break;
+ case 3:
+ dc_printf("\\");
+ break;
+ }
+
+ float percent = (float)count / total;
+
+ /*
+ int totbars = 50;
+ int bars =(int)(percent * totbars);
+ for(int i = 0; i < bars; i ++) {
+ putchar(219);
+ }
+ for(i = bars; i < totbars; i ++) {
+ putchar(176);
+ }
+ */
+
+ dc_printf(" %d triangles: ", count);
+ dc_printf(" %f%% complete.", 100 * percent);
+ }
#endif
-
- }
- putchar(13);
+ }
+ putchar(13);
}
/* Prepare a triangle for insertion into the octree; call the other
addTriangle() to (recursively) build the octree */
void Octree::addTriangle(Triangle *trian, int triind)
{
- int i, j;
-
- /* Project the triangle's coordinates into the grid */
- for (i = 0; i < 3; i++) {
- for (j = 0; j < 3; j++)
- trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range;
- }
-
- /* Generate projections */
- int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}};
- int64_t trig[3][3];
- for (i = 0; i < 3; i++) {
- for (j = 0; j < 3; j++)
- trig[i][j] = (int64_t)(trian->vt[i][j]);
- }
-
- /* Add triangle to the octree */
- int64_t errorvec = (int64_t)(0);
- CubeTriangleIsect *proj = new CubeTriangleIsect(cube, trig, errorvec, triind);
- root = (Node *)addTriangle(&root->internal, proj, maxDepth);
-
- delete proj->inherit;
- delete proj;
+ int i, j;
+
+ /* Project the triangle's coordinates into the grid */
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ trian->vt[i][j] = dimen * (trian->vt[i][j] - origin[j]) / range;
+ }
+
+ /* Generate projections */
+ int64_t cube[2][3] = {{0, 0, 0}, {dimen, dimen, dimen}};
+ int64_t trig[3][3];
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ trig[i][j] = (int64_t)(trian->vt[i][j]);
+ }
+
+ /* Add triangle to the octree */
+ int64_t errorvec = (int64_t)(0);
+ CubeTriangleIsect *proj = new CubeTriangleIsect(cube, trig, errorvec, triind);
+ root = (Node *)addTriangle(&root->internal, proj, maxDepth);
+
+ delete proj->inherit;
+ delete proj;
}
#if 0
static void print_depth(int height, int maxDepth)
{
- for (int i = 0; i < maxDepth - height; i++)
- printf(" ");
+ for (int i = 0; i < maxDepth - height; i++)
+ printf(" ");
}
#endif
InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int height)
{
- int i;
- const int vertdiff[8][3] = {
- {0, 0, 0},
- {0, 0, 1},
- {0, 1, -1},
- {0, 0, 1},
- {1, -1, -1},
- {0, 0, 1},
- {0, 1, -1},
- {0, 0, 1}};
- unsigned char boxmask = p->getBoxMask();
- CubeTriangleIsect *subp = new CubeTriangleIsect(p);
-
- int count = 0;
- int tempdiff[3] = {0, 0, 0};
-
- /* Check triangle against each of the input node's children */
- for (i = 0; i < 8; i++) {
- tempdiff[0] += vertdiff[i][0];
- tempdiff[1] += vertdiff[i][1];
- tempdiff[2] += vertdiff[i][2];
-
- /* Quick pruning using bounding box */
- if (boxmask & (1 << i)) {
- subp->shift(tempdiff);
- tempdiff[0] = tempdiff[1] = tempdiff[2] = 0;
-
- /* Pruning using intersection test */
- if (subp->isIntersecting()) {
- if (!node->has_child(i)) {
- if (height == 1)
- node = addLeafChild(node, i, count, createLeaf(0));
- else
- node = addInternalChild(node, i, count, createInternal(0));
- }
- Node *chd = node->get_child(count);
-
- if (node->is_child_leaf(i))
- node->set_child(count, (Node *)updateCell(&chd->leaf, subp));
- else
- node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1));
- }
- }
-
- if (node->has_child(i))
- count++;
- }
-
- delete subp;
-
- return node;
+ int i;
+ const int vertdiff[8][3] = {
+ {0, 0, 0}, {0, 0, 1}, {0, 1, -1}, {0, 0, 1}, {1, -1, -1}, {0, 0, 1}, {0, 1, -1}, {0, 0, 1}};
+ unsigned char boxmask = p->getBoxMask();
+ CubeTriangleIsect *subp = new CubeTriangleIsect(p);
+
+ int count = 0;
+ int tempdiff[3] = {0, 0, 0};
+
+ /* Check triangle against each of the input node's children */
+ for (i = 0; i < 8; i++) {
+ tempdiff[0] += vertdiff[i][0];
+ tempdiff[1] += vertdiff[i][1];
+ tempdiff[2] += vertdiff[i][2];
+
+ /* Quick pruning using bounding box */
+ if (boxmask & (1 << i)) {
+ subp->shift(tempdiff);
+ tempdiff[0] = tempdiff[1] = tempdiff[2] = 0;
+
+ /* Pruning using intersection test */
+ if (subp->isIntersecting()) {
+ if (!node->has_child(i)) {
+ if (height == 1)
+ node = addLeafChild(node, i, count, createLeaf(0));
+ else
+ node = addInternalChild(node, i, count, createInternal(0));
+ }
+ Node *chd = node->get_child(count);
+
+ if (node->is_child_leaf(i))
+ node->set_child(count, (Node *)updateCell(&chd->leaf, subp));
+ else
+ node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1));
+ }
+ }
+
+ if (node->has_child(i))
+ count++;
+ }
+
+ delete subp;
+
+ return node;
}
LeafNode *Octree::updateCell(LeafNode *node, CubeTriangleIsect *p)
{
- int i;
-
- // Edge connectivity
- int mask[3] = {0, 4, 8 };
- int oldc = 0, newc = 0;
- float offs[3];
- float a[3], b[3], c[3];
-
- for (i = 0; i < 3; i++) {
- if (!getEdgeParity(node, mask[i])) {
- if (p->isIntersectingPrimary(i)) {
- // actualQuads ++;
- setEdge(node, mask[i]);
- offs[newc] = p->getIntersectionPrimary(i);
- a[newc] = (float) p->inherit->norm[0];
- b[newc] = (float) p->inherit->norm[1];
- c[newc] = (float) p->inherit->norm[2];
- newc++;
- }
- }
- else {
- offs[newc] = getEdgeOffsetNormal(node, oldc, a[newc], b[newc], c[newc]);
-
- oldc++;
- newc++;
- }
- }
-
- if (newc > oldc) {
- // New offsets added, update this node
- node = updateEdgeOffsetsNormals(node, oldc, newc, offs, a, b, c);
- }
-
- return node;
+ int i;
+
+ // Edge connectivity
+ int mask[3] = {0, 4, 8};
+ int oldc = 0, newc = 0;
+ float offs[3];
+ float a[3], b[3], c[3];
+
+ for (i = 0; i < 3; i++) {
+ if (!getEdgeParity(node, mask[i])) {
+ if (p->isIntersectingPrimary(i)) {
+ // actualQuads ++;
+ setEdge(node, mask[i]);
+ offs[newc] = p->getIntersectionPrimary(i);
+ a[newc] = (float)p->inherit->norm[0];
+ b[newc] = (float)p->inherit->norm[1];
+ c[newc] = (float)p->inherit->norm[2];
+ newc++;
+ }
+ }
+ else {
+ offs[newc] = getEdgeOffsetNormal(node, oldc, a[newc], b[newc], c[newc]);
+
+ oldc++;
+ newc++;
+ }
+ }
+
+ if (newc > oldc) {
+ // New offsets added, update this node
+ node = updateEdgeOffsetsNormals(node, oldc, newc, offs, a, b, c);
+ }
+
+ return node;
}
void Octree::preparePrimalEdgesMask(InternalNode *node)
{
- int count = 0;
- for (int i = 0; i < 8; i++) {
- if (node->has_child(i)) {
- if (node->is_child_leaf(i))
- createPrimalEdgesMask(&node->get_child(count)->leaf);
- else
- preparePrimalEdgesMask(&node->get_child(count)->internal);
-
- count++;
- }
- }
+ int count = 0;
+ for (int i = 0; i < 8; i++) {
+ if (node->has_child(i)) {
+ if (node->is_child_leaf(i))
+ createPrimalEdgesMask(&node->get_child(count)->leaf);
+ else
+ preparePrimalEdgesMask(&node->get_child(count)->internal);
+
+ count++;
+ }
+ }
}
void Octree::trace()
{
- int st[3] = {0, 0, 0, };
- numRings = 0;
- totRingLengths = 0;
- maxRingLength = 0;
-
- PathList *chdpath = NULL;
- root = trace(root, st, dimen, maxDepth, chdpath);
-
- if (chdpath != NULL) {
- dc_printf("there are incomplete rings.\n");
- printPaths(chdpath);
- };
+ int st[3] = {
+ 0,
+ 0,
+ 0,
+ };
+ numRings = 0;
+ totRingLengths = 0;
+ maxRingLength = 0;
+
+ PathList *chdpath = NULL;
+ root = trace(root, st, dimen, maxDepth, chdpath);
+
+ if (chdpath != NULL) {
+ dc_printf("there are incomplete rings.\n");
+ printPaths(chdpath);
+ };
}
-Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *& paths)
+Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths)
{
- len >>= 1;
- PathList *chdpaths[8];
- Node *chd[8];
- int nst[8][3];
- int i, j;
-
- // Get children paths
- int chdleaf[8];
- newnode->internal.fill_children(chd, chdleaf);
-
- // int count = 0;
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 3; j++) {
- nst[i][j] = st[j] + len * vertmap[i][j];
- }
-
- if (chd[i] == NULL || newnode->internal.is_child_leaf(i)) {
- chdpaths[i] = NULL;
- }
- else {
- trace(chd[i], nst[i], len, depth - 1, chdpaths[i]);
- }
- }
-
- // Get connectors on the faces
- PathList *conn[12];
- Node *nf[2];
- int lf[2];
- int df[2] = {depth - 1, depth - 1};
- int *nstf[2];
-
- newnode->internal.fill_children(chd, chdleaf);
-
- for (i = 0; i < 12; i++) {
- int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
-
- for (int j = 0; j < 2; j++) {
- lf[j] = chdleaf[c[j]];
- nf[j] = chd[c[j]];
- nstf[j] = nst[c[j]];
- }
-
- conn[i] = NULL;
-
- findPaths((Node **)nf, lf, df, nstf, depth - 1, cellProcFaceMask[i][2], conn[i]);
-
- //if(conn[i]) {
- // printPath(conn[i]);
- //}
- }
-
- // Connect paths
- PathList *rings = NULL;
- combinePaths(chdpaths[0], chdpaths[1], conn[8], rings);
- combinePaths(chdpaths[2], chdpaths[3], conn[9], rings);
- combinePaths(chdpaths[4], chdpaths[5], conn[10], rings);
- combinePaths(chdpaths[6], chdpaths[7], conn[11], rings);
-
- combinePaths(chdpaths[0], chdpaths[2], conn[4], rings);
- combinePaths(chdpaths[4], chdpaths[6], conn[5], rings);
- combinePaths(chdpaths[0], NULL, conn[6], rings);
- combinePaths(chdpaths[4], NULL, conn[7], rings);
-
- combinePaths(chdpaths[0], chdpaths[4], conn[0], rings);
- combinePaths(chdpaths[0], NULL, conn[1], rings);
- combinePaths(chdpaths[0], NULL, conn[2], rings);
- combinePaths(chdpaths[0], NULL, conn[3], rings);
-
- // By now, only chdpaths[0] and rings have contents
-
- // Process rings
- if (rings) {
- // printPath(rings);
-
- /* Let's count first */
- PathList *trings = rings;
- while (trings) {
- numRings++;
- totRingLengths += trings->length;
- if (trings->length > maxRingLength) {
- maxRingLength = trings->length;
- }
- trings = trings->next;
- }
-
- // printPath(rings);
- newnode = patch(newnode, st, (len << 1), rings);
- }
-
- // Return incomplete paths
- paths = chdpaths[0];
- return newnode;
+ len >>= 1;
+ PathList *chdpaths[8];
+ Node *chd[8];
+ int nst[8][3];
+ int i, j;
+
+ // Get children paths
+ int chdleaf[8];
+ newnode->internal.fill_children(chd, chdleaf);
+
+ // int count = 0;
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 3; j++) {
+ nst[i][j] = st[j] + len * vertmap[i][j];
+ }
+
+ if (chd[i] == NULL || newnode->internal.is_child_leaf(i)) {
+ chdpaths[i] = NULL;
+ }
+ else {
+ trace(chd[i], nst[i], len, depth - 1, chdpaths[i]);
+ }
+ }
+
+ // Get connectors on the faces
+ PathList *conn[12];
+ Node *nf[2];
+ int lf[2];
+ int df[2] = {depth - 1, depth - 1};
+ int *nstf[2];
+
+ newnode->internal.fill_children(chd, chdleaf);
+
+ for (i = 0; i < 12; i++) {
+ int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
+
+ for (int j = 0; j < 2; j++) {
+ lf[j] = chdleaf[c[j]];
+ nf[j] = chd[c[j]];
+ nstf[j] = nst[c[j]];
+ }
+
+ conn[i] = NULL;
+
+ findPaths((Node **)nf, lf, df, nstf, depth - 1, cellProcFaceMask[i][2], conn[i]);
+
+ //if(conn[i]) {
+ // printPath(conn[i]);
+ //}
+ }
+
+ // Connect paths
+ PathList *rings = NULL;
+ combinePaths(chdpaths[0], chdpaths[1], conn[8], rings);
+ combinePaths(chdpaths[2], chdpaths[3], conn[9], rings);
+ combinePaths(chdpaths[4], chdpaths[5], conn[10], rings);
+ combinePaths(chdpaths[6], chdpaths[7], conn[11], rings);
+
+ combinePaths(chdpaths[0], chdpaths[2], conn[4], rings);
+ combinePaths(chdpaths[4], chdpaths[6], conn[5], rings);
+ combinePaths(chdpaths[0], NULL, conn[6], rings);
+ combinePaths(chdpaths[4], NULL, conn[7], rings);
+
+ combinePaths(chdpaths[0], chdpaths[4], conn[0], rings);
+ combinePaths(chdpaths[0], NULL, conn[1], rings);
+ combinePaths(chdpaths[0], NULL, conn[2], rings);
+ combinePaths(chdpaths[0], NULL, conn[3], rings);
+
+ // By now, only chdpaths[0] and rings have contents
+
+ // Process rings
+ if (rings) {
+ // printPath(rings);
+
+ /* Let's count first */
+ PathList *trings = rings;
+ while (trings) {
+ numRings++;
+ totRingLengths += trings->length;
+ if (trings->length > maxRingLength) {
+ maxRingLength = trings->length;
+ }
+ trings = trings->next;
+ }
+
+ // printPath(rings);
+ newnode = patch(newnode, st, (len << 1), rings);
+ }
+
+ // Return incomplete paths
+ paths = chdpaths[0];
+ return newnode;
}
-void Octree::findPaths(Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *& paths)
+void Octree::findPaths(
+ Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *&paths)
{
- if (!(node[0] && node[1])) {
- return;
- }
-
- if (!(leaf[0] && leaf[1])) {
- // Not at the bottom, recur
-
- // Fill children nodes
- int i, j;
- Node *chd[2][8];
- int chdleaf[2][8];
- int nst[2][8][3];
-
- for (j = 0; j < 2; j++) {
- if (!leaf[j]) {
- node[j]->internal.fill_children(chd[j], chdleaf[j]);
-
- int len = (dimen >> (maxDepth - depth[j] + 1));
- for (i = 0; i < 8; i++) {
- for (int k = 0; k < 3; k++) {
- nst[j][i][k] = st[j][k] + len * vertmap[i][k];
- }
- }
-
- }
- }
-
- // 4 face calls
- Node *nf[2];
- int df[2];
- int lf[2];
- int *nstf[2];
- for (i = 0; i < 4; i++) {
- int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
- for (int j = 0; j < 2; j++) {
- if (leaf[j]) {
- lf[j] = leaf[j];
- nf[j] = node[j];
- df[j] = depth[j];
- nstf[j] = st[j];
- }
- else {
- lf[j] = chdleaf[j][c[j]];
- nf[j] = chd[j][c[j]];
- df[j] = depth[j] - 1;
- nstf[j] = nst[j][c[j]];
- }
- }
- findPaths(nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[dir][i][2], paths);
- }
-
- }
- else {
- // At the bottom, check this face
- int ind = (depth[0] == maxdep ? 0 : 1);
- int fcind = 2 * dir + (1 - ind);
- if (getFaceParity((LeafNode *)node[ind], fcind)) {
- // Add into path
- PathElement *ele1 = new PathElement;
- PathElement *ele2 = new PathElement;
-
- ele1->pos[0] = st[0][0];
- ele1->pos[1] = st[0][1];
- ele1->pos[2] = st[0][2];
-
- ele2->pos[0] = st[1][0];
- ele2->pos[1] = st[1][1];
- ele2->pos[2] = st[1][2];
-
- ele1->next = ele2;
- ele2->next = NULL;
-
- PathList *lst = new PathList;
- lst->head = ele1;
- lst->tail = ele2;
- lst->length = 2;
- lst->next = paths;
- paths = lst;
-
- // int l =(dimen >> maxDepth);
- }
- }
-
+ if (!(node[0] && node[1])) {
+ return;
+ }
+
+ if (!(leaf[0] && leaf[1])) {
+ // Not at the bottom, recur
+
+ // Fill children nodes
+ int i, j;
+ Node *chd[2][8];
+ int chdleaf[2][8];
+ int nst[2][8][3];
+
+ for (j = 0; j < 2; j++) {
+ if (!leaf[j]) {
+ node[j]->internal.fill_children(chd[j], chdleaf[j]);
+
+ int len = (dimen >> (maxDepth - depth[j] + 1));
+ for (i = 0; i < 8; i++) {
+ for (int k = 0; k < 3; k++) {
+ nst[j][i][k] = st[j][k] + len * vertmap[i][k];
+ }
+ }
+ }
+ }
+
+ // 4 face calls
+ Node *nf[2];
+ int df[2];
+ int lf[2];
+ int *nstf[2];
+ for (i = 0; i < 4; i++) {
+ int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
+ for (int j = 0; j < 2; j++) {
+ if (leaf[j]) {
+ lf[j] = leaf[j];
+ nf[j] = node[j];
+ df[j] = depth[j];
+ nstf[j] = st[j];
+ }
+ else {
+ lf[j] = chdleaf[j][c[j]];
+ nf[j] = chd[j][c[j]];
+ df[j] = depth[j] - 1;
+ nstf[j] = nst[j][c[j]];
+ }
+ }
+ findPaths(nf, lf, df, nstf, maxdep - 1, faceProcFaceMask[dir][i][2], paths);
+ }
+ }
+ else {
+ // At the bottom, check this face
+ int ind = (depth[0] == maxdep ? 0 : 1);
+ int fcind = 2 * dir + (1 - ind);
+ if (getFaceParity((LeafNode *)node[ind], fcind)) {
+ // Add into path
+ PathElement *ele1 = new PathElement;
+ PathElement *ele2 = new PathElement;
+
+ ele1->pos[0] = st[0][0];
+ ele1->pos[1] = st[0][1];
+ ele1->pos[2] = st[0][2];
+
+ ele2->pos[0] = st[1][0];
+ ele2->pos[1] = st[1][1];
+ ele2->pos[2] = st[1][2];
+
+ ele1->next = ele2;
+ ele2->next = NULL;
+
+ PathList *lst = new PathList;
+ lst->head = ele1;
+ lst->tail = ele2;
+ lst->length = 2;
+ lst->next = paths;
+ paths = lst;
+
+ // int l =(dimen >> maxDepth);
+ }
+ }
}
-void Octree::combinePaths(PathList *& list1, PathList *list2, PathList *paths, PathList *& rings)
+void Octree::combinePaths(PathList *&list1, PathList *list2, PathList *paths, PathList *&rings)
{
- // Make new list of paths
- PathList *nlist = NULL;
-
- // Search for each connectors in paths
- PathList *tpaths = paths;
- PathList *tlist, *pre;
- while (tpaths) {
- PathList *singlist = tpaths;
- PathList *templist;
- tpaths = tpaths->next;
- singlist->next = NULL;
-
- // Look for hookup in list1
- tlist = list1;
- pre = NULL;
- while (tlist) {
- if ((templist = combineSinglePath(list1, pre, tlist, singlist, NULL, singlist)) != NULL) {
- singlist = templist;
- continue;
- }
- pre = tlist;
- tlist = tlist->next;
- }
-
- // Look for hookup in list2
- tlist = list2;
- pre = NULL;
- while (tlist) {
- if ((templist = combineSinglePath(list2, pre, tlist, singlist, NULL, singlist)) != NULL) {
- singlist = templist;
- continue;
- }
- pre = tlist;
- tlist = tlist->next;
- }
-
- // Look for hookup in nlist
- tlist = nlist;
- pre = NULL;
- while (tlist) {
- if ((templist = combineSinglePath(nlist, pre, tlist, singlist, NULL, singlist)) != NULL) {
- singlist = templist;
- continue;
- }
- pre = tlist;
- tlist = tlist->next;
- }
-
- // Add to nlist or rings
- if (isEqual(singlist->head, singlist->tail)) {
- PathElement *temp = singlist->head;
- singlist->head = temp->next;
- delete temp;
- singlist->length--;
- singlist->tail->next = singlist->head;
-
- singlist->next = rings;
- rings = singlist;
- }
- else {
- singlist->next = nlist;
- nlist = singlist;
- }
-
- }
-
- // Append list2 and nlist to the end of list1
- tlist = list1;
- if (tlist != NULL) {
- while (tlist->next != NULL) {
- tlist = tlist->next;
- }
- tlist->next = list2;
- }
- else {
- tlist = list2;
- list1 = list2;
- }
-
- if (tlist != NULL) {
- while (tlist->next != NULL) {
- tlist = tlist->next;
- }
- tlist->next = nlist;
- }
- else {
- tlist = nlist;
- list1 = nlist;
- }
-
+ // Make new list of paths
+ PathList *nlist = NULL;
+
+ // Search for each connectors in paths
+ PathList *tpaths = paths;
+ PathList *tlist, *pre;
+ while (tpaths) {
+ PathList *singlist = tpaths;
+ PathList *templist;
+ tpaths = tpaths->next;
+ singlist->next = NULL;
+
+ // Look for hookup in list1
+ tlist = list1;
+ pre = NULL;
+ while (tlist) {
+ if ((templist = combineSinglePath(list1, pre, tlist, singlist, NULL, singlist)) != NULL) {
+ singlist = templist;
+ continue;
+ }
+ pre = tlist;
+ tlist = tlist->next;
+ }
+
+ // Look for hookup in list2
+ tlist = list2;
+ pre = NULL;
+ while (tlist) {
+ if ((templist = combineSinglePath(list2, pre, tlist, singlist, NULL, singlist)) != NULL) {
+ singlist = templist;
+ continue;
+ }
+ pre = tlist;
+ tlist = tlist->next;
+ }
+
+ // Look for hookup in nlist
+ tlist = nlist;
+ pre = NULL;
+ while (tlist) {
+ if ((templist = combineSinglePath(nlist, pre, tlist, singlist, NULL, singlist)) != NULL) {
+ singlist = templist;
+ continue;
+ }
+ pre = tlist;
+ tlist = tlist->next;
+ }
+
+ // Add to nlist or rings
+ if (isEqual(singlist->head, singlist->tail)) {
+ PathElement *temp = singlist->head;
+ singlist->head = temp->next;
+ delete temp;
+ singlist->length--;
+ singlist->tail->next = singlist->head;
+
+ singlist->next = rings;
+ rings = singlist;
+ }
+ else {
+ singlist->next = nlist;
+ nlist = singlist;
+ }
+ }
+
+ // Append list2 and nlist to the end of list1
+ tlist = list1;
+ if (tlist != NULL) {
+ while (tlist->next != NULL) {
+ tlist = tlist->next;
+ }
+ tlist->next = list2;
+ }
+ else {
+ tlist = list2;
+ list1 = list2;
+ }
+
+ if (tlist != NULL) {
+ while (tlist->next != NULL) {
+ tlist = tlist->next;
+ }
+ tlist->next = nlist;
+ }
+ else {
+ tlist = nlist;
+ list1 = nlist;
+ }
}
-PathList *Octree::combineSinglePath(PathList *& head1, PathList *pre1, PathList *& list1, PathList *& head2, PathList *pre2, PathList *& list2)
+PathList *Octree::combineSinglePath(PathList *&head1,
+ PathList *pre1,
+ PathList *&list1,
+ PathList *&head2,
+ PathList *pre2,
+ PathList *&list2)
{
- if (isEqual(list1->head, list2->head) || isEqual(list1->tail, list2->tail)) {
- // Reverse the list
- if (list1->length < list2->length) {
- // Reverse list1
- PathElement *prev = list1->head;
- PathElement *next = prev->next;
- prev->next = NULL;
- while (next != NULL) {
- PathElement *tnext = next->next;
- next->next = prev;
-
- prev = next;
- next = tnext;
- }
-
- list1->tail = list1->head;
- list1->head = prev;
- }
- else {
- // Reverse list2
- PathElement *prev = list2->head;
- PathElement *next = prev->next;
- prev->next = NULL;
- while (next != NULL) {
- PathElement *tnext = next->next;
- next->next = prev;
-
- prev = next;
- next = tnext;
- }
-
- list2->tail = list2->head;
- list2->head = prev;
- }
- }
-
- if (isEqual(list1->head, list2->tail)) {
-
- // Easy case
- PathElement *temp = list1->head->next;
- delete list1->head;
- list2->tail->next = temp;
-
- PathList *nlist = new PathList;
- nlist->length = list1->length + list2->length - 1;
- nlist->head = list2->head;
- nlist->tail = list1->tail;
- nlist->next = NULL;
-
- deletePath(head1, pre1, list1);
- deletePath(head2, pre2, list2);
-
- return nlist;
- }
- else if (isEqual(list1->tail, list2->head)) {
- // Easy case
- PathElement *temp = list2->head->next;
- delete list2->head;
- list1->tail->next = temp;
-
- PathList *nlist = new PathList;
- nlist->length = list1->length + list2->length - 1;
- nlist->head = list1->head;
- nlist->tail = list2->tail;
- nlist->next = NULL;
-
- deletePath(head1, pre1, list1);
- deletePath(head2, pre2, list2);
-
- return nlist;
- }
-
- return NULL;
+ if (isEqual(list1->head, list2->head) || isEqual(list1->tail, list2->tail)) {
+ // Reverse the list
+ if (list1->length < list2->length) {
+ // Reverse list1
+ PathElement *prev = list1->head;
+ PathElement *next = prev->next;
+ prev->next = NULL;
+ while (next != NULL) {
+ PathElement *tnext = next->next;
+ next->next = prev;
+
+ prev = next;
+ next = tnext;
+ }
+
+ list1->tail = list1->head;
+ list1->head = prev;
+ }
+ else {
+ // Reverse list2
+ PathElement *prev = list2->head;
+ PathElement *next = prev->next;
+ prev->next = NULL;
+ while (next != NULL) {
+ PathElement *tnext = next->next;
+ next->next = prev;
+
+ prev = next;
+ next = tnext;
+ }
+
+ list2->tail = list2->head;
+ list2->head = prev;
+ }
+ }
+
+ if (isEqual(list1->head, list2->tail)) {
+
+ // Easy case
+ PathElement *temp = list1->head->next;
+ delete list1->head;
+ list2->tail->next = temp;
+
+ PathList *nlist = new PathList;
+ nlist->length = list1->length + list2->length - 1;
+ nlist->head = list2->head;
+ nlist->tail = list1->tail;
+ nlist->next = NULL;
+
+ deletePath(head1, pre1, list1);
+ deletePath(head2, pre2, list2);
+
+ return nlist;
+ }
+ else if (isEqual(list1->tail, list2->head)) {
+ // Easy case
+ PathElement *temp = list2->head->next;
+ delete list2->head;
+ list1->tail->next = temp;
+
+ PathList *nlist = new PathList;
+ nlist->length = list1->length + list2->length - 1;
+ nlist->head = list1->head;
+ nlist->tail = list2->tail;
+ nlist->next = NULL;
+
+ deletePath(head1, pre1, list1);
+ deletePath(head2, pre2, list2);
+
+ return nlist;
+ }
+
+ return NULL;
}
-void Octree::deletePath(PathList *& head, PathList *pre, PathList *& curr)
+void Octree::deletePath(PathList *&head, PathList *pre, PathList *&curr)
{
- PathList *temp = curr;
- curr = temp->next;
- delete temp;
-
- if (pre == NULL) {
- head = curr;
- }
- else {
- pre->next = curr;
- }
+ PathList *temp = curr;
+ curr = temp->next;
+ delete temp;
+
+ if (pre == NULL) {
+ head = curr;
+ }
+ else {
+ pre->next = curr;
+ }
}
void Octree::printElement(PathElement *ele)
{
- if (ele != NULL) {
- dc_printf("(%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2]);
- }
+ if (ele != NULL) {
+ dc_printf("(%d %d %d)", ele->pos[0], ele->pos[1], ele->pos[2]);
+ }
}
void Octree::printPath(PathList *path)
{
- PathElement *n = path->head;
- int same = 0;
+ PathElement *n = path->head;
+ int same = 0;
#if DC_DEBUG
- int len = (dimen >> maxDepth);
+ int len = (dimen >> maxDepth);
#endif
- while (n && (same == 0 || n != path->head)) {
- same++;
- dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len);
- n = n->next;
- }
-
- if (n == path->head) {
- dc_printf(" Ring!\n");
- }
- else {
- dc_printf(" %p end!\n", n);
- }
+ while (n && (same == 0 || n != path->head)) {
+ same++;
+ dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len);
+ n = n->next;
+ }
+
+ if (n == path->head) {
+ dc_printf(" Ring!\n");
+ }
+ else {
+ dc_printf(" %p end!\n", n);
+ }
}
void Octree::printPath(PathElement *path)
{
- PathElement *n = path;
- int same = 0;
+ PathElement *n = path;
+ int same = 0;
#if DC_DEBUG
- int len = (dimen >> maxDepth);
+ int len = (dimen >> maxDepth);
#endif
- while (n && (same == 0 || n != path)) {
- same++;
- dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len);
- n = n->next;
- }
-
- if (n == path) {
- dc_printf(" Ring!\n");
- }
- else {
- dc_printf(" %p end!\n", n);
- }
-
+ while (n && (same == 0 || n != path)) {
+ same++;
+ dc_printf("(%d %d %d)", n->pos[0] / len, n->pos[1] / len, n->pos[2] / len);
+ n = n->next;
+ }
+
+ if (n == path) {
+ dc_printf(" Ring!\n");
+ }
+ else {
+ dc_printf(" %p end!\n", n);
+ }
}
-
void Octree::printPaths(PathList *path)
{
- PathList *iter = path;
- int i = 0;
- while (iter != NULL) {
- dc_printf("Path %d:\n", i);
- printPath(iter);
- iter = iter->next;
- i++;
- }
+ PathList *iter = path;
+ int i = 0;
+ while (iter != NULL) {
+ dc_printf("Path %d:\n", i);
+ printPath(iter);
+ iter = iter->next;
+ i++;
+ }
}
Node *Octree::patch(Node *newnode, int st[3], int len, PathList *rings)
{
#ifdef IN_DEBUG_MODE
- dc_printf("Call to PATCH with rings: \n");
- printPaths(rings);
+ dc_printf("Call to PATCH with rings: \n");
+ printPaths(rings);
#endif
- /* Do nothing but couting
- PathList* tlist = rings;
- PathList* ttlist;
- PathElement* telem, * ttelem;
- while(tlist!= NULL) {
- // printPath(tlist);
- numRings ++;
- totRingLengths += tlist->length;
- if(tlist->length > maxRingLength) {
- maxRingLength = tlist->length;
- }
- ttlist = tlist;
- tlist = tlist->next;
- }
- return node;
- */
-
-
- /* Pass onto separate calls in each direction */
- if (len == mindimen) {
- dc_printf("Error! should have no list by now.\n");
- exit(0);
- }
-
- // YZ plane
- PathList *xlists[2];
- newnode = patchSplit(newnode, st, len, rings, 0, xlists[0], xlists[1]);
-
- // XZ plane
- PathList *ylists[4];
- newnode = patchSplit(newnode, st, len, xlists[0], 1, ylists[0], ylists[1]);
- newnode = patchSplit(newnode, st, len, xlists[1], 1, ylists[2], ylists[3]);
-
- // XY plane
- PathList *zlists[8];
- newnode = patchSplit(newnode, st, len, ylists[0], 2, zlists[0], zlists[1]);
- newnode = patchSplit(newnode, st, len, ylists[1], 2, zlists[2], zlists[3]);
- newnode = patchSplit(newnode, st, len, ylists[2], 2, zlists[4], zlists[5]);
- newnode = patchSplit(newnode, st, len, ylists[3], 2, zlists[6], zlists[7]);
-
- // Recur
- len >>= 1;
- int count = 0;
- for (int i = 0; i < 8; i++) {
- if (zlists[i] != NULL) {
- int nori[3] = {
- st[0] + len * vertmap[i][0],
- st[1] + len * vertmap[i][1],
- st[2] + len * vertmap[i][2]
- };
- patch(newnode->internal.get_child(count), nori, len, zlists[i]);
- }
-
- if (newnode->internal.has_child(i)) {
- count++;
- }
- }
+ /* Do nothing but couting
+ PathList* tlist = rings;
+ PathList* ttlist;
+ PathElement* telem, * ttelem;
+ while(tlist!= NULL) {
+ // printPath(tlist);
+ numRings ++;
+ totRingLengths += tlist->length;
+ if(tlist->length > maxRingLength) {
+ maxRingLength = tlist->length;
+ }
+ ttlist = tlist;
+ tlist = tlist->next;
+ }
+ return node;
+ */
+
+ /* Pass onto separate calls in each direction */
+ if (len == mindimen) {
+ dc_printf("Error! should have no list by now.\n");
+ exit(0);
+ }
+
+ // YZ plane
+ PathList *xlists[2];
+ newnode = patchSplit(newnode, st, len, rings, 0, xlists[0], xlists[1]);
+
+ // XZ plane
+ PathList *ylists[4];
+ newnode = patchSplit(newnode, st, len, xlists[0], 1, ylists[0], ylists[1]);
+ newnode = patchSplit(newnode, st, len, xlists[1], 1, ylists[2], ylists[3]);
+
+ // XY plane
+ PathList *zlists[8];
+ newnode = patchSplit(newnode, st, len, ylists[0], 2, zlists[0], zlists[1]);
+ newnode = patchSplit(newnode, st, len, ylists[1], 2, zlists[2], zlists[3]);
+ newnode = patchSplit(newnode, st, len, ylists[2], 2, zlists[4], zlists[5]);
+ newnode = patchSplit(newnode, st, len, ylists[3], 2, zlists[6], zlists[7]);
+
+ // Recur
+ len >>= 1;
+ int count = 0;
+ for (int i = 0; i < 8; i++) {
+ if (zlists[i] != NULL) {
+ int nori[3] = {
+ st[0] + len * vertmap[i][0], st[1] + len * vertmap[i][1], st[2] + len * vertmap[i][2]};
+ patch(newnode->internal.get_child(count), nori, len, zlists[i]);
+ }
+
+ if (newnode->internal.has_child(i)) {
+ count++;
+ }
+ }
#ifdef IN_DEBUG_MODE
- dc_printf("Return from PATCH\n");
+ dc_printf("Return from PATCH\n");
#endif
- return newnode;
-
+ return newnode;
}
-
-Node *Octree::patchSplit(Node *newnode, int st[3], int len, PathList *rings,
- int dir, PathList *& nrings1, PathList *& nrings2)
+Node *Octree::patchSplit(Node *newnode,
+ int st[3],
+ int len,
+ PathList *rings,
+ int dir,
+ PathList *&nrings1,
+ PathList *&nrings2)
{
#ifdef IN_DEBUG_MODE
- dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir);
- printPaths(rings);
+ dc_printf("Call to PATCHSPLIT with direction %d and rings: \n", dir);
+ printPaths(rings);
#endif
- nrings1 = NULL;
- nrings2 = NULL;
- PathList *tmp;
- while (rings != NULL) {
- // Process this ring
- newnode = patchSplitSingle(newnode, st, len, rings->head, dir, nrings1, nrings2);
+ nrings1 = NULL;
+ nrings2 = NULL;
+ PathList *tmp;
+ while (rings != NULL) {
+ // Process this ring
+ newnode = patchSplitSingle(newnode, st, len, rings->head, dir, nrings1, nrings2);
- // Delete this ring from the group
- tmp = rings;
- rings = rings->next;
- delete tmp;
- }
+ // Delete this ring from the group
+ tmp = rings;
+ rings = rings->next;
+ delete tmp;
+ }
#ifdef IN_DEBUG_MODE
- dc_printf("Return from PATCHSPLIT with \n");
- dc_printf("Rings gourp 1:\n");
- printPaths(nrings1);
- dc_printf("Rings group 2:\n");
- printPaths(nrings2);
+ dc_printf("Return from PATCHSPLIT with \n");
+ dc_printf("Rings gourp 1:\n");
+ printPaths(nrings1);
+ dc_printf("Rings group 2:\n");
+ printPaths(nrings2);
#endif
- return newnode;
+ return newnode;
}
-Node *Octree::patchSplitSingle(Node *newnode, int st[3], int len, PathElement *head, int dir, PathList *& nrings1, PathList *& nrings2)
+Node *Octree::patchSplitSingle(Node *newnode,
+ int st[3],
+ int len,
+ PathElement *head,
+ int dir,
+ PathList *&nrings1,
+ PathList *&nrings2)
{
#ifdef IN_DEBUG_MODE
- dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir);
- printPath(head);
+ dc_printf("Call to PATCHSPLITSINGLE with direction %d and path: \n", dir);
+ printPath(head);
#endif
- if (head == NULL) {
+ if (head == NULL) {
#ifdef IN_DEBUG_MODE
- dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n");
+ dc_printf("Return from PATCHSPLITSINGLE with head==NULL.\n");
#endif
- return newnode;
- }
- else {
- // printPath(head);
- }
-
- // Walk along the ring to find pair of intersections
- PathElement *pre1 = NULL;
- PathElement *pre2 = NULL;
- int side = findPair(head, st[dir] + len / 2, dir, pre1, pre2);
-
- /*
- if(pre1 == pre2) {
- int edgelen =(dimen >> maxDepth);
- dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen);
- printPath(head);
- exit(0);
- }
- */
-
- if (side) {
- // Entirely on one side
- PathList *nring = new PathList();
- nring->head = head;
-
- if (side == -1) {
- nring->next = nrings1;
- nrings1 = nring;
- }
- else {
- nring->next = nrings2;
- nrings2 = nring;
- }
- }
- else {
- // Break into two parts
- PathElement *nxt1 = pre1->next;
- PathElement *nxt2 = pre2->next;
- pre1->next = nxt2;
- pre2->next = nxt1;
-
- newnode = connectFace(newnode, st, len, dir, pre1, pre2);
-
- if (isEqual(pre1, pre1->next)) {
- if (pre1 == pre1->next) {
- delete pre1;
- pre1 = NULL;
- }
- else {
- PathElement *temp = pre1->next;
- pre1->next = temp->next;
- delete temp;
- }
- }
- if (isEqual(pre2, pre2->next)) {
- if (pre2 == pre2->next) {
- delete pre2;
- pre2 = NULL;
- }
- else {
- PathElement *temp = pre2->next;
- pre2->next = temp->next;
- delete temp;
- }
- }
-
- compressRing(pre1);
- compressRing(pre2);
-
- // Recur
- newnode = patchSplitSingle(newnode, st, len, pre1, dir, nrings1, nrings2);
- newnode = patchSplitSingle(newnode, st, len, pre2, dir, nrings1, nrings2);
-
- }
+ return newnode;
+ }
+ else {
+ // printPath(head);
+ }
+
+ // Walk along the ring to find pair of intersections
+ PathElement *pre1 = NULL;
+ PathElement *pre2 = NULL;
+ int side = findPair(head, st[dir] + len / 2, dir, pre1, pre2);
+
+ /*
+ if(pre1 == pre2) {
+ int edgelen =(dimen >> maxDepth);
+ dc_printf("Location: %d %d %d Direction: %d Reso: %d\n", st[0]/edgelen, st[1]/edgelen, st[2]/edgelen, dir, len/edgelen);
+ printPath(head);
+ exit(0);
+ }
+ */
+
+ if (side) {
+ // Entirely on one side
+ PathList *nring = new PathList();
+ nring->head = head;
+
+ if (side == -1) {
+ nring->next = nrings1;
+ nrings1 = nring;
+ }
+ else {
+ nring->next = nrings2;
+ nrings2 = nring;
+ }
+ }
+ else {
+ // Break into two parts
+ PathElement *nxt1 = pre1->next;
+ PathElement *nxt2 = pre2->next;
+ pre1->next = nxt2;
+ pre2->next = nxt1;
+
+ newnode = connectFace(newnode, st, len, dir, pre1, pre2);
+
+ if (isEqual(pre1, pre1->next)) {
+ if (pre1 == pre1->next) {
+ delete pre1;
+ pre1 = NULL;
+ }
+ else {
+ PathElement *temp = pre1->next;
+ pre1->next = temp->next;
+ delete temp;
+ }
+ }
+ if (isEqual(pre2, pre2->next)) {
+ if (pre2 == pre2->next) {
+ delete pre2;
+ pre2 = NULL;
+ }
+ else {
+ PathElement *temp = pre2->next;
+ pre2->next = temp->next;
+ delete temp;
+ }
+ }
+
+ compressRing(pre1);
+ compressRing(pre2);
+
+ // Recur
+ newnode = patchSplitSingle(newnode, st, len, pre1, dir, nrings1, nrings2);
+ newnode = patchSplitSingle(newnode, st, len, pre2, dir, nrings1, nrings2);
+ }
#ifdef IN_DEBUG_MODE
- dc_printf("Return from PATCHSPLITSINGLE with \n");
- dc_printf("Rings gourp 1:\n");
- printPaths(nrings1);
- dc_printf("Rings group 2:\n");
- printPaths(nrings2);
+ dc_printf("Return from PATCHSPLITSINGLE with \n");
+ dc_printf("Rings gourp 1:\n");
+ printPaths(nrings1);
+ dc_printf("Rings group 2:\n");
+ printPaths(nrings2);
#endif
- return newnode;
+ return newnode;
}
-Node *Octree::connectFace(Node *newnode, int st[3], int len, int dir,
- PathElement *f1, PathElement *f2)
+Node *Octree::connectFace(
+ Node *newnode, int st[3], int len, int dir, PathElement *f1, PathElement *f2)
{
#ifdef IN_DEBUG_MODE
- dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len);
- dc_printf("Path(low side): \n");
- printPath(f1);
-// checkPath(f1);
- dc_printf("Path(high side): \n");
- printPath(f2);
-// checkPath(f2);
+ dc_printf("Call to CONNECTFACE with direction %d and length %d path: \n", dir, len);
+ dc_printf("Path(low side): \n");
+ printPath(f1);
+ // checkPath(f1);
+ dc_printf("Path(high side): \n");
+ printPath(f2);
+// checkPath(f2);
#endif
- // Setup 2D
- int pos = st[dir] + len / 2;
- int xdir = (dir + 1) % 3;
- int ydir = (dir + 2) % 3;
-
- // Use existing intersections on f1 and f2
- int x1, y1, x2, y2;
- float p1, q1, p2, q2;
-
- getFacePoint(f2->next, dir, x1, y1, p1, q1);
- getFacePoint(f2, dir, x2, y2, p2, q2);
-
- float dx = x2 + p2 - x1 - p1;
- float dy = y2 + q2 - y1 - q1;
-
- // Do adapted Bresenham line drawing
- float rx = p1, ry = q1;
- int incx = 1, incy = 1;
- int lx = x1, ly = y1;
- int hx = x2, hy = y2;
- int choice;
- if (x2 < x1) {
- incx = -1;
- rx = 1 - rx;
- lx = x2;
- hx = x1;
- }
- if (y2 < y1) {
- incy = -1;
- ry = 1 - ry;
- ly = y2;
- hy = y1;
- }
-
- float sx = dx * incx;
- float sy = dy * incy;
-
- int ori[3];
- ori[dir] = pos / mindimen;
- ori[xdir] = x1;
- ori[ydir] = y1;
- int walkdir;
- int inc;
- float alpha;
-
- PathElement *curEleN = f1;
- PathElement *curEleP = f2->next;
- Node *nodeN = NULL, *nodeP = NULL;
- LeafNode *curN = locateLeaf(&newnode->internal, len, f1->pos);
- LeafNode *curP = locateLeaf(&newnode->internal, len, f2->next->pos);
- if (curN == NULL || curP == NULL) {
- exit(0);
- }
- int stN[3], stP[3];
- int lenN, lenP;
-
- /* Unused code, leaving for posterity
-
- float stpt[3], edpt[3];
- stpt[dir] = edpt[dir] =(float) pos;
- stpt[xdir] =(x1 + p1) * mindimen;
- stpt[ydir] =(y1 + q1) * mindimen;
- edpt[xdir] =(x2 + p2) * mindimen;
- edpt[ydir] =(y2 + q2) * mindimen;
- */
- while (ori[xdir] != x2 || ori[ydir] != y2) {
- int next;
- if (sy * (1 - rx) > sx * (1 - ry)) {
- choice = 1;
- next = ori[ydir] + incy;
- if (next < ly || next > hy) {
- choice = 4;
- next = ori[xdir] + incx;
- }
- }
- else {
- choice = 2;
- next = ori[xdir] + incx;
- if (next < lx || next > hx) {
- choice = 3;
- next = ori[ydir] + incy;
- }
- }
-
- if (choice & 1) {
- ori[ydir] = next;
- if (choice == 1) {
- rx += (sy == 0 ? 0 : (1 - ry) * sx / sy);
- ry = 0;
- }
-
- walkdir = 2;
- inc = incy;
- alpha = x2 < x1 ? 1 - rx : rx;
- }
- else {
- ori[xdir] = next;
- if (choice == 2) {
- ry += (sx == 0 ? 0 : (1 - rx) * sy / sx);
- rx = 0;
- }
-
- walkdir = 1;
- inc = incx;
- alpha = y2 < y1 ? 1 - ry : ry;
- }
-
-
-
- // Get the exact location of the marcher
- int nori[3] = {ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen};
- float spt[3] = {(float) nori[0], (float) nori[1], (float) nori[2]};
- spt[(dir + (3 - walkdir)) % 3] += alpha * mindimen;
- if (inc < 0) {
- spt[(dir + walkdir) % 3] += mindimen;
- }
-
- // dc_printf("new x,y: %d %d\n", ori[xdir] / edgelen, ori[ydir] / edgelen);
- // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir);
- // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2]);
-
- // Locate the current cells on both sides
- newnode = locateCell(&newnode->internal, st, len, nori, dir, 1, nodeN, stN, lenN);
- newnode = locateCell(&newnode->internal, st, len, nori, dir, 0, nodeP, stP, lenP);
-
- updateParent(&newnode->internal, len, st);
-
- int flag = 0;
- // Add the cells to the rings and fill in the patch
- PathElement *newEleN;
- if (curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2]) {
- if (curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] || curEleN->next->pos[2] != stN[2]) {
- newEleN = new PathElement;
- newEleN->next = curEleN->next;
- newEleN->pos[0] = stN[0];
- newEleN->pos[1] = stN[1];
- newEleN->pos[2] = stN[2];
-
- curEleN->next = newEleN;
- }
- else {
- newEleN = curEleN->next;
- }
- curN = patchAdjacent(&newnode->internal, len, curEleN->pos, curN,
- newEleN->pos, (LeafNode *)nodeN, walkdir,
- inc, dir, 1, alpha);
-
- curEleN = newEleN;
- flag++;
- }
-
- PathElement *newEleP;
- if (curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2]) {
- if (f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2]) {
- newEleP = new PathElement;
- newEleP->next = curEleP;
- newEleP->pos[0] = stP[0];
- newEleP->pos[1] = stP[1];
- newEleP->pos[2] = stP[2];
-
- f2->next = newEleP;
- }
- else {
- newEleP = f2;
- }
- curP = patchAdjacent(&newnode->internal, len, curEleP->pos, curP,
- newEleP->pos, (LeafNode *)nodeP, walkdir,
- inc, dir, 0, alpha);
-
-
-
- curEleP = newEleP;
- flag++;
- }
-
-
- /*
- if(flag == 0) {
- dc_printf("error: non-synchronized patching! at \n");
- }
- */
- }
+ // Setup 2D
+ int pos = st[dir] + len / 2;
+ int xdir = (dir + 1) % 3;
+ int ydir = (dir + 2) % 3;
+
+ // Use existing intersections on f1 and f2
+ int x1, y1, x2, y2;
+ float p1, q1, p2, q2;
+
+ getFacePoint(f2->next, dir, x1, y1, p1, q1);
+ getFacePoint(f2, dir, x2, y2, p2, q2);
+
+ float dx = x2 + p2 - x1 - p1;
+ float dy = y2 + q2 - y1 - q1;
+
+ // Do adapted Bresenham line drawing
+ float rx = p1, ry = q1;
+ int incx = 1, incy = 1;
+ int lx = x1, ly = y1;
+ int hx = x2, hy = y2;
+ int choice;
+ if (x2 < x1) {
+ incx = -1;
+ rx = 1 - rx;
+ lx = x2;
+ hx = x1;
+ }
+ if (y2 < y1) {
+ incy = -1;
+ ry = 1 - ry;
+ ly = y2;
+ hy = y1;
+ }
+
+ float sx = dx * incx;
+ float sy = dy * incy;
+
+ int ori[3];
+ ori[dir] = pos / mindimen;
+ ori[xdir] = x1;
+ ori[ydir] = y1;
+ int walkdir;
+ int inc;
+ float alpha;
+
+ PathElement *curEleN = f1;
+ PathElement *curEleP = f2->next;
+ Node *nodeN = NULL, *nodeP = NULL;
+ LeafNode *curN = locateLeaf(&newnode->internal, len, f1->pos);
+ LeafNode *curP = locateLeaf(&newnode->internal, len, f2->next->pos);
+ if (curN == NULL || curP == NULL) {
+ exit(0);
+ }
+ int stN[3], stP[3];
+ int lenN, lenP;
+
+ /* Unused code, leaving for posterity
+
+ float stpt[3], edpt[3];
+ stpt[dir] = edpt[dir] =(float) pos;
+ stpt[xdir] =(x1 + p1) * mindimen;
+ stpt[ydir] =(y1 + q1) * mindimen;
+ edpt[xdir] =(x2 + p2) * mindimen;
+ edpt[ydir] =(y2 + q2) * mindimen;
+ */
+ while (ori[xdir] != x2 || ori[ydir] != y2) {
+ int next;
+ if (sy * (1 - rx) > sx * (1 - ry)) {
+ choice = 1;
+ next = ori[ydir] + incy;
+ if (next < ly || next > hy) {
+ choice = 4;
+ next = ori[xdir] + incx;
+ }
+ }
+ else {
+ choice = 2;
+ next = ori[xdir] + incx;
+ if (next < lx || next > hx) {
+ choice = 3;
+ next = ori[ydir] + incy;
+ }
+ }
+
+ if (choice & 1) {
+ ori[ydir] = next;
+ if (choice == 1) {
+ rx += (sy == 0 ? 0 : (1 - ry) * sx / sy);
+ ry = 0;
+ }
+
+ walkdir = 2;
+ inc = incy;
+ alpha = x2 < x1 ? 1 - rx : rx;
+ }
+ else {
+ ori[xdir] = next;
+ if (choice == 2) {
+ ry += (sx == 0 ? 0 : (1 - rx) * sy / sx);
+ rx = 0;
+ }
+
+ walkdir = 1;
+ inc = incx;
+ alpha = y2 < y1 ? 1 - ry : ry;
+ }
+
+ // Get the exact location of the marcher
+ int nori[3] = {ori[0] * mindimen, ori[1] * mindimen, ori[2] * mindimen};
+ float spt[3] = {(float)nori[0], (float)nori[1], (float)nori[2]};
+ spt[(dir + (3 - walkdir)) % 3] += alpha * mindimen;
+ if (inc < 0) {
+ spt[(dir + walkdir) % 3] += mindimen;
+ }
+
+ // dc_printf("new x,y: %d %d\n", ori[xdir] / edgelen, ori[ydir] / edgelen);
+ // dc_printf("nori: %d %d %d alpha: %f walkdir: %d\n", nori[0], nori[1], nori[2], alpha, walkdir);
+ // dc_printf("%f %f %f\n", spt[0], spt[1], spt[2]);
+
+ // Locate the current cells on both sides
+ newnode = locateCell(&newnode->internal, st, len, nori, dir, 1, nodeN, stN, lenN);
+ newnode = locateCell(&newnode->internal, st, len, nori, dir, 0, nodeP, stP, lenP);
+
+ updateParent(&newnode->internal, len, st);
+
+ int flag = 0;
+ // Add the cells to the rings and fill in the patch
+ PathElement *newEleN;
+ if (curEleN->pos[0] != stN[0] || curEleN->pos[1] != stN[1] || curEleN->pos[2] != stN[2]) {
+ if (curEleN->next->pos[0] != stN[0] || curEleN->next->pos[1] != stN[1] ||
+ curEleN->next->pos[2] != stN[2]) {
+ newEleN = new PathElement;
+ newEleN->next = curEleN->next;
+ newEleN->pos[0] = stN[0];
+ newEleN->pos[1] = stN[1];
+ newEleN->pos[2] = stN[2];
+
+ curEleN->next = newEleN;
+ }
+ else {
+ newEleN = curEleN->next;
+ }
+ curN = patchAdjacent(&newnode->internal,
+ len,
+ curEleN->pos,
+ curN,
+ newEleN->pos,
+ (LeafNode *)nodeN,
+ walkdir,
+ inc,
+ dir,
+ 1,
+ alpha);
+
+ curEleN = newEleN;
+ flag++;
+ }
+
+ PathElement *newEleP;
+ if (curEleP->pos[0] != stP[0] || curEleP->pos[1] != stP[1] || curEleP->pos[2] != stP[2]) {
+ if (f2->pos[0] != stP[0] || f2->pos[1] != stP[1] || f2->pos[2] != stP[2]) {
+ newEleP = new PathElement;
+ newEleP->next = curEleP;
+ newEleP->pos[0] = stP[0];
+ newEleP->pos[1] = stP[1];
+ newEleP->pos[2] = stP[2];
+
+ f2->next = newEleP;
+ }
+ else {
+ newEleP = f2;
+ }
+ curP = patchAdjacent(&newnode->internal,
+ len,
+ curEleP->pos,
+ curP,
+ newEleP->pos,
+ (LeafNode *)nodeP,
+ walkdir,
+ inc,
+ dir,
+ 0,
+ alpha);
+
+ curEleP = newEleP;
+ flag++;
+ }
+
+ /*
+ if(flag == 0) {
+ dc_printf("error: non-synchronized patching! at \n");
+ }
+ */
+ }
#ifdef IN_DEBUG_MODE
- dc_printf("Return from CONNECTFACE with \n");
- dc_printf("Path(low side):\n");
- printPath(f1);
- checkPath(f1);
- dc_printf("Path(high side):\n");
- printPath(f2);
- checkPath(f2);
+ dc_printf("Return from CONNECTFACE with \n");
+ dc_printf("Path(low side):\n");
+ printPath(f1);
+ checkPath(f1);
+ dc_printf("Path(high side):\n");
+ printPath(f2);
+ checkPath(f2);
#endif
-
- return newnode;
+ return newnode;
}
-LeafNode *Octree::patchAdjacent(InternalNode *node, int len, int st1[3],
- LeafNode *leaf1, int st2[3], LeafNode *leaf2,
- int walkdir, int inc, int dir, int side,
+LeafNode *Octree::patchAdjacent(InternalNode *node,
+ int len,
+ int st1[3],
+ LeafNode *leaf1,
+ int st2[3],
+ LeafNode *leaf2,
+ int walkdir,
+ int inc,
+ int dir,
+ int side,
float alpha)
{
#ifdef IN_DEBUG_MODE
- dc_printf("Before patching.\n");
- printInfo(st1);
- printInfo(st2);
- dc_printf("-----------------%d %d %d; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2]);
+ dc_printf("Before patching.\n");
+ printInfo(st1);
+ printInfo(st2);
+ dc_printf(
+ "-----------------%d %d %d; %d %d %d\n", st1[0], st2[1], st1[2], st2[0], st2[1], st2[2]);
#endif
- // Get edge index on each leaf
- int edgedir = (dir + (3 - walkdir)) % 3;
- int incdir = (dir + walkdir) % 3;
- int ind1 = (edgedir == 1 ? (dir + 3 - edgedir) % 3 - 1 : 2 - (dir + 3 - edgedir) % 3);
- int ind2 = (edgedir == 1 ? (incdir + 3 - edgedir) % 3 - 1 : 2 - (incdir + 3 - edgedir) % 3);
+ // Get edge index on each leaf
+ int edgedir = (dir + (3 - walkdir)) % 3;
+ int incdir = (dir + walkdir) % 3;
+ int ind1 = (edgedir == 1 ? (dir + 3 - edgedir) % 3 - 1 : 2 - (dir + 3 - edgedir) % 3);
+ int ind2 = (edgedir == 1 ? (incdir + 3 - edgedir) % 3 - 1 : 2 - (incdir + 3 - edgedir) % 3);
- int eind1 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 1 : 0) << ind2));
- int eind2 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 0 : 1) << ind2));
+ int eind1 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 1 : 0) << ind2));
+ int eind2 = ((edgedir << 2) | (side << ind1) | ((inc > 0 ? 0 : 1) << ind2));
#ifdef IN_DEBUG_MODE
- dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
- /*
- if(alpha < 0 || alpha > 1) {
- dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
- printInfo(st1);
- printInfo(st2);
- }
- */
+ dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
+ /*
+ if(alpha < 0 || alpha > 1) {
+ dc_printf("Index 1: %d Alpha 1: %f Index 2: %d Alpha 2: %f\n", eind1, alpha, eind2, alpha);
+ printInfo(st1);
+ printInfo(st2);
+ }
+ */
#endif
- // Flip edge parity
- LeafNode *nleaf1 = flipEdge(leaf1, eind1, alpha);
- LeafNode *nleaf2 = flipEdge(leaf2, eind2, alpha);
-
- // Update parent link
- updateParent(node, len, st1, nleaf1);
- updateParent(node, len, st2, nleaf2);
- // updateParent(nleaf1, mindimen, st1);
- // updateParent(nleaf2, mindimen, st2);
-
- /*
- float m[3];
- dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2]);
- getMinimizer(leaf1, m);
- dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2]);
- getMinimizer(leaf2, m);
- dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2]);
- */
+ // Flip edge parity
+ LeafNode *nleaf1 = flipEdge(leaf1, eind1, alpha);
+ LeafNode *nleaf2 = flipEdge(leaf2, eind2, alpha);
+
+ // Update parent link
+ updateParent(node, len, st1, nleaf1);
+ updateParent(node, len, st2, nleaf2);
+ // updateParent(nleaf1, mindimen, st1);
+ // updateParent(nleaf2, mindimen, st2);
+
+ /*
+ float m[3];
+ dc_printf("Adding new point: %f %f %f\n", spt[0], spt[1], spt[2]);
+ getMinimizer(leaf1, m);
+ dc_printf("Cell %d now has minimizer %f %f %f\n", leaf1, m[0], m[1], m[2]);
+ getMinimizer(leaf2, m);
+ dc_printf("Cell %d now has minimizer %f %f %f\n", leaf2, m[0], m[1], m[2]);
+ */
#ifdef IN_DEBUG_MODE
- dc_printf("After patching.\n");
- printInfo(st1);
- printInfo(st2);
+ dc_printf("After patching.\n");
+ printInfo(st1);
+ printInfo(st2);
#endif
- return nleaf2;
+ return nleaf2;
}
-Node *Octree::locateCell(InternalNode *node, int st[3], int len, int ori[3], int dir, int side, Node *& rleaf, int rst[3], int& rlen)
+Node *Octree::locateCell(InternalNode *node,
+ int st[3],
+ int len,
+ int ori[3],
+ int dir,
+ int side,
+ Node *&rleaf,
+ int rst[3],
+ int &rlen)
{
#ifdef IN_DEBUG_MODE
- // dc_printf("Call to LOCATECELL with node ");
- // printNode(node);
+ // dc_printf("Call to LOCATECELL with node ");
+ // printNode(node);
#endif
- int i;
- len >>= 1;
- int ind = 0;
- for (i = 0; i < 3; i++) {
- ind <<= 1;
- if (i == dir && side == 1) {
- ind |= (ori[i] <= (st[i] + len) ? 0 : 1);
- }
- else {
- ind |= (ori[i] < (st[i] + len) ? 0 : 1);
- }
- }
+ int i;
+ len >>= 1;
+ int ind = 0;
+ for (i = 0; i < 3; i++) {
+ ind <<= 1;
+ if (i == dir && side == 1) {
+ ind |= (ori[i] <= (st[i] + len) ? 0 : 1);
+ }
+ else {
+ ind |= (ori[i] < (st[i] + len) ? 0 : 1);
+ }
+ }
#ifdef IN_DEBUG_MODE
- // dc_printf("In LOCATECELL index of ori(%d %d %d) with dir %d side %d in st(%d %d %d, %d) is: %d\n",
- // ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind);
+ // dc_printf("In LOCATECELL index of ori(%d %d %d) with dir %d side %d in st(%d %d %d, %d) is: %d\n",
+ // ori[0], ori[1], ori[2], dir, side, st[0], st[1], st[2], len, ind);
#endif
- rst[0] = st[0] + vertmap[ind][0] * len;
- rst[1] = st[1] + vertmap[ind][1] * len;
- rst[2] = st[2] + vertmap[ind][2] * len;
-
- if (node->has_child(ind)) {
- int count = node->get_child_count(ind);
- Node *chd = node->get_child(count);
- if (node->is_child_leaf(ind)) {
- rleaf = chd;
- rlen = len;
- }
- else {
- // Recur
- node->set_child(count, locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen));
- }
- }
- else {
- // Create a new child here
- if (len == mindimen) {
- LeafNode *chd = createLeaf(0);
- node = addChild(node, ind, (Node *)chd, 1);
- rleaf = (Node *)chd;
- rlen = len;
- }
- else {
- // Subdivide the empty cube
- InternalNode *chd = createInternal(0);
- node = addChild(node, ind,
- locateCell(chd, rst, len, ori, dir, side, rleaf, rst, rlen), 0);
- }
- }
+ rst[0] = st[0] + vertmap[ind][0] * len;
+ rst[1] = st[1] + vertmap[ind][1] * len;
+ rst[2] = st[2] + vertmap[ind][2] * len;
+
+ if (node->has_child(ind)) {
+ int count = node->get_child_count(ind);
+ Node *chd = node->get_child(count);
+ if (node->is_child_leaf(ind)) {
+ rleaf = chd;
+ rlen = len;
+ }
+ else {
+ // Recur
+ node->set_child(count,
+ locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen));
+ }
+ }
+ else {
+ // Create a new child here
+ if (len == mindimen) {
+ LeafNode *chd = createLeaf(0);
+ node = addChild(node, ind, (Node *)chd, 1);
+ rleaf = (Node *)chd;
+ rlen = len;
+ }
+ else {
+ // Subdivide the empty cube
+ InternalNode *chd = createInternal(0);
+ node = addChild(node, ind, locateCell(chd, rst, len, ori, dir, side, rleaf, rst, rlen), 0);
+ }
+ }
#ifdef IN_DEBUG_MODE
- // dc_printf("Return from LOCATECELL with node ");
- // printNode(newnode);
+ // dc_printf("Return from LOCATECELL with node ");
+ // printNode(newnode);
#endif
- return (Node *)node;
+ return (Node *)node;
}
void Octree::checkElement(PathElement * /*ele*/)
{
- /*
- if(ele != NULL && locateLeafCheck(ele->pos) != ele->node) {
- dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift);
- exit(0);
- }
- */
+ /*
+ if(ele != NULL && locateLeafCheck(ele->pos) != ele->node) {
+ dc_printf("Screwed! at pos: %d %d %d\n", ele->pos[0]>>minshift, ele->pos[1]>>minshift, ele->pos[2]>>minshift);
+ exit(0);
+ }
+ */
}
void Octree::checkPath(PathElement *path)
{
- PathElement *n = path;
- int same = 0;
- while (n && (same == 0 || n != path)) {
- same++;
- checkElement(n);
- n = n->next;
- }
-
+ PathElement *n = path;
+ int same = 0;
+ while (n && (same == 0 || n != path)) {
+ same++;
+ checkElement(n);
+ n = n->next;
+ }
}
void Octree::testFacePoint(PathElement *e1, PathElement *e2)
{
- int i;
- PathElement *e = NULL;
- for (i = 0; i < 3; i++) {
- if (e1->pos[i] != e2->pos[i]) {
- if (e1->pos[i] < e2->pos[i]) {
- e = e2;
- }
- else {
- e = e1;
- }
- break;
- }
- }
-
- int x, y;
- float p, q;
- dc_printf("Test.");
- getFacePoint(e, i, x, y, p, q);
+ int i;
+ PathElement *e = NULL;
+ for (i = 0; i < 3; i++) {
+ if (e1->pos[i] != e2->pos[i]) {
+ if (e1->pos[i] < e2->pos[i]) {
+ e = e2;
+ }
+ else {
+ e = e1;
+ }
+ break;
+ }
+ }
+
+ int x, y;
+ float p, q;
+ dc_printf("Test.");
+ getFacePoint(e, i, x, y, p, q);
}
-void Octree::getFacePoint(PathElement *leaf, int dir, int& x, int& y, float& p, float& q)
+void Octree::getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p, float &q)
{
- // Find average intersections
- float avg[3] = {0, 0, 0};
- float off[3];
- int num = 0, num2 = 0;
-
- LeafNode *leafnode = locateLeaf(leaf->pos);
- for (int i = 0; i < 4; i++) {
- int edgeind = faceMap[dir * 2][i];
- int nst[3];
- for (int j = 0; j < 3; j++) {
- nst[j] = leaf->pos[j] + mindimen * vertmap[edgemap[edgeind][0]][j];
- }
-
- if (getEdgeIntersectionByIndex(nst, edgeind / 4, off, 1)) {
- avg[0] += off[0];
- avg[1] += off[1];
- avg[2] += off[2];
- num++;
- }
- if (getEdgeParity(leafnode, edgeind)) {
- num2++;
- }
- }
- if (num == 0) {
- dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n", dir, leaf->pos[0] >> minshift, leaf->pos[1] >> minshift, leaf->pos[2] >> minshift, num2);
- avg[0] = (float) leaf->pos[0];
- avg[1] = (float) leaf->pos[1];
- avg[2] = (float) leaf->pos[2];
- }
- else {
-
- avg[0] /= num;
- avg[1] /= num;
- avg[2] /= num;
-
- //avg[0] =(float) leaf->pos[0];
- //avg[1] =(float) leaf->pos[1];
- //avg[2] =(float) leaf->pos[2];
- }
-
- int xdir = (dir + 1) % 3;
- int ydir = (dir + 2) % 3;
-
- float xf = avg[xdir];
- float yf = avg[ydir];
+ // Find average intersections
+ float avg[3] = {0, 0, 0};
+ float off[3];
+ int num = 0, num2 = 0;
+
+ LeafNode *leafnode = locateLeaf(leaf->pos);
+ for (int i = 0; i < 4; i++) {
+ int edgeind = faceMap[dir * 2][i];
+ int nst[3];
+ for (int j = 0; j < 3; j++) {
+ nst[j] = leaf->pos[j] + mindimen * vertmap[edgemap[edgeind][0]][j];
+ }
+
+ if (getEdgeIntersectionByIndex(nst, edgeind / 4, off, 1)) {
+ avg[0] += off[0];
+ avg[1] += off[1];
+ avg[2] += off[2];
+ num++;
+ }
+ if (getEdgeParity(leafnode, edgeind)) {
+ num2++;
+ }
+ }
+ if (num == 0) {
+ dc_printf("Wrong! dir: %d pos: %d %d %d num: %d\n",
+ dir,
+ leaf->pos[0] >> minshift,
+ leaf->pos[1] >> minshift,
+ leaf->pos[2] >> minshift,
+ num2);
+ avg[0] = (float)leaf->pos[0];
+ avg[1] = (float)leaf->pos[1];
+ avg[2] = (float)leaf->pos[2];
+ }
+ else {
+
+ avg[0] /= num;
+ avg[1] /= num;
+ avg[2] /= num;
+
+ //avg[0] =(float) leaf->pos[0];
+ //avg[1] =(float) leaf->pos[1];
+ //avg[2] =(float) leaf->pos[2];
+ }
+
+ int xdir = (dir + 1) % 3;
+ int ydir = (dir + 2) % 3;
+
+ float xf = avg[xdir];
+ float yf = avg[ydir];
#ifdef IN_DEBUG_MODE
- // Is it outside?
- // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2;
- /*
- float* m =(leaf == leaf1 ? m1 : m2);
- if(xf < leaf->pos[xdir] ||
- yf < leaf->pos[ydir] ||
- xf > leaf->pos[xdir] + leaf->len ||
- yf > leaf->pos[ydir] + leaf->len) {
- dc_printf("Outside cube(%d %d %d), %d : %d %d %f %f\n", leaf->pos[0], leaf->pos[1], leaf->pos[2], leaf->len,
- pos, dir, xf, yf);
-
- // For now, snap to cell
- xf = m[xdir];
- yf = m[ydir];
- }
- */
-
- /*
- if(alpha < 0 || alpha > 1 ||
- xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len ||
- yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len) {
- dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node);
- dc_printf("GETFACEPOINT result:(%d %d %d) %d min:(%f %f %f);(%d %d %d) %d min:(%f %f %f).\n",
- leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2],
- leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]);
- dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf);
- }
- */
+ // Is it outside?
+ // PathElement* leaf = leaf1->len < leaf2->len ? leaf1 : leaf2;
+ /*
+ float* m =(leaf == leaf1 ? m1 : m2);
+ if(xf < leaf->pos[xdir] ||
+ yf < leaf->pos[ydir] ||
+ xf > leaf->pos[xdir] + leaf->len ||
+ yf > leaf->pos[ydir] + leaf->len) {
+ dc_printf("Outside cube(%d %d %d), %d : %d %d %f %f\n", leaf->pos[0], leaf->pos[1], leaf->pos[2], leaf->len,
+ pos, dir, xf, yf);
+
+ // For now, snap to cell
+ xf = m[xdir];
+ yf = m[ydir];
+ }
+ */
+
+ /*
+ if(alpha < 0 || alpha > 1 ||
+ xf < leaf->pos[xdir] || xf > leaf->pos[xdir] + leaf->len ||
+ yf < leaf->pos[ydir] || yf > leaf->pos[ydir] + leaf->len) {
+ dc_printf("Alpha: %f Address: %d and %d\n", alpha, leaf1->node, leaf2->node);
+ dc_printf("GETFACEPOINT result:(%d %d %d) %d min:(%f %f %f);(%d %d %d) %d min:(%f %f %f).\n",
+ leaf1->pos[0], leaf1->pos[1], leaf1->pos[2], leaf1->len, m1[0], m1[1], m1[2],
+ leaf2->pos[0], leaf2->pos[1], leaf2->pos[2], leaf2->len, m2[0], m2[1], m2[2]);
+ dc_printf("Face point at dir %d pos %d: %f %f\n", dir, pos, xf, yf);
+ }
+ */
#endif
+ // Get the integer and float part
+ x = ((leaf->pos[xdir]) >> minshift);
+ y = ((leaf->pos[ydir]) >> minshift);
- // Get the integer and float part
- x = ((leaf->pos[xdir]) >> minshift);
- y = ((leaf->pos[ydir]) >> minshift);
-
- p = (xf - leaf->pos[xdir]) / mindimen;
- q = (yf - leaf->pos[ydir]) / mindimen;
-
+ p = (xf - leaf->pos[xdir]) / mindimen;
+ q = (yf - leaf->pos[ydir]) / mindimen;
#ifdef IN_DEBUG_MODE
- dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf);
+ dc_printf("Face point at dir %d : %f %f\n", dir, xf, yf);
#endif
}
-int Octree::findPair(PathElement *head, int pos, int dir, PathElement *& pre1, PathElement *& pre2)
+int Octree::findPair(PathElement *head, int pos, int dir, PathElement *&pre1, PathElement *&pre2)
{
- int side = getSide(head, pos, dir);
- PathElement *cur = head;
- PathElement *anchor;
- PathElement *ppre1, *ppre2;
-
- // Start from this face, find a pair
- anchor = cur;
- ppre1 = cur;
- cur = cur->next;
- while (cur != anchor && (getSide(cur, pos, dir) == side)) {
- ppre1 = cur;
- cur = cur->next;
- }
- if (cur == anchor) {
- // No pair found
- return side;
- }
-
- side = getSide(cur, pos, dir);
- ppre2 = cur;
- cur = cur->next;
- while (getSide(cur, pos, dir) == side) {
- ppre2 = cur;
- cur = cur->next;
- }
-
-
- // Switch pre1 and pre2 if we start from the higher side
- if (side == -1) {
- cur = ppre1;
- ppre1 = ppre2;
- ppre2 = cur;
- }
-
- pre1 = ppre1;
- pre2 = ppre2;
-
- return 0;
+ int side = getSide(head, pos, dir);
+ PathElement *cur = head;
+ PathElement *anchor;
+ PathElement *ppre1, *ppre2;
+
+ // Start from this face, find a pair
+ anchor = cur;
+ ppre1 = cur;
+ cur = cur->next;
+ while (cur != anchor && (getSide(cur, pos, dir) == side)) {
+ ppre1 = cur;
+ cur = cur->next;
+ }
+ if (cur == anchor) {
+ // No pair found
+ return side;
+ }
+
+ side = getSide(cur, pos, dir);
+ ppre2 = cur;
+ cur = cur->next;
+ while (getSide(cur, pos, dir) == side) {
+ ppre2 = cur;
+ cur = cur->next;
+ }
+
+ // Switch pre1 and pre2 if we start from the higher side
+ if (side == -1) {
+ cur = ppre1;
+ ppre1 = ppre2;
+ ppre2 = cur;
+ }
+
+ pre1 = ppre1;
+ pre2 = ppre2;
+
+ return 0;
}
int Octree::getSide(PathElement *e, int pos, int dir)
{
- return (e->pos[dir] < pos ? -1 : 1);
+ return (e->pos[dir] < pos ? -1 : 1);
}
int Octree::isEqual(PathElement *e1, PathElement *e2)
{
- return (e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2]);
+ return (e1->pos[0] == e2->pos[0] && e1->pos[1] == e2->pos[1] && e1->pos[2] == e2->pos[2]);
}
-void Octree::compressRing(PathElement *& ring)
+void Octree::compressRing(PathElement *&ring)
{
- if (ring == NULL) {
- return;
- }
+ if (ring == NULL) {
+ return;
+ }
#ifdef IN_DEBUG_MODE
- dc_printf("Call to COMPRESSRING with path: \n");
- printPath(ring);
+ dc_printf("Call to COMPRESSRING with path: \n");
+ printPath(ring);
#endif
- PathElement *cur = ring->next->next;
- PathElement *pre = ring->next;
- PathElement *prepre = ring;
- PathElement *anchor = prepre;
-
- do {
- while (isEqual(cur, prepre)) {
- // Delete
- if (cur == prepre) {
- // The ring has shrinked to a point
- delete pre;
- delete cur;
- anchor = NULL;
- break;
- }
- else {
- prepre->next = cur->next;
- delete pre;
- delete cur;
- pre = prepre->next;
- cur = pre->next;
- anchor = prepre;
- }
- }
-
- if (anchor == NULL) {
- break;
- }
-
- prepre = pre;
- pre = cur;
- cur = cur->next;
- } while (prepre != anchor);
-
- ring = anchor;
+ PathElement *cur = ring->next->next;
+ PathElement *pre = ring->next;
+ PathElement *prepre = ring;
+ PathElement *anchor = prepre;
+
+ do {
+ while (isEqual(cur, prepre)) {
+ // Delete
+ if (cur == prepre) {
+ // The ring has shrinked to a point
+ delete pre;
+ delete cur;
+ anchor = NULL;
+ break;
+ }
+ else {
+ prepre->next = cur->next;
+ delete pre;
+ delete cur;
+ pre = prepre->next;
+ cur = pre->next;
+ anchor = prepre;
+ }
+ }
+
+ if (anchor == NULL) {
+ break;
+ }
+
+ prepre = pre;
+ pre = cur;
+ cur = cur->next;
+ } while (prepre != anchor);
+
+ ring = anchor;
#ifdef IN_DEBUG_MODE
- dc_printf("Return from COMPRESSRING with path: \n");
- printPath(ring);
+ dc_printf("Return from COMPRESSRING with path: \n");
+ printPath(ring);
#endif
}
void Octree::buildSigns()
{
- // First build a lookup table
- // dc_printf("Building up look up table...\n");
- int size = 1 << 12;
- unsigned char table[1 << 12];
- for (int i = 0; i < size; i++) {
- table[i] = 0;
- }
- for (int i = 0; i < 256; i++) {
- int ind = 0;
- for (int j = 11; j >= 0; j--) {
- ind <<= 1;
- if (((i >> edgemap[j][0]) & 1) ^ ((i >> edgemap[j][1]) & 1)) {
- ind |= 1;
- }
- }
-
- table[ind] = i;
- }
-
- // Next, traverse the grid
- int sg = 1;
- int cube[8];
- buildSigns(table, root, 0, sg, cube);
+ // First build a lookup table
+ // dc_printf("Building up look up table...\n");
+ int size = 1 << 12;
+ unsigned char table[1 << 12];
+ for (int i = 0; i < size; i++) {
+ table[i] = 0;
+ }
+ for (int i = 0; i < 256; i++) {
+ int ind = 0;
+ for (int j = 11; j >= 0; j--) {
+ ind <<= 1;
+ if (((i >> edgemap[j][0]) & 1) ^ ((i >> edgemap[j][1]) & 1)) {
+ ind |= 1;
+ }
+ }
+
+ table[ind] = i;
+ }
+
+ // Next, traverse the grid
+ int sg = 1;
+ int cube[8];
+ buildSigns(table, root, 0, sg, cube);
}
void Octree::buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, int rvalue[8])
{
- if (node == NULL) {
- for (int i = 0; i < 8; i++) {
- rvalue[i] = sg;
- }
- return;
- }
-
- if (isLeaf == 0) {
- // Internal node
- Node *chd[8];
- int leaf[8];
- node->internal.fill_children(chd, leaf);
-
- // Get the signs at the corners of the first cube
- rvalue[0] = sg;
- int oris[8];
- buildSigns(table, chd[0], leaf[0], sg, oris);
-
- // Get the rest
- int cube[8];
- for (int i = 1; i < 8; i++) {
- buildSigns(table, chd[i], leaf[i], oris[i], cube);
- rvalue[i] = cube[i];
- }
-
- }
- else {
- // Leaf node
- generateSigns(&node->leaf, table, sg);
-
- for (int i = 0; i < 8; i++) {
- rvalue[i] = getSign(&node->leaf, i);
- }
- }
+ if (node == NULL) {
+ for (int i = 0; i < 8; i++) {
+ rvalue[i] = sg;
+ }
+ return;
+ }
+
+ if (isLeaf == 0) {
+ // Internal node
+ Node *chd[8];
+ int leaf[8];
+ node->internal.fill_children(chd, leaf);
+
+ // Get the signs at the corners of the first cube
+ rvalue[0] = sg;
+ int oris[8];
+ buildSigns(table, chd[0], leaf[0], sg, oris);
+
+ // Get the rest
+ int cube[8];
+ for (int i = 1; i < 8; i++) {
+ buildSigns(table, chd[i], leaf[i], oris[i], cube);
+ rvalue[i] = cube[i];
+ }
+ }
+ else {
+ // Leaf node
+ generateSigns(&node->leaf, table, sg);
+
+ for (int i = 0; i < 8; i++) {
+ rvalue[i] = getSign(&node->leaf, i);
+ }
+ }
}
void Octree::floodFill()
{
- // int threshold =(int)((dimen/mindimen) *(dimen/mindimen) * 0.5f);
- int st[3] = {0, 0, 0};
-
- // First, check for largest component
- // size stored in -threshold
- clearProcessBits(root, maxDepth);
- int threshold = floodFill(root, st, dimen, maxDepth, 0);
-
- // Next remove
- dc_printf("Largest component: %d\n", threshold);
- threshold *= thresh;
- dc_printf("Removing all components smaller than %d\n", threshold);
-
- int st2[3] = {0, 0, 0};
- clearProcessBits(root, maxDepth);
- floodFill(root, st2, dimen, maxDepth, threshold);
-
+ // int threshold =(int)((dimen/mindimen) *(dimen/mindimen) * 0.5f);
+ int st[3] = {0, 0, 0};
+
+ // First, check for largest component
+ // size stored in -threshold
+ clearProcessBits(root, maxDepth);
+ int threshold = floodFill(root, st, dimen, maxDepth, 0);
+
+ // Next remove
+ dc_printf("Largest component: %d\n", threshold);
+ threshold *= thresh;
+ dc_printf("Removing all components smaller than %d\n", threshold);
+
+ int st2[3] = {0, 0, 0};
+ clearProcessBits(root, maxDepth);
+ floodFill(root, st2, dimen, maxDepth, threshold);
}
void Octree::clearProcessBits(Node *node, int height)
{
- int i;
-
- if (height == 0) {
- // Leaf cell,
- for (i = 0; i < 12; i++) {
- setOutProcess(&node->leaf, i);
- }
- }
- else {
- // Internal cell, recur
- int count = 0;
- for (i = 0; i < 8; i++) {
- if (node->internal.has_child(i)) {
- clearProcessBits(node->internal.get_child(count), height - 1);
- count++;
- }
- }
- }
+ int i;
+
+ if (height == 0) {
+ // Leaf cell,
+ for (i = 0; i < 12; i++) {
+ setOutProcess(&node->leaf, i);
+ }
+ }
+ else {
+ // Internal cell, recur
+ int count = 0;
+ for (i = 0; i < 8; i++) {
+ if (node->internal.has_child(i)) {
+ clearProcessBits(node->internal.get_child(count), height - 1);
+ count++;
+ }
+ }
+ }
}
int Octree::floodFill(LeafNode *leaf, int st[3], int len, int /*height*/, int threshold)
{
- int i, j;
- int maxtotal = 0;
-
- // Leaf cell,
- int par, inp;
-
- // Test if the leaf has intersection edges
- for (i = 0; i < 12; i++) {
- par = getEdgeParity(leaf, i);
- inp = isInProcess(leaf, i);
-
- if (par == 1 && inp == 0) {
- // Intersection edge, hasn't been processed
- // Let's start filling
- GridQueue *queue = new GridQueue();
- int total = 1;
-
- // Set to in process
- int mst[3];
- mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len;
- mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len;
- mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
- int mdir = i / 4;
- setInProcessAll(mst, mdir);
-
- // Put this edge into queue
- queue->pushQueue(mst, mdir);
-
- // Queue processing
- int nst[3], dir;
- while (queue->popQueue(nst, dir) == 1) {
- // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir);
- // locations
- int stMask[3][3] = {
- {0, 0 - len, 0 - len},
- {0 - len, 0, 0 - len},
- {0 - len, 0 - len, 0}
- };
- int cst[2][3];
- for (j = 0; j < 3; j++) {
- cst[0][j] = nst[j];
- cst[1][j] = nst[j] + stMask[dir][j];
- }
-
- // cells
- LeafNode *cs[2];
- for (j = 0; j < 2; j++) {
- cs[j] = locateLeaf(cst[j]);
- }
-
- // Middle sign
- int s = getSign(cs[0], 0);
-
- // Masks
- int fcCells[4] = {1, 0, 1, 0};
- int fcEdges[3][4][3] = {
- {{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}},
- {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}},
- {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}
- };
-
- // Search for neighboring connected intersection edges
- for (int find = 0; find < 4; find++) {
- int cind = fcCells[find];
- int eind, edge;
- if (s == 0) {
- // Original order
- for (eind = 0; eind < 3; eind++) {
- edge = fcEdges[dir][find][eind];
- if (getEdgeParity(cs[cind], edge) == 1) {
- break;
- }
- }
- }
- else {
- // Inverse order
- for (eind = 2; eind >= 0; eind--) {
- edge = fcEdges[dir][find][eind];
- if (getEdgeParity(cs[cind], edge) == 1) {
- break;
- }
- }
- }
-
- if (eind == 3 || eind == -1) {
- dc_printf("Wrong! this is not a consistent sign. %d\n", eind);
- }
- else {
- int est[3];
- est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len;
- est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len;
- est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len;
- int edir = edge / 4;
-
- if (isInProcess(cs[cind], edge) == 0) {
- setInProcessAll(est, edir);
- queue->pushQueue(est, edir);
- // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir);
- total++;
- }
- }
- }
- }
-
- dc_printf("Size of component: %d ", total);
-
- if (threshold == 0) {
- // Measuring stage
- if (total > maxtotal) {
- maxtotal = total;
- }
- dc_printf(".\n");
- delete queue;
- continue;
- }
-
- if (total >= threshold) {
- dc_printf("Maintained.\n");
- delete queue;
- continue;
- }
- dc_printf("Less then %d, removing...\n", threshold);
-
- // We have to remove this noise
-
- // Flip parity
- // setOutProcessAll(mst, mdir);
- flipParityAll(mst, mdir);
-
- // Put this edge into queue
- queue->pushQueue(mst, mdir);
-
- // Queue processing
- while (queue->popQueue(nst, dir) == 1) {
- // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir);
- // locations
- int stMask[3][3] = {
- {0, 0 - len, 0 - len},
- {0 - len, 0, 0 - len},
- {0 - len, 0 - len, 0}
- };
- int cst[2][3];
- for (j = 0; j < 3; j++) {
- cst[0][j] = nst[j];
- cst[1][j] = nst[j] + stMask[dir][j];
- }
-
- // cells
- LeafNode *cs[2];
- for (j = 0; j < 2; j++)
- cs[j] = locateLeaf(cst[j]);
-
- // Middle sign
- int s = getSign(cs[0], 0);
-
- // Masks
- int fcCells[4] = {1, 0, 1, 0};
- int fcEdges[3][4][3] = {
- {{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}},
- {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}},
- {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}
- };
-
- // Search for neighboring connected intersection edges
- for (int find = 0; find < 4; find++) {
- int cind = fcCells[find];
- int eind, edge;
- if (s == 0) {
- // Original order
- for (eind = 0; eind < 3; eind++) {
- edge = fcEdges[dir][find][eind];
- if (isInProcess(cs[cind], edge) == 1) {
- break;
- }
- }
- }
- else {
- // Inverse order
- for (eind = 2; eind >= 0; eind--) {
- edge = fcEdges[dir][find][eind];
- if (isInProcess(cs[cind], edge) == 1) {
- break;
- }
- }
- }
-
- if (eind == 3 || eind == -1) {
- dc_printf("Wrong! this is not a consistent sign. %d\n", eind);
- }
- else {
- int est[3];
- est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len;
- est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len;
- est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len;
- int edir = edge / 4;
-
- if (getEdgeParity(cs[cind], edge) == 1) {
- flipParityAll(est, edir);
- queue->pushQueue(est, edir);
- // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir);
- total++;
- }
- }
- }
- }
-
- delete queue;
- }
- }
-
- return maxtotal;
+ int i, j;
+ int maxtotal = 0;
+
+ // Leaf cell,
+ int par, inp;
+
+ // Test if the leaf has intersection edges
+ for (i = 0; i < 12; i++) {
+ par = getEdgeParity(leaf, i);
+ inp = isInProcess(leaf, i);
+
+ if (par == 1 && inp == 0) {
+ // Intersection edge, hasn't been processed
+ // Let's start filling
+ GridQueue *queue = new GridQueue();
+ int total = 1;
+
+ // Set to in process
+ int mst[3];
+ mst[0] = st[0] + vertmap[edgemap[i][0]][0] * len;
+ mst[1] = st[1] + vertmap[edgemap[i][0]][1] * len;
+ mst[2] = st[2] + vertmap[edgemap[i][0]][2] * len;
+ int mdir = i / 4;
+ setInProcessAll(mst, mdir);
+
+ // Put this edge into queue
+ queue->pushQueue(mst, mdir);
+
+ // Queue processing
+ int nst[3], dir;
+ while (queue->popQueue(nst, dir) == 1) {
+ // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir);
+ // locations
+ int stMask[3][3] = {{0, 0 - len, 0 - len}, {0 - len, 0, 0 - len}, {0 - len, 0 - len, 0}};
+ int cst[2][3];
+ for (j = 0; j < 3; j++) {
+ cst[0][j] = nst[j];
+ cst[1][j] = nst[j] + stMask[dir][j];
+ }
+
+ // cells
+ LeafNode *cs[2];
+ for (j = 0; j < 2; j++) {
+ cs[j] = locateLeaf(cst[j]);
+ }
+
+ // Middle sign
+ int s = getSign(cs[0], 0);
+
+ // Masks
+ int fcCells[4] = {1, 0, 1, 0};
+ int fcEdges[3][4][3] = {{{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}},
+ {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}},
+ {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}};
+
+ // Search for neighboring connected intersection edges
+ for (int find = 0; find < 4; find++) {
+ int cind = fcCells[find];
+ int eind, edge;
+ if (s == 0) {
+ // Original order
+ for (eind = 0; eind < 3; eind++) {
+ edge = fcEdges[dir][find][eind];
+ if (getEdgeParity(cs[cind], edge) == 1) {
+ break;
+ }
+ }
+ }
+ else {
+ // Inverse order
+ for (eind = 2; eind >= 0; eind--) {
+ edge = fcEdges[dir][find][eind];
+ if (getEdgeParity(cs[cind], edge) == 1) {
+ break;
+ }
+ }
+ }
+
+ if (eind == 3 || eind == -1) {
+ dc_printf("Wrong! this is not a consistent sign. %d\n", eind);
+ }
+ else {
+ int est[3];
+ est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len;
+ est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len;
+ est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len;
+ int edir = edge / 4;
+
+ if (isInProcess(cs[cind], edge) == 0) {
+ setInProcessAll(est, edir);
+ queue->pushQueue(est, edir);
+ // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir);
+ total++;
+ }
+ }
+ }
+ }
+
+ dc_printf("Size of component: %d ", total);
+
+ if (threshold == 0) {
+ // Measuring stage
+ if (total > maxtotal) {
+ maxtotal = total;
+ }
+ dc_printf(".\n");
+ delete queue;
+ continue;
+ }
+
+ if (total >= threshold) {
+ dc_printf("Maintained.\n");
+ delete queue;
+ continue;
+ }
+ dc_printf("Less then %d, removing...\n", threshold);
+
+ // We have to remove this noise
+
+ // Flip parity
+ // setOutProcessAll(mst, mdir);
+ flipParityAll(mst, mdir);
+
+ // Put this edge into queue
+ queue->pushQueue(mst, mdir);
+
+ // Queue processing
+ while (queue->popQueue(nst, dir) == 1) {
+ // dc_printf("nst: %d %d %d, dir: %d\n", nst[0]/mindimen, nst[1]/mindimen, nst[2]/mindimen, dir);
+ // locations
+ int stMask[3][3] = {{0, 0 - len, 0 - len}, {0 - len, 0, 0 - len}, {0 - len, 0 - len, 0}};
+ int cst[2][3];
+ for (j = 0; j < 3; j++) {
+ cst[0][j] = nst[j];
+ cst[1][j] = nst[j] + stMask[dir][j];
+ }
+
+ // cells
+ LeafNode *cs[2];
+ for (j = 0; j < 2; j++)
+ cs[j] = locateLeaf(cst[j]);
+
+ // Middle sign
+ int s = getSign(cs[0], 0);
+
+ // Masks
+ int fcCells[4] = {1, 0, 1, 0};
+ int fcEdges[3][4][3] = {{{9, 2, 11}, {8, 1, 10}, {5, 1, 7}, {4, 2, 6}},
+ {{10, 6, 11}, {8, 5, 9}, {1, 5, 3}, {0, 6, 2}},
+ {{6, 10, 7}, {4, 9, 5}, {2, 9, 3}, {0, 10, 1}}};
+
+ // Search for neighboring connected intersection edges
+ for (int find = 0; find < 4; find++) {
+ int cind = fcCells[find];
+ int eind, edge;
+ if (s == 0) {
+ // Original order
+ for (eind = 0; eind < 3; eind++) {
+ edge = fcEdges[dir][find][eind];
+ if (isInProcess(cs[cind], edge) == 1) {
+ break;
+ }
+ }
+ }
+ else {
+ // Inverse order
+ for (eind = 2; eind >= 0; eind--) {
+ edge = fcEdges[dir][find][eind];
+ if (isInProcess(cs[cind], edge) == 1) {
+ break;
+ }
+ }
+ }
+
+ if (eind == 3 || eind == -1) {
+ dc_printf("Wrong! this is not a consistent sign. %d\n", eind);
+ }
+ else {
+ int est[3];
+ est[0] = cst[cind][0] + vertmap[edgemap[edge][0]][0] * len;
+ est[1] = cst[cind][1] + vertmap[edgemap[edge][0]][1] * len;
+ est[2] = cst[cind][2] + vertmap[edgemap[edge][0]][2] * len;
+ int edir = edge / 4;
+
+ if (getEdgeParity(cs[cind], edge) == 1) {
+ flipParityAll(est, edir);
+ queue->pushQueue(est, edir);
+ // dc_printf("Pushed: est: %d %d %d, edir: %d\n", est[0]/len, est[1]/len, est[2]/len, edir);
+ total++;
+ }
+ }
+ }
+ }
+
+ delete queue;
+ }
+ }
+
+ return maxtotal;
}
int Octree::floodFill(Node *node, int st[3], int len, int height, int threshold)
{
- int i;
- int maxtotal = 0;
-
- if (height == 0) {
- maxtotal = floodFill(&node->leaf, st, len, height, threshold);
- }
- else {
- // Internal cell, recur
- int count = 0;
- len >>= 1;
- for (i = 0; i < 8; i++) {
- if (node->internal.has_child(i)) {
- int nst[3];
- nst[0] = st[0] + vertmap[i][0] * len;
- nst[1] = st[1] + vertmap[i][1] * len;
- nst[2] = st[2] + vertmap[i][2] * len;
-
- int d = floodFill(node->internal.get_child(count), nst, len, height - 1, threshold);
- if (d > maxtotal) {
- maxtotal = d;
- }
- count++;
- }
- }
- }
-
-
- return maxtotal;
-
+ int i;
+ int maxtotal = 0;
+
+ if (height == 0) {
+ maxtotal = floodFill(&node->leaf, st, len, height, threshold);
+ }
+ else {
+ // Internal cell, recur
+ int count = 0;
+ len >>= 1;
+ for (i = 0; i < 8; i++) {
+ if (node->internal.has_child(i)) {
+ int nst[3];
+ nst[0] = st[0] + vertmap[i][0] * len;
+ nst[1] = st[1] + vertmap[i][1] * len;
+ nst[2] = st[2] + vertmap[i][2] * len;
+
+ int d = floodFill(node->internal.get_child(count), nst, len, height - 1, threshold);
+ if (d > maxtotal) {
+ maxtotal = d;
+ }
+ count++;
+ }
+ }
+ }
+
+ return maxtotal;
}
void Octree::writeOut()
{
- int numQuads = 0;
- int numVertices = 0;
- int numEdges = 0;
+ int numQuads = 0;
+ int numVertices = 0;
+ int numEdges = 0;
- countIntersection(root, maxDepth, numQuads, numVertices, numEdges);
+ countIntersection(root, maxDepth, numQuads, numVertices, numEdges);
- dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads);
- output_mesh = alloc_output(numVertices, numQuads);
- int offset = 0;
- int st[3] = {0, 0, 0};
+ dc_printf("Vertices counted: %d Polys counted: %d \n", numVertices, numQuads);
+ output_mesh = alloc_output(numVertices, numQuads);
+ int offset = 0;
+ int st[3] = {0, 0, 0};
- // First, output vertices
- offset = 0;
- actualVerts = 0;
- actualQuads = 0;
+ // First, output vertices
+ offset = 0;
+ actualVerts = 0;
+ actualQuads = 0;
- generateMinimizer(root, st, dimen, maxDepth, offset);
- cellProcContour(root, 0, maxDepth);
- dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads);
+ generateMinimizer(root, st, dimen, maxDepth, offset);
+ cellProcContour(root, 0, maxDepth);
+ dc_printf("Vertices written: %d Quads written: %d \n", offset, actualQuads);
}
-void Octree::countIntersection(Node *node, int height, int& nedge, int& ncell, int& nface)
+void Octree::countIntersection(Node *node, int height, int &nedge, int &ncell, int &nface)
{
- if (height > 0) {
- int total = node->internal.get_num_children();
- for (int i = 0; i < total; i++) {
- countIntersection(node->internal.get_child(i), height - 1, nedge, ncell, nface);
- }
- }
- else {
- nedge += getNumEdges2(&node->leaf);
-
- int smask = getSignMask(&node->leaf);
-
- if (use_manifold) {
- int comps = manifold_table[smask].comps;
- ncell += comps;
- }
- else {
- if (smask > 0 && smask < 255) {
- ncell++;
- }
- }
-
- for (int i = 0; i < 3; i++) {
- if (getFaceEdgeNum(&node->leaf, i * 2)) {
- nface++;
- }
- }
- }
+ if (height > 0) {
+ int total = node->internal.get_num_children();
+ for (int i = 0; i < total; i++) {
+ countIntersection(node->internal.get_child(i), height - 1, nedge, ncell, nface);
+ }
+ }
+ else {
+ nedge += getNumEdges2(&node->leaf);
+
+ int smask = getSignMask(&node->leaf);
+
+ if (use_manifold) {
+ int comps = manifold_table[smask].comps;
+ ncell += comps;
+ }
+ else {
+ if (smask > 0 && smask < 255) {
+ ncell++;
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ if (getFaceEdgeNum(&node->leaf, i * 2)) {
+ nface++;
+ }
+ }
+ }
}
/* from http://eigen.tuxfamily.org/bz/show_bug.cgi?id=257 */
@@ -2099,751 +2121,713 @@ void pseudoInverse(const _Matrix_Type_ &a,
_Matrix_Type_ &result,
double epsilon = std::numeric_limits<typename _Matrix_Type_::Scalar>::epsilon())
{
- Eigen::JacobiSVD< _Matrix_Type_ > svd = a.jacobiSvd(Eigen::ComputeFullU |
- Eigen::ComputeFullV);
-
- typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(),
- a.rows()) *
- svd.singularValues().array().abs().maxCoeff();
-
- result = svd.matrixV() *
- _Matrix_Type_((svd.singularValues().array().abs() >
- tolerance).select(svd.singularValues().
- array().inverse(), 0)).asDiagonal() *
- svd.matrixU().adjoint();
+ Eigen::JacobiSVD<_Matrix_Type_> svd = a.jacobiSvd(Eigen::ComputeFullU | Eigen::ComputeFullV);
+
+ typename _Matrix_Type_::Scalar tolerance = epsilon * std::max(a.cols(), a.rows()) *
+ svd.singularValues().array().abs().maxCoeff();
+
+ result = svd.matrixV() *
+ _Matrix_Type_((svd.singularValues().array().abs() > tolerance)
+ .select(svd.singularValues().array().inverse(), 0))
+ .asDiagonal() *
+ svd.matrixU().adjoint();
}
-static void solve_least_squares(const float halfA[], const float b[],
- const float midpoint[], float rvalue[])
+static void solve_least_squares(const float halfA[],
+ const float b[],
+ const float midpoint[],
+ float rvalue[])
{
- /* calculate pseudo-inverse */
- Eigen::MatrixXf A(3, 3), pinv(3, 3);
- A << halfA[0], halfA[1], halfA[2],
- halfA[1], halfA[3], halfA[4],
- halfA[2], halfA[4], halfA[5];
- pseudoInverse(A, pinv);
-
- Eigen::Vector3f b2(b), mp(midpoint), result;
- b2 = b2 + A * -mp;
- result = pinv * b2 + mp;
-
- for (int i = 0; i < 3; i++)
- rvalue[i] = result(i);
+ /* calculate pseudo-inverse */
+ Eigen::MatrixXf A(3, 3), pinv(3, 3);
+ A << halfA[0], halfA[1], halfA[2], halfA[1], halfA[3], halfA[4], halfA[2], halfA[4], halfA[5];
+ pseudoInverse(A, pinv);
+
+ Eigen::Vector3f b2(b), mp(midpoint), result;
+ b2 = b2 + A * -mp;
+ result = pinv * b2 + mp;
+
+ for (int i = 0; i < 3; i++)
+ rvalue[i] = result(i);
}
static void mass_point(float mp[3], const float pts[12][3], const int parity[12])
{
- int ec = 0;
-
- for (int i = 0; i < 12; i++) {
- if (parity[i]) {
- const float *p = pts[i];
-
- mp[0] += p[0];
- mp[1] += p[1];
- mp[2] += p[2];
-
- ec++;
- }
- }
-
- if (ec == 0) {
- return;
- }
- mp[0] /= ec;
- mp[1] /= ec;
- mp[2] /= ec;
+ int ec = 0;
+
+ for (int i = 0; i < 12; i++) {
+ if (parity[i]) {
+ const float *p = pts[i];
+
+ mp[0] += p[0];
+ mp[1] += p[1];
+ mp[2] += p[2];
+
+ ec++;
+ }
+ }
+
+ if (ec == 0) {
+ return;
+ }
+ mp[0] /= ec;
+ mp[1] /= ec;
+ mp[2] /= ec;
}
-static void minimize(float rvalue[3], float mp[3], const float pts[12][3],
- const float norms[12][3], const int parity[12])
+static void minimize(float rvalue[3],
+ float mp[3],
+ const float pts[12][3],
+ const float norms[12][3],
+ const int parity[12])
{
- float ata[6] = {0, 0, 0, 0, 0, 0};
- float atb[3] = {0, 0, 0};
- int ec = 0;
-
- for (int i = 0; i < 12; i++) {
- // if(getEdgeParity(leaf, i))
- if (parity[i]) {
- const float *norm = norms[i];
- const float *p = pts[i];
-
- // QEF
- ata[0] += (float)(norm[0] * norm[0]);
- ata[1] += (float)(norm[0] * norm[1]);
- ata[2] += (float)(norm[0] * norm[2]);
- ata[3] += (float)(norm[1] * norm[1]);
- ata[4] += (float)(norm[1] * norm[2]);
- ata[5] += (float)(norm[2] * norm[2]);
-
- const float pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2];
-
- atb[0] += (float)(norm[0] * pn);
- atb[1] += (float)(norm[1] * pn);
- atb[2] += (float)(norm[2] * pn);
-
- // Minimizer
- mp[0] += p[0];
- mp[1] += p[1];
- mp[2] += p[2];
-
- ec++;
- }
- }
-
- if (ec == 0) {
- return;
- }
- mp[0] /= ec;
- mp[1] /= ec;
- mp[2] /= ec;
-
- // Solve least squares
- solve_least_squares(ata, atb, mp, rvalue);
+ float ata[6] = {0, 0, 0, 0, 0, 0};
+ float atb[3] = {0, 0, 0};
+ int ec = 0;
+
+ for (int i = 0; i < 12; i++) {
+ // if(getEdgeParity(leaf, i))
+ if (parity[i]) {
+ const float *norm = norms[i];
+ const float *p = pts[i];
+
+ // QEF
+ ata[0] += (float)(norm[0] * norm[0]);
+ ata[1] += (float)(norm[0] * norm[1]);
+ ata[2] += (float)(norm[0] * norm[2]);
+ ata[3] += (float)(norm[1] * norm[1]);
+ ata[4] += (float)(norm[1] * norm[2]);
+ ata[5] += (float)(norm[2] * norm[2]);
+
+ const float pn = p[0] * norm[0] + p[1] * norm[1] + p[2] * norm[2];
+
+ atb[0] += (float)(norm[0] * pn);
+ atb[1] += (float)(norm[1] * pn);
+ atb[2] += (float)(norm[2] * pn);
+
+ // Minimizer
+ mp[0] += p[0];
+ mp[1] += p[1];
+ mp[2] += p[2];
+
+ ec++;
+ }
+ }
+
+ if (ec == 0) {
+ return;
+ }
+ mp[0] /= ec;
+ mp[1] /= ec;
+ mp[2] /= ec;
+
+ // Solve least squares
+ solve_least_squares(ata, atb, mp, rvalue);
}
-void Octree::computeMinimizer(const LeafNode *leaf, int st[3], int len,
- float rvalue[3]) const
+void Octree::computeMinimizer(const LeafNode *leaf, int st[3], int len, float rvalue[3]) const
{
- // First, gather all edge intersections
- float pts[12][3], norms[12][3];
- int parity[12];
- fillEdgeIntersections(leaf, st, len, pts, norms, parity);
-
- switch (mode) {
- case DUALCON_CENTROID:
- rvalue[0] = (float) st[0] + len / 2;
- rvalue[1] = (float) st[1] + len / 2;
- rvalue[2] = (float) st[2] + len / 2;
- break;
-
- case DUALCON_MASS_POINT:
- rvalue[0] = rvalue[1] = rvalue[2] = 0;
- mass_point(rvalue, pts, parity);
- break;
-
- default: {
- // Sharp features */
-
- // construct QEF and minimizer
- float mp[3] = {0, 0, 0};
- minimize(rvalue, mp, pts, norms, parity);
-
- /* Restraining the location of the minimizer */
- float nh1 = hermite_num * len;
- float nh2 = (1 + hermite_num) * len;
-
- if (rvalue[0] < st[0] - nh1 ||
- rvalue[1] < st[1] - nh1 ||
- rvalue[2] < st[2] - nh1 ||
-
- rvalue[0] > st[0] + nh2 ||
- rvalue[1] > st[1] + nh2 ||
- rvalue[2] > st[2] + nh2)
- {
- // Use mass point instead
- rvalue[0] = mp[0];
- rvalue[1] = mp[1];
- rvalue[2] = mp[2];
- }
- break;
- }
- }
+ // First, gather all edge intersections
+ float pts[12][3], norms[12][3];
+ int parity[12];
+ fillEdgeIntersections(leaf, st, len, pts, norms, parity);
+
+ switch (mode) {
+ case DUALCON_CENTROID:
+ rvalue[0] = (float)st[0] + len / 2;
+ rvalue[1] = (float)st[1] + len / 2;
+ rvalue[2] = (float)st[2] + len / 2;
+ break;
+
+ case DUALCON_MASS_POINT:
+ rvalue[0] = rvalue[1] = rvalue[2] = 0;
+ mass_point(rvalue, pts, parity);
+ break;
+
+ default: {
+ // Sharp features */
+
+ // construct QEF and minimizer
+ float mp[3] = {0, 0, 0};
+ minimize(rvalue, mp, pts, norms, parity);
+
+ /* Restraining the location of the minimizer */
+ float nh1 = hermite_num * len;
+ float nh2 = (1 + hermite_num) * len;
+
+ if (rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 ||
+
+ rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2) {
+ // Use mass point instead
+ rvalue[0] = mp[0];
+ rvalue[1] = mp[1];
+ rvalue[2] = mp[2];
+ }
+ break;
+ }
+ }
}
-void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int& offset)
+void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int &offset)
{
- int i, j;
-
- if (height == 0) {
- // Leaf cell, generate
-
- // First, find minimizer
- float rvalue[3];
- rvalue[0] = (float) st[0] + len / 2;
- rvalue[1] = (float) st[1] + len / 2;
- rvalue[2] = (float) st[2] + len / 2;
- computeMinimizer(&node->leaf, st, len, rvalue);
-
- // Update
- //float fnst[3];
- for (j = 0; j < 3; j++) {
- rvalue[j] = rvalue[j] * range / dimen + origin[j];
- //fnst[j] = st[j] * range / dimen + origin[j];
- }
-
- int mult = 0, smask = getSignMask(&node->leaf);
-
- if (use_manifold) {
- mult = manifold_table[smask].comps;
- }
- else {
- if (smask > 0 && smask < 255) {
- mult = 1;
- }
- }
-
- for (j = 0; j < mult; j++) {
- add_vert(output_mesh, rvalue);
- }
-
- // Store the index
- setMinimizerIndex(&node->leaf, offset);
-
- offset += mult;
- }
- else {
- // Internal cell, recur
- int count = 0;
- len >>= 1;
- for (i = 0; i < 8; i++) {
- if (node->internal.has_child(i)) {
- int nst[3];
- nst[0] = st[0] + vertmap[i][0] * len;
- nst[1] = st[1] + vertmap[i][1] * len;
- nst[2] = st[2] + vertmap[i][2] * len;
-
- generateMinimizer(node->internal.get_child(count),
- nst, len, height - 1, offset);
- count++;
- }
- }
- }
+ int i, j;
+
+ if (height == 0) {
+ // Leaf cell, generate
+
+ // First, find minimizer
+ float rvalue[3];
+ rvalue[0] = (float)st[0] + len / 2;
+ rvalue[1] = (float)st[1] + len / 2;
+ rvalue[2] = (float)st[2] + len / 2;
+ computeMinimizer(&node->leaf, st, len, rvalue);
+
+ // Update
+ //float fnst[3];
+ for (j = 0; j < 3; j++) {
+ rvalue[j] = rvalue[j] * range / dimen + origin[j];
+ //fnst[j] = st[j] * range / dimen + origin[j];
+ }
+
+ int mult = 0, smask = getSignMask(&node->leaf);
+
+ if (use_manifold) {
+ mult = manifold_table[smask].comps;
+ }
+ else {
+ if (smask > 0 && smask < 255) {
+ mult = 1;
+ }
+ }
+
+ for (j = 0; j < mult; j++) {
+ add_vert(output_mesh, rvalue);
+ }
+
+ // Store the index
+ setMinimizerIndex(&node->leaf, offset);
+
+ offset += mult;
+ }
+ else {
+ // Internal cell, recur
+ int count = 0;
+ len >>= 1;
+ for (i = 0; i < 8; i++) {
+ if (node->internal.has_child(i)) {
+ int nst[3];
+ nst[0] = st[0] + vertmap[i][0] * len;
+ nst[1] = st[1] + vertmap[i][1] * len;
+ nst[2] = st[2] + vertmap[i][2] * len;
+
+ generateMinimizer(node->internal.get_child(count), nst, len, height - 1, offset);
+ count++;
+ }
+ }
+ }
}
void Octree::processEdgeWrite(Node *node[4], int /*depth*/[4], int /*maxdep*/, int dir)
{
- //int color = 0;
-
- int i = 3;
- {
- if (getEdgeParity((LeafNode *)(node[i]), processEdgeMask[dir][i])) {
- int flip = 0;
- int edgeind = processEdgeMask[dir][i];
- if (getSign((LeafNode *)node[i], edgemap[edgeind][1]) > 0) {
- flip = 1;
- }
-
- int num = 0;
- {
- int ind[8];
- if (use_manifold) {
- int vind[2];
- int seq[4] = {0, 1, 3, 2};
- for (int k = 0; k < 4; k++) {
- getMinimizerIndices((LeafNode *)(node[seq[k]]), processEdgeMask[dir][seq[k]], vind);
- ind[num] = vind[0];
- num++;
-
- if (vind[1] != -1) {
- ind[num] = vind[1];
- num++;
- if (flip == 0) {
- ind[num - 1] = vind[0];
- ind[num - 2] = vind[1];
- }
- }
- }
-
- /* we don't use the manifold option, but if it is
- ever enabled again note that it can output
- non-quads */
- }
- else {
- if (flip) {
- ind[0] = getMinimizerIndex((LeafNode *)(node[2]));
- ind[1] = getMinimizerIndex((LeafNode *)(node[3]));
- ind[2] = getMinimizerIndex((LeafNode *)(node[1]));
- ind[3] = getMinimizerIndex((LeafNode *)(node[0]));
- }
- else {
- ind[0] = getMinimizerIndex((LeafNode *)(node[0]));
- ind[1] = getMinimizerIndex((LeafNode *)(node[1]));
- ind[2] = getMinimizerIndex((LeafNode *)(node[3]));
- ind[3] = getMinimizerIndex((LeafNode *)(node[2]));
- }
-
- add_quad(output_mesh, ind);
- }
- }
- return;
- }
- else {
- return;
- }
- }
+ //int color = 0;
+
+ int i = 3;
+ {
+ if (getEdgeParity((LeafNode *)(node[i]), processEdgeMask[dir][i])) {
+ int flip = 0;
+ int edgeind = processEdgeMask[dir][i];
+ if (getSign((LeafNode *)node[i], edgemap[edgeind][1]) > 0) {
+ flip = 1;
+ }
+
+ int num = 0;
+ {
+ int ind[8];
+ if (use_manifold) {
+ int vind[2];
+ int seq[4] = {0, 1, 3, 2};
+ for (int k = 0; k < 4; k++) {
+ getMinimizerIndices((LeafNode *)(node[seq[k]]), processEdgeMask[dir][seq[k]], vind);
+ ind[num] = vind[0];
+ num++;
+
+ if (vind[1] != -1) {
+ ind[num] = vind[1];
+ num++;
+ if (flip == 0) {
+ ind[num - 1] = vind[0];
+ ind[num - 2] = vind[1];
+ }
+ }
+ }
+
+ /* we don't use the manifold option, but if it is
+ ever enabled again note that it can output
+ non-quads */
+ }
+ else {
+ if (flip) {
+ ind[0] = getMinimizerIndex((LeafNode *)(node[2]));
+ ind[1] = getMinimizerIndex((LeafNode *)(node[3]));
+ ind[2] = getMinimizerIndex((LeafNode *)(node[1]));
+ ind[3] = getMinimizerIndex((LeafNode *)(node[0]));
+ }
+ else {
+ ind[0] = getMinimizerIndex((LeafNode *)(node[0]));
+ ind[1] = getMinimizerIndex((LeafNode *)(node[1]));
+ ind[2] = getMinimizerIndex((LeafNode *)(node[3]));
+ ind[3] = getMinimizerIndex((LeafNode *)(node[2]));
+ }
+
+ add_quad(output_mesh, ind);
+ }
+ }
+ return;
+ }
+ else {
+ return;
+ }
+ }
}
-
void Octree::edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir)
{
- if (!(node[0] && node[1] && node[2] && node[3])) {
- return;
- }
- if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
- processEdgeWrite(node, depth, maxdep, dir);
- }
- else {
- int i, j;
- Node *chd[4][8];
- for (j = 0; j < 4; j++) {
- for (i = 0; i < 8; i++) {
- chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
- node[j]->internal.get_child(
- node[j]->internal.get_child_count(i)) : NULL;
- }
- }
-
- // 2 edge calls
- Node *ne[4];
- int le[4];
- int de[4];
- for (i = 0; i < 2; i++) {
- int c[4] = {edgeProcEdgeMask[dir][i][0],
- edgeProcEdgeMask[dir][i][1],
- edgeProcEdgeMask[dir][i][2],
- edgeProcEdgeMask[dir][i][3]};
-
- for (int j = 0; j < 4; j++) {
- if (leaf[j]) {
- le[j] = leaf[j];
- ne[j] = node[j];
- de[j] = depth[j];
- }
- else {
- le[j] = node[j]->internal.is_child_leaf(c[j]);
- ne[j] = chd[j][c[j]];
- de[j] = depth[j] - 1;
- }
- }
-
- edgeProcContour(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]);
- }
-
- }
+ if (!(node[0] && node[1] && node[2] && node[3])) {
+ return;
+ }
+ if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
+ processEdgeWrite(node, depth, maxdep, dir);
+ }
+ else {
+ int i, j;
+ Node *chd[4][8];
+ for (j = 0; j < 4; j++) {
+ for (i = 0; i < 8; i++) {
+ chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
+ node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
+ NULL;
+ }
+ }
+
+ // 2 edge calls
+ Node *ne[4];
+ int le[4];
+ int de[4];
+ for (i = 0; i < 2; i++) {
+ int c[4] = {edgeProcEdgeMask[dir][i][0],
+ edgeProcEdgeMask[dir][i][1],
+ edgeProcEdgeMask[dir][i][2],
+ edgeProcEdgeMask[dir][i][3]};
+
+ for (int j = 0; j < 4; j++) {
+ if (leaf[j]) {
+ le[j] = leaf[j];
+ ne[j] = node[j];
+ de[j] = depth[j];
+ }
+ else {
+ le[j] = node[j]->internal.is_child_leaf(c[j]);
+ ne[j] = chd[j][c[j]];
+ de[j] = depth[j] - 1;
+ }
+ }
+
+ edgeProcContour(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]);
+ }
+ }
}
void Octree::faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir)
{
- if (!(node[0] && node[1])) {
- return;
- }
-
- if (!(leaf[0] && leaf[1])) {
- int i, j;
- // Fill children nodes
- Node *chd[2][8];
- for (j = 0; j < 2; j++) {
- for (i = 0; i < 8; i++) {
- chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
- node[j]->internal.get_child(
- node[j]->internal.get_child_count(i)) : NULL;
- }
- }
-
- // 4 face calls
- Node *nf[2];
- int df[2];
- int lf[2];
- for (i = 0; i < 4; i++) {
- int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
- for (int j = 0; j < 2; j++) {
- if (leaf[j]) {
- lf[j] = leaf[j];
- nf[j] = node[j];
- df[j] = depth[j];
- }
- else {
- lf[j] = node[j]->internal.is_child_leaf(c[j]);
- nf[j] = chd[j][c[j]];
- df[j] = depth[j] - 1;
- }
- }
- faceProcContour(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]);
- }
-
- // 4 edge calls
- int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
- Node *ne[4];
- int le[4];
- int de[4];
-
- for (i = 0; i < 4; i++) {
- int c[4] = {faceProcEdgeMask[dir][i][1], faceProcEdgeMask[dir][i][2],
- faceProcEdgeMask[dir][i][3], faceProcEdgeMask[dir][i][4]};
- int *order = orders[faceProcEdgeMask[dir][i][0]];
-
- for (int j = 0; j < 4; j++) {
- if (leaf[order[j]]) {
- le[j] = leaf[order[j]];
- ne[j] = node[order[j]];
- de[j] = depth[order[j]];
- }
- else {
- le[j] = node[order[j]]->internal.is_child_leaf(c[j]);
- ne[j] = chd[order[j]][c[j]];
- de[j] = depth[order[j]] - 1;
- }
- }
-
- edgeProcContour(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]);
- }
- }
+ if (!(node[0] && node[1])) {
+ return;
+ }
+
+ if (!(leaf[0] && leaf[1])) {
+ int i, j;
+ // Fill children nodes
+ Node *chd[2][8];
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 8; i++) {
+ chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
+ node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
+ NULL;
+ }
+ }
+
+ // 4 face calls
+ Node *nf[2];
+ int df[2];
+ int lf[2];
+ for (i = 0; i < 4; i++) {
+ int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
+ for (int j = 0; j < 2; j++) {
+ if (leaf[j]) {
+ lf[j] = leaf[j];
+ nf[j] = node[j];
+ df[j] = depth[j];
+ }
+ else {
+ lf[j] = node[j]->internal.is_child_leaf(c[j]);
+ nf[j] = chd[j][c[j]];
+ df[j] = depth[j] - 1;
+ }
+ }
+ faceProcContour(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]);
+ }
+
+ // 4 edge calls
+ int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
+ Node *ne[4];
+ int le[4];
+ int de[4];
+
+ for (i = 0; i < 4; i++) {
+ int c[4] = {faceProcEdgeMask[dir][i][1],
+ faceProcEdgeMask[dir][i][2],
+ faceProcEdgeMask[dir][i][3],
+ faceProcEdgeMask[dir][i][4]};
+ int *order = orders[faceProcEdgeMask[dir][i][0]];
+
+ for (int j = 0; j < 4; j++) {
+ if (leaf[order[j]]) {
+ le[j] = leaf[order[j]];
+ ne[j] = node[order[j]];
+ de[j] = depth[order[j]];
+ }
+ else {
+ le[j] = node[order[j]]->internal.is_child_leaf(c[j]);
+ ne[j] = chd[order[j]][c[j]];
+ de[j] = depth[order[j]] - 1;
+ }
+ }
+
+ edgeProcContour(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]);
+ }
+ }
}
-
void Octree::cellProcContour(Node *node, int leaf, int depth)
{
- if (node == NULL) {
- return;
- }
-
- if (!leaf) {
- int i;
-
- // Fill children nodes
- Node *chd[8];
- for (i = 0; i < 8; i++) {
- chd[i] = ((!leaf) && node->internal.has_child(i)) ?
- node->internal.get_child(node->internal.get_child_count(i)) : NULL;
- }
-
- // 8 Cell calls
- for (i = 0; i < 8; i++) {
- cellProcContour(chd[i], node->internal.is_child_leaf(i), depth - 1);
- }
-
- // 12 face calls
- Node *nf[2];
- int lf[2];
- int df[2] = {depth - 1, depth - 1};
- for (i = 0; i < 12; i++) {
- int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
-
- lf[0] = node->internal.is_child_leaf(c[0]);
- lf[1] = node->internal.is_child_leaf(c[1]);
-
- nf[0] = chd[c[0]];
- nf[1] = chd[c[1]];
-
- faceProcContour(nf, lf, df, depth - 1, cellProcFaceMask[i][2]);
- }
-
- // 6 edge calls
- Node *ne[4];
- int le[4];
- int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
- for (i = 0; i < 6; i++) {
- int c[4] = {cellProcEdgeMask[i][0], cellProcEdgeMask[i][1], cellProcEdgeMask[i][2], cellProcEdgeMask[i][3]};
-
- for (int j = 0; j < 4; j++) {
- le[j] = node->internal.is_child_leaf(c[j]);
- ne[j] = chd[c[j]];
- }
-
- edgeProcContour(ne, le, de, depth - 1, cellProcEdgeMask[i][4]);
- }
- }
-
+ if (node == NULL) {
+ return;
+ }
+
+ if (!leaf) {
+ int i;
+
+ // Fill children nodes
+ Node *chd[8];
+ for (i = 0; i < 8; i++) {
+ chd[i] = ((!leaf) && node->internal.has_child(i)) ?
+ node->internal.get_child(node->internal.get_child_count(i)) :
+ NULL;
+ }
+
+ // 8 Cell calls
+ for (i = 0; i < 8; i++) {
+ cellProcContour(chd[i], node->internal.is_child_leaf(i), depth - 1);
+ }
+
+ // 12 face calls
+ Node *nf[2];
+ int lf[2];
+ int df[2] = {depth - 1, depth - 1};
+ for (i = 0; i < 12; i++) {
+ int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
+
+ lf[0] = node->internal.is_child_leaf(c[0]);
+ lf[1] = node->internal.is_child_leaf(c[1]);
+
+ nf[0] = chd[c[0]];
+ nf[1] = chd[c[1]];
+
+ faceProcContour(nf, lf, df, depth - 1, cellProcFaceMask[i][2]);
+ }
+
+ // 6 edge calls
+ Node *ne[4];
+ int le[4];
+ int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
+ for (i = 0; i < 6; i++) {
+ int c[4] = {cellProcEdgeMask[i][0],
+ cellProcEdgeMask[i][1],
+ cellProcEdgeMask[i][2],
+ cellProcEdgeMask[i][3]};
+
+ for (int j = 0; j < 4; j++) {
+ le[j] = node->internal.is_child_leaf(c[j]);
+ ne[j] = chd[c[j]];
+ }
+
+ edgeProcContour(ne, le, de, depth - 1, cellProcEdgeMask[i][4]);
+ }
+ }
}
void Octree::processEdgeParity(LeafNode *node[4], int /*depth*/[4], int /*maxdep*/, int dir)
{
- int con = 0;
- for (int i = 0; i < 4; i++) {
- // Minimal cell
- // if(op == 0)
- {
- if (getEdgeParity(node[i], processEdgeMask[dir][i])) {
- con = 1;
- break;
- }
- }
- }
-
- if (con == 1) {
- for (int i = 0; i < 4; i++) {
- setEdge(node[i], processEdgeMask[dir][i]);
- }
- }
-
+ int con = 0;
+ for (int i = 0; i < 4; i++) {
+ // Minimal cell
+ // if(op == 0)
+ {
+ if (getEdgeParity(node[i], processEdgeMask[dir][i])) {
+ con = 1;
+ break;
+ }
+ }
+ }
+
+ if (con == 1) {
+ for (int i = 0; i < 4; i++) {
+ setEdge(node[i], processEdgeMask[dir][i]);
+ }
+ }
}
void Octree::edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir)
{
- if (!(node[0] && node[1] && node[2] && node[3])) {
- return;
- }
- if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
- processEdgeParity((LeafNode **)node, depth, maxdep, dir);
- }
- else {
- int i, j;
- Node *chd[4][8];
- for (j = 0; j < 4; j++) {
- for (i = 0; i < 8; i++) {
- chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
- node[j]->internal.get_child( node[j]->internal.get_child_count(i)) : NULL;
- }
- }
-
- // 2 edge calls
- Node *ne[4];
- int le[4];
- int de[4];
- for (i = 0; i < 2; i++) {
- int c[4] = {edgeProcEdgeMask[dir][i][0],
- edgeProcEdgeMask[dir][i][1],
- edgeProcEdgeMask[dir][i][2],
- edgeProcEdgeMask[dir][i][3]};
-
- // int allleaf = 1;
- for (int j = 0; j < 4; j++) {
-
- if (leaf[j]) {
- le[j] = leaf[j];
- ne[j] = node[j];
- de[j] = depth[j];
- }
- else {
- le[j] = node[j]->internal.is_child_leaf(c[j]);
- ne[j] = chd[j][c[j]];
- de[j] = depth[j] - 1;
-
- }
-
- }
-
- edgeProcParity(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]);
- }
-
- }
+ if (!(node[0] && node[1] && node[2] && node[3])) {
+ return;
+ }
+ if (leaf[0] && leaf[1] && leaf[2] && leaf[3]) {
+ processEdgeParity((LeafNode **)node, depth, maxdep, dir);
+ }
+ else {
+ int i, j;
+ Node *chd[4][8];
+ for (j = 0; j < 4; j++) {
+ for (i = 0; i < 8; i++) {
+ chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
+ node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
+ NULL;
+ }
+ }
+
+ // 2 edge calls
+ Node *ne[4];
+ int le[4];
+ int de[4];
+ for (i = 0; i < 2; i++) {
+ int c[4] = {edgeProcEdgeMask[dir][i][0],
+ edgeProcEdgeMask[dir][i][1],
+ edgeProcEdgeMask[dir][i][2],
+ edgeProcEdgeMask[dir][i][3]};
+
+ // int allleaf = 1;
+ for (int j = 0; j < 4; j++) {
+
+ if (leaf[j]) {
+ le[j] = leaf[j];
+ ne[j] = node[j];
+ de[j] = depth[j];
+ }
+ else {
+ le[j] = node[j]->internal.is_child_leaf(c[j]);
+ ne[j] = chd[j][c[j]];
+ de[j] = depth[j] - 1;
+ }
+ }
+
+ edgeProcParity(ne, le, de, maxdep - 1, edgeProcEdgeMask[dir][i][4]);
+ }
+ }
}
void Octree::faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir)
{
- if (!(node[0] && node[1])) {
- return;
- }
-
- if (!(leaf[0] && leaf[1])) {
- int i, j;
- // Fill children nodes
- Node *chd[2][8];
- for (j = 0; j < 2; j++) {
- for (i = 0; i < 8; i++) {
- chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
- node[j]->internal.get_child(
- node[j]->internal.get_child_count(i)) : NULL;
- }
- }
-
- // 4 face calls
- Node *nf[2];
- int df[2];
- int lf[2];
- for (i = 0; i < 4; i++) {
- int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
- for (int j = 0; j < 2; j++) {
- if (leaf[j]) {
- lf[j] = leaf[j];
- nf[j] = node[j];
- df[j] = depth[j];
- }
- else {
- lf[j] = node[j]->internal.is_child_leaf(c[j]);
- nf[j] = chd[j][c[j]];
- df[j] = depth[j] - 1;
- }
- }
- faceProcParity(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]);
- }
-
- // 4 edge calls
- int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
- Node *ne[4];
- int le[4];
- int de[4];
-
- for (i = 0; i < 4; i++) {
- int c[4] = {faceProcEdgeMask[dir][i][1], faceProcEdgeMask[dir][i][2],
- faceProcEdgeMask[dir][i][3], faceProcEdgeMask[dir][i][4]};
- int *order = orders[faceProcEdgeMask[dir][i][0]];
-
- for (int j = 0; j < 4; j++) {
- if (leaf[order[j]]) {
- le[j] = leaf[order[j]];
- ne[j] = node[order[j]];
- de[j] = depth[order[j]];
- }
- else {
- le[j] = node[order[j]]->internal.is_child_leaf(c[j]);
- ne[j] = chd[order[j]][c[j]];
- de[j] = depth[order[j]] - 1;
- }
- }
-
- edgeProcParity(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]);
- }
- }
+ if (!(node[0] && node[1])) {
+ return;
+ }
+
+ if (!(leaf[0] && leaf[1])) {
+ int i, j;
+ // Fill children nodes
+ Node *chd[2][8];
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 8; i++) {
+ chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ?
+ node[j]->internal.get_child(node[j]->internal.get_child_count(i)) :
+ NULL;
+ }
+ }
+
+ // 4 face calls
+ Node *nf[2];
+ int df[2];
+ int lf[2];
+ for (i = 0; i < 4; i++) {
+ int c[2] = {faceProcFaceMask[dir][i][0], faceProcFaceMask[dir][i][1]};
+ for (int j = 0; j < 2; j++) {
+ if (leaf[j]) {
+ lf[j] = leaf[j];
+ nf[j] = node[j];
+ df[j] = depth[j];
+ }
+ else {
+ lf[j] = node[j]->internal.is_child_leaf(c[j]);
+ nf[j] = chd[j][c[j]];
+ df[j] = depth[j] - 1;
+ }
+ }
+ faceProcParity(nf, lf, df, maxdep - 1, faceProcFaceMask[dir][i][2]);
+ }
+
+ // 4 edge calls
+ int orders[2][4] = {{0, 0, 1, 1}, {0, 1, 0, 1}};
+ Node *ne[4];
+ int le[4];
+ int de[4];
+
+ for (i = 0; i < 4; i++) {
+ int c[4] = {faceProcEdgeMask[dir][i][1],
+ faceProcEdgeMask[dir][i][2],
+ faceProcEdgeMask[dir][i][3],
+ faceProcEdgeMask[dir][i][4]};
+ int *order = orders[faceProcEdgeMask[dir][i][0]];
+
+ for (int j = 0; j < 4; j++) {
+ if (leaf[order[j]]) {
+ le[j] = leaf[order[j]];
+ ne[j] = node[order[j]];
+ de[j] = depth[order[j]];
+ }
+ else {
+ le[j] = node[order[j]]->internal.is_child_leaf(c[j]);
+ ne[j] = chd[order[j]][c[j]];
+ de[j] = depth[order[j]] - 1;
+ }
+ }
+
+ edgeProcParity(ne, le, de, maxdep - 1, faceProcEdgeMask[dir][i][5]);
+ }
+ }
}
-
void Octree::cellProcParity(Node *node, int leaf, int depth)
{
- if (node == NULL) {
- return;
- }
-
- if (!leaf) {
- int i;
-
- // Fill children nodes
- Node *chd[8];
- for (i = 0; i < 8; i++) {
- chd[i] = ((!leaf) && node->internal.has_child(i)) ?
- node->internal.get_child(node->internal.get_child_count(i)) : NULL;
- }
-
- // 8 Cell calls
- for (i = 0; i < 8; i++) {
- cellProcParity(chd[i], node->internal.is_child_leaf(i), depth - 1);
- }
-
- // 12 face calls
- Node *nf[2];
- int lf[2];
- int df[2] = {depth - 1, depth - 1};
- for (i = 0; i < 12; i++) {
- int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
-
- lf[0] = node->internal.is_child_leaf(c[0]);
- lf[1] = node->internal.is_child_leaf(c[1]);
-
- nf[0] = chd[c[0]];
- nf[1] = chd[c[1]];
-
- faceProcParity(nf, lf, df, depth - 1, cellProcFaceMask[i][2]);
- }
-
- // 6 edge calls
- Node *ne[4];
- int le[4];
- int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
- for (i = 0; i < 6; i++) {
- int c[4] = {cellProcEdgeMask[i][0], cellProcEdgeMask[i][1], cellProcEdgeMask[i][2], cellProcEdgeMask[i][3]};
-
- for (int j = 0; j < 4; j++) {
- le[j] = node->internal.is_child_leaf(c[j]);
- ne[j] = chd[c[j]];
- }
-
- edgeProcParity(ne, le, de, depth - 1, cellProcEdgeMask[i][4]);
- }
- }
-
+ if (node == NULL) {
+ return;
+ }
+
+ if (!leaf) {
+ int i;
+
+ // Fill children nodes
+ Node *chd[8];
+ for (i = 0; i < 8; i++) {
+ chd[i] = ((!leaf) && node->internal.has_child(i)) ?
+ node->internal.get_child(node->internal.get_child_count(i)) :
+ NULL;
+ }
+
+ // 8 Cell calls
+ for (i = 0; i < 8; i++) {
+ cellProcParity(chd[i], node->internal.is_child_leaf(i), depth - 1);
+ }
+
+ // 12 face calls
+ Node *nf[2];
+ int lf[2];
+ int df[2] = {depth - 1, depth - 1};
+ for (i = 0; i < 12; i++) {
+ int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]};
+
+ lf[0] = node->internal.is_child_leaf(c[0]);
+ lf[1] = node->internal.is_child_leaf(c[1]);
+
+ nf[0] = chd[c[0]];
+ nf[1] = chd[c[1]];
+
+ faceProcParity(nf, lf, df, depth - 1, cellProcFaceMask[i][2]);
+ }
+
+ // 6 edge calls
+ Node *ne[4];
+ int le[4];
+ int de[4] = {depth - 1, depth - 1, depth - 1, depth - 1};
+ for (i = 0; i < 6; i++) {
+ int c[4] = {cellProcEdgeMask[i][0],
+ cellProcEdgeMask[i][1],
+ cellProcEdgeMask[i][2],
+ cellProcEdgeMask[i][3]};
+
+ for (int j = 0; j < 4; j++) {
+ le[j] = node->internal.is_child_leaf(c[j]);
+ ne[j] = chd[c[j]];
+ }
+
+ edgeProcParity(ne, le, de, depth - 1, cellProcEdgeMask[i][4]);
+ }
+ }
}
/* definitions for global arrays */
const int edgemask[3] = {5, 3, 6};
const int faceMap[6][4] = {
- {4, 8, 5, 9},
- {6, 10, 7, 11},
- {0, 8, 1, 10},
- {2, 9, 3, 11},
- {0, 4, 2, 6},
- {1, 5, 3, 7},
+ {4, 8, 5, 9},
+ {6, 10, 7, 11},
+ {0, 8, 1, 10},
+ {2, 9, 3, 11},
+ {0, 4, 2, 6},
+ {1, 5, 3, 7},
};
const int cellProcFaceMask[12][3] = {
- {0, 4, 0},
- {1, 5, 0},
- {2, 6, 0},
- {3, 7, 0},
- {0, 2, 1},
- {4, 6, 1},
- {1, 3, 1},
- {5, 7, 1},
- {0, 1, 2},
- {2, 3, 2},
- {4, 5, 2},
- {6, 7, 2},
+ {0, 4, 0},
+ {1, 5, 0},
+ {2, 6, 0},
+ {3, 7, 0},
+ {0, 2, 1},
+ {4, 6, 1},
+ {1, 3, 1},
+ {5, 7, 1},
+ {0, 1, 2},
+ {2, 3, 2},
+ {4, 5, 2},
+ {6, 7, 2},
};
const int cellProcEdgeMask[6][5] = {
- {0, 1, 2, 3, 0},
- {4, 5, 6, 7, 0},
- {0, 4, 1, 5, 1},
- {2, 6, 3, 7, 1},
- {0, 2, 4, 6, 2},
- {1, 3, 5, 7, 2},
+ {0, 1, 2, 3, 0},
+ {4, 5, 6, 7, 0},
+ {0, 4, 1, 5, 1},
+ {2, 6, 3, 7, 1},
+ {0, 2, 4, 6, 2},
+ {1, 3, 5, 7, 2},
};
-const int faceProcFaceMask[3][4][3] = {
- {{4, 0, 0},
- {5, 1, 0},
- {6, 2, 0},
- {7, 3, 0}},
- {{2, 0, 1},
- {6, 4, 1},
- {3, 1, 1},
- {7, 5, 1}},
- {{1, 0, 2},
- {3, 2, 2},
- {5, 4, 2},
- {7, 6, 2}}
-};
+const int faceProcFaceMask[3][4][3] = {{{4, 0, 0}, {5, 1, 0}, {6, 2, 0}, {7, 3, 0}},
+ {{2, 0, 1}, {6, 4, 1}, {3, 1, 1}, {7, 5, 1}},
+ {{1, 0, 2}, {3, 2, 2}, {5, 4, 2}, {7, 6, 2}}};
const int faceProcEdgeMask[3][4][6] = {
- {{1, 4, 0, 5, 1, 1},
- {1, 6, 2, 7, 3, 1},
- {0, 4, 6, 0, 2, 2},
- {0, 5, 7, 1, 3, 2}},
- {{0, 2, 3, 0, 1, 0},
- {0, 6, 7, 4, 5, 0},
- {1, 2, 0, 6, 4, 2},
- {1, 3, 1, 7, 5, 2}},
- {{1, 1, 0, 3, 2, 0},
- {1, 5, 4, 7, 6, 0},
- {0, 1, 5, 0, 4, 1},
- {0, 3, 7, 2, 6, 1}}
-};
+ {{1, 4, 0, 5, 1, 1}, {1, 6, 2, 7, 3, 1}, {0, 4, 6, 0, 2, 2}, {0, 5, 7, 1, 3, 2}},
+ {{0, 2, 3, 0, 1, 0}, {0, 6, 7, 4, 5, 0}, {1, 2, 0, 6, 4, 2}, {1, 3, 1, 7, 5, 2}},
+ {{1, 1, 0, 3, 2, 0}, {1, 5, 4, 7, 6, 0}, {0, 1, 5, 0, 4, 1}, {0, 3, 7, 2, 6, 1}}};
const int edgeProcEdgeMask[3][2][5] = {
- {{3, 2, 1, 0, 0},
- {7, 6, 5, 4, 0}},
- {{5, 1, 4, 0, 1},
- {7, 3, 6, 2, 1}},
- {{6, 4, 2, 0, 2},
- {7, 5, 3, 1, 2}},
+ {{3, 2, 1, 0, 0}, {7, 6, 5, 4, 0}},
+ {{5, 1, 4, 0, 1}, {7, 3, 6, 2, 1}},
+ {{6, 4, 2, 0, 2}, {7, 5, 3, 1, 2}},
};
const int processEdgeMask[3][4] = {
- {3, 2, 1, 0},
- {7, 5, 6, 4},
- {11, 10, 9, 8},
+ {3, 2, 1, 0},
+ {7, 5, 6, 4},
+ {11, 10, 9, 8},
};
-const int dirCell[3][4][3] = {
- {{0, -1, -1},
- {0, -1, 0},
- {0, 0, -1},
- {0, 0, 0}},
- {{-1, 0, -1},
- {-1, 0, 0},
- {0, 0, -1},
- {0, 0, 0}},
- {{-1, -1, 0},
- {-1, 0, 0},
- {0, -1, 0},
- {0, 0, 0}}
-};
+const int dirCell[3][4][3] = {{{0, -1, -1}, {0, -1, 0}, {0, 0, -1}, {0, 0, 0}},
+ {{-1, 0, -1}, {-1, 0, 0}, {0, 0, -1}, {0, 0, 0}},
+ {{-1, -1, 0}, {-1, 0, 0}, {0, -1, 0}, {0, 0, 0}}};
const int dirEdge[3][4] = {
- {3, 2, 1, 0},
- {7, 6, 5, 4},
- {11, 10, 9, 8},
+ {3, 2, 1, 0},
+ {7, 6, 5, 4},
+ {11, 10, 9, 8},
};
int InternalNode::numChildrenTable[256];
diff --git a/intern/dualcon/intern/octree.h b/intern/dualcon/intern/octree.h
index 5075a5603b6..db945e36390 100644
--- a/intern/dualcon/intern/octree.h
+++ b/intern/dualcon/intern/octree.h
@@ -37,7 +37,6 @@
* @author Tao Ju
*/
-
/* Global defines */
// Uncomment to see debug information
// #define IN_DEBUG_MODE
@@ -53,98 +52,97 @@ union Node;
struct LeafNode;
struct InternalNode {
- /* Initialized in Octree::BuildTable */
- static int numChildrenTable[256];
- static int childrenCountTable[256][8];
- static int childrenIndexTable[256][8];
-
- /* Bit N indicates whether child N exists or not */
- unsigned char has_child_bitfield;
- /* Bit N indicates whether child N is a leaf or not */
- unsigned char child_is_leaf_bitfield;
-
- /* Can have up to eight children */
- Node *children[0];
-
- /// Test if child is leaf
- int is_child_leaf(int index) const
- {
- return (child_is_leaf_bitfield >> index) & 1;
- }
-
- /// If child index exists
- int has_child(int index) const
- {
- return (has_child_bitfield >> index) & 1;
- }
-
- /// Get the pointer to child index
- Node *get_child(int count)
- {
- return children[count];
- }
-
- const Node *get_child(int count) const
- {
- return children[count];
- }
-
- /// Get total number of children
- int get_num_children() const
- {
- return numChildrenTable[has_child_bitfield];
- }
-
- /// Get the count of children
- int get_child_count(int index) const
- {
- return childrenCountTable[has_child_bitfield][index];
- }
- int get_child_index(int count)
- {
- return childrenIndexTable[has_child_bitfield][count];
- }
- const int *get_child_counts() const
- {
- return childrenCountTable[has_child_bitfield];
- }
-
- /// Get all children
- void fill_children(Node *children[8], int leaf[8])
- {
- int count = 0;
- for (int i = 0; i < 8; i++) {
- leaf[i] = is_child_leaf(i);
- if (has_child(i)) {
- children[i] = get_child(count);
- count++;
- }
- else {
- children[i] = NULL;
- leaf[i] = 0;
- }
- }
- }
-
- /// Sets the child pointer
- void set_child(int count, Node *chd)
- {
- children[count] = chd;
- }
- void set_internal_child(int index, int count, InternalNode *chd)
- {
- set_child(count, (Node *)chd);
- has_child_bitfield |= (1 << index);
- }
- void set_leaf_child(int index, int count, LeafNode *chd)
- {
- set_child(count, (Node *)chd);
- has_child_bitfield |= (1 << index);
- child_is_leaf_bitfield |= (1 << index);
- }
+ /* Initialized in Octree::BuildTable */
+ static int numChildrenTable[256];
+ static int childrenCountTable[256][8];
+ static int childrenIndexTable[256][8];
+
+ /* Bit N indicates whether child N exists or not */
+ unsigned char has_child_bitfield;
+ /* Bit N indicates whether child N is a leaf or not */
+ unsigned char child_is_leaf_bitfield;
+
+ /* Can have up to eight children */
+ Node *children[0];
+
+ /// Test if child is leaf
+ int is_child_leaf(int index) const
+ {
+ return (child_is_leaf_bitfield >> index) & 1;
+ }
+
+ /// If child index exists
+ int has_child(int index) const
+ {
+ return (has_child_bitfield >> index) & 1;
+ }
+
+ /// Get the pointer to child index
+ Node *get_child(int count)
+ {
+ return children[count];
+ }
+
+ const Node *get_child(int count) const
+ {
+ return children[count];
+ }
+
+ /// Get total number of children
+ int get_num_children() const
+ {
+ return numChildrenTable[has_child_bitfield];
+ }
+
+ /// Get the count of children
+ int get_child_count(int index) const
+ {
+ return childrenCountTable[has_child_bitfield][index];
+ }
+ int get_child_index(int count)
+ {
+ return childrenIndexTable[has_child_bitfield][count];
+ }
+ const int *get_child_counts() const
+ {
+ return childrenCountTable[has_child_bitfield];
+ }
+
+ /// Get all children
+ void fill_children(Node *children[8], int leaf[8])
+ {
+ int count = 0;
+ for (int i = 0; i < 8; i++) {
+ leaf[i] = is_child_leaf(i);
+ if (has_child(i)) {
+ children[i] = get_child(count);
+ count++;
+ }
+ else {
+ children[i] = NULL;
+ leaf[i] = 0;
+ }
+ }
+ }
+
+ /// Sets the child pointer
+ void set_child(int count, Node *chd)
+ {
+ children[count] = chd;
+ }
+ void set_internal_child(int index, int count, InternalNode *chd)
+ {
+ set_child(count, (Node *)chd);
+ has_child_bitfield |= (1 << index);
+ }
+ void set_leaf_child(int index, int count, LeafNode *chd)
+ {
+ set_child(count, (Node *)chd);
+ has_child_bitfield |= (1 << index);
+ child_is_leaf_bitfield |= (1 << index);
+ }
};
-
/**
* Bits order
*
@@ -157,27 +155,27 @@ struct InternalNode {
* Byte 5: edge intersections(4 bytes per inter, or 12 bytes if USE_HERMIT)
*/
struct LeafNode /* TODO: remove this attribute once everything is fixed */ {
- unsigned short edge_parity : 12;
- unsigned short primary_edge_intersections : 3;
+ unsigned short edge_parity : 12;
+ unsigned short primary_edge_intersections : 3;
- /* XXX: maybe actually unused? */
- unsigned short in_process : 1;
+ /* XXX: maybe actually unused? */
+ unsigned short in_process : 1;
- /* bitfield */
- char signs;
+ /* bitfield */
+ char signs;
- int minimizer_index;
+ int minimizer_index;
- unsigned short flood_fill;
+ unsigned short flood_fill;
- float edge_intersections[0];
+ float edge_intersections[0];
};
/* Doesn't get directly allocated anywhere, just used for passing
pointers to nodes that could be internal or leaf. */
union Node {
- InternalNode internal;
- LeafNode leaf;
+ InternalNode internal;
+ LeafNode leaf;
};
/* Global variables */
@@ -197,1195 +195,1209 @@ extern const int dirEdge[3][4];
*/
struct PathElement {
- // Origin
- int pos[3];
+ // Origin
+ int pos[3];
- // link
- PathElement *next;
+ // link
+ PathElement *next;
};
struct PathList {
- // Head
- PathElement *head;
- PathElement *tail;
+ // Head
+ PathElement *head;
+ PathElement *tail;
- // Length of the list
- int length;
+ // Length of the list
+ int length;
- // Next list
- PathList *next;
+ // Next list
+ PathList *next;
};
-
/**
* Class for building and processing an octree
*/
-class Octree
-{
+class Octree {
public:
- /* Public members */
+ /* Public members */
- /// Memory allocators
- VirtualMemoryAllocator *alloc[9];
- VirtualMemoryAllocator *leafalloc[4];
+ /// Memory allocators
+ VirtualMemoryAllocator *alloc[9];
+ VirtualMemoryAllocator *leafalloc[4];
- /// Root node
- Node *root;
+ /// Root node
+ Node *root;
- /// Model reader
- ModelReader *reader;
+ /// Model reader
+ ModelReader *reader;
- /// Marching cubes table
- Cubes *cubes;
+ /// Marching cubes table
+ Cubes *cubes;
- /// Length of grid
- int dimen;
- int mindimen, minshift;
+ /// Length of grid
+ int dimen;
+ int mindimen, minshift;
- /// Maximum depth
- int maxDepth;
+ /// Maximum depth
+ int maxDepth;
- /// The lower corner of the bounding box and the size
- float origin[3];
- float range;
+ /// The lower corner of the bounding box and the size
+ float origin[3];
+ float range;
- /// Counting information
- int nodeCount;
- int nodeSpace;
- int nodeCounts[9];
+ /// Counting information
+ int nodeCount;
+ int nodeSpace;
+ int nodeCounts[9];
- int actualQuads, actualVerts;
+ int actualQuads, actualVerts;
- PathList *ringList;
+ PathList *ringList;
- int maxTrianglePerCell;
- int outType; // 0 for OFF, 1 for PLY, 2 for VOL
+ int maxTrianglePerCell;
+ int outType; // 0 for OFF, 1 for PLY, 2 for VOL
- // For flood filling
- int use_flood_fill;
- float thresh;
+ // For flood filling
+ int use_flood_fill;
+ float thresh;
- int use_manifold;
+ int use_manifold;
- float hermite_num;
+ float hermite_num;
- DualConMode mode;
+ DualConMode mode;
public:
- /**
- * Construtor
- */
- Octree(ModelReader *mr,
- DualConAllocOutput alloc_output_func,
- DualConAddVert add_vert_func,
- DualConAddQuad add_quad_func,
- DualConFlags flags, DualConMode mode, int depth,
- float threshold, float hermite_num);
-
- /**
- * Destructor
- */
- ~Octree();
-
- /**
- * Scan convert
- */
- void scanConvert();
-
- void *getOutputMesh() {
- return output_mesh;
- }
+ /**
+ * Construtor
+ */
+ Octree(ModelReader *mr,
+ DualConAllocOutput alloc_output_func,
+ DualConAddVert add_vert_func,
+ DualConAddQuad add_quad_func,
+ DualConFlags flags,
+ DualConMode mode,
+ int depth,
+ float threshold,
+ float hermite_num);
+
+ /**
+ * Destructor
+ */
+ ~Octree();
+
+ /**
+ * Scan convert
+ */
+ void scanConvert();
+
+ void *getOutputMesh()
+ {
+ return output_mesh;
+ }
private:
- /* Helper functions */
-
- /**
- * Initialize memory allocators
- */
- void initMemory();
-
- /**
- * Release memory
- */
- void freeMemory();
-
- /**
- * Print memory usage
- */
- void printMemUsage();
-
-
- /**
- * Methods to set / restore minimum edges
- */
- void resetMinimalEdges();
-
- void cellProcParity(Node *node, int leaf, int depth);
- void faceProcParity(Node * node[2], int leaf[2], int depth[2], int maxdep, int dir);
- void edgeProcParity(Node * node[4], int leaf[4], int depth[4], int maxdep, int dir);
-
- void processEdgeParity(LeafNode * node[4], int depths[4], int maxdep, int dir);
-
- /**
- * Add triangles to the tree
- */
- void addAllTriangles();
- void addTriangle(Triangle *trian, int triind);
- InternalNode *addTriangle(InternalNode *node, CubeTriangleIsect *p, int height);
-
- /**
- * Method to update minimizer in a cell: update edge intersections instead
- */
- LeafNode *updateCell(LeafNode *node, CubeTriangleIsect *p);
-
- /* Routines to detect and patch holes */
- int numRings;
- int totRingLengths;
- int maxRingLength;
-
- /**
- * Entry routine.
- */
- void trace();
- /**
- * Trace the given node, find patches and fill them in
- */
- Node *trace(Node *node, int *st, int len, int depth, PathList *& paths);
- /**
- * Look for path on the face and add to paths
- */
- void findPaths(Node * node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList * &paths);
- /**
- * Combine two list1 and list2 into list1 using connecting paths list3,
- * while closed paths are appended to rings
- */
- void combinePaths(PathList *& list1, PathList *list2, PathList *paths, PathList *& rings);
- /**
- * Helper function: combine current paths in list1 and list2 to a single path and append to list3
- */
- PathList *combineSinglePath(PathList *& head1, PathList *pre1, PathList *& list1, PathList *& head2, PathList *pre2, PathList *& list2);
-
- /**
- * Functions to patch rings in a node
- */
- Node *patch(Node *node, int st[3], int len, PathList * rings);
- Node *patchSplit(Node *node, int st[3], int len, PathList * rings, int dir, PathList * &nrings1, PathList * &nrings2);
- Node *patchSplitSingle(Node *node, int st[3], int len, PathElement *head, int dir, PathList * &nrings1, PathList * &nrings2);
- Node *connectFace(Node *node, int st[3], int len, int dir, PathElement * f1, PathElement * f2);
- Node *locateCell(InternalNode *node, int st[3], int len, int ori[3], int dir, int side, Node * &rleaf, int rst[3], int& rlen);
- void compressRing(PathElement *& ring);
- void getFacePoint(PathElement *leaf, int dir, int& x, int& y, float& p, float& q);
- LeafNode *patchAdjacent(InternalNode *node, int len, int st1[3], LeafNode * leaf1, int st2[3], LeafNode * leaf2, int walkdir, int inc, int dir, int side, float alpha);
- int findPair(PathElement *head, int pos, int dir, PathElement *& pre1, PathElement *& pre2);
- int getSide(PathElement *e, int pos, int dir);
- int isEqual(PathElement *e1, PathElement *e2);
- void preparePrimalEdgesMask(InternalNode *node);
- void testFacePoint(PathElement *e1, PathElement *e2);
-
- /**
- * Path-related functions
- */
- void deletePath(PathList *& head, PathList *pre, PathList *& curr);
- void printPath(PathList *path);
- void printPath(PathElement *path);
- void printElement(PathElement *ele);
- void printPaths(PathList *path);
- void checkElement(PathElement *ele);
- void checkPath(PathElement *path);
-
-
- /**
- * Routines to build signs to create a partitioned volume
- *(after patching rings)
- */
- void buildSigns();
- void buildSigns(unsigned char table[], Node * node, int isLeaf, int sg, int rvalue[8]);
-
- /************************************************************************/
- /* To remove disconnected components */
- /************************************************************************/
- void floodFill();
- void clearProcessBits(Node *node, int height);
- int floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold);
- int floodFill(Node *node, int st[3], int len, int height, int threshold);
-
- /**
- * Write out polygon file
- */
- void writeOut();
-
- void countIntersection(Node *node, int height, int& nedge, int& ncell, int& nface);
- void generateMinimizer(Node *node, int st[3], int len, int height, int& offset);
- void computeMinimizer(const LeafNode * leaf, int st[3], int len,
- float rvalue[3]) const;
- /**
- * Traversal functions to generate polygon model
- * op: 0 for counting, 1 for writing OBJ, 2 for writing OFF, 3 for writing PLY
- */
- void cellProcContour(Node *node, int leaf, int depth);
- void faceProcContour(Node * node[2], int leaf[2], int depth[2], int maxdep, int dir);
- void edgeProcContour(Node * node[4], int leaf[4], int depth[4], int maxdep, int dir);
- void processEdgeWrite(Node * node[4], int depths[4], int maxdep, int dir);
-
- /* output callbacks/data */
- DualConAllocOutput alloc_output;
- DualConAddVert add_vert;
- DualConAddQuad add_quad;
- void *output_mesh;
+ /* Helper functions */
+
+ /**
+ * Initialize memory allocators
+ */
+ void initMemory();
+
+ /**
+ * Release memory
+ */
+ void freeMemory();
+
+ /**
+ * Print memory usage
+ */
+ void printMemUsage();
+
+ /**
+ * Methods to set / restore minimum edges
+ */
+ void resetMinimalEdges();
+
+ void cellProcParity(Node *node, int leaf, int depth);
+ void faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir);
+ void edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir);
+
+ void processEdgeParity(LeafNode *node[4], int depths[4], int maxdep, int dir);
+
+ /**
+ * Add triangles to the tree
+ */
+ void addAllTriangles();
+ void addTriangle(Triangle *trian, int triind);
+ InternalNode *addTriangle(InternalNode *node, CubeTriangleIsect *p, int height);
+
+ /**
+ * Method to update minimizer in a cell: update edge intersections instead
+ */
+ LeafNode *updateCell(LeafNode *node, CubeTriangleIsect *p);
+
+ /* Routines to detect and patch holes */
+ int numRings;
+ int totRingLengths;
+ int maxRingLength;
+
+ /**
+ * Entry routine.
+ */
+ void trace();
+ /**
+ * Trace the given node, find patches and fill them in
+ */
+ Node *trace(Node *node, int *st, int len, int depth, PathList *&paths);
+ /**
+ * Look for path on the face and add to paths
+ */
+ void findPaths(
+ Node *node[2], int leaf[2], int depth[2], int *st[2], int maxdep, int dir, PathList *&paths);
+ /**
+ * Combine two list1 and list2 into list1 using connecting paths list3,
+ * while closed paths are appended to rings
+ */
+ void combinePaths(PathList *&list1, PathList *list2, PathList *paths, PathList *&rings);
+ /**
+ * Helper function: combine current paths in list1 and list2 to a single path and append to list3
+ */
+ PathList *combineSinglePath(PathList *&head1,
+ PathList *pre1,
+ PathList *&list1,
+ PathList *&head2,
+ PathList *pre2,
+ PathList *&list2);
+
+ /**
+ * Functions to patch rings in a node
+ */
+ Node *patch(Node *node, int st[3], int len, PathList *rings);
+ Node *patchSplit(Node *node,
+ int st[3],
+ int len,
+ PathList *rings,
+ int dir,
+ PathList *&nrings1,
+ PathList *&nrings2);
+ Node *patchSplitSingle(Node *node,
+ int st[3],
+ int len,
+ PathElement *head,
+ int dir,
+ PathList *&nrings1,
+ PathList *&nrings2);
+ Node *connectFace(Node *node, int st[3], int len, int dir, PathElement *f1, PathElement *f2);
+ Node *locateCell(InternalNode *node,
+ int st[3],
+ int len,
+ int ori[3],
+ int dir,
+ int side,
+ Node *&rleaf,
+ int rst[3],
+ int &rlen);
+ void compressRing(PathElement *&ring);
+ void getFacePoint(PathElement *leaf, int dir, int &x, int &y, float &p, float &q);
+ LeafNode *patchAdjacent(InternalNode *node,
+ int len,
+ int st1[3],
+ LeafNode *leaf1,
+ int st2[3],
+ LeafNode *leaf2,
+ int walkdir,
+ int inc,
+ int dir,
+ int side,
+ float alpha);
+ int findPair(PathElement *head, int pos, int dir, PathElement *&pre1, PathElement *&pre2);
+ int getSide(PathElement *e, int pos, int dir);
+ int isEqual(PathElement *e1, PathElement *e2);
+ void preparePrimalEdgesMask(InternalNode *node);
+ void testFacePoint(PathElement *e1, PathElement *e2);
+
+ /**
+ * Path-related functions
+ */
+ void deletePath(PathList *&head, PathList *pre, PathList *&curr);
+ void printPath(PathList *path);
+ void printPath(PathElement *path);
+ void printElement(PathElement *ele);
+ void printPaths(PathList *path);
+ void checkElement(PathElement *ele);
+ void checkPath(PathElement *path);
+
+ /**
+ * Routines to build signs to create a partitioned volume
+ *(after patching rings)
+ */
+ void buildSigns();
+ void buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, int rvalue[8]);
+
+ /************************************************************************/
+ /* To remove disconnected components */
+ /************************************************************************/
+ void floodFill();
+ void clearProcessBits(Node *node, int height);
+ int floodFill(LeafNode *leaf, int st[3], int len, int height, int threshold);
+ int floodFill(Node *node, int st[3], int len, int height, int threshold);
+
+ /**
+ * Write out polygon file
+ */
+ void writeOut();
+
+ void countIntersection(Node *node, int height, int &nedge, int &ncell, int &nface);
+ void generateMinimizer(Node *node, int st[3], int len, int height, int &offset);
+ void computeMinimizer(const LeafNode *leaf, int st[3], int len, float rvalue[3]) const;
+ /**
+ * Traversal functions to generate polygon model
+ * op: 0 for counting, 1 for writing OBJ, 2 for writing OFF, 3 for writing PLY
+ */
+ void cellProcContour(Node *node, int leaf, int depth);
+ void faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxdep, int dir);
+ void edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxdep, int dir);
+ void processEdgeWrite(Node *node[4], int depths[4], int maxdep, int dir);
+
+ /* output callbacks/data */
+ DualConAllocOutput alloc_output;
+ DualConAddVert add_vert;
+ DualConAddQuad add_quad;
+ void *output_mesh;
private:
- /************ Operators for all nodes ************/
-
- /// Lookup table
- int numEdgeTable[8];
- int edgeCountTable[8][3];
-
- /// Build up lookup table
- void buildTable()
- {
- for (int i = 0; i < 256; i++) {
- InternalNode::numChildrenTable[i] = 0;
- int count = 0;
- for (int j = 0; j < 8; j++) {
- InternalNode::numChildrenTable[i] += ((i >> j) & 1);
- InternalNode::childrenCountTable[i][j] = count;
- InternalNode::childrenIndexTable[i][count] = j;
- count += ((i >> j) & 1);
- }
- }
-
- for (int i = 0; i < 8; i++) {
- numEdgeTable[i] = 0;
- int count = 0;
- for (int j = 0; j < 3; j++) {
- numEdgeTable[i] += ((i >> j) & 1);
- edgeCountTable[i][j] = count;
- count += ((i >> j) & 1);
- }
- }
- }
-
- int getSign(Node *node, int height, int index)
- {
- if (height == 0) {
- return getSign(&node->leaf, index);
- }
- else {
- if (node->internal.has_child(index)) {
- return getSign(node->internal.get_child(node->internal.get_child_count(index)),
- height - 1,
- index);
- }
- else {
- return getSign(node->internal.get_child(0),
- height - 1,
- 7 - node->internal.get_child_index(0));
- }
- }
- }
-
- /************ Operators for leaf nodes ************/
-
- void printInfo(int st[3])
- {
- printf("INFO AT: %d %d %d\n", st[0] >> minshift, st[1] >> minshift, st[2] >> minshift);
- LeafNode *leaf = (LeafNode *)locateLeafCheck(st);
- if (leaf)
- printInfo(leaf);
- else
- printf("Leaf not exists!\n");
- }
-
- void printInfo(const LeafNode *leaf)
- {
- /*
- printf("Edge mask: ");
- for(int i = 0; i < 12; i ++)
- {
- printf("%d ", getEdgeParity(leaf, i));
- }
- printf("\n");
- printf("Stored edge mask: ");
- for(i = 0; i < 3; i ++)
- {
- printf("%d ", getStoredEdgesParity(leaf, i));
- }
- printf("\n");
- */
- printf("Sign mask: ");
- for (int i = 0; i < 8; i++) {
- printf("%d ", getSign(leaf, i));
- }
- printf("\n");
-
- }
-
- /// Retrieve signs
- int getSign(const LeafNode *leaf, int index)
- {
- return ((leaf->signs >> index) & 1);
- }
-
- /// Set sign
- void setSign(LeafNode *leaf, int index)
- {
- leaf->signs |= (1 << index);
- }
-
- void setSign(LeafNode *leaf, int index, int sign)
- {
- leaf->signs &= (~(1 << index));
- leaf->signs |= ((sign & 1) << index);
- }
-
- int getSignMask(const LeafNode *leaf) const
- {
- return leaf->signs;
- }
-
- void setInProcessAll(int st[3], int dir)
- {
- int nst[3], eind;
- for (int i = 0; i < 4; i++) {
- nst[0] = st[0] + dirCell[dir][i][0] * mindimen;
- nst[1] = st[1] + dirCell[dir][i][1] * mindimen;
- nst[2] = st[2] + dirCell[dir][i][2] * mindimen;
- eind = dirEdge[dir][i];
-
- LeafNode *cell = locateLeafCheck(nst);
- assert(cell);
-
- setInProcess(cell, eind);
- }
- }
-
- void flipParityAll(int st[3], int dir)
- {
- int nst[3], eind;
- for (int i = 0; i < 4; i++) {
- nst[0] = st[0] + dirCell[dir][i][0] * mindimen;
- nst[1] = st[1] + dirCell[dir][i][1] * mindimen;
- nst[2] = st[2] + dirCell[dir][i][2] * mindimen;
- eind = dirEdge[dir][i];
-
- LeafNode *cell = locateLeaf(nst);
- flipEdge(cell, eind);
- }
- }
-
- void setInProcess(LeafNode *leaf, int eind)
- {
- assert(eind >= 0 && eind <= 11);
-
- leaf->flood_fill |= (1 << eind);
- }
-
- void setOutProcess(LeafNode *leaf, int eind)
- {
- assert(eind >= 0 && eind <= 11);
-
- leaf->flood_fill &= ~(1 << eind);
- }
-
- int isInProcess(LeafNode *leaf, int eind)
- {
- assert(eind >= 0 && eind <= 11);
-
- return (leaf->flood_fill >> eind) & 1;
- }
-
- /// Generate signs at the corners from the edge parity
- void generateSigns(LeafNode *leaf, unsigned char table[], int start)
- {
- leaf->signs = table[leaf->edge_parity];
-
- if ((start ^ leaf->signs) & 1) {
- leaf->signs = ~(leaf->signs);
- }
- }
-
- /// Get edge parity
- int getEdgeParity(const LeafNode *leaf, int index) const
- {
- assert(index >= 0 && index <= 11);
-
- return (leaf->edge_parity >> index) & 1;
- }
-
- /// Get edge parity on a face
- int getFaceParity(LeafNode *leaf, int index)
- {
- int a = getEdgeParity(leaf, faceMap[index][0]) +
- getEdgeParity(leaf, faceMap[index][1]) +
- getEdgeParity(leaf, faceMap[index][2]) +
- getEdgeParity(leaf, faceMap[index][3]);
- return (a & 1);
- }
- int getFaceEdgeNum(LeafNode *leaf, int index)
- {
- int a = getEdgeParity(leaf, faceMap[index][0]) +
- getEdgeParity(leaf, faceMap[index][1]) +
- getEdgeParity(leaf, faceMap[index][2]) +
- getEdgeParity(leaf, faceMap[index][3]);
- return a;
- }
-
- /// Set edge parity
- void flipEdge(LeafNode *leaf, int index)
- {
- assert(index >= 0 && index <= 11);
-
- leaf->edge_parity ^= (1 << index);
- }
-
- /// Set 1
- void setEdge(LeafNode *leaf, int index)
- {
- assert(index >= 0 && index <= 11);
-
- leaf->edge_parity |= (1 << index);
- }
-
- /// Set 0
- void resetEdge(LeafNode *leaf, int index)
- {
- assert(index >= 0 && index <= 11);
-
- leaf->edge_parity &= ~(1 << index);
- }
-
- /// Flipping with a new intersection offset
- void createPrimalEdgesMask(LeafNode *leaf)
- {
- leaf->primary_edge_intersections = getPrimalEdgesMask2(leaf);
- }
-
- void setStoredEdgesParity(LeafNode *leaf, int pindex)
- {
- assert(pindex <= 2 && pindex >= 0);
-
- leaf->primary_edge_intersections |= (1 << pindex);
- }
-
- int getStoredEdgesParity(const LeafNode *leaf, int pindex) const
- {
- assert(pindex <= 2 && pindex >= 0);
-
- return (leaf->primary_edge_intersections >> pindex) & 1;
- }
-
- LeafNode *flipEdge(LeafNode *leaf, int index, float alpha)
- {
- flipEdge(leaf, index);
-
- if ((index & 3) == 0) {
- int ind = index / 4;
- if (getEdgeParity(leaf, index) && !getStoredEdgesParity(leaf, ind)) {
- // Create a new node
- int num = getNumEdges(leaf) + 1;
- setStoredEdgesParity(leaf, ind);
- int count = getEdgeCount(leaf, ind);
- LeafNode *nleaf = createLeaf(num);
- *nleaf = *leaf;
-
- setEdgeOffset(nleaf, alpha, count);
-
- if (num > 1) {
- float *pts = leaf->edge_intersections;
- float *npts = nleaf->edge_intersections;
- for (int i = 0; i < count; i++) {
- for (int j = 0; j < EDGE_FLOATS; j++) {
- npts[i * EDGE_FLOATS + j] = pts[i * EDGE_FLOATS + j];
- }
- }
- for (int i = count + 1; i < num; i++) {
- for (int j = 0; j < EDGE_FLOATS; j++) {
- npts[i * EDGE_FLOATS + j] = pts[(i - 1) * EDGE_FLOATS + j];
- }
- }
- }
-
-
- removeLeaf(num - 1, (LeafNode *)leaf);
- leaf = nleaf;
- }
- }
-
- return leaf;
- }
-
- /// Update parent link
- void updateParent(InternalNode *node, int len, int st[3], LeafNode *leaf)
- {
- // First, locate the parent
- int count;
- InternalNode *parent = locateParent(node, len, st, count);
-
- // Update
- parent->set_child(count, (Node *)leaf);
- }
-
- void updateParent(InternalNode *node, int len, int st[3])
- {
- if (len == dimen) {
- root = (Node *)node;
- return;
- }
-
- // First, locate the parent
- int count;
- InternalNode *parent = locateParent(len, st, count);
-
- // UPdate
- parent->set_child(count, (Node *)node);
- }
-
- /// Find edge intersection on a given edge
- int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) const
- {
- // First, locat the leaf
- const LeafNode *leaf;
- if (check) {
- leaf = locateLeafCheck(st);
- }
- else {
- leaf = locateLeaf(st);
- }
-
- if (leaf && getStoredEdgesParity(leaf, index)) {
- float off = getEdgeOffset(leaf, getEdgeCount(leaf, index));
- pt[0] = (float) st[0];
- pt[1] = (float) st[1];
- pt[2] = (float) st[2];
- pt[index] += off * mindimen;
-
- return 1;
- }
- else {
- return 0;
- }
- }
-
- /// Retrieve number of edges intersected
- int getPrimalEdgesMask(const LeafNode *leaf) const
- {
- return leaf->primary_edge_intersections;
- }
-
- int getPrimalEdgesMask2(LeafNode *leaf)
- {
- return (((leaf->edge_parity & 0x1) >> 0) |
- ((leaf->edge_parity & 0x10) >> 3) |
- ((leaf->edge_parity & 0x100) >> 6));
- }
-
- /// Get the count for a primary edge
- int getEdgeCount(const LeafNode *leaf, int index) const
- {
- return edgeCountTable[getPrimalEdgesMask(leaf)][index];
- }
- int getNumEdges(LeafNode *leaf)
- {
- return numEdgeTable[getPrimalEdgesMask(leaf)];
- }
-
- int getNumEdges2(LeafNode *leaf)
- {
- return numEdgeTable[getPrimalEdgesMask2(leaf)];
- }
-
- /// Set edge intersection
- void setEdgeOffset(LeafNode *leaf, float pt, int count)
- {
- float *pts = leaf->edge_intersections;
- pts[EDGE_FLOATS * count] = pt;
- pts[EDGE_FLOATS * count + 1] = 0;
- pts[EDGE_FLOATS * count + 2] = 0;
- pts[EDGE_FLOATS * count + 3] = 0;
- }
-
- /// Set multiple edge intersections
- void setEdgeOffsets(LeafNode *leaf, float pt[3], int len)
- {
- float *pts = leaf->edge_intersections;
- for (int i = 0; i < len; i++) {
- pts[i] = pt[i];
- }
- }
-
- /// Retrieve edge intersection
- float getEdgeOffset(const LeafNode *leaf, int count) const
- {
- return leaf->edge_intersections[4 * count];
- }
-
- /// Update method
- LeafNode *updateEdgeOffsets(LeafNode *leaf, int oldlen, int newlen, float offs[3])
- {
- // First, create a new leaf node
- LeafNode *nleaf = createLeaf(newlen);
- *nleaf = *leaf;
-
- // Next, fill in the offsets
- setEdgeOffsets(nleaf, offs, newlen);
-
- // Finally, delete the old leaf
- removeLeaf(oldlen, leaf);
-
- return nleaf;
- }
-
- /// Set minimizer index
- void setMinimizerIndex(LeafNode *leaf, int index)
- {
- leaf->minimizer_index = index;
- }
-
- /// Get minimizer index
- int getMinimizerIndex(LeafNode *leaf)
- {
- return leaf->minimizer_index;
- }
-
- int getMinimizerIndex(LeafNode *leaf, int eind)
- {
- int add = manifold_table[getSignMask(leaf)].pairs[eind][0] - 1;
- assert(add >= 0);
- return leaf->minimizer_index + add;
- }
-
- void getMinimizerIndices(LeafNode *leaf, int eind, int inds[2])
- {
- const int *add = manifold_table[getSignMask(leaf)].pairs[eind];
- inds[0] = leaf->minimizer_index + add[0] - 1;
- if (add[0] == add[1]) {
- inds[1] = -1;
- }
- else {
- inds[1] = leaf->minimizer_index + add[1] - 1;
- }
- }
-
-
- /// Set edge intersection
- void setEdgeOffsetNormal(LeafNode *leaf, float pt, float a, float b, float c, int count)
- {
- float *pts = leaf->edge_intersections;
- pts[4 * count] = pt;
- pts[4 * count + 1] = a;
- pts[4 * count + 2] = b;
- pts[4 * count + 3] = c;
- }
-
- float getEdgeOffsetNormal(LeafNode *leaf, int count, float& a, float& b, float& c)
- {
- float *pts = leaf->edge_intersections;
- a = pts[4 * count + 1];
- b = pts[4 * count + 2];
- c = pts[4 * count + 3];
- return pts[4 * count];
- }
-
- /// Set multiple edge intersections
- void setEdgeOffsetsNormals(LeafNode *leaf, const float pt[],
- const float a[], const float b[],
- const float c[], int len)
- {
- float *pts = leaf->edge_intersections;
- for (int i = 0; i < len; i++) {
- if (pt[i] > 1 || pt[i] < 0) {
- printf("\noffset: %f\n", pt[i]);
- }
- pts[i * 4] = pt[i];
- pts[i * 4 + 1] = a[i];
- pts[i * 4 + 2] = b[i];
- pts[i * 4 + 3] = c[i];
- }
- }
-
- /// Retrieve complete edge intersection
- void getEdgeIntersectionByIndex(const LeafNode *leaf, int index, int st[3],
- int len, float pt[3], float nm[3]) const
- {
- int count = getEdgeCount(leaf, index);
- const float *pts = leaf->edge_intersections;
-
- float off = pts[4 * count];
-
- pt[0] = (float) st[0];
- pt[1] = (float) st[1];
- pt[2] = (float) st[2];
- pt[index] += (off * len);
-
- nm[0] = pts[4 * count + 1];
- nm[1] = pts[4 * count + 2];
- nm[2] = pts[4 * count + 3];
- }
-
- float getEdgeOffsetNormalByIndex(LeafNode *leaf, int index, float nm[3])
- {
- int count = getEdgeCount(leaf, index);
- float *pts = leaf->edge_intersections;
-
- float off = pts[4 * count];
-
- nm[0] = pts[4 * count + 1];
- nm[1] = pts[4 * count + 2];
- nm[2] = pts[4 * count + 3];
-
- return off;
- }
-
- void fillEdgeIntersections(const LeafNode *leaf, int st[3], int len,
- float pts[12][3], float norms[12][3]) const
- {
- int i;
- // int stt[3] = {0, 0, 0};
-
- // The three primal edges are easy
- int pmask[3] = {0, 4, 8};
- for (i = 0; i < 3; i++) {
- if (getEdgeParity(leaf, pmask[i])) {
- // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]);
- getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]);
- }
- }
-
- // 3 face adjacent cubes
- int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
- int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
- for (i = 0; i < 3; i++) {
- int e1 = getEdgeParity(leaf, fmask[i][0]);
- int e2 = getEdgeParity(leaf, fmask[i][1]);
- if (e1 || e2) {
- int nst[3] = {st[0], st[1], st[2]};
- nst[i] += len;
- // int nstt[3] = {0, 0, 0};
- // nstt[i] += 1;
- const LeafNode *node = locateLeaf(nst);
-
- if (e1) {
- // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]);
- getEdgeIntersectionByIndex(node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]);
- }
- if (e2) {
- // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]);
- getEdgeIntersectionByIndex(node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]);
- }
- }
- }
-
- // 3 edge adjacent cubes
- int emask[3] = {3, 7, 11};
- int eemask[3] = {0, 1, 2};
- for (i = 0; i < 3; i++) {
- if (getEdgeParity(leaf, emask[i])) {
- int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
- nst[i] -= len;
- // int nstt[3] = {1, 1, 1};
- // nstt[i] -= 1;
- const LeafNode *node = locateLeaf(nst);
-
- // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]);
- getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]);
- }
- }
- }
-
-
- void fillEdgeIntersections(const LeafNode *leaf, int st[3], int len,
- float pts[12][3], float norms[12][3],
- int parity[12]) const
- {
- int i;
- for (i = 0; i < 12; i++) {
- parity[i] = 0;
- }
- // int stt[3] = {0, 0, 0};
-
- // The three primal edges are easy
- int pmask[3] = {0, 4, 8};
- for (i = 0; i < 3; i++) {
- if (getStoredEdgesParity(leaf, i)) {
- // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]);
- getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]);
- parity[pmask[i]] = 1;
- }
- }
-
- // 3 face adjacent cubes
- int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
- int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
- for (i = 0; i < 3; i++) {
- {
- int nst[3] = {st[0], st[1], st[2]};
- nst[i] += len;
- // int nstt[3] = {0, 0, 0};
- // nstt[i] += 1;
- const LeafNode *node = locateLeafCheck(nst);
- if (node == NULL) {
- continue;
- }
-
- int e1 = getStoredEdgesParity(node, femask[i][0]);
- int e2 = getStoredEdgesParity(node, femask[i][1]);
-
- if (e1) {
- // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]);
- getEdgeIntersectionByIndex(node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]);
- parity[fmask[i][0]] = 1;
- }
- if (e2) {
- // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]);
- getEdgeIntersectionByIndex(node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]);
- parity[fmask[i][1]] = 1;
- }
- }
- }
-
- // 3 edge adjacent cubes
- int emask[3] = {3, 7, 11};
- int eemask[3] = {0, 1, 2};
- for (i = 0; i < 3; i++) {
- // if(getEdgeParity(leaf, emask[i]))
- {
- int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
- nst[i] -= len;
- // int nstt[3] = {1, 1, 1};
- // nstt[i] -= 1;
- const LeafNode *node = locateLeafCheck(nst);
- if (node == NULL) {
- continue;
- }
-
- if (getStoredEdgesParity(node, eemask[i])) {
- // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]);
- getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]);
- parity[emask[i]] = 1;
- }
- }
- }
- }
-
- void fillEdgeOffsetsNormals(LeafNode *leaf, int st[3], int len, float pts[12], float norms[12][3], int parity[12])
- {
- int i;
- for (i = 0; i < 12; i++) {
- parity[i] = 0;
- }
- // int stt[3] = {0, 0, 0};
-
- // The three primal edges are easy
- int pmask[3] = {0, 4, 8};
- for (i = 0; i < 3; i++) {
- if (getStoredEdgesParity(leaf, i)) {
- pts[pmask[i]] = getEdgeOffsetNormalByIndex(leaf, i, norms[pmask[i]]);
- parity[pmask[i]] = 1;
- }
- }
-
- // 3 face adjacent cubes
- int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
- int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
- for (i = 0; i < 3; i++) {
- {
- int nst[3] = {st[0], st[1], st[2]};
- nst[i] += len;
- // int nstt[3] = {0, 0, 0};
- // nstt[i] += 1;
- LeafNode *node = locateLeafCheck(nst);
- if (node == NULL) {
- continue;
- }
-
- int e1 = getStoredEdgesParity(node, femask[i][0]);
- int e2 = getStoredEdgesParity(node, femask[i][1]);
-
- if (e1) {
- pts[fmask[i][0]] = getEdgeOffsetNormalByIndex(node, femask[i][0], norms[fmask[i][0]]);
- parity[fmask[i][0]] = 1;
- }
- if (e2) {
- pts[fmask[i][1]] = getEdgeOffsetNormalByIndex(node, femask[i][1], norms[fmask[i][1]]);
- parity[fmask[i][1]] = 1;
- }
- }
- }
-
- // 3 edge adjacent cubes
- int emask[3] = {3, 7, 11};
- int eemask[3] = {0, 1, 2};
- for (i = 0; i < 3; i++) {
- // if(getEdgeParity(leaf, emask[i]))
- {
- int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
- nst[i] -= len;
- // int nstt[3] = {1, 1, 1};
- // nstt[i] -= 1;
- LeafNode *node = locateLeafCheck(nst);
- if (node == NULL) {
- continue;
- }
-
- if (getStoredEdgesParity(node, eemask[i])) {
- pts[emask[i]] = getEdgeOffsetNormalByIndex(node, eemask[i], norms[emask[i]]);
- parity[emask[i]] = 1;
- }
- }
- }
- }
-
-
- /// Update method
- LeafNode *updateEdgeOffsetsNormals(LeafNode *leaf, int oldlen, int newlen, float offs[3], float a[3], float b[3], float c[3])
- {
- // First, create a new leaf node
- LeafNode *nleaf = createLeaf(newlen);
- *nleaf = *leaf;
-
- // Next, fill in the offsets
- setEdgeOffsetsNormals(nleaf, offs, a, b, c, newlen);
-
- // Finally, delete the old leaf
- removeLeaf(oldlen, leaf);
-
- return nleaf;
- }
-
- /// Locate a leaf
- /// WARNING: assuming this leaf already exists!
-
- LeafNode *locateLeaf(int st[3])
- {
- Node *node = (Node *)root;
- for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
- int index = (((st[0] >> i) & 1) << 2) |
- (((st[1] >> i) & 1) << 1) |
- (((st[2] >> i) & 1));
- node = node->internal.get_child(node->internal.get_child_count(index));
- }
-
- return &node->leaf;
- }
-
- const LeafNode *locateLeaf(int st[3]) const
- {
- const Node *node = root;
- for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
- int index = (((st[0] >> i) & 1) << 2) |
- (((st[1] >> i) & 1) << 1) |
- (((st[2] >> i) & 1));
- node = node->internal.get_child(node->internal.get_child_count(index));
- }
-
- return &node->leaf;
- }
-
- LeafNode *locateLeaf(InternalNode *parent, int len, int st[3])
- {
- Node *node = (Node *)parent;
- int index;
- for (int i = len / 2; i >= mindimen; i >>= 1) {
- index = (((st[0] & i) ? 4 : 0) |
- ((st[1] & i) ? 2 : 0) |
- ((st[2] & i) ? 1 : 0));
- node = node->internal.get_child(node->internal.get_child_count(index));
- }
-
- return &node->leaf;
- }
-
- LeafNode *locateLeafCheck(int st[3])
- {
- Node *node = (Node *)root;
- for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
- int index = (((st[0] >> i) & 1) << 2) |
- (((st[1] >> i) & 1) << 1) |
- (((st[2] >> i) & 1));
- if (!node->internal.has_child(index)) {
- return NULL;
- }
- node = node->internal.get_child(node->internal.get_child_count(index));
- }
-
- return &node->leaf;
- }
-
- const LeafNode *locateLeafCheck(int st[3]) const
- {
- const Node *node = root;
- for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
- int index = (((st[0] >> i) & 1) << 2) |
- (((st[1] >> i) & 1) << 1) |
- (((st[2] >> i) & 1));
- if (!node->internal.has_child(index)) {
- return NULL;
- }
- node = node->internal.get_child(node->internal.get_child_count(index));
- }
-
- return &node->leaf;
- }
-
- InternalNode *locateParent(int len, int st[3], int& count)
- {
- InternalNode *node = (InternalNode *)root;
- InternalNode *pre = NULL;
- int index = 0;
- for (int i = dimen / 2; i >= len; i >>= 1) {
- index = (((st[0] & i) ? 4 : 0) |
- ((st[1] & i) ? 2 : 0) |
- ((st[2] & i) ? 1 : 0));
- pre = node;
- node = &node->get_child(node->get_child_count(index))->internal;
- }
-
- count = pre->get_child_count(index);
- return pre;
- }
-
- InternalNode *locateParent(InternalNode *parent, int len, int st[3], int& count)
- {
- InternalNode *node = parent;
- InternalNode *pre = NULL;
- int index = 0;
- for (int i = len / 2; i >= mindimen; i >>= 1) {
- index = (((st[0] & i) ? 4 : 0) |
- ((st[1] & i) ? 2 : 0) |
- ((st[2] & i) ? 1 : 0));
- pre = node;
- node = &node->get_child(node->get_child_count(index))->internal;
- }
-
- count = pre->get_child_count(index);
- return pre;
- }
-
- /************ Operators for internal nodes ************/
-
-
- /// Add a kid to an existing internal node
- InternalNode *addChild(InternalNode *node, int index, Node *child, int aLeaf)
- {
- // Create new internal node
- int num = node->get_num_children();
- InternalNode *rnode = createInternal(num + 1);
-
- // Establish children
- int i;
- int count1 = 0, count2 = 0;
- for (i = 0; i < 8; i++) {
- if (i == index) {
- if (aLeaf) {
- rnode->set_leaf_child(i, count2, &child->leaf);
- }
- else {
- rnode->set_internal_child(i, count2, &child->internal);
- }
- count2++;
- }
- else if (node->has_child(i)) {
- if (node->is_child_leaf(i)) {
- rnode->set_leaf_child(i, count2, &node->get_child(count1)->leaf);
- }
- else {
- rnode->set_internal_child(i, count2, &node->get_child(count1)->internal);
- }
- count1++;
- count2++;
- }
- }
-
- removeInternal(num, node);
- return rnode;
- }
-
- /// Allocate a node
- InternalNode *createInternal(int length)
- {
- InternalNode *inode = (InternalNode *)alloc[length]->allocate();
- inode->has_child_bitfield = 0;
- inode->child_is_leaf_bitfield = 0;
- return inode;
- }
-
- LeafNode *createLeaf(int length)
- {
- assert(length <= 3);
-
- LeafNode *lnode = (LeafNode *)leafalloc[length]->allocate();
- lnode->edge_parity = 0;
- lnode->primary_edge_intersections = 0;
- lnode->signs = 0;
-
- return lnode;
- }
-
- void removeInternal(int num, InternalNode *node)
- {
- alloc[num]->deallocate(node);
- }
-
- void removeLeaf(int num, LeafNode *leaf)
- {
- assert(num >= 0 && num <= 3);
- leafalloc[num]->deallocate(leaf);
- }
-
- /// Add a leaf (by creating a new par node with the leaf added)
- InternalNode *addLeafChild(InternalNode *par, int index, int count,
- LeafNode *leaf)
- {
- int num = par->get_num_children() + 1;
- InternalNode *npar = createInternal(num);
- *npar = *par;
-
- if (num == 1) {
- npar->set_leaf_child(index, 0, leaf);
- }
- else {
- int i;
- for (i = 0; i < count; i++) {
- npar->set_child(i, par->get_child(i));
- }
- npar->set_leaf_child(index, count, leaf);
- for (i = count + 1; i < num; i++) {
- npar->set_child(i, par->get_child(i - 1));
- }
- }
-
- removeInternal(num - 1, par);
- return npar;
- }
-
- InternalNode *addInternalChild(InternalNode *par, int index, int count,
- InternalNode *node)
- {
- int num = par->get_num_children() + 1;
- InternalNode *npar = createInternal(num);
- *npar = *par;
-
- if (num == 1) {
- npar->set_internal_child(index, 0, node);
- }
- else {
- int i;
- for (i = 0; i < count; i++) {
- npar->set_child(i, par->get_child(i));
- }
- npar->set_internal_child(index, count, node);
- for (i = count + 1; i < num; i++) {
- npar->set_child(i, par->get_child(i - 1));
- }
- }
-
- removeInternal(num - 1, par);
- return npar;
- }
+ /************ Operators for all nodes ************/
+
+ /// Lookup table
+ int numEdgeTable[8];
+ int edgeCountTable[8][3];
+
+ /// Build up lookup table
+ void buildTable()
+ {
+ for (int i = 0; i < 256; i++) {
+ InternalNode::numChildrenTable[i] = 0;
+ int count = 0;
+ for (int j = 0; j < 8; j++) {
+ InternalNode::numChildrenTable[i] += ((i >> j) & 1);
+ InternalNode::childrenCountTable[i][j] = count;
+ InternalNode::childrenIndexTable[i][count] = j;
+ count += ((i >> j) & 1);
+ }
+ }
+
+ for (int i = 0; i < 8; i++) {
+ numEdgeTable[i] = 0;
+ int count = 0;
+ for (int j = 0; j < 3; j++) {
+ numEdgeTable[i] += ((i >> j) & 1);
+ edgeCountTable[i][j] = count;
+ count += ((i >> j) & 1);
+ }
+ }
+ }
+
+ int getSign(Node *node, int height, int index)
+ {
+ if (height == 0) {
+ return getSign(&node->leaf, index);
+ }
+ else {
+ if (node->internal.has_child(index)) {
+ return getSign(
+ node->internal.get_child(node->internal.get_child_count(index)), height - 1, index);
+ }
+ else {
+ return getSign(
+ node->internal.get_child(0), height - 1, 7 - node->internal.get_child_index(0));
+ }
+ }
+ }
+
+ /************ Operators for leaf nodes ************/
+
+ void printInfo(int st[3])
+ {
+ printf("INFO AT: %d %d %d\n", st[0] >> minshift, st[1] >> minshift, st[2] >> minshift);
+ LeafNode *leaf = (LeafNode *)locateLeafCheck(st);
+ if (leaf)
+ printInfo(leaf);
+ else
+ printf("Leaf not exists!\n");
+ }
+
+ void printInfo(const LeafNode *leaf)
+ {
+ /*
+ printf("Edge mask: ");
+ for(int i = 0; i < 12; i ++)
+ {
+ printf("%d ", getEdgeParity(leaf, i));
+ }
+ printf("\n");
+ printf("Stored edge mask: ");
+ for(i = 0; i < 3; i ++)
+ {
+ printf("%d ", getStoredEdgesParity(leaf, i));
+ }
+ printf("\n");
+ */
+ printf("Sign mask: ");
+ for (int i = 0; i < 8; i++) {
+ printf("%d ", getSign(leaf, i));
+ }
+ printf("\n");
+ }
+
+ /// Retrieve signs
+ int getSign(const LeafNode *leaf, int index)
+ {
+ return ((leaf->signs >> index) & 1);
+ }
+
+ /// Set sign
+ void setSign(LeafNode *leaf, int index)
+ {
+ leaf->signs |= (1 << index);
+ }
+
+ void setSign(LeafNode *leaf, int index, int sign)
+ {
+ leaf->signs &= (~(1 << index));
+ leaf->signs |= ((sign & 1) << index);
+ }
+
+ int getSignMask(const LeafNode *leaf) const
+ {
+ return leaf->signs;
+ }
+
+ void setInProcessAll(int st[3], int dir)
+ {
+ int nst[3], eind;
+ for (int i = 0; i < 4; i++) {
+ nst[0] = st[0] + dirCell[dir][i][0] * mindimen;
+ nst[1] = st[1] + dirCell[dir][i][1] * mindimen;
+ nst[2] = st[2] + dirCell[dir][i][2] * mindimen;
+ eind = dirEdge[dir][i];
+
+ LeafNode *cell = locateLeafCheck(nst);
+ assert(cell);
+
+ setInProcess(cell, eind);
+ }
+ }
+
+ void flipParityAll(int st[3], int dir)
+ {
+ int nst[3], eind;
+ for (int i = 0; i < 4; i++) {
+ nst[0] = st[0] + dirCell[dir][i][0] * mindimen;
+ nst[1] = st[1] + dirCell[dir][i][1] * mindimen;
+ nst[2] = st[2] + dirCell[dir][i][2] * mindimen;
+ eind = dirEdge[dir][i];
+
+ LeafNode *cell = locateLeaf(nst);
+ flipEdge(cell, eind);
+ }
+ }
+
+ void setInProcess(LeafNode *leaf, int eind)
+ {
+ assert(eind >= 0 && eind <= 11);
+
+ leaf->flood_fill |= (1 << eind);
+ }
+
+ void setOutProcess(LeafNode *leaf, int eind)
+ {
+ assert(eind >= 0 && eind <= 11);
+
+ leaf->flood_fill &= ~(1 << eind);
+ }
+
+ int isInProcess(LeafNode *leaf, int eind)
+ {
+ assert(eind >= 0 && eind <= 11);
+
+ return (leaf->flood_fill >> eind) & 1;
+ }
+
+ /// Generate signs at the corners from the edge parity
+ void generateSigns(LeafNode *leaf, unsigned char table[], int start)
+ {
+ leaf->signs = table[leaf->edge_parity];
+
+ if ((start ^ leaf->signs) & 1) {
+ leaf->signs = ~(leaf->signs);
+ }
+ }
+
+ /// Get edge parity
+ int getEdgeParity(const LeafNode *leaf, int index) const
+ {
+ assert(index >= 0 && index <= 11);
+
+ return (leaf->edge_parity >> index) & 1;
+ }
+
+ /// Get edge parity on a face
+ int getFaceParity(LeafNode *leaf, int index)
+ {
+ int a = getEdgeParity(leaf, faceMap[index][0]) + getEdgeParity(leaf, faceMap[index][1]) +
+ getEdgeParity(leaf, faceMap[index][2]) + getEdgeParity(leaf, faceMap[index][3]);
+ return (a & 1);
+ }
+ int getFaceEdgeNum(LeafNode *leaf, int index)
+ {
+ int a = getEdgeParity(leaf, faceMap[index][0]) + getEdgeParity(leaf, faceMap[index][1]) +
+ getEdgeParity(leaf, faceMap[index][2]) + getEdgeParity(leaf, faceMap[index][3]);
+ return a;
+ }
+
+ /// Set edge parity
+ void flipEdge(LeafNode *leaf, int index)
+ {
+ assert(index >= 0 && index <= 11);
+
+ leaf->edge_parity ^= (1 << index);
+ }
+
+ /// Set 1
+ void setEdge(LeafNode *leaf, int index)
+ {
+ assert(index >= 0 && index <= 11);
+
+ leaf->edge_parity |= (1 << index);
+ }
+
+ /// Set 0
+ void resetEdge(LeafNode *leaf, int index)
+ {
+ assert(index >= 0 && index <= 11);
+
+ leaf->edge_parity &= ~(1 << index);
+ }
+
+ /// Flipping with a new intersection offset
+ void createPrimalEdgesMask(LeafNode *leaf)
+ {
+ leaf->primary_edge_intersections = getPrimalEdgesMask2(leaf);
+ }
+
+ void setStoredEdgesParity(LeafNode *leaf, int pindex)
+ {
+ assert(pindex <= 2 && pindex >= 0);
+
+ leaf->primary_edge_intersections |= (1 << pindex);
+ }
+
+ int getStoredEdgesParity(const LeafNode *leaf, int pindex) const
+ {
+ assert(pindex <= 2 && pindex >= 0);
+
+ return (leaf->primary_edge_intersections >> pindex) & 1;
+ }
+
+ LeafNode *flipEdge(LeafNode *leaf, int index, float alpha)
+ {
+ flipEdge(leaf, index);
+
+ if ((index & 3) == 0) {
+ int ind = index / 4;
+ if (getEdgeParity(leaf, index) && !getStoredEdgesParity(leaf, ind)) {
+ // Create a new node
+ int num = getNumEdges(leaf) + 1;
+ setStoredEdgesParity(leaf, ind);
+ int count = getEdgeCount(leaf, ind);
+ LeafNode *nleaf = createLeaf(num);
+ *nleaf = *leaf;
+
+ setEdgeOffset(nleaf, alpha, count);
+
+ if (num > 1) {
+ float *pts = leaf->edge_intersections;
+ float *npts = nleaf->edge_intersections;
+ for (int i = 0; i < count; i++) {
+ for (int j = 0; j < EDGE_FLOATS; j++) {
+ npts[i * EDGE_FLOATS + j] = pts[i * EDGE_FLOATS + j];
+ }
+ }
+ for (int i = count + 1; i < num; i++) {
+ for (int j = 0; j < EDGE_FLOATS; j++) {
+ npts[i * EDGE_FLOATS + j] = pts[(i - 1) * EDGE_FLOATS + j];
+ }
+ }
+ }
+
+ removeLeaf(num - 1, (LeafNode *)leaf);
+ leaf = nleaf;
+ }
+ }
+
+ return leaf;
+ }
+
+ /// Update parent link
+ void updateParent(InternalNode *node, int len, int st[3], LeafNode *leaf)
+ {
+ // First, locate the parent
+ int count;
+ InternalNode *parent = locateParent(node, len, st, count);
+
+ // Update
+ parent->set_child(count, (Node *)leaf);
+ }
+
+ void updateParent(InternalNode *node, int len, int st[3])
+ {
+ if (len == dimen) {
+ root = (Node *)node;
+ return;
+ }
+
+ // First, locate the parent
+ int count;
+ InternalNode *parent = locateParent(len, st, count);
+
+ // UPdate
+ parent->set_child(count, (Node *)node);
+ }
+
+ /// Find edge intersection on a given edge
+ int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) const
+ {
+ // First, locat the leaf
+ const LeafNode *leaf;
+ if (check) {
+ leaf = locateLeafCheck(st);
+ }
+ else {
+ leaf = locateLeaf(st);
+ }
+
+ if (leaf && getStoredEdgesParity(leaf, index)) {
+ float off = getEdgeOffset(leaf, getEdgeCount(leaf, index));
+ pt[0] = (float)st[0];
+ pt[1] = (float)st[1];
+ pt[2] = (float)st[2];
+ pt[index] += off * mindimen;
+
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /// Retrieve number of edges intersected
+ int getPrimalEdgesMask(const LeafNode *leaf) const
+ {
+ return leaf->primary_edge_intersections;
+ }
+
+ int getPrimalEdgesMask2(LeafNode *leaf)
+ {
+ return (((leaf->edge_parity & 0x1) >> 0) | ((leaf->edge_parity & 0x10) >> 3) |
+ ((leaf->edge_parity & 0x100) >> 6));
+ }
+
+ /// Get the count for a primary edge
+ int getEdgeCount(const LeafNode *leaf, int index) const
+ {
+ return edgeCountTable[getPrimalEdgesMask(leaf)][index];
+ }
+ int getNumEdges(LeafNode *leaf)
+ {
+ return numEdgeTable[getPrimalEdgesMask(leaf)];
+ }
+
+ int getNumEdges2(LeafNode *leaf)
+ {
+ return numEdgeTable[getPrimalEdgesMask2(leaf)];
+ }
+
+ /// Set edge intersection
+ void setEdgeOffset(LeafNode *leaf, float pt, int count)
+ {
+ float *pts = leaf->edge_intersections;
+ pts[EDGE_FLOATS * count] = pt;
+ pts[EDGE_FLOATS * count + 1] = 0;
+ pts[EDGE_FLOATS * count + 2] = 0;
+ pts[EDGE_FLOATS * count + 3] = 0;
+ }
+
+ /// Set multiple edge intersections
+ void setEdgeOffsets(LeafNode *leaf, float pt[3], int len)
+ {
+ float *pts = leaf->edge_intersections;
+ for (int i = 0; i < len; i++) {
+ pts[i] = pt[i];
+ }
+ }
+
+ /// Retrieve edge intersection
+ float getEdgeOffset(const LeafNode *leaf, int count) const
+ {
+ return leaf->edge_intersections[4 * count];
+ }
+
+ /// Update method
+ LeafNode *updateEdgeOffsets(LeafNode *leaf, int oldlen, int newlen, float offs[3])
+ {
+ // First, create a new leaf node
+ LeafNode *nleaf = createLeaf(newlen);
+ *nleaf = *leaf;
+
+ // Next, fill in the offsets
+ setEdgeOffsets(nleaf, offs, newlen);
+
+ // Finally, delete the old leaf
+ removeLeaf(oldlen, leaf);
+
+ return nleaf;
+ }
+
+ /// Set minimizer index
+ void setMinimizerIndex(LeafNode *leaf, int index)
+ {
+ leaf->minimizer_index = index;
+ }
+
+ /// Get minimizer index
+ int getMinimizerIndex(LeafNode *leaf)
+ {
+ return leaf->minimizer_index;
+ }
+
+ int getMinimizerIndex(LeafNode *leaf, int eind)
+ {
+ int add = manifold_table[getSignMask(leaf)].pairs[eind][0] - 1;
+ assert(add >= 0);
+ return leaf->minimizer_index + add;
+ }
+
+ void getMinimizerIndices(LeafNode *leaf, int eind, int inds[2])
+ {
+ const int *add = manifold_table[getSignMask(leaf)].pairs[eind];
+ inds[0] = leaf->minimizer_index + add[0] - 1;
+ if (add[0] == add[1]) {
+ inds[1] = -1;
+ }
+ else {
+ inds[1] = leaf->minimizer_index + add[1] - 1;
+ }
+ }
+
+ /// Set edge intersection
+ void setEdgeOffsetNormal(LeafNode *leaf, float pt, float a, float b, float c, int count)
+ {
+ float *pts = leaf->edge_intersections;
+ pts[4 * count] = pt;
+ pts[4 * count + 1] = a;
+ pts[4 * count + 2] = b;
+ pts[4 * count + 3] = c;
+ }
+
+ float getEdgeOffsetNormal(LeafNode *leaf, int count, float &a, float &b, float &c)
+ {
+ float *pts = leaf->edge_intersections;
+ a = pts[4 * count + 1];
+ b = pts[4 * count + 2];
+ c = pts[4 * count + 3];
+ return pts[4 * count];
+ }
+
+ /// Set multiple edge intersections
+ void setEdgeOffsetsNormals(
+ LeafNode *leaf, const float pt[], const float a[], const float b[], const float c[], int len)
+ {
+ float *pts = leaf->edge_intersections;
+ for (int i = 0; i < len; i++) {
+ if (pt[i] > 1 || pt[i] < 0) {
+ printf("\noffset: %f\n", pt[i]);
+ }
+ pts[i * 4] = pt[i];
+ pts[i * 4 + 1] = a[i];
+ pts[i * 4 + 2] = b[i];
+ pts[i * 4 + 3] = c[i];
+ }
+ }
+
+ /// Retrieve complete edge intersection
+ void getEdgeIntersectionByIndex(
+ const LeafNode *leaf, int index, int st[3], int len, float pt[3], float nm[3]) const
+ {
+ int count = getEdgeCount(leaf, index);
+ const float *pts = leaf->edge_intersections;
+
+ float off = pts[4 * count];
+
+ pt[0] = (float)st[0];
+ pt[1] = (float)st[1];
+ pt[2] = (float)st[2];
+ pt[index] += (off * len);
+
+ nm[0] = pts[4 * count + 1];
+ nm[1] = pts[4 * count + 2];
+ nm[2] = pts[4 * count + 3];
+ }
+
+ float getEdgeOffsetNormalByIndex(LeafNode *leaf, int index, float nm[3])
+ {
+ int count = getEdgeCount(leaf, index);
+ float *pts = leaf->edge_intersections;
+
+ float off = pts[4 * count];
+
+ nm[0] = pts[4 * count + 1];
+ nm[1] = pts[4 * count + 2];
+ nm[2] = pts[4 * count + 3];
+
+ return off;
+ }
+
+ void fillEdgeIntersections(
+ const LeafNode *leaf, int st[3], int len, float pts[12][3], float norms[12][3]) const
+ {
+ int i;
+ // int stt[3] = {0, 0, 0};
+
+ // The three primal edges are easy
+ int pmask[3] = {0, 4, 8};
+ for (i = 0; i < 3; i++) {
+ if (getEdgeParity(leaf, pmask[i])) {
+ // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]);
+ getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]);
+ }
+ }
+
+ // 3 face adjacent cubes
+ int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
+ int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
+ for (i = 0; i < 3; i++) {
+ int e1 = getEdgeParity(leaf, fmask[i][0]);
+ int e2 = getEdgeParity(leaf, fmask[i][1]);
+ if (e1 || e2) {
+ int nst[3] = {st[0], st[1], st[2]};
+ nst[i] += len;
+ // int nstt[3] = {0, 0, 0};
+ // nstt[i] += 1;
+ const LeafNode *node = locateLeaf(nst);
+
+ if (e1) {
+ // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]);
+ getEdgeIntersectionByIndex(
+ node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]);
+ }
+ if (e2) {
+ // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]);
+ getEdgeIntersectionByIndex(
+ node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]);
+ }
+ }
+ }
+
+ // 3 edge adjacent cubes
+ int emask[3] = {3, 7, 11};
+ int eemask[3] = {0, 1, 2};
+ for (i = 0; i < 3; i++) {
+ if (getEdgeParity(leaf, emask[i])) {
+ int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
+ nst[i] -= len;
+ // int nstt[3] = {1, 1, 1};
+ // nstt[i] -= 1;
+ const LeafNode *node = locateLeaf(nst);
+
+ // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]);
+ getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]);
+ }
+ }
+ }
+
+ void fillEdgeIntersections(const LeafNode *leaf,
+ int st[3],
+ int len,
+ float pts[12][3],
+ float norms[12][3],
+ int parity[12]) const
+ {
+ int i;
+ for (i = 0; i < 12; i++) {
+ parity[i] = 0;
+ }
+ // int stt[3] = {0, 0, 0};
+
+ // The three primal edges are easy
+ int pmask[3] = {0, 4, 8};
+ for (i = 0; i < 3; i++) {
+ if (getStoredEdgesParity(leaf, i)) {
+ // getEdgeIntersectionByIndex(leaf, i, stt, 1, pts[pmask[i]], norms[pmask[i]]);
+ getEdgeIntersectionByIndex(leaf, i, st, len, pts[pmask[i]], norms[pmask[i]]);
+ parity[pmask[i]] = 1;
+ }
+ }
+
+ // 3 face adjacent cubes
+ int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
+ int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
+ for (i = 0; i < 3; i++) {
+ {
+ int nst[3] = {st[0], st[1], st[2]};
+ nst[i] += len;
+ // int nstt[3] = {0, 0, 0};
+ // nstt[i] += 1;
+ const LeafNode *node = locateLeafCheck(nst);
+ if (node == NULL) {
+ continue;
+ }
+
+ int e1 = getStoredEdgesParity(node, femask[i][0]);
+ int e2 = getStoredEdgesParity(node, femask[i][1]);
+
+ if (e1) {
+ // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]);
+ getEdgeIntersectionByIndex(
+ node, femask[i][0], nst, len, pts[fmask[i][0]], norms[fmask[i][0]]);
+ parity[fmask[i][0]] = 1;
+ }
+ if (e2) {
+ // getEdgeIntersectionByIndex(node, femask[i][1], nstt, 1, pts[fmask[i][1]], norms[fmask[i][1]]);
+ getEdgeIntersectionByIndex(
+ node, femask[i][1], nst, len, pts[fmask[i][1]], norms[fmask[i][1]]);
+ parity[fmask[i][1]] = 1;
+ }
+ }
+ }
+
+ // 3 edge adjacent cubes
+ int emask[3] = {3, 7, 11};
+ int eemask[3] = {0, 1, 2};
+ for (i = 0; i < 3; i++) {
+ // if(getEdgeParity(leaf, emask[i]))
+ {
+ int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
+ nst[i] -= len;
+ // int nstt[3] = {1, 1, 1};
+ // nstt[i] -= 1;
+ const LeafNode *node = locateLeafCheck(nst);
+ if (node == NULL) {
+ continue;
+ }
+
+ if (getStoredEdgesParity(node, eemask[i])) {
+ // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]);
+ getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]);
+ parity[emask[i]] = 1;
+ }
+ }
+ }
+ }
+
+ void fillEdgeOffsetsNormals(
+ LeafNode *leaf, int st[3], int len, float pts[12], float norms[12][3], int parity[12])
+ {
+ int i;
+ for (i = 0; i < 12; i++) {
+ parity[i] = 0;
+ }
+ // int stt[3] = {0, 0, 0};
+
+ // The three primal edges are easy
+ int pmask[3] = {0, 4, 8};
+ for (i = 0; i < 3; i++) {
+ if (getStoredEdgesParity(leaf, i)) {
+ pts[pmask[i]] = getEdgeOffsetNormalByIndex(leaf, i, norms[pmask[i]]);
+ parity[pmask[i]] = 1;
+ }
+ }
+
+ // 3 face adjacent cubes
+ int fmask[3][2] = {{6, 10}, {2, 9}, {1, 5}};
+ int femask[3][2] = {{1, 2}, {0, 2}, {0, 1}};
+ for (i = 0; i < 3; i++) {
+ {
+ int nst[3] = {st[0], st[1], st[2]};
+ nst[i] += len;
+ // int nstt[3] = {0, 0, 0};
+ // nstt[i] += 1;
+ LeafNode *node = locateLeafCheck(nst);
+ if (node == NULL) {
+ continue;
+ }
+
+ int e1 = getStoredEdgesParity(node, femask[i][0]);
+ int e2 = getStoredEdgesParity(node, femask[i][1]);
+
+ if (e1) {
+ pts[fmask[i][0]] = getEdgeOffsetNormalByIndex(node, femask[i][0], norms[fmask[i][0]]);
+ parity[fmask[i][0]] = 1;
+ }
+ if (e2) {
+ pts[fmask[i][1]] = getEdgeOffsetNormalByIndex(node, femask[i][1], norms[fmask[i][1]]);
+ parity[fmask[i][1]] = 1;
+ }
+ }
+ }
+
+ // 3 edge adjacent cubes
+ int emask[3] = {3, 7, 11};
+ int eemask[3] = {0, 1, 2};
+ for (i = 0; i < 3; i++) {
+ // if(getEdgeParity(leaf, emask[i]))
+ {
+ int nst[3] = {st[0] + len, st[1] + len, st[2] + len};
+ nst[i] -= len;
+ // int nstt[3] = {1, 1, 1};
+ // nstt[i] -= 1;
+ LeafNode *node = locateLeafCheck(nst);
+ if (node == NULL) {
+ continue;
+ }
+
+ if (getStoredEdgesParity(node, eemask[i])) {
+ pts[emask[i]] = getEdgeOffsetNormalByIndex(node, eemask[i], norms[emask[i]]);
+ parity[emask[i]] = 1;
+ }
+ }
+ }
+ }
+
+ /// Update method
+ LeafNode *updateEdgeOffsetsNormals(
+ LeafNode *leaf, int oldlen, int newlen, float offs[3], float a[3], float b[3], float c[3])
+ {
+ // First, create a new leaf node
+ LeafNode *nleaf = createLeaf(newlen);
+ *nleaf = *leaf;
+
+ // Next, fill in the offsets
+ setEdgeOffsetsNormals(nleaf, offs, a, b, c, newlen);
+
+ // Finally, delete the old leaf
+ removeLeaf(oldlen, leaf);
+
+ return nleaf;
+ }
+
+ /// Locate a leaf
+ /// WARNING: assuming this leaf already exists!
+
+ LeafNode *locateLeaf(int st[3])
+ {
+ Node *node = (Node *)root;
+ for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
+ int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
+ node = node->internal.get_child(node->internal.get_child_count(index));
+ }
+
+ return &node->leaf;
+ }
+
+ const LeafNode *locateLeaf(int st[3]) const
+ {
+ const Node *node = root;
+ for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
+ int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
+ node = node->internal.get_child(node->internal.get_child_count(index));
+ }
+
+ return &node->leaf;
+ }
+
+ LeafNode *locateLeaf(InternalNode *parent, int len, int st[3])
+ {
+ Node *node = (Node *)parent;
+ int index;
+ for (int i = len / 2; i >= mindimen; i >>= 1) {
+ index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0));
+ node = node->internal.get_child(node->internal.get_child_count(index));
+ }
+
+ return &node->leaf;
+ }
+
+ LeafNode *locateLeafCheck(int st[3])
+ {
+ Node *node = (Node *)root;
+ for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
+ int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
+ if (!node->internal.has_child(index)) {
+ return NULL;
+ }
+ node = node->internal.get_child(node->internal.get_child_count(index));
+ }
+
+ return &node->leaf;
+ }
+
+ const LeafNode *locateLeafCheck(int st[3]) const
+ {
+ const Node *node = root;
+ for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) {
+ int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1));
+ if (!node->internal.has_child(index)) {
+ return NULL;
+ }
+ node = node->internal.get_child(node->internal.get_child_count(index));
+ }
+
+ return &node->leaf;
+ }
+
+ InternalNode *locateParent(int len, int st[3], int &count)
+ {
+ InternalNode *node = (InternalNode *)root;
+ InternalNode *pre = NULL;
+ int index = 0;
+ for (int i = dimen / 2; i >= len; i >>= 1) {
+ index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0));
+ pre = node;
+ node = &node->get_child(node->get_child_count(index))->internal;
+ }
+
+ count = pre->get_child_count(index);
+ return pre;
+ }
+
+ InternalNode *locateParent(InternalNode *parent, int len, int st[3], int &count)
+ {
+ InternalNode *node = parent;
+ InternalNode *pre = NULL;
+ int index = 0;
+ for (int i = len / 2; i >= mindimen; i >>= 1) {
+ index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0));
+ pre = node;
+ node = &node->get_child(node->get_child_count(index))->internal;
+ }
+
+ count = pre->get_child_count(index);
+ return pre;
+ }
+
+ /************ Operators for internal nodes ************/
+
+ /// Add a kid to an existing internal node
+ InternalNode *addChild(InternalNode *node, int index, Node *child, int aLeaf)
+ {
+ // Create new internal node
+ int num = node->get_num_children();
+ InternalNode *rnode = createInternal(num + 1);
+
+ // Establish children
+ int i;
+ int count1 = 0, count2 = 0;
+ for (i = 0; i < 8; i++) {
+ if (i == index) {
+ if (aLeaf) {
+ rnode->set_leaf_child(i, count2, &child->leaf);
+ }
+ else {
+ rnode->set_internal_child(i, count2, &child->internal);
+ }
+ count2++;
+ }
+ else if (node->has_child(i)) {
+ if (node->is_child_leaf(i)) {
+ rnode->set_leaf_child(i, count2, &node->get_child(count1)->leaf);
+ }
+ else {
+ rnode->set_internal_child(i, count2, &node->get_child(count1)->internal);
+ }
+ count1++;
+ count2++;
+ }
+ }
+
+ removeInternal(num, node);
+ return rnode;
+ }
+
+ /// Allocate a node
+ InternalNode *createInternal(int length)
+ {
+ InternalNode *inode = (InternalNode *)alloc[length]->allocate();
+ inode->has_child_bitfield = 0;
+ inode->child_is_leaf_bitfield = 0;
+ return inode;
+ }
+
+ LeafNode *createLeaf(int length)
+ {
+ assert(length <= 3);
+
+ LeafNode *lnode = (LeafNode *)leafalloc[length]->allocate();
+ lnode->edge_parity = 0;
+ lnode->primary_edge_intersections = 0;
+ lnode->signs = 0;
+
+ return lnode;
+ }
+
+ void removeInternal(int num, InternalNode *node)
+ {
+ alloc[num]->deallocate(node);
+ }
+
+ void removeLeaf(int num, LeafNode *leaf)
+ {
+ assert(num >= 0 && num <= 3);
+ leafalloc[num]->deallocate(leaf);
+ }
+
+ /// Add a leaf (by creating a new par node with the leaf added)
+ InternalNode *addLeafChild(InternalNode *par, int index, int count, LeafNode *leaf)
+ {
+ int num = par->get_num_children() + 1;
+ InternalNode *npar = createInternal(num);
+ *npar = *par;
+
+ if (num == 1) {
+ npar->set_leaf_child(index, 0, leaf);
+ }
+ else {
+ int i;
+ for (i = 0; i < count; i++) {
+ npar->set_child(i, par->get_child(i));
+ }
+ npar->set_leaf_child(index, count, leaf);
+ for (i = count + 1; i < num; i++) {
+ npar->set_child(i, par->get_child(i - 1));
+ }
+ }
+
+ removeInternal(num - 1, par);
+ return npar;
+ }
+
+ InternalNode *addInternalChild(InternalNode *par, int index, int count, InternalNode *node)
+ {
+ int num = par->get_num_children() + 1;
+ InternalNode *npar = createInternal(num);
+ *npar = *par;
+
+ if (num == 1) {
+ npar->set_internal_child(index, 0, node);
+ }
+ else {
+ int i;
+ for (i = 0; i < count; i++) {
+ npar->set_child(i, par->get_child(i));
+ }
+ npar->set_internal_child(index, count, node);
+ for (i = count + 1; i < num; i++) {
+ npar->set_child(i, par->get_child(i - 1));
+ }
+ }
+
+ removeInternal(num - 1, par);
+ return npar;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Octree")
+ MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:Octree")
#endif
};
-#endif /* __OCTREE_H__ */
+#endif /* __OCTREE_H__ */