diff --git a/.github/workflows/test_and_coverage.yml b/.github/workflows/test_and_coverage.yml index ae1c149..3dfc111 100644 --- a/.github/workflows/test_and_coverage.yml +++ b/.github/workflows/test_and_coverage.yml @@ -10,7 +10,7 @@ jobs: sudo apt-get update -y && sudo apt-get install -y build-essential - name: Run tests run: | - cargo test -- --nocapture + RUST_BACKTRACE=1 cargo test -- --nocapture - name: Install cargo-llvm-cov run: | curl -LsSf https://github.com/taiki-e/cargo-llvm-cov/releases/latest/download/cargo-llvm-cov-x86_64-unknown-linux-gnu.tar.gz | tar xzf - -C ~/.cargo/bin diff --git a/.github/workflows/windows_and_macos.yml b/.github/workflows/windows_and_macos.yml new file mode 100644 index 0000000..f84a0da --- /dev/null +++ b/.github/workflows/windows_and_macos.yml @@ -0,0 +1,30 @@ +name: Windows & macOS + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + + matrix: + os: + - macos-latest + - windows-latest + + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose -- --nocapture diff --git a/build.rs b/build.rs index 4163d9d..7092ce5 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,4 @@ +#[cfg(any(target_os = "linux", target_os = "macos"))] fn main() { cc::Build::new() .file("c_code/triangle.c") @@ -17,3 +18,19 @@ fn main() { .flag("-Wno-unused-but-set-variable") .compile("c_code_interface_tetgen"); } + +#[cfg(target_os = "windows")] +fn main() { + cc::Build::new() + .file("c_code/triangle.c") + .file("c_code/tricall_report.c") + .file("c_code/interface_triangle.c") + .define("NO_TIMER", None) + .compile("c_code_interface_triangle"); + cc::Build::new() + .cpp(true) + .file("c_code/predicates.cxx") + .file("c_code/tetgen.cxx") + .file("c_code/interface_tetgen.cpp") + .compile("c_code_interface_tetgen"); +} diff --git a/c_code/interface_triangle.c b/c_code/interface_triangle.c index 63618ad..e25607d 100644 --- a/c_code/interface_triangle.c +++ b/c_code/interface_triangle.c @@ -486,7 +486,7 @@ int32_t tri_out_voronoi_npoint(struct ExtTrigen *trigen) { return trigen->voronoi.numberofpoints; } -int32_t tri_out_voronoi_point(struct ExtTrigen *trigen, int32_t index, int32_t dim) { +double tri_out_voronoi_point(struct ExtTrigen *trigen, int32_t index, int32_t dim) { if (trigen == NULL) { return 0.0; } diff --git a/c_code/interface_triangle.h b/c_code/interface_triangle.h index 02a9eeb..9613c2c 100644 --- a/c_code/interface_triangle.h +++ b/c_code/interface_triangle.h @@ -57,7 +57,7 @@ int32_t tri_out_cell_attribute(struct ExtTrigen *trigen, int32_t index); int32_t tri_out_voronoi_npoint(struct ExtTrigen *trigen); -int32_t tri_out_voronoi_point(struct ExtTrigen *trigen, int32_t index, int32_t dim); +double tri_out_voronoi_point(struct ExtTrigen *trigen, int32_t index, int32_t dim); int32_t tri_out_voronoi_nedge(struct ExtTrigen *trigen); diff --git a/c_code/tetgen.cxx b/c_code/tetgen.cxx index 2aab450..a582556 100644 --- a/c_code/tetgen.cxx +++ b/c_code/tetgen.cxx @@ -10868,9 +10868,9 @@ void tetgenmesh::brio_multiscale_sort(point* vertexarray, int arraysize, // // /////////////////////////////////////////////////////////////////////////////// -unsigned long tetgenmesh::randomnation(unsigned int choices) +ULONG tetgenmesh::randomnation(unsigned int choices) { - unsigned long newrandom; + ULONG newrandom; if (choices >= 714025l) { newrandom = (randomseed * 1366l + 150889l) % 714025l; @@ -26959,9 +26959,9 @@ void tetgenmesh::optimizemesh() // // /////////////////////////////////////////////////////////////////////////////// -void tetgenmesh::printfcomma(unsigned long n) +void tetgenmesh::printfcomma(ULONG n) { - unsigned long n2 = 0; + ULONG n2 = 0; int scale = 1; while (n >= 1000) { n2 = n2 + scale * (n % 1000); @@ -27911,10 +27911,10 @@ void tetgenmesh::qualitystatistics() REAL tetaspect, tetradius; REAL smalldiangle, bigdiangle; REAL smallfaangle, bigfaangle; - unsigned long radiustable[12]; - unsigned long aspecttable[16]; - unsigned long dihedangletable[18]; - unsigned long faceangletable[18]; + ULONG radiustable[12]; + ULONG aspecttable[16]; + ULONG dihedangletable[18]; + ULONG faceangletable[18]; int indx[4]; int radiusindex; int aspectindex; @@ -28301,7 +28301,7 @@ void tetgenmesh::memorystatistics() } // Calculate the total memory (in bytes) used by storing meshes. - unsigned long totalmeshmemory = 0l, totalt2shmemory = 0l; + ULONG totalmeshmemory = 0l, totalt2shmemory = 0l; totalmeshmemory = points->maxitems * points->itembytes + tetrahedrons->maxitems * tetrahedrons->itembytes; if (b->plc || b->refine) { @@ -28311,7 +28311,7 @@ void tetgenmesh::memorystatistics() tet2segpool->maxitems * tet2segpool->itembytes); } - unsigned long totalalgomemory = 0l; + ULONG totalalgomemory = 0l; totalalgomemory = cavetetlist->totalmemory + cavebdrylist->totalmemory + caveoldtetlist->totalmemory + flippool->maxitems * flippool->itembytes; diff --git a/c_code/tetgen.h b/c_code/tetgen.h index 27ffab1..d7bea90 100644 --- a/c_code/tetgen.h +++ b/c_code/tetgen.h @@ -53,28 +53,12 @@ #include // dorival -// The types 'intptr_t' and 'uintptr_t' are signed and unsigned integer types, -// respectively. They are guaranteed to be the same width as a pointer. -// They are defined in by the C99 Standard. However, Microsoft -// Visual C++ 2003 -- 2008 (Visual C++ 7.1 - 9) doesn't ship with this header -// file. In such case, we can define them by ourself. -// Update (learned from Stack Overflow): Visual Studio 2010 and Visual C++ 2010 -// Express both have stdint.h - -// The following piece of code was provided by Steven Johnson (MIT). Define the -// symbol _MSC_VER if you are using Microsoft Visual C++. Moreover, define -// the _WIN64 symbol if you are running TetGen on Win64 systems. - -#ifdef _MSC_VER // Microsoft Visual C++ -# ifdef _WIN64 - typedef __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -# else // not _WIN64 - typedef int intptr_t; - typedef unsigned int uintptr_t; -# endif -#else // not Visual C++ -# include +// dorival +#ifdef _MSC_VER +#define ULONG ptrdiff_t +#else +#include +#define ULONG unsigned long #endif /////////////////////////////////////////////////////////////////////////////// @@ -997,7 +981,7 @@ class tetgenmesh { int toparraylen; char **toparray; long objects; - unsigned long totalmemory; + ULONG totalmemory; void restart(); void poolinit(int sizeofobject, int log2objperblk); @@ -1335,7 +1319,7 @@ class tetgenmesh { int autofliplinklevel; // The increase of link levels, default is 1. int useinsertradius; // Save the insertion radius for Steiner points. long samples; // Number of random samples for point location. - unsigned long randomseed; // Current random number seed. + ULONG randomseed; // Current random number seed. REAL cosmaxdihed, cosmindihed; // The cosine values of max/min dihedral. REAL cossmtdihed; // The cosine value of a bad dihedral to be smoothed. REAL cosslidihed; // The cosine value of the max dihedral of a sliver. @@ -1358,7 +1342,7 @@ class tetgenmesh { long flip14count, flip26count, flipn2ncount; long flip23count, flip32count, flip44count, flip41count; long flip31count, flip22count; - unsigned long totalworkmemory; // Total memory used by working arrays. + ULONG totalworkmemory; // Total memory used by working arrays. /////////////////////////////////////////////////////////////////////////////// @@ -1749,7 +1733,7 @@ class tetgenmesh { void brio_multiscale_sort(point*,int,int threshold,REAL ratio,int* depth); // Point location. - unsigned long randomnation(unsigned int choices); + ULONG randomnation(unsigned int choices); void randomsample(point searchpt, triface *searchtet); enum locateresult locate(point searchpt, triface *searchtet); @@ -2046,7 +2030,7 @@ class tetgenmesh { int checkconforming(int); // Mesh statistics. - void printfcomma(unsigned long n); + void printfcomma(ULONG n); void qualitystatistics(); void memorystatistics(); void statistics(); diff --git a/c_code/triangle.c b/c_code/triangle.c index 7f8be3b..a67f540 100644 --- a/c_code/triangle.c +++ b/c_code/triangle.c @@ -343,6 +343,7 @@ #include #include #include +#include #include #ifndef NO_TIMER #include @@ -633,7 +634,7 @@ struct memorypool { int itembytes; int itemsperblock; int itemsfirstblock; - long items, maxitems; + ptrdiff_t items, maxitems; int unallocateditems; int pathitemsleft; }; @@ -650,7 +651,7 @@ REAL o3derrboundA, o3derrboundB, o3derrboundC; /* Random number seed is not constant, but I've made it global anyway. */ -unsigned long randomseed; /* Current random number seed. */ +size_t randomseed; /* Current random number seed. */ /* Mesh data structure. Triangle operates on only one mesh, but the mesh */ @@ -693,11 +694,11 @@ struct mesh { int holes; /* Number of input holes. */ int regions; /* Number of input regions. */ int undeads; /* Number of input vertices that don't appear in the mesh. */ - long edges; /* Number of output edges. */ + ptrdiff_t edges; /* Number of output edges. */ int mesh_dim; /* Dimension (ought to be 2). */ int nextras; /* Number of attributes per vertex. */ int eextras; /* Number of attributes per triangle. */ - long hullsize; /* Number of edges in convex hull. */ + ptrdiff_t hullsize; /* Number of edges in convex hull. */ int steinerleft; /* Number of Steiner points not yet used. */ int vertexmarkindex; /* Index to find boundary marker of a vertex. */ int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */ @@ -707,14 +708,14 @@ struct mesh { int checksegments; /* Are there segments in the triangulation yet? */ int checkquality; /* Has quality triangulation begun yet? */ int readnodefile; /* Has a .node file been read? */ - long samples; /* Number of random samples for point location. */ + ptrdiff_t samples; /* Number of random samples for point location. */ - long incirclecount; /* Number of incircle tests performed. */ - long counterclockcount; /* Number of counterclockwise tests performed. */ - long orient3dcount; /* Number of 3D orientation tests performed. */ - long hyperbolacount; /* Number of right-of-hyperbola tests performed. */ - long circumcentercount; /* Number of circumcenter calculations performed. */ - long circletopcount; /* Number of circle top calculations performed. */ + ptrdiff_t incirclecount; /* Number of incircle tests performed. */ + ptrdiff_t counterclockcount; /* Number of counterclockwise tests performed. */ + ptrdiff_t orient3dcount; /* Number of 3D orientation tests performed. */ + ptrdiff_t hyperbolacount; /* Number of right-of-hyperbola tests performed. */ + ptrdiff_t circumcentercount; /* Number of circumcenter calculations performed. */ + ptrdiff_t circletopcount; /* Number of circle top calculations performed. */ /* Triangular bounding box vertices. */ @@ -827,8 +828,8 @@ struct behavior { /* extracting an orientation (in the range 0 to 2) and a pointer to the */ /* beginning of a triangle. The encode() routine compresses a pointer to a */ /* triangle and an orientation into a single pointer. My assumptions that */ -/* triangles are four-byte-aligned and that the `unsigned long' type is */ -/* long enough to hold a pointer are two of the few kludges in this program.*/ +/* triangles are four-byte-aligned and that the `size_t' type is */ +/* ptrdiff_t enough to hold a pointer are two of the few kludges in this program.*/ /* */ /* Subsegments are manipulated similarly. A pointer to a subsegment */ /* carries both an address and an orientation in the range 0 to 1. */ @@ -938,16 +939,16 @@ int minus1mod3[3] = {2, 0, 1}; /* extracted from the two least significant bits of the pointer. */ #define decode(ptr, otri) \ - (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \ + (otri).orient = (int) ((size_t) (ptr) & (size_t) 3l); \ (otri).tri = (triangle *) \ - ((unsigned long) (ptr) ^ (unsigned long) (otri).orient) + ((size_t) (ptr) ^ (size_t) (otri).orient) /* encode() compresses an oriented triangle into a single pointer. It */ /* relies on the assumption that all triangles are aligned to four-byte */ /* boundaries, so the two least significant bits of (otri).tri are zero. */ #define encode(otri) \ - (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient) + (triangle) ((size_t) (otri).tri | (size_t) (otri).orient) /* The following handle manipulation primitives are all described by Guibas */ /* and Stolfi. However, Guibas and Stolfi use an edge-based data */ @@ -1111,16 +1112,16 @@ int minus1mod3[3] = {2, 0, 1}; #define infect(otri) \ (otri).tri[6] = (triangle) \ - ((unsigned long) (otri).tri[6] | (unsigned long) 2l) + ((size_t) (otri).tri[6] | (size_t) 2l) #define uninfect(otri) \ (otri).tri[6] = (triangle) \ - ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l) + ((size_t) (otri).tri[6] & ~ (size_t) 2l) /* Test a triangle for viral infection. */ #define infected(otri) \ - (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l) + (((size_t) (otri).tri[6] & (size_t) 2l) != 0l) /* Check or set a triangle's attributes. */ @@ -1158,16 +1159,16 @@ int minus1mod3[3] = {2, 0, 1}; /* are masked out to produce the real pointer. */ #define sdecode(sptr, osub) \ - (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \ + (osub).ssorient = (int) ((size_t) (sptr) & (size_t) 1l); \ (osub).ss = (subseg *) \ - ((unsigned long) (sptr) & ~ (unsigned long) 3l) + ((size_t) (sptr) & ~ (size_t) 3l) /* sencode() compresses an oriented subsegment into a single pointer. It */ /* relies on the assumption that all subsegments are aligned to two-byte */ /* boundaries, so the least significant bit of (osub).ss is zero. */ #define sencode(osub) \ - (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient) + (subseg) ((size_t) (osub).ss | (size_t) (osub).ssorient) /* ssym() toggles the orientation of a subsegment. */ @@ -3675,27 +3676,27 @@ struct otri *t; struct osub printsh; vertex printvertex; - printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri, + printf("triangle x%lx with orientation %d:\n", (size_t) t->tri, t->orient); decode(t->tri[0], printtri); if (printtri.tri == m->dummytri) { printf(" [0] = Outer space\n"); } else { - printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri, + printf(" [0] = x%lx %d\n", (size_t) printtri.tri, printtri.orient); } decode(t->tri[1], printtri); if (printtri.tri == m->dummytri) { printf(" [1] = Outer space\n"); } else { - printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri, + printf(" [1] = x%lx %d\n", (size_t) printtri.tri, printtri.orient); } decode(t->tri[2], printtri); if (printtri.tri == m->dummytri) { printf(" [2] = Outer space\n"); } else { - printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri, + printf(" [2] = x%lx %d\n", (size_t) printtri.tri, printtri.orient); } @@ -3704,37 +3705,37 @@ struct otri *t; printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3); else printf(" Origin[%d] = x%lx (%.12g, %.12g)\n", - (t->orient + 1) % 3 + 3, (unsigned long) printvertex, + (t->orient + 1) % 3 + 3, (size_t) printvertex, printvertex[0], printvertex[1]); dest(*t, printvertex); if (printvertex == (vertex) NULL) printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3); else printf(" Dest [%d] = x%lx (%.12g, %.12g)\n", - (t->orient + 2) % 3 + 3, (unsigned long) printvertex, + (t->orient + 2) % 3 + 3, (size_t) printvertex, printvertex[0], printvertex[1]); apex(*t, printvertex); if (printvertex == (vertex) NULL) printf(" Apex [%d] = NULL\n", t->orient + 3); else printf(" Apex [%d] = x%lx (%.12g, %.12g)\n", - t->orient + 3, (unsigned long) printvertex, + t->orient + 3, (size_t) printvertex, printvertex[0], printvertex[1]); if (b->usesegments) { sdecode(t->tri[6], printsh); if (printsh.ss != m->dummysub) { - printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss, + printf(" [6] = x%lx %d\n", (size_t) printsh.ss, printsh.ssorient); } sdecode(t->tri[7], printsh); if (printsh.ss != m->dummysub) { - printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss, + printf(" [7] = x%lx %d\n", (size_t) printsh.ss, printsh.ssorient); } sdecode(t->tri[8], printsh); if (printsh.ss != m->dummysub) { - printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss, + printf(" [8] = x%lx %d\n", (size_t) printsh.ss, printsh.ssorient); } } @@ -3770,19 +3771,19 @@ struct osub *s; vertex printvertex; printf("subsegment x%lx with orientation %d and mark %d:\n", - (unsigned long) s->ss, s->ssorient, mark(*s)); + (size_t) s->ss, s->ssorient, mark(*s)); sdecode(s->ss[0], printsh); if (printsh.ss == m->dummysub) { printf(" [0] = No subsegment\n"); } else { - printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss, + printf(" [0] = x%lx %d\n", (size_t) printsh.ss, printsh.ssorient); } sdecode(s->ss[1], printsh); if (printsh.ss == m->dummysub) { printf(" [1] = No subsegment\n"); } else { - printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss, + printf(" [1] = x%lx %d\n", (size_t) printsh.ss, printsh.ssorient); } @@ -3791,28 +3792,28 @@ struct osub *s; printf(" Origin[%d] = NULL\n", 2 + s->ssorient); else printf(" Origin[%d] = x%lx (%.12g, %.12g)\n", - 2 + s->ssorient, (unsigned long) printvertex, + 2 + s->ssorient, (size_t) printvertex, printvertex[0], printvertex[1]); sdest(*s, printvertex); if (printvertex == (vertex) NULL) printf(" Dest [%d] = NULL\n", 3 - s->ssorient); else printf(" Dest [%d] = x%lx (%.12g, %.12g)\n", - 3 - s->ssorient, (unsigned long) printvertex, + 3 - s->ssorient, (size_t) printvertex, printvertex[0], printvertex[1]); decode(s->ss[6], printtri); if (printtri.tri == m->dummytri) { printf(" [6] = Outer space\n"); } else { - printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri, + printf(" [6] = x%lx %d\n", (size_t) printtri.tri, printtri.orient); } decode(s->ss[7], printtri); if (printtri.tri == m->dummytri) { printf(" [7] = Outer space\n"); } else { - printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri, + printf(" [7] = x%lx %d\n", (size_t) printtri.tri, printtri.orient); } @@ -3821,14 +3822,14 @@ struct osub *s; printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient); else printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n", - 4 + s->ssorient, (unsigned long) printvertex, + 4 + s->ssorient, (size_t) printvertex, printvertex[0], printvertex[1]); segdest(*s, printvertex); if (printvertex == (vertex) NULL) printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient); else printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n", - 5 - s->ssorient, (unsigned long) printvertex, + 5 - s->ssorient, (size_t) printvertex, printvertex[0], printvertex[1]); } @@ -3891,7 +3892,7 @@ struct memorypool *pool; #endif /* not ANSI_DECLARATORS */ { - unsigned long alignptr; + size_t alignptr; pool->items = 0; pool->maxitems = 0; @@ -3899,11 +3900,11 @@ struct memorypool *pool; /* Set the currently active block. */ pool->nowblock = pool->firstblock; /* Find the first item in the pool. Increment by the size of (VOID *). */ - alignptr = (unsigned long) (pool->nowblock + 1); + alignptr = (size_t) (pool->nowblock + 1); /* Align the item on an `alignbytes'-byte boundary. */ pool->nextitem = (VOID *) - (alignptr + (unsigned long) pool->alignbytes - - (alignptr % (unsigned long) pool->alignbytes)); + (alignptr + (size_t) pool->alignbytes - + (alignptr % (size_t) pool->alignbytes)); /* There are lots of unallocated items left in this block. */ pool->unallocateditems = pool->itemsfirstblock; /* The stack of deallocated items is empty. */ @@ -4008,7 +4009,7 @@ struct memorypool *pool; { VOID *newitem; VOID **newblock; - unsigned long alignptr; + size_t alignptr; /* First check the linked list of dead items. If the list is not */ /* empty, allocate an item from the list rather than a fresh one. */ @@ -4033,11 +4034,11 @@ struct memorypool *pool; pool->nowblock = (VOID **) *(pool->nowblock); /* Find the first item in the block. */ /* Increment by the size of (VOID *). */ - alignptr = (unsigned long) (pool->nowblock + 1); + alignptr = (size_t) (pool->nowblock + 1); /* Align the item on an `alignbytes'-byte boundary. */ pool->nextitem = (VOID *) - (alignptr + (unsigned long) pool->alignbytes - - (alignptr % (unsigned long) pool->alignbytes)); + (alignptr + (size_t) pool->alignbytes - + (alignptr % (size_t) pool->alignbytes)); /* There are lots of unallocated items left in this block. */ pool->unallocateditems = pool->itemsperblock; } @@ -4092,16 +4093,16 @@ struct memorypool *pool; #endif /* not ANSI_DECLARATORS */ { - unsigned long alignptr; + size_t alignptr; /* Begin the traversal in the first block. */ pool->pathblock = pool->firstblock; /* Find the first item in the block. Increment by the size of (VOID *). */ - alignptr = (unsigned long) (pool->pathblock + 1); + alignptr = (size_t) (pool->pathblock + 1); /* Align with item on an `alignbytes'-byte boundary. */ pool->pathitem = (VOID *) - (alignptr + (unsigned long) pool->alignbytes - - (alignptr % (unsigned long) pool->alignbytes)); + (alignptr + (size_t) pool->alignbytes - + (alignptr % (size_t) pool->alignbytes)); /* Set the number of items left in the current block. */ pool->pathitemsleft = pool->itemsfirstblock; } @@ -4129,7 +4130,7 @@ struct memorypool *pool; { VOID *newitem; - unsigned long alignptr; + size_t alignptr; /* Stop upon exhausting the list of items. */ if (pool->pathitem == pool->nextitem) { @@ -4141,11 +4142,11 @@ struct memorypool *pool; /* Find the next block. */ pool->pathblock = (VOID **) *(pool->pathblock); /* Find the first item in the block. Increment by the size of (VOID *). */ - alignptr = (unsigned long) (pool->pathblock + 1); + alignptr = (size_t) (pool->pathblock + 1); /* Align with item on an `alignbytes'-byte boundary. */ pool->pathitem = (VOID *) - (alignptr + (unsigned long) pool->alignbytes - - (alignptr % (unsigned long) pool->alignbytes)); + (alignptr + (size_t) pool->alignbytes - + (alignptr % (size_t) pool->alignbytes)); /* Set the number of items left in the current block. */ pool->pathitemsleft = pool->itemsperblock; } @@ -4197,16 +4198,16 @@ int subsegbytes; #endif /* not ANSI_DECLARATORS */ { - unsigned long alignptr; + size_t alignptr; /* Set up `dummytri', the `triangle' that occupies "outer space." */ m->dummytribase = (triangle *) trimalloc(trianglebytes + m->triangles.alignbytes); /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */ - alignptr = (unsigned long) m->dummytribase; + alignptr = (size_t) m->dummytribase; m->dummytri = (triangle *) - (alignptr + (unsigned long) m->triangles.alignbytes - - (alignptr % (unsigned long) m->triangles.alignbytes)); + (alignptr + (size_t) m->triangles.alignbytes - + (alignptr % (size_t) m->triangles.alignbytes)); /* Initialize the three adjoining triangles to be "outer space." These */ /* will eventually be changed by various bonding operations, but their */ /* values don't really matter, as long as they can legally be */ @@ -4226,10 +4227,10 @@ int subsegbytes; m->dummysubbase = (subseg *) trimalloc(subsegbytes + m->subsegs.alignbytes); /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */ - alignptr = (unsigned long) m->dummysubbase; + alignptr = (size_t) m->dummysubbase; m->dummysub = (subseg *) - (alignptr + (unsigned long) m->subsegs.alignbytes - - (alignptr % (unsigned long) m->subsegs.alignbytes)); + (alignptr + (size_t) m->subsegs.alignbytes - + (alignptr % (size_t) m->subsegs.alignbytes)); /* Initialize the two adjoining subsegments to be the omnipresent */ /* subsegment. These will eventually be changed by various bonding */ /* operations, but their values don't really matter, as long as they */ @@ -4586,7 +4587,7 @@ int number; { VOID **getblock; char *foundvertex; - unsigned long alignptr; + size_t alignptr; int current; getblock = m->vertices.firstblock; @@ -4603,9 +4604,9 @@ int number; } /* Now find the right vertex. */ - alignptr = (unsigned long) (getblock + 1); - foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes - - (alignptr % (unsigned long) m->vertices.alignbytes)); + alignptr = (size_t) (getblock + 1); + foundvertex = (char *) (alignptr + (size_t) m->vertices.alignbytes - + (alignptr % (size_t) m->vertices.alignbytes)); return (vertex) (foundvertex + m->vertices.itembytes * (number - current)); } @@ -6673,9 +6674,9 @@ struct mesh *m; /*****************************************************************************/ #ifdef ANSI_DECLARATORS -unsigned long randomnation(unsigned int choices) +size_t randomnation(unsigned int choices) #else /* not ANSI_DECLARATORS */ -unsigned long randomnation(choices) +size_t randomnation(choices) unsigned int choices; #endif /* not ANSI_DECLARATORS */ @@ -7655,11 +7656,11 @@ struct otri *searchtri; char *firsttri; struct otri sampletri; vertex torg, tdest; - unsigned long alignptr; + size_t alignptr; REAL searchdist, dist; REAL ahead; - long samplesperblock, totalsamplesleft, samplesleft; - long population, totalpopulation; + ptrdiff_t samplesperblock, totalsamplesleft, samplesleft; + ptrdiff_t population, totalpopulation; triangle ptr; /* Temporary variable used by sym(). */ if (b->verbose > 2) { @@ -7727,11 +7728,11 @@ struct otri *searchtri; population = totalpopulation; } /* Find a pointer to the first triangle in the block. */ - alignptr = (unsigned long) (sampleblock + 1); + alignptr = (size_t) (sampleblock + 1); firsttri = (char *) (alignptr + - (unsigned long) m->triangles.alignbytes - + (size_t) m->triangles.alignbytes - (alignptr % - (unsigned long) m->triangles.alignbytes)); + (size_t) m->triangles.alignbytes)); /* Choose `samplesleft' randomly sampled triangles in this block. */ do { @@ -9925,7 +9926,7 @@ struct otri *startghost; struct otri dissolveedge; struct otri deadtriangle; vertex markorg; - long hullsize; + ptrdiff_t hullsize; triangle ptr; /* Temporary variable used by sym(). */ if (b->verbose) { @@ -10141,7 +10142,7 @@ struct behavior *b; struct otri checkedge; struct otri nextedge, finaledge, dissolveedge; vertex markorg; - long hullsize; + ptrdiff_t hullsize; triangle ptr; /* Temporary variable used by sym(). */ if (b->verbose) { @@ -11027,7 +11028,7 @@ struct behavior *b; #endif /* not ANSI_DECLARATORS */ { - long hulledges; + ptrdiff_t hulledges; m->eextras = 0; initializetrisubpools(m, b); @@ -11167,9 +11168,9 @@ FILE *polyfile; int segmentmarkers; int boundmarker; int aroundvertex; - long hullsize; + ptrdiff_t hullsize; int notfound; - long elementnumber, segmentnumber; + ptrdiff_t elementnumber, segmentnumber; int i, j; triangle ptr; /* Temporary variable used by sym(). */ @@ -14364,7 +14365,7 @@ char **argv; FILE *outfile; #endif /* not TRILIBRARY */ vertex vertexloop; - long outvertices; + ptrdiff_t outvertices; int vertexnumber; int i; @@ -14536,7 +14537,7 @@ char **argv; struct otri triangleloop; vertex p1, p2, p3; vertex mid1, mid2, mid3; - long elementnumber; + ptrdiff_t elementnumber; int i; #ifdef TRILIBRARY @@ -14678,11 +14679,11 @@ char **argv; int index; #else /* not TRILIBRARY */ FILE *outfile; - long holenumber, regionnumber; + ptrdiff_t holenumber, regionnumber; #endif /* not TRILIBRARY */ struct osub subsegloop; vertex endpoint1, endpoint2; - long subsegnumber; + ptrdiff_t subsegnumber; #ifdef TRILIBRARY if (!b->quiet) { @@ -14822,7 +14823,7 @@ char **argv; struct otri triangleloop, trisym; struct osub checkmark; vertex p1, p2; - long edgenumber; + ptrdiff_t edgenumber; triangle ptr; /* Temporary variable used by sym(). */ subseg sptr; /* Temporary variable used by tspivot(). */ @@ -14987,7 +14988,7 @@ char **argv; vertex torg, tdest, tapex; REAL circumcenter[2]; REAL xi, eta; - long vnodenumber, vedgenumber; + ptrdiff_t vnodenumber, vedgenumber; int p1, p2; int i; triangle ptr; /* Temporary variable used by sym(). */ @@ -15184,7 +15185,7 @@ char **argv; FILE *outfile; #endif /* not TRILIBRARY */ struct otri triangleloop, trisym; - long elementnumber; + ptrdiff_t elementnumber; int neighbor1, neighbor2, neighbor3; triangle ptr; /* Temporary variable used by sym(). */ @@ -15283,7 +15284,7 @@ char **argv; struct otri triangleloop; vertex vertexloop; vertex p1, p2, p3; - long outvertices; + ptrdiff_t outvertices; if (!b->quiet) { printf("Writing %s.\n", offfilename); diff --git a/src/trigen.rs b/src/trigen.rs index 8dc8c27..f2863e3 100644 --- a/src/trigen.rs +++ b/src/trigen.rs @@ -953,6 +953,13 @@ impl Trigen { max[dim] = f64::max(max[dim], x[dim]); } } + let mut gap = vec![0.0; 2]; + for dim in 0..2 { + gap[dim] = 0.05 * (max[dim] - min[dim]); + gap[dim] = 0.05 * (max[dim] - min[dim]); + min[dim] -= gap[dim]; + max[dim] += gap[dim]; + } let mut canvas = Canvas::new(); canvas.polycurve_begin(); for e in 0..self.out_voronoi_nedge() { @@ -992,6 +999,13 @@ impl Trigen { max[1] = f64::max(max[1], yb); canvas.polycurve_add(xa, ya, PolyCode::MoveTo); canvas.polycurve_add(xb, yb, PolyCode::LineTo); + } else { + canvas.polycurve_add(xa, ya, PolyCode::MoveTo); + if dx == 0.0 { + canvas.polycurve_add(xa, ya + dy * gap[1], PolyCode::LineTo); + } else if dy == 0.0 { + canvas.polycurve_add(xa + dx * gap[0], ya, PolyCode::LineTo); + } } } } @@ -1153,14 +1167,39 @@ mod tests { #[test] fn voronoi_1_works() -> Result<(), StrError> { - let mut trigen = Trigen::new(3, None, None, None)?; + let mut trigen = Trigen::new(5, None, None, None)?; trigen .set_point(0, 0, 0.0, 0.0)? .set_point(1, 0, 1.0, 0.0)? - .set_point(2, 0, 0.0, 1.0)?; + .set_point(2, 0, 0.0, 1.0)? + .set_point(3, 0, 1.0, 1.0)? + .set_point(4, 0, 0.5, 0.5)?; trigen.generate_voronoi(false)?; - assert_eq!(trigen.out_npoint(), 3); - assert_eq!(trigen.out_ncell(), 1); + if SAVE_FIGURE { + let mut plot = Plot::new(); + trigen.draw_voronoi(&mut plot); + plot.set_equal_axes(true) + .set_figure_size_points(600.0, 600.0) + .save("/tmp/tritet/voronoi_1_works.svg")?; + } + for i in 0..trigen.out_voronoi_npoint() { + println!( + "{}: {:?}, {:?}", + i, + trigen.out_voronoi_point(i, 0), + trigen.out_voronoi_point(i, 1) + ); + } + for e in 0..trigen.out_voronoi_nedge() { + println!( + "{}: {:?} => {:?}", + e, + trigen.out_voronoi_edge_point_a(e), + trigen.out_voronoi_edge_point_b(e) + ); + } + assert_eq!(trigen.out_npoint(), 5); + assert_eq!(trigen.out_ncell(), 4); assert_eq!(trigen.out_cell_npoint(), 3); assert_eq!(trigen.out_point(0, 0), 0.0); assert_eq!(trigen.out_point(0, 1), 0.0); @@ -1168,24 +1207,47 @@ mod tests { assert_eq!(trigen.out_point(1, 1), 0.0); assert_eq!(trigen.out_point(2, 0), 0.0); assert_eq!(trigen.out_point(2, 1), 1.0); - assert_eq!(trigen.out_voronoi_npoint(), 1); - assert_eq!(trigen.out_voronoi_point(0, 0), 0.5); + assert_eq!(trigen.out_point(3, 0), 1.0); + assert_eq!(trigen.out_point(3, 1), 1.0); + assert_eq!(trigen.out_point(4, 0), 0.5); + assert_eq!(trigen.out_point(4, 1), 0.5); + assert_eq!(trigen.out_voronoi_npoint(), 4); + assert_eq!(trigen.out_voronoi_point(0, 0), 0.0); assert_eq!(trigen.out_voronoi_point(0, 1), 0.5); - assert_eq!(trigen.out_voronoi_nedge(), 3); + assert_eq!(trigen.out_voronoi_point(1, 0), 1.0); + assert_eq!(trigen.out_voronoi_point(1, 1), 0.5); + assert_eq!(trigen.out_voronoi_point(2, 0), 0.5); + assert_eq!(trigen.out_voronoi_point(2, 1), 0.0); + assert_eq!(trigen.out_voronoi_point(3, 0), 0.5); + assert_eq!(trigen.out_voronoi_point(3, 1), 1.0); + assert_eq!(trigen.out_voronoi_nedge(), 8); assert_eq!(trigen.out_voronoi_edge_point_a(0), 0); assert_eq!( format!("{:?}", trigen.out_voronoi_edge_point_b(0)), - "Direction(0.0, -1.0)" + "Direction(-1.0, 0.0)" ); assert_eq!(trigen.out_voronoi_edge_point_a(1), 0); + assert_eq!(format!("{:?}", trigen.out_voronoi_edge_point_b(1)), "Index(2)"); + assert_eq!(trigen.out_voronoi_edge_point_a(2), 0); + assert_eq!(format!("{:?}", trigen.out_voronoi_edge_point_b(2)), "Index(3)"); + assert_eq!(trigen.out_voronoi_edge_point_a(3), 1); + assert_eq!(format!("{:?}", trigen.out_voronoi_edge_point_b(3)), "Index(2)"); + assert_eq!(trigen.out_voronoi_edge_point_a(4), 1); assert_eq!( - format!("{:?}", trigen.out_voronoi_edge_point_b(1)), - "Direction(1.0, 1.0)" + format!("{:?}", trigen.out_voronoi_edge_point_b(4)), + "Direction(1.0, 0.0)" ); - assert_eq!(trigen.out_voronoi_edge_point_a(2), 0); + assert_eq!(trigen.out_voronoi_edge_point_a(5), 1); + assert_eq!(format!("{:?}", trigen.out_voronoi_edge_point_b(5)), "Index(3)"); + assert_eq!(trigen.out_voronoi_edge_point_a(6), 2); assert_eq!( - format!("{:?}", trigen.out_voronoi_edge_point_b(2)), - "Direction(-1.0, 0.0)" + format!("{:?}", trigen.out_voronoi_edge_point_b(6)), + "Direction(0.0, -1.0)" + ); + assert_eq!(trigen.out_voronoi_edge_point_a(7), 3); + assert_eq!( + format!("{:?}", trigen.out_voronoi_edge_point_b(7)), + "Direction(0.0, 1.0)" ); Ok(()) } @@ -1257,10 +1319,10 @@ mod tests { assert_eq!(trigen.out_ncell(), 4); assert_eq!(trigen.out_cell_npoint(), 3); - println!("point markers"); - for i in 0..trigen.out_npoint() { - println!("{} => {}", i, trigen.out_point_marker(i)); - } + // println!("point markers"); + // for i in 0..trigen.out_npoint() { + // println!("{} => {}", i, trigen.out_point_marker(i)); + // } assert_eq!(trigen.out_point_marker(0), -100); assert_eq!(trigen.out_point_marker(1), -200); @@ -1268,13 +1330,13 @@ mod tests { assert_eq!(trigen.out_point_marker(3), -400); assert_eq!(trigen.out_point_marker(4), 0); - println!("segments"); - for i in 0..trigen.out_nsegment() { - let a = trigen.out_segment_point(i, 0); - let b = trigen.out_segment_point(i, 1); - let marker = trigen.out_segment_marker(i); - println!("{:2} - {:2} => {}", a, b, marker); - } + // println!("segments"); + // for i in 0..trigen.out_nsegment() { + // let a = trigen.out_segment_point(i, 0); + // let b = trigen.out_segment_point(i, 1); + // let marker = trigen.out_segment_marker(i); + // println!("{:2} - {:2} => {}", a, b, marker); + // } let mut sides0 = vec![trigen.out_segment_point(0, 0), trigen.out_segment_point(0, 1)]; let mut sides1 = vec![trigen.out_segment_point(1, 0), trigen.out_segment_point(1, 1)]; @@ -1323,10 +1385,10 @@ mod tests { assert_eq!(trigen.out_ncell(), 16); assert_eq!(trigen.out_cell_npoint(), 3); - println!("point markers"); - for i in 0..trigen.out_npoint() { - println!("{} => {}", i, trigen.out_point_marker(i)); - } + // println!("point markers"); + // for i in 0..trigen.out_npoint() { + // println!("{} => {}", i, trigen.out_point_marker(i)); + // } assert_eq!(trigen.out_point_marker(0), -100); assert_eq!(trigen.out_point_marker(1), -200); @@ -1342,13 +1404,13 @@ mod tests { assert_eq!(trigen.out_point_marker(11), 0); assert_eq!(trigen.out_point_marker(12), 0); - println!("segments"); - for i in 0..trigen.out_nsegment() { - let a = trigen.out_segment_point(i, 0); - let b = trigen.out_segment_point(i, 1); - let marker = trigen.out_segment_marker(i); - println!("{:2} - {:2} => {}", a, b, marker); - } + // println!("segments"); + // for i in 0..trigen.out_nsegment() { + // let a = trigen.out_segment_point(i, 0); + // let b = trigen.out_segment_point(i, 1); + // let marker = trigen.out_segment_marker(i); + // println!("{:2} - {:2} => {}", a, b, marker); + // } let mut sides0 = vec![trigen.out_segment_point(0, 0), trigen.out_segment_point(0, 1)]; let mut sides1 = vec![trigen.out_segment_point(1, 0), trigen.out_segment_point(1, 1)];