TetGenProcess
The GeMA wrapper plugin to the TetGen mesh generator
Loading...
Searching...
No Matches
tetgen.h
1//============================================================================//
2// //
3// TetGen //
4// //
5// A Quality Tetrahedral Mesh Generator and A 3D Delaunay Triangulator //
6// //
7// Version 1.6.0 //
8// August 31, 2020 //
9// //
10// Copyright (C) 2002--2020 //
11// //
12// Hang Si //
13// Research Group: Numerical Mathematics and Scientific Computing //
14// Weierstrass Institute for Applied Analysis and Stochastics (WIAS) //
15// Mohrenstr. 39, 10117 Berlin, Germany //
16// si@wias-berlin.de //
17// //
18// TetGen is a tetrahedral mesh generator. It creates 3d triangulations of //
19// polyhedral domains. It generates meshes with well-shaped elements whose //
20// sizes are adapted to the geometric features or user-provided sizing //
21// functions. It has applications in various applications in scientific //
22// computing, such as computer graphics (CG), computer-aided design (CAD), //
23// geometry processing (parametrizations and computer animation), and //
24// physical simulations (finite element analysis). //
25// //
26// TetGen computes (weighted) Delaunay triangulations for three-dimensional //
27// (weighted) point sets, and constrained Delaunay triangulations for //
28// three-dimensional polyhedral domains. In the latter case, input edges //
29// and triangles can be completely preserved in the output meshes. TetGen //
30// can refine or coarsen an existing mesh to result in good quality and //
31// size-adapted mesh according to the geometric features and user-defined //
32// mesh sizing functions. //
33// //
34// TetGen implements theoretically proven algorithms for computing the //
35// Delaunay and constrained Delaunay tetrahedralizations. TetGen achieves //
36// robustness and efficiency by using advanced techniques in computational //
37// geometry. A technical paper describes the algorithms and methods //
38// implemented in TetGen is available in ACM-TOMS, Hang Si ``TetGen, a //
39// Delaunay-Based Quality Tetrahedral Mesh Generator", ACM Transactions on //
40// Mathematical Software, February 2015, https://doi.org/10.1145/2629697. //
41// //
42// TetGen is freely available through the website: http://www.tetgen.org. //
43// It may be copied, modified, and redistributed for non-commercial use. //
44// Please consult the file LICENSE for the detailed copyright notices. //
45// //
46//============================================================================//
47
48
49#ifndef tetgenH
50#define tetgenH
51
52// To compile TetGen as a library instead of an executable program, define
53// the TETLIBRARY symbol.
54
55#define TETLIBRARY
56
57
58// TetGen default uses the double-precision (64 bit) for a real number.
59// Alternatively, one can use the single-precision (32 bit) 'float' if the
60// memory is limited.
61
62#define REAL double // #define REAL float
63
64// The maximum number of characters in a file name (including the null).
65
66#define FILENAMESIZE 1024
67
68// The maximum number of chars in a line read from a file (including the null).
69
70#define INPUTLINESIZE 2048
71
72// C standard libraries to perform Input/output operations, general utililities,
73// manipulate strings and arrays, compute common mathematical operations,
74// get date and time information.
75
76#include <stdio.h>
77#include <stdlib.h>
78#include <string.h>
79#include <math.h>
80#include <time.h>
81
82// The types 'intptr_t' and 'uintptr_t' are signed and unsigned integer types,
83// respectively. They are guaranteed to be the same width as a pointer.
84// They are defined in <stdint.h> by the C99 Standard.
85
86#include <stdint.h>
87
88//============================================================================//
89// //
90// tetgenio //
91// //
92// A structure for transferring input/output data between the user and //
93// TetGen's internal data structure (class tetgenmesh). //
94// //
95// This data structure contains a collection of arrays, i.e., points, facets, //
96// tetrahedra. It contains functions to read input data from files (.node, //
97// .poly, .face, .edge, .ele) as well as write output data into files. //
98// //
99// Once an object of tetgenio is declared, no array is created. One has to //
100// allocate enough memory for them. On the deletion of this object, the //
101// memory occupied by these arrays needs to be freed. The routine //
102// deinitialize() will be automatically called. It frees the memory for //
103// an array if it is not a NULL. Note that it assumes that the memory is //
104// allocated by the C++ "new" operator. Otherwise, the user is responsible //
105// to free them and all pointers must be NULL. //
106// //
107//============================================================================//
108
109class tetgenio {
110
111public:
112
113 // A "polygon" describes a simple polygon (no holes). It is not necessarily
114 // convex. Each polygon contains a number of corners (points) and the same
115 // number of sides (edges). The points of the polygon must be given in
116 // either counterclockwise or clockwise order and they form a ring, so
117 // every two consecutive points forms an edge of the polygon.
118 typedef struct {
119 int *vertexlist;
120 int numberofvertices;
121 } polygon;
122
123 // A "facet" describes a polygonal region possibly with holes, edges, and
124 // points floating in it. Each facet consists of a list of polygons and
125 // a list of hole points (which lie strictly inside holes).
126 typedef struct {
127 polygon *polygonlist;
128 int numberofpolygons;
129 REAL *holelist;
130 int numberofholes;
131 } facet;
132
133 // A "voroedge" is an edge of the Voronoi diagram. It corresponds to a
134 // Delaunay face. Each voroedge is either a line segment connecting
135 // two Voronoi vertices or a ray starting from a Voronoi vertex to an
136 // "infinite vertex". 'v1' and 'v2' are two indices pointing to the
137 // list of Voronoi vertices. 'v1' must be non-negative, while 'v2' may
138 // be -1 if it is a ray, in this case, the unit normal of this ray is
139 // given in 'vnormal'.
140 typedef struct {
141 int v1, v2;
142 REAL vnormal[3];
143 } voroedge;
144
145 // A "vorofacet" is an facet of the Voronoi diagram. It corresponds to a
146 // Delaunay edge. Each Voronoi facet is a convex polygon formed by a
147 // list of Voronoi edges, it may not be closed. 'c1' and 'c2' are two
148 // indices pointing into the list of Voronoi cells, i.e., the two cells
149 // share this facet. 'elist' is an array of indices pointing into the
150 // list of Voronoi edges, 'elist[0]' saves the number of Voronoi edges
151 // (including rays) of this facet.
152 typedef struct {
153 int c1, c2;
154 int *elist;
155 } vorofacet;
156
157
158 // Additional parameters associated with an input (or mesh) vertex.
159 // These informations are provided by CAD libraries.
160 typedef struct {
161 REAL uv[2];
162 int tag;
163 int type; // 0, 1, or 2.
164 } pointparam;
165
166 // Callback functions for meshing PSCs.
167 typedef REAL (* GetVertexParamOnEdge)(void*, int, int);
168 typedef void (* GetSteinerOnEdge)(void*, int, REAL, REAL*);
169 typedef void (* GetVertexParamOnFace)(void*, int, int, REAL*);
170 typedef void (* GetEdgeSteinerParamOnFace)(void*, int, REAL, int, REAL*);
171 typedef void (* GetSteinerOnFace)(void*, int, REAL*, REAL*);
172
173 // A callback function for mesh refinement.
174 typedef bool (* TetSizeFunc)(REAL*, REAL*, REAL*, REAL*, REAL*, REAL);
175
176 // Items are numbered starting from 'firstnumber' (0 or 1), default is 0.
177 int firstnumber;
178
179 // Dimension of the mesh (2 or 3), default is 3.
180 int mesh_dim;
181
182 // Does the lines in .node file contain index or not, default is 1.
183 int useindex;
184
185 // 'pointlist': An array of point coordinates. The first point's x
186 // coordinate is at index [0] and its y coordinate at index [1], its
187 // z coordinate is at index [2], followed by the coordinates of the
188 // remaining points. Each point occupies three REALs.
189 // 'pointattributelist': An array of point attributes. Each point's
190 // attributes occupy 'numberofpointattributes' REALs.
191 // 'pointmtrlist': An array of metric tensors at points. Each point's
192 // tensor occupies 'numberofpointmtr' REALs.
193 // 'pointmarkerlist': An array of point markers; one integer per point.
194 // 'point2tetlist': An array of tetrahedra indices; one integer per point.
195 REAL *pointlist;
196 REAL *pointattributelist;
197 REAL *pointmtrlist;
198 int *pointmarkerlist;
199 int *point2tetlist;
200 pointparam *pointparamlist;
201 int numberofpoints;
202 int numberofpointattributes;
203 int numberofpointmtrs;
204
205 // 'tetrahedronlist': An array of tetrahedron corners. The first
206 // tetrahedron's first corner is at index [0], followed by its other
207 // corners, followed by six nodes on the edges of the tetrahedron if the
208 // second order option (-o2) is applied. Each tetrahedron occupies
209 // 'numberofcorners' ints. The second order nodes are ouput only.
210 // 'tetrahedronattributelist': An array of tetrahedron attributes. Each
211 // tetrahedron's attributes occupy 'numberoftetrahedronattributes' REALs.
212 // 'tetrahedronvolumelist': An array of constraints, i.e. tetrahedron's
213 // volume; one REAL per element. Input only.
214 // 'neighborlist': An array of tetrahedron neighbors; 4 ints per element.
215 // 'tet2facelist': An array of tetrahedron face indices; 4 ints per element.
216 // 'tet2edgelist': An array of tetrahedron edge indices; 6 ints per element.
217 int *tetrahedronlist;
218 REAL *tetrahedronattributelist;
219 REAL *tetrahedronvolumelist;
220 int *neighborlist;
221 int *tet2facelist;
222 int *tet2edgelist;
223 int numberoftetrahedra;
224 int numberofcorners;
225 int numberoftetrahedronattributes;
226
227 // 'facetlist': An array of facets. Each entry is a structure of facet.
228 // 'facetmarkerlist': An array of facet markers; one int per facet.
229 facet *facetlist;
230 int *facetmarkerlist;
231 int numberoffacets;
232
233 // 'holelist': An array of holes (in volume). Each hole is given by a
234 // seed (point) which lies strictly inside it. The first seed's x, y and z
235 // coordinates are at indices [0], [1] and [2], followed by the
236 // remaining seeds. Three REALs per hole.
237 REAL *holelist;
238 int numberofholes;
239
240 // 'regionlist': An array of regions (subdomains). Each region is given by
241 // a seed (point) which lies strictly inside it. The first seed's x, y and
242 // z coordinates are at indices [0], [1] and [2], followed by the regional
243 // attribute at index [3], followed by the maximum volume at index [4].
244 // Five REALs per region.
245 // Note that each regional attribute is used only if you select the 'A'
246 // switch, and each volume constraint is used only if you select the
247 // 'a' switch (with no number following).
248 REAL *regionlist;
249 int numberofregions;
250
251 // 'refine_elem_list': An array of tetrahedra to be refined. The first
252 // tetrahedron's first corner is at index [0], followed by its other
253 // corners. Four integers per element.
254 // 'refine_elem_vol_list': An array of constraints, i.e. tetrahedron's
255 // volume; one REAL per element.
256 int *refine_elem_list;
257 REAL *refine_elem_vol_list;
258 int numberofrefineelems;
259
260 // 'facetconstraintlist': An array of facet constraints. Each constraint
261 // specifies a maximum area bound on the subfaces of that facet. The
262 // first facet constraint is given by a facet marker at index [0] and its
263 // maximum area bound at index [1], followed by the remaining facet con-
264 // straints. Two REALs per facet constraint. Note: the facet marker is
265 // actually an integer.
266 REAL *facetconstraintlist;
267 int numberoffacetconstraints;
268
269 // 'segmentconstraintlist': An array of segment constraints. Each constraint
270 // specifies a maximum length bound on the subsegments of that segment.
271 // The first constraint is given by the two endpoints of the segment at
272 // index [0] and [1], and the maximum length bound at index [2], followed
273 // by the remaining segment constraints. Three REALs per constraint.
274 // Note the segment endpoints are actually integers.
275 REAL *segmentconstraintlist;
276 int numberofsegmentconstraints;
277
278
279 // 'trifacelist': An array of face (triangle) corners. The first face's
280 // three corners are at indices [0], [1] and [2], followed by the remaining
281 // faces. Three ints per face.
282 // 'trifacemarkerlist': An array of face markers; one int per face.
283 // 'o2facelist': An array of second order nodes (on the edges) of the face.
284 // It is output only if the second order option (-o2) is applied. The
285 // first face's three second order nodes are at [0], [1], and [2],
286 // followed by the remaining faces. Three ints per face.
287 // 'face2tetlist': An array of tetrahedra indices; 2 ints per face.
288 // 'face2edgelist': An array of edge indices; 3 ints per face.
289 int *trifacelist;
290 int *trifacemarkerlist;
291 int *o2facelist;
292 int *face2tetlist;
293 int *face2edgelist;
294 int numberoftrifaces;
295
296 // 'edgelist': An array of edge endpoints. The first edge's endpoints
297 // are at indices [0] and [1], followed by the remaining edges.
298 // Two ints per edge.
299 // 'edgemarkerlist': An array of edge markers; one int per edge.
300 // 'o2edgelist': An array of midpoints of edges. It is output only if the
301 // second order option (-o2) is applied. One int per edge.
302 // 'edge2tetlist': An array of tetrahedra indices. One int per edge.
303 int *edgelist;
304 int *edgemarkerlist;
305 int *o2edgelist;
306 int *edge2tetlist;
307 int numberofedges;
308
309 // 'vpointlist': An array of Voronoi vertex coordinates (like pointlist).
310 // 'vedgelist': An array of Voronoi edges. Each entry is a 'voroedge'.
311 // 'vfacetlist': An array of Voronoi facets. Each entry is a 'vorofacet'.
312 // 'vcelllist': An array of Voronoi cells. Each entry is an array of
313 // indices pointing into 'vfacetlist'. The 0th entry is used to store
314 // the length of this array.
315 REAL *vpointlist;
316 voroedge *vedgelist;
317 vorofacet *vfacetlist;
318 int **vcelllist;
319 int numberofvpoints;
320 int numberofvedges;
321 int numberofvfacets;
322 int numberofvcells;
323
324
325 // Variable (and callback functions) for meshing PSCs.
326 void *geomhandle;
327 GetVertexParamOnEdge getvertexparamonedge;
328 GetSteinerOnEdge getsteineronedge;
329 GetVertexParamOnFace getvertexparamonface;
330 GetEdgeSteinerParamOnFace getedgesteinerparamonface;
331 GetSteinerOnFace getsteineronface;
332
333 // A callback function.
334 TetSizeFunc tetunsuitable;
335
336 // Input & output routines.
337 bool load_node_call(FILE* infile, int markers, int uvflag, char*);
338 bool load_node(char*);
339 bool load_edge(char*);
340 bool load_face(char*);
341 bool load_tet(char*);
342 bool load_vol(char*);
343 bool load_var(char*);
344 bool load_mtr(char*);
345 bool load_elem(char*);
346 bool load_poly(char*);
347 bool load_off(char*);
348 bool load_ply(char*);
349 bool load_stl(char*);
350 bool load_vtk(char*);
351 bool load_medit(char*, int);
352 bool load_neumesh(char*, int);
353 bool load_plc(char*, int);
354 bool load_tetmesh(char*, int);
355 void save_nodes(const char*);
356 void save_elements(const char*);
357 void save_faces(const char*);
358 void save_edges(char*);
359 void save_neighbors(char*);
360 void save_poly(const char*);
361 void save_faces2smesh(char*);
362
363 // Read line and parse string functions.
364 char *readline(char* string, FILE* infile, int *linenumber);
365 char *findnextfield(char* string);
366 char *readnumberline(char* string, FILE* infile, char* infilename);
367 char *findnextnumber(char* string);
368
369 static void init(polygon* p) {
370 p->vertexlist = (int *) NULL;
371 p->numberofvertices = 0;
372 }
373
374 static void init(facet* f) {
375 f->polygonlist = (polygon *) NULL;
376 f->numberofpolygons = 0;
377 f->holelist = (REAL *) NULL;
378 f->numberofholes = 0;
379 }
380
381 // Initialize routine.
382 void initialize()
383 {
384 firstnumber = 0;
385 mesh_dim = 3;
386 useindex = 1;
387
388 pointlist = (REAL *) NULL;
389 pointattributelist = (REAL *) NULL;
390 pointmtrlist = (REAL *) NULL;
391 pointmarkerlist = (int *) NULL;
392 point2tetlist = (int *) NULL;
393 pointparamlist = (pointparam *) NULL;
394 numberofpoints = 0;
395 numberofpointattributes = 0;
396 numberofpointmtrs = 0;
397
398 tetrahedronlist = (int *) NULL;
399 tetrahedronattributelist = (REAL *) NULL;
400 tetrahedronvolumelist = (REAL *) NULL;
401 neighborlist = (int *) NULL;
402 tet2facelist = (int *) NULL;
403 tet2edgelist = (int *) NULL;
404 numberoftetrahedra = 0;
405 numberofcorners = 4;
406 numberoftetrahedronattributes = 0;
407
408 trifacelist = (int *) NULL;
409 trifacemarkerlist = (int *) NULL;
410 o2facelist = (int *) NULL;
411 face2tetlist = (int *) NULL;
412 face2edgelist = (int *) NULL;
413 numberoftrifaces = 0;
414
415 edgelist = (int *) NULL;
416 edgemarkerlist = (int *) NULL;
417 o2edgelist = (int *) NULL;
418 edge2tetlist = (int *) NULL;
419 numberofedges = 0;
420
421 facetlist = (facet *) NULL;
422 facetmarkerlist = (int *) NULL;
423 numberoffacets = 0;
424
425 holelist = (REAL *) NULL;
426 numberofholes = 0;
427
428 regionlist = (REAL *) NULL;
429 numberofregions = 0;
430
431 refine_elem_list = (int *) NULL;
432 refine_elem_vol_list = (REAL *) NULL;
433 numberofrefineelems = 0;
434
435 facetconstraintlist = (REAL *) NULL;
436 numberoffacetconstraints = 0;
437 segmentconstraintlist = (REAL *) NULL;
438 numberofsegmentconstraints = 0;
439
440
441 vpointlist = (REAL *) NULL;
442 vedgelist = (voroedge *) NULL;
443 vfacetlist = (vorofacet *) NULL;
444 vcelllist = (int **) NULL;
445 numberofvpoints = 0;
446 numberofvedges = 0;
447 numberofvfacets = 0;
448 numberofvcells = 0;
449
450
451 tetunsuitable = NULL;
452
453 geomhandle = NULL;
454 getvertexparamonedge = NULL;
455 getsteineronedge = NULL;
456 getvertexparamonface = NULL;
457 getedgesteinerparamonface = NULL;
458 getsteineronface = NULL;
459 }
460
461 // Free the memory allocated in 'tetgenio'. Note that it assumes that the
462 // memory was allocated by the "new" operator (C++).
463 void clean_memory()
464 {
465 int i, j;
466
467 if (pointlist != (REAL *) NULL) {
468 delete [] pointlist;
469 }
470 if (pointattributelist != (REAL *) NULL) {
471 delete [] pointattributelist;
472 }
473 if (pointmtrlist != (REAL *) NULL) {
474 delete [] pointmtrlist;
475 }
476 if (pointmarkerlist != (int *) NULL) {
477 delete [] pointmarkerlist;
478 }
479 if (point2tetlist != (int *) NULL) {
480 delete [] point2tetlist;
481 }
482 if (pointparamlist != (pointparam *) NULL) {
483 delete [] pointparamlist;
484 }
485
486 if (tetrahedronlist != (int *) NULL) {
487 delete [] tetrahedronlist;
488 }
489 if (tetrahedronattributelist != (REAL *) NULL) {
490 delete [] tetrahedronattributelist;
491 }
492 if (tetrahedronvolumelist != (REAL *) NULL) {
493 delete [] tetrahedronvolumelist;
494 }
495 if (neighborlist != (int *) NULL) {
496 delete [] neighborlist;
497 }
498 if (tet2facelist != (int *) NULL) {
499 delete [] tet2facelist;
500 }
501 if (tet2edgelist != (int *) NULL) {
502 delete [] tet2edgelist;
503 }
504
505 if (trifacelist != (int *) NULL) {
506 delete [] trifacelist;
507 }
508 if (trifacemarkerlist != (int *) NULL) {
509 delete [] trifacemarkerlist;
510 }
511 if (o2facelist != (int *) NULL) {
512 delete [] o2facelist;
513 }
514 if (face2tetlist != (int *) NULL) {
515 delete [] face2tetlist;
516 }
517 if (face2edgelist != (int *) NULL) {
518 delete [] face2edgelist;
519 }
520
521 if (edgelist != (int *) NULL) {
522 delete [] edgelist;
523 }
524 if (edgemarkerlist != (int *) NULL) {
525 delete [] edgemarkerlist;
526 }
527 if (o2edgelist != (int *) NULL) {
528 delete [] o2edgelist;
529 }
530 if (edge2tetlist != (int *) NULL) {
531 delete [] edge2tetlist;
532 }
533
534 if (facetlist != (facet *) NULL) {
535 facet *f;
536 polygon *p;
537 for (i = 0; i < numberoffacets; i++) {
538 f = &facetlist[i];
539 for (j = 0; j < f->numberofpolygons; j++) {
540 p = &f->polygonlist[j];
541 delete [] p->vertexlist;
542 }
543 delete [] f->polygonlist;
544 if (f->holelist != (REAL *) NULL) {
545 delete [] f->holelist;
546 }
547 }
548 delete [] facetlist;
549 }
550 if (facetmarkerlist != (int *) NULL) {
551 delete [] facetmarkerlist;
552 }
553
554 if (holelist != (REAL *) NULL) {
555 delete [] holelist;
556 }
557 if (regionlist != (REAL *) NULL) {
558 delete [] regionlist;
559 }
560 if (refine_elem_list != (int *) NULL) {
561 delete [] refine_elem_list;
562 if (refine_elem_vol_list != (REAL *) NULL) {
563 delete [] refine_elem_vol_list;
564 }
565 }
566 if (facetconstraintlist != (REAL *) NULL) {
567 delete [] facetconstraintlist;
568 }
569 if (segmentconstraintlist != (REAL *) NULL) {
570 delete [] segmentconstraintlist;
571 }
572 if (vpointlist != (REAL *) NULL) {
573 delete [] vpointlist;
574 }
575 if (vedgelist != (voroedge *) NULL) {
576 delete [] vedgelist;
577 }
578 if (vfacetlist != (vorofacet *) NULL) {
579 for (i = 0; i < numberofvfacets; i++) {
580 delete [] vfacetlist[i].elist;
581 }
582 delete [] vfacetlist;
583 }
584 if (vcelllist != (int **) NULL) {
585 for (i = 0; i < numberofvcells; i++) {
586 delete [] vcelllist[i];
587 }
588 delete [] vcelllist;
589 }
590 }
591
592 // Constructor & destructor.
593 tetgenio() {initialize();}
594 ~tetgenio() {clean_memory();}
595
596}; // class tetgenio
597
598//============================================================================//
599// //
600// tetgenbehavior //
601// //
602// A structure for maintaining the switches and parameters used by TetGen's //
603// internal data structure and algorithms. //
604// //
605// All switches and parameters are initialized with default values. They are //
606// set by the command line arguments (argc, argv). //
607// //
608// NOTE: Some switches are incompatible with others. While some may depend //
609// on other switches. The routine parse_commandline() sets the switches from //
610// the command line (a list of strings) and checks the consistency of the //
611// applied switches. //
612// //
613//============================================================================//
614
616
617public:
618
619 // Switches of TetGen.
620 int plc; // '-p', 0.
621 int psc; // '-s', 0.
622 int refine; // '-r', 0.
623 int quality; // '-q', 0.
624 int nobisect; // '-Y', 0.
625 int cdt; // '-D', 0.
626 int cdtrefine; // '-D#', 7.
627 int coarsen; // '-R', 0.
628 int weighted; // '-w', 0.
629 int brio_hilbert; // '-b', 1.
630 int flipinsert; // '-L', 0.
631 int metric; // '-m', 0.
632 int varvolume; // '-a', 0.
633 int fixedvolume; // '-a', 0.
634 int regionattrib; // '-A', 0.
635 int insertaddpoints; // '-i', 0.
636 int diagnose; // '-d', 0.
637 int convex; // '-c', 0.
638 int nomergefacet; // '-M', 0.
639 int nomergevertex; // '-M', 0.
640 int noexact; // '-X', 0.
641 int nostaticfilter; // '-X', 0.
642 int zeroindex; // '-z', 0.
643 int facesout; // '-f', 0.
644 int edgesout; // '-e', 0.
645 int neighout; // '-n', 0.
646 int voroout; // '-v', 0.
647 int meditview; // '-g', 0.
648 int vtkview; // '-k', 0.
649 int vtksurfview; // '-k', 0.
650 int nobound; // '-B', 0.
651 int nonodewritten; // '-N', 0.
652 int noelewritten; // '-E', 0.
653 int nofacewritten; // '-F', 0.
654 int noiterationnum; // '-I', 0.
655 int nojettison; // '-J', 0.
656 int docheck; // '-C', 0.
657 int quiet; // '-Q', 0.
658 int nowarning; // '-W', 0.
659 int verbose; // '-V', 0.
660
661 // Parameters of TetGen.
662 int vertexperblock; // '-x', 4092.
663 int tetrahedraperblock; // '-x', 8188.
664 int shellfaceperblock; // '-x', 2044.
665 int supsteiner_level; // '-Y/', 2.
666 int addsteiner_algo; // '-Y//', 1.
667 int coarsen_param; // '-R', 0.
668 int weighted_param; // '-w', 0.
669 int fliplinklevel; // -1.
670 int flipstarsize; // -1.
671 int fliplinklevelinc; // 1.
672 int opt_max_flip_level; // '-O', 3.
673 int opt_scheme; // '-O/#', 7.
674 int opt_iterations; // -O//#, 3.
675 int smooth_cirterion; // -s, 1.
676 int smooth_maxiter; // -s, 7.
677 int delmaxfliplevel; // 1.
678 int order; // '-o', 1.
679 int reversetetori; // '-o/', 0.
680 int steinerleft; // '-S', 0.
681 int unflip_queue_limit; // '-U#', 1000.
682 int no_sort; // 0.
683 int hilbert_order; // '-b///', 52.
684 int hilbert_limit; // '-b//' 8.
685 int brio_threshold; // '-b' 64.
686 REAL brio_ratio; // '-b/' 0.125.
687 REAL epsilon; // '-T', 1.0e-8.
688 REAL facet_separate_ang_tol; // '-p', 179.9.
689 REAL collinear_ang_tol; // '-p/', 179.9.
690 REAL facet_small_ang_tol; // '-p//', 15.0.
691 REAL maxvolume; // '-a', -1.0.
692 REAL maxvolume_length; // '-a', -1.0.
693 REAL minratio; // '-q', 0.0.
694 REAL opt_max_asp_ratio; // 1000.0.
695 REAL opt_max_edge_ratio; // 100.0.
696 REAL mindihedral; // '-q', 5.0.
697 REAL optmaxdihedral; // -o/# 177.0.
698 REAL metric_scale; // -m#, 1.0.
699 REAL smooth_alpha; // '-s', 0.3.
700 REAL coarsen_percent; // -R1/#, 1.0.
701 REAL elem_growth_ratio; // Growth ratio of # elements, -r#, 0.0.
702 REAL refine_progress_ratio; // -r/#, 0.333.
703
704 // Strings of command line arguments and input/output file names.
705 char commandline[1024];
706 char infilename[1024];
707 char outfilename[1024];
708 char addinfilename[1024];
709 char bgmeshfilename[1024];
710
711 // Read an additional tetrahedral mesh and treat it as holes [2018-07-30].
712 int hole_mesh; // '-H', 0.
713 char hole_mesh_filename[1024];
714
715 // The input object of TetGen. They are recognized by either the input
716 // file extensions or by the specified options.
717 // Currently the following objects are supported:
718 // - NODES, a list of nodes (.node);
719 // - POLY, a piecewise linear complex (.poly or .smesh);
720 // - OFF, a polyhedron (.off, Geomview's file format);
721 // - PLY, a polyhedron (.ply, file format from gatech, only ASCII);
722 // - STL, a surface mesh (.stl, stereolithography format);
723 // - MEDIT, a surface mesh (.mesh, Medit's file format);
724 // - MESH, a tetrahedral mesh (.ele).
725 // If no extension is available, the imposed command line switch
726 // (-p or -r) implies the object.
727 enum objecttype {NODES, POLY, OFF, PLY, STL, MEDIT, VTK, MESH, NEU_MESH} object;
728
729
730 void syntax();
731 void usage();
732
733 // Command line parse routine.
734 bool parse_commandline(int argc, char **argv);
735 bool parse_commandline(const char *switches) {
736 char* sc = (char*)switches;
737 return parse_commandline(0, &sc);
738 }
739
740 // Initialize all variables.
742 {
743 plc = 0;
744 psc = 0;
745 refine = 0;
746 quality = 0;
747 nobisect = 0;
748 cdt = 0; // set by -D (without a number following it)
749 cdtrefine = 7; // default, set by -D#
750 coarsen = 0;
751 metric = 0;
752 weighted = 0;
753 brio_hilbert = 1;
754 flipinsert = 0;
755 varvolume = 0;
756 fixedvolume = 0;
757 noexact = 0;
758 nostaticfilter = 0;
759 insertaddpoints = 0;
760 regionattrib = 0;
761 diagnose = 0;
762 convex = 0;
763 zeroindex = 0;
764 facesout = 0;
765 edgesout = 0;
766 neighout = 0;
767 voroout = 0;
768 meditview = 0;
769 vtkview = 0;
770 vtksurfview = 0;
771 nobound = 0;
772 nonodewritten = 0;
773 noelewritten = 0;
774 nofacewritten = 0;
775 noiterationnum = 0;
776 nomergefacet = 0;
777 nomergevertex = 0;
778 nojettison = 0;
779 docheck = 0;
780 quiet = 0;
781 nowarning = 0;
782 verbose = 0;
783
784 vertexperblock = 4092;
785 tetrahedraperblock = 8188;
786 shellfaceperblock = 4092;
787 supsteiner_level = 2;
788 addsteiner_algo = 1;
789 coarsen_param = 0;
790 weighted_param = 0;
791 fliplinklevel = -1;
792 flipstarsize = -1;
793 fliplinklevelinc = 1;
794 opt_scheme = 7;
795 opt_max_flip_level = 3;
796 opt_iterations = 3;
797 delmaxfliplevel = 1;
798 order = 1;
799 reversetetori = 0;
800 steinerleft = -1;
801 unflip_queue_limit = 1000;
802 no_sort = 0;
803 hilbert_order = 52; //-1;
804 hilbert_limit = 8;
805 brio_threshold = 64;
806 brio_ratio = 0.125;
807 facet_separate_ang_tol = 179.9;
808 collinear_ang_tol = 179.9;
809 facet_small_ang_tol = 15.0;
810 maxvolume = -1.0;
811 maxvolume_length = -1.0;
812 minratio = 2.0;
813 opt_max_asp_ratio = 1000.;
814 opt_max_edge_ratio = 100.;
815 mindihedral = 3.5;
816 optmaxdihedral = 177.00;
817 epsilon = 1.0e-8;
818 coarsen_percent = 1.0;
819 metric_scale = 1.0; // -m#
820 elem_growth_ratio = 0.0; // -r#
821 refine_progress_ratio = 0.333; // -r/#
822 object = NODES;
823
824 smooth_cirterion = 3; // -s# default smooth surface and volume vertices.
825 smooth_maxiter = 7; // set by -s#/7
826 smooth_alpha = 0.3; // relax parameter, set by -s#/#/0.3
827
828 commandline[0] = '\0';
829 infilename[0] = '\0';
830 outfilename[0] = '\0';
831 addinfilename[0] = '\0';
832 bgmeshfilename[0] = '\0';
833
834 hole_mesh = 0;
835 hole_mesh_filename[0] = '\0';
836
837 }
838
839}; // class tetgenbehavior
840
841//============================================================================//
842// //
843// Robust Geometric predicates //
844// //
845// The following routines are the robust geometric predicates for orientation //
846// test and point-in-sphere test implemented by Jonathan Shewchuk. //
847// He generously provided the source code in the public domain, //
848// http://www.cs.cmu.edu/~quake/robust.html. //
849// predicates.cxx is a C++ version of the original C code. //
850// //
851// The original predicates of Shewchuk only use "dynamic filters", i.e., it //
852// computes the error at runtime step by step. TetGen first uses a "static //
853// filter" in each predicate. It estimates the maximal possible error in all //
854// cases. It safely and quickly "filters" many easy cases. //
855// //
856//============================================================================//
857
858void exactinit(int, int, int, REAL, REAL, REAL);
859
860REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd);
861REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe);
862REAL orient4d(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe,
863 REAL ah, REAL bh, REAL ch, REAL dh, REAL eh);
864
865REAL orient2dexact(REAL *pa, REAL *pb, REAL *pc);
866REAL orient3dexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd);
867REAL orient4dexact(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
868 REAL ah, REAL bh, REAL ch, REAL dh, REAL eh);
869
870
871//============================================================================//
872// //
873// tetgenmesh TetGen's internal mesh data structure. //
874// //
875// It uses a tetrahedron-based mesh data structure. It implements elementary //
876// flip operations to locally modify the mesh. It implements basic meshing //
877// algorithms to create Delaunay tetrahedraliations, to perform boundary //
878// recovery, to place Steiner points in the mesh domain, and to optimize the //
879// quality of the mesh. //
880// //
881//============================================================================//
882
884
885public:
886
887//============================================================================//
888// //
889// Mesh data structure //
890// //
891// A tetrahedral mesh T of a 3D piecewise linear complex (PLC) X is a 3D //
892// simplicial complex whose underlying space is equal to the space of X. T //
893// contains a 2D subcomplex S which is a triangular mesh of the boundary of //
894// X. S contains a 1D subcomplex L which is a linear mesh of the boundary of //
895// S. Faces and edges in S and L are respectively called subfaces and segme- //
896// nts to distinguish them from others in T. //
897// //
898// TetGen uses a tetrahedron-based data structure. It stores tetrahedra and //
899// vertices. This data structure is pointer-based. Each tetrahedron contains //
900// pointers to its vertices and adjacent tetrahedra. Each vertex holds its x-,//
901// y-, z-coordinates, and a pointer to one of the tetrahedra having it. Both //
902// tetrahedra and vertices may contain user data. //
903// //
904// Let T be a tetrahedralization. Each triangular face of T belongs to either //
905// two or one tetrahedron. In the latter case, it is an exterior boundary //
906// face of T. TetGen attaches tetrahedra (one-to-one) to such faces. All such //
907// tetrahedra contain an "infinite vertex" (which has no geometric coordinates//
908// ). One can imagine such a vertex lies in 4D space and is visible by all //
909// exterior boundary faces simultaneously. This extended set of tetrahedra //
910// (including the infinite vertex) becomes a tetrahedralization of a 3-sphere //
911// that has no boundary in 3d. It has the nice property that every triangular //
912// face is shared by exactly two tetrahedra. //
913// //
914// The current version of TetGen stores explicitly the subfaces and segments //
915// (which are in surface mesh S and the linear mesh L), respectively. Extra //
916// pointers are allocated in tetrahedra and subfaces to point each other. //
917// //
918//============================================================================//
919
920 // The tetrahedron data structure. It includes the following fields:
921 // - a list of four adjoining tetrahedra;
922 // - a list of four vertices;
923 // - a pointer to a list of four subfaces (optional, for -p switch);
924 // - a pointer to a list of six segments (optional, for -p switch);
925 // - a list of user-defined floating-point attributes (optional);
926 // - a volume constraint (optional, for -a switch);
927 // - an integer of element marker (and flags);
928 // The structure of a tetrahedron is an array of pointers. Its actual size
929 // (the length of the array) is determined at runtime.
930
931 typedef REAL **tetrahedron;
932
933 // The subface data structure. It includes the following fields:
934 // - a list of three adjoining subfaces;
935 // - a list of three vertices;
936 // - a list of three adjoining segments;
937 // - two adjoining tetrahedra;
938 // - an area constraint (optional, for -q switch);
939 // - an integer for boundary marker;
940 // - an integer for type, flags, etc.
941
942 typedef REAL **shellface;
943
944 // The point data structure. It includes the following fields:
945 // - x, y and z coordinates;
946 // - a list of user-defined point attributes (optional);
947 // - u, v coordinates (optional, for -s switch);
948 // - a metric tensor (optional, for -q or -m switch);
949 // - a pointer to an adjacent tetrahedron;
950 // - a pointer to a parent (or a duplicate) point;
951 // - a pointer to an adjacent subface or segment (optional, -p switch);
952 // - a pointer to a tet in background mesh (optional, for -m switch);
953 // - an integer for boundary marker (point index);
954 // - an integer for point type (and flags).
955 // - an integer for geometry tag (optional, for -s switch).
956 // The structure of a point is an array of REALs. Its acutal size is
957 // determined at the runtime.
958
959 typedef REAL *point;
960
961//============================================================================//
962// //
963// Handles //
964// //
965// Navigation and manipulation in a tetrahedralization are accomplished by //
966// operating on structures referred as ``handles". A handle is a pair (t,v), //
967// where t is a pointer to a tetrahedron, and v is a 4-bit integer, in the //
968// range from 0 to 11. v is called the ``version'' of a tetrahedron, it rep- //
969// resents a directed edge of a specific face of the tetrahedron. //
970// //
971// There are 12 even permutations of the four vertices, each of them corres- //
972// ponds to a directed edge (a version) of the tetrahedron. The 12 versions //
973// can be grouped into 4 distinct ``edge rings'' in 4 ``oriented faces'' of //
974// this tetrahedron. One can encode each version (a directed edge) into a //
975// 4-bit integer such that the two upper bits encode the index (from 0 to 2) //
976// of this edge in the edge ring, and the two lower bits encode the index ( //
977// from 0 to 3) of the oriented face which contains this edge. //
978// //
979// The four vertices of a tetrahedron are indexed from 0 to 3 (according to //
980// their storage in the data structure). Give each face the same index as //
981// the node opposite it in the tetrahedron. Denote the edge connecting face //
982// i to face j as i/j. We number the twelve versions as follows: //
983// //
984// | edge 0 edge 1 edge 2 //
985// --------|-------------------------------- //
986// face 0 | 0 (0/1) 4 (0/3) 8 (0/2) //
987// face 1 | 1 (1/2) 5 (1/3) 9 (1/0) //
988// face 2 | 2 (2/3) 6 (2/1) 10 (2/0) //
989// face 3 | 3 (3/0) 7 (3/1) 11 (3/2) //
990// //
991// Similarly, navigation and manipulation in a (boundary) triangulation are //
992// done by using handles of triangles. Each handle is a pair (s, v), where s //
993// is a pointer to a triangle, and v is a version in the range from 0 to 5. //
994// Each version corresponds to a directed edge of this triangle. //
995// //
996// Number the three vertices of a triangle from 0 to 2 (according to their //
997// storage in the data structure). Give each edge the same index as the node //
998// opposite it in the triangle. The six versions of a triangle are: //
999// //
1000// | edge 0 edge 1 edge 2 //
1001// ---------------|-------------------------- //
1002// ccw orieation | 0 2 4 //
1003// cw orieation | 1 3 5 //
1004// //
1005// In the following, a 'triface' is a handle of tetrahedron, and a 'face' is //
1006// a handle of a triangle. //
1007// //
1008//============================================================================//
1009
1010 class triface {
1011 public:
1012 tetrahedron *tet;
1013 int ver; // Range from 0 to 11.
1014 triface() : tet(0), ver(0) {}
1015 triface& operator=(const triface& t) {
1016 tet = t.tet; ver = t.ver;
1017 return *this;
1018 }
1019 };
1020
1021 class face {
1022 public:
1023 shellface *sh;
1024 int shver; // Range from 0 to 5.
1025 face() : sh(0), shver(0) {}
1026 face& operator=(const face& s) {
1027 sh = s.sh; shver = s.shver;
1028 return *this;
1029 }
1030 };
1031
1032//============================================================================//
1033// //
1034// Arraypool //
1035// //
1036// A dynamic linear array. (It is written by J. Shewchuk) //
1037// //
1038// Each arraypool contains an array of pointers to a number of blocks. Each //
1039// block contains the same fixed number of objects. Each index of the array //
1040// addresses a particular object in the pool. The most significant bits add- //
1041// ress the index of the block containing the object. The less significant //
1042// bits address this object within the block. //
1043// //
1044// 'objectbytes' is the size of one object in blocks; 'log2objectsperblock' //
1045// is the base-2 logarithm of 'objectsperblock'; 'objects' counts the number //
1046// of allocated objects; 'totalmemory' is the total memory in bytes. //
1047// //
1048//============================================================================//
1049
1051
1052 public:
1053
1054 int objectbytes;
1055 int objectsperblock;
1056 int log2objectsperblock;
1057 int objectsperblockmark;
1058 int toparraylen;
1059 char **toparray;
1060 long objects;
1061 unsigned long totalmemory;
1062
1063 void restart();
1064 void poolinit(int sizeofobject, int log2objperblk);
1065 char* getblock(int objectindex);
1066 void* lookup(int objectindex);
1067 int newindex(void **newptr);
1068
1069 arraypool(int sizeofobject, int log2objperblk);
1070 ~arraypool();
1071 };
1072
1073// fastlookup() -- A fast, unsafe operation. Return the pointer to the object
1074// with a given index. Note: The object's block must have been allocated,
1075// i.e., by the function newindex().
1076
1077#define fastlookup(pool, index) \
1078 (void *) ((pool)->toparray[(index) >> (pool)->log2objectsperblock] + \
1079 ((index) & (pool)->objectsperblockmark) * (pool)->objectbytes)
1080
1081//============================================================================//
1082// //
1083// Memorypool //
1084// //
1085// A structure for memory allocation. (It is written by J. Shewchuk) //
1086// //
1087// firstblock is the first block of items. nowblock is the block from which //
1088// items are currently being allocated. nextitem points to the next slab //
1089// of free memory for an item. deaditemstack is the head of a linked list //
1090// (stack) of deallocated items that can be recycled. unallocateditems is //
1091// the number of items that remain to be allocated from nowblock. //
1092// //
1093// Traversal is the process of walking through the entire list of items, and //
1094// is separate from allocation. Note that a traversal will visit items on //
1095// the "deaditemstack" stack as well as live items. pathblock points to //
1096// the block currently being traversed. pathitem points to the next item //
1097// to be traversed. pathitemsleft is the number of items that remain to //
1098// be traversed in pathblock. //
1099// //
1100//============================================================================//
1101
1103
1104 public:
1105
1106 void **firstblock, **nowblock;
1107 void *nextitem;
1108 void *deaditemstack;
1109 void **pathblock;
1110 void *pathitem;
1111 int alignbytes;
1112 int itembytes, itemwords;
1113 int itemsperblock;
1114 long items, maxitems;
1115 int unallocateditems;
1116 int pathitemsleft;
1117
1118 memorypool();
1119 memorypool(int, int, int, int);
1120 ~memorypool();
1121
1122 void poolinit(int, int, int, int);
1123 void restart();
1124 void *alloc();
1125 void dealloc(void*);
1126 void traversalinit();
1127 void *traverse();
1128 };
1129
1130//============================================================================//
1131// //
1132// badface //
1133// //
1134// Despite of its name, a 'badface' can be used to represent one of the //
1135// following objects: //
1136// - a face of a tetrahedron which is (possibly) non-Delaunay; //
1137// - an encroached subsegment or subface; //
1138// - a bad-quality tetrahedron, i.e, has too large radius-edge ratio; //
1139// - a sliver, i.e., has good radius-edge ratio but nearly zero volume; //
1140// - a recently flipped face (saved for undoing the flip later). //
1141// //
1142//============================================================================//
1143
1144 class badface {
1145 public:
1146 triface tt;
1147 face ss;
1148 REAL key, cent[6]; // circumcenter or cos(dihedral angles) at 6 edges.
1149 point forg, fdest, fapex, foppo, noppo;
1150 badface *nextitem;
1151 badface() : key(0), forg(0), fdest(0), fapex(0), foppo(0), noppo(0),
1152 nextitem(0) {}
1153 void init() {
1154 key = 0.;
1155 for (int k = 0; k < 6; k++) cent[k] = 0.;
1156 tt.tet = NULL; tt.ver = 0;
1157 ss.sh = NULL; ss.shver = 0;
1158 forg = fdest = fapex = foppo = noppo = NULL;
1159 nextitem = NULL;
1160 }
1161 };
1162
1163//============================================================================//
1164// //
1165// insertvertexflags //
1166// //
1167// A collection of flags that pass to the routine insertvertex(). //
1168// //
1169//============================================================================//
1170
1172
1173 public:
1174
1175 int iloc; // input/output.
1176 int bowywat, lawson;
1177 int splitbdflag, validflag, respectbdflag;
1178 int rejflag, chkencflag, cdtflag;
1179 int assignmeshsize;
1180 int sloc, sbowywat;
1181
1182 // Used by Delaunay refinement.
1183 int collect_inial_cavity_flag;
1184 int ignore_near_vertex;
1185 int check_insert_radius;
1186 int refineflag; // 0, 1, 2, 3
1187 triface refinetet;
1188 face refinesh;
1189 int smlenflag; // for useinsertradius.
1190 REAL smlen; // for useinsertradius.
1191 point parentpt;
1192
1193 void init() {
1194 iloc = bowywat = lawson = 0;
1195 splitbdflag = validflag = respectbdflag = 0;
1196 rejflag = chkencflag = cdtflag = 0;
1197 assignmeshsize = 0;
1198 sloc = sbowywat = 0;
1199
1200 collect_inial_cavity_flag = 0;
1201 ignore_near_vertex = 0;
1202 check_insert_radius = 0;
1203 refineflag = 0;
1204 refinetet.tet = NULL;
1205 refinesh.sh = NULL;
1206 smlenflag = 0;
1207 smlen = 0.0;
1208 parentpt = NULL;
1209 }
1210
1212 init();
1213 }
1214 };
1215
1216//============================================================================//
1217// //
1218// flipconstraints //
1219// //
1220// A structure of a collection of data (options and parameters) which pass //
1221// to the edge flip function flipnm(). //
1222// //
1223//============================================================================//
1224
1226
1227 public:
1228
1229 // Elementary flip flags.
1230 int enqflag; // (= flipflag)
1231 int chkencflag;
1232
1233 // Control flags
1234 int unflip; // Undo the performed flips.
1235 int collectnewtets; // Collect the new tets created by flips.
1236 int collectencsegflag;
1237
1238 // Optimization flags.
1239 int noflip_in_surface; // do not flip edges (not segment) in surface.
1240 int remove_ndelaunay_edge; // Remove a non-Delaunay edge.
1241 REAL bak_tetprism_vol; // The value to be minimized.
1242 REAL tetprism_vol_sum;
1243 int remove_large_angle; // Remove a large dihedral angle at edge.
1244 REAL cosdihed_in; // The input cosine of the dihedral angle (> 0).
1245 REAL cosdihed_out; // The improved cosine of the dihedral angle.
1246 REAL max_asp_out; // Max asp ratio after the improvement of dihedral angle.
1247
1248 // Boundary recovery flags.
1249 int checkflipeligibility;
1250 point seg[2]; // A constraining edge to be recovered.
1251 point fac[3]; // A constraining face to be recovered.
1252 point remvert; // A vertex to be removed.
1253
1254
1255 flipconstraints() {
1256 enqflag = 0;
1257 chkencflag = 0;
1258
1259 unflip = 0;
1260 collectnewtets = 0;
1261 collectencsegflag = 0;
1262
1263 noflip_in_surface = 0;
1264 remove_ndelaunay_edge = 0;
1265 bak_tetprism_vol = 0.0;
1266 tetprism_vol_sum = 0.0;
1267 remove_large_angle = 0;
1268 cosdihed_in = 0.0;
1269 cosdihed_out = 0.0;
1270 max_asp_out = 0.0;
1271
1272 checkflipeligibility = 0;
1273 seg[0] = NULL;
1274 fac[0] = NULL;
1275 remvert = NULL;
1276 }
1277 };
1278
1279//============================================================================//
1280// //
1281// optparameters //
1282// //
1283// Optimization options and parameters. //
1284// //
1285//============================================================================//
1286
1288
1289 public:
1290
1291 // The one of goals of optimization.
1292 int max_min_volume; // Maximize the minimum volume.
1293 int min_max_aspectratio; // Minimize the maximum aspect ratio.
1294 int min_max_dihedangle; // Minimize the maximum dihedral angle.
1295
1296 // The initial and improved value.
1297 REAL initval, imprval;
1298
1299 int numofsearchdirs;
1300 REAL searchstep;
1301 int maxiter; // Maximum smoothing iterations (disabled by -1).
1302 int smthiter; // Performed iterations.
1303
1304
1305 optparameters() {
1306 max_min_volume = 0;
1307 min_max_aspectratio = 0;
1308 min_max_dihedangle = 0;
1309
1310 initval = imprval = 0.0;
1311
1312 numofsearchdirs = 10;
1313 searchstep = 0.01;
1314 maxiter = -1; // Unlimited smoothing iterations.
1315 smthiter = 0;
1316
1317 }
1318 };
1319
1320
1321//============================================================================//
1322// //
1323// Labels (enumeration declarations) used by TetGen. //
1324// //
1325//============================================================================//
1326
1327 // Labels that signify the type of a vertex.
1328 enum verttype {UNUSEDVERTEX, DUPLICATEDVERTEX, RIDGEVERTEX, /*ACUTEVERTEX,*/
1329 FACETVERTEX, VOLVERTEX, FREESEGVERTEX, FREEFACETVERTEX,
1330 FREEVOLVERTEX, NREGULARVERTEX, DEADVERTEX};
1331
1332 // Labels that signify the result of triangle-triangle intersection test.
1333 enum interresult {DISJOINT, INTERSECT, SHAREVERT, SHAREEDGE, SHAREFACE,
1334 TOUCHEDGE, TOUCHFACE, ACROSSVERT, ACROSSEDGE, ACROSSFACE,
1335 SELF_INTERSECT};
1336
1337 // Labels that signify the result of point location.
1338 enum locateresult {UNKNOWN, OUTSIDE, INTETRAHEDRON, ONFACE, ONEDGE, ONVERTEX,
1339 ENCVERTEX, ENCSEGMENT, ENCSUBFACE, NEARVERTEX, NONREGULAR,
1340 INSTAR, BADELEMENT, NULLCAVITY, SHARPCORNER, FENSEDIN,
1341 NONCOPLANAR, SELF_ENCROACH};
1342
1343//============================================================================//
1344// //
1345// Variables of TetGen //
1346// //
1347//============================================================================//
1348
1349 // Pointer to the input data (a set of nodes, a PLC, or a mesh).
1350 tetgenio *in, *addin;
1351
1352 // Pointer to the switches and parameters.
1353 tetgenbehavior *b;
1354
1355 // Pointer to a background mesh (contains size specification map).
1356 tetgenmesh *bgm;
1357
1358 // Memorypools to store mesh elements (points, tetrahedra, subfaces, and
1359 // segments) and extra pointers between tetrahedra, subfaces, and segments.
1360 memorypool *tetrahedrons, *subfaces, *subsegs, *points;
1361 memorypool *tet2subpool, *tet2segpool;
1362
1363 // Memorypools to store bad-quality (or encroached) elements.
1364 memorypool *badtetrahedrons, *badsubfacs, *badsubsegs;
1365 memorypool *split_subfaces_pool, *split_segments_pool;
1366 arraypool *unsplit_badtets, *unsplit_subfaces, *unsplit_segments;
1367 arraypool *check_tets_list;
1368
1369 badface *stack_enc_segments, *stack_enc_subfaces;
1370
1371 // Bad quality subfaces are ordered by priority queues.
1372 badface *queuefront[64];
1373 badface *queuetail[64];
1374 int nextnonemptyq[64];
1375 int firstnonemptyq, recentq;
1376
1377 // Bad quality tetrahedra are ordered by priority queues.
1378 memorypool *badqual_tets_pool;
1379 badface *bt_queuefront[64];
1380 badface *bt_queuetail[64];
1381 int bt_nextnonemptyq[64];
1382 int bt_firstnonemptyq, bt_recentq;
1383
1384 // A memorypool to store faces to be flipped.
1385 memorypool *flippool;
1386 arraypool *later_unflip_queue, *unflipqueue;
1387 badface *flipstack, *unflip_queue_front, *unflip_queue_tail;
1388
1389 // Arrays used for point insertion (the Bowyer-Watson algorithm).
1390 arraypool *cavetetlist, *cavebdrylist, *caveoldtetlist;
1391 arraypool *cave_oldtet_list; // only tetrahedron's
1392 arraypool *cavetetshlist, *cavetetseglist, *cavetetvertlist;
1393 arraypool *caveencshlist, *caveencseglist;
1394 arraypool *caveshlist, *caveshbdlist, *cavesegshlist;
1395 triface _bw_faces[4096]; // _bw_faces[64][64];
1396
1397 // Stacks used for CDT construction and boundary recovery.
1398 arraypool *subsegstack, *subfacstack, *subvertstack;
1399 arraypool *skipped_segment_list, *skipped_facet_list;
1400
1401 // Arrays of encroached segments and subfaces (for mesh refinement).
1402 arraypool *encseglist, *encshlist;
1403
1404 // The map between facets to their vertices (for mesh refinement).
1405 int number_of_facets;
1406 int *idx2facetlist;
1407 point *facetverticeslist;
1408 int *idx_segment_facet_list; // segment-to-facet map.
1409 int *segment_facet_list;
1410 int *idx_ridge_vertex_facet_list; // vertex-to-facet map.
1411 int *ridge_vertex_facet_list;
1412
1413 // The map between segments to their endpoints (for mesh refinement).
1414 int segmentendpointslist_length;
1415 point *segmentendpointslist;
1416 double *segment_info_list;
1417 int *idx_segment_ridge_vertex_list; // are two ridge vertices form a segment?
1418 point *segment_ridge_vertex_list;
1419
1420 // The infinite vertex.
1421 point dummypoint;
1422 // The recently visited tetrahedron, subface.
1423 triface recenttet;
1424 face recentsh;
1425
1426 // PI is the ratio of a circle's circumference to its diameter.
1427 static REAL PI;
1428
1429 // The list of subdomains. (-A option).
1430 int subdomains; // Number of subdomains.
1431 int *subdomain_markers;
1432
1433 // Various variables.
1434 int numpointattrib; // Number of point attributes.
1435 int numelemattrib; // Number of tetrahedron attributes.
1436 int sizeoftensor; // Number of REALs per metric tensor.
1437 int pointmtrindex; // Index to find the metric tensor of a point.
1438 int pointparamindex; // Index to find the u,v coordinates of a point.
1439 int point2simindex; // Index to find a simplex adjacent to a point.
1440 int pointmarkindex; // Index to find boundary marker of a point.
1441 int pointinsradiusindex; // Index to find the insertion radius of a point.
1442 int elemattribindex; // Index to find attributes of a tetrahedron.
1443 int polarindex; // Index to find the polar plane parameters.
1444 int volumeboundindex; // Index to find volume bound of a tetrahedron.
1445 int elemmarkerindex; // Index to find marker of a tetrahedron.
1446 int shmarkindex; // Index to find boundary marker of a subface.
1447 int areaboundindex; // Index to find area bound of a subface.
1448 int checksubsegflag; // Are there segments in the tetrahedralization yet?
1449 int checksubfaceflag; // Are there subfaces in the tetrahedralization yet?
1450 int boundary_recovery_flag;
1451 int checkconstraints; // Are there variant (node, seg, facet) constraints?
1452 int nonconvex; // Is current mesh non-convex?
1453 int autofliplinklevel; // The increase of link levels, default is 1.
1454 int useinsertradius; // Save the insertion radius for Steiner points.
1455 long samples; // Number of random samples for point location.
1456 unsigned long randomseed; // Current random number seed.
1457 REAL cosmaxdihed, cosmindihed; // The cosine values of max/min dihedral.
1458 REAL cossmtdihed; // The cosine value of a bad dihedral to be smoothed.
1459 REAL cosslidihed; // The cosine value of the max dihedral of a sliver.
1460 REAL cos_large_dihed; // The cosine value of large dihedral (135 degree).
1461 REAL opt_max_sliver_asp_ratio; // = 10 x b->opt_max_asp_ratio.
1462 REAL minfaceang, minfacetdihed; // The minimum input (dihedral) angles.
1463 REAL cos_facet_separate_ang_tol;
1464 REAL cos_collinear_ang_tol;
1465 REAL tetprism_vol_sum; // The total volume of tetrahedral-prisms (in 4D).
1466 REAL longest; // The longest possible edge length.
1467 REAL minedgelength; // = longest * b->epsion.
1468 REAL xmax, xmin, ymax, ymin, zmax, zmin; // Bounding box of points.
1469
1470 // Options for mesh refinement.
1471 REAL big_radius_edge_ratio; // calculated by qualitystatistics().
1472 REAL smallest_insradius; // Save the smallest insertion radius.
1473 long elem_limit;
1474 long insert_point_count; // number of attempted insertions.
1475 long report_refine_progress; // the next report event.
1476 long last_point_count; // number of points after last report event.
1477 long last_insertion_count; // number of insertions after last report event.
1478
1479 // Counters.
1480 long insegments; // Number of input segments.
1481 long hullsize; // Number of exterior boundary faces.
1482 long meshedges; // Number of mesh edges.
1483 long meshhulledges; // Number of boundary mesh edges.
1484 long steinerleft; // Number of Steiner points not yet used.
1485 long dupverts; // Are there duplicated vertices?
1486 long unuverts; // Are there unused vertices?
1487 long duplicated_facets_count; // Are there duplicated facets.?
1488 long nonregularcount; // Are there non-regular vertices?
1489 long st_segref_count, st_facref_count, st_volref_count; // Steiner points.
1490 long fillregioncount, cavitycount, cavityexpcount;
1491 long flip14count, flip26count, flipn2ncount;
1492 long flip23count, flip32count, flip44count, flip41count;
1493 long flip31count, flip22count;
1494 long opt_flips_count, opt_collapse_count, opt_smooth_count;
1495 long recover_delaunay_count;
1496 unsigned long totalworkmemory; // Total memory used by working arrays.
1497
1498
1499//============================================================================//
1500// //
1501// Mesh manipulation primitives //
1502// //
1503//============================================================================//
1504
1505 // Fast lookup tables for mesh manipulation primitives.
1506 static int bondtbl[12][12], fsymtbl[12][12];
1507 static int esymtbl[12], enexttbl[12], eprevtbl[12];
1508 static int enextesymtbl[12], eprevesymtbl[12];
1509 static int eorgoppotbl[12], edestoppotbl[12];
1510 static int facepivot1[12], facepivot2[12][12];
1511 static int orgpivot[12], destpivot[12], apexpivot[12], oppopivot[12];
1512 static int tsbondtbl[12][6], stbondtbl[12][6];
1513 static int tspivottbl[12][6], stpivottbl[12][6];
1514 static int ver2edge[12], edge2ver[6], epivot[12];
1515 static int sorgpivot [6], sdestpivot[6], sapexpivot[6];
1516 static int snextpivot[6];
1517
1518 void inittables();
1519
1520 // Primitives for tetrahedra.
1521 inline tetrahedron encode(triface& t);
1522 inline tetrahedron encode2(tetrahedron* ptr, int ver);
1523 inline void decode(tetrahedron ptr, triface& t);
1524 inline tetrahedron* decode_tet_only(tetrahedron ptr);
1525 inline int decode_ver_only(tetrahedron ptr);
1526 inline void bond(triface& t1, triface& t2);
1527 inline void dissolve(triface& t);
1528 inline void esym(triface& t1, triface& t2);
1529 inline void esymself(triface& t);
1530 inline void enext(triface& t1, triface& t2);
1531 inline void enextself(triface& t);
1532 inline void eprev(triface& t1, triface& t2);
1533 inline void eprevself(triface& t);
1534 inline void enextesym(triface& t1, triface& t2);
1535 inline void enextesymself(triface& t);
1536 inline void eprevesym(triface& t1, triface& t2);
1537 inline void eprevesymself(triface& t);
1538 inline void eorgoppo(triface& t1, triface& t2);
1539 inline void eorgoppoself(triface& t);
1540 inline void edestoppo(triface& t1, triface& t2);
1541 inline void edestoppoself(triface& t);
1542 inline void fsym(triface& t1, triface& t2);
1543 inline void fsymself(triface& t);
1544 inline void fnext(triface& t1, triface& t2);
1545 inline void fnextself(triface& t);
1546 inline point org (triface& t);
1547 inline point dest(triface& t);
1548 inline point apex(triface& t);
1549 inline point oppo(triface& t);
1550 inline void setorg (triface& t, point p);
1551 inline void setdest(triface& t, point p);
1552 inline void setapex(triface& t, point p);
1553 inline void setoppo(triface& t, point p);
1554 inline REAL elemattribute(tetrahedron* ptr, int attnum);
1555 inline void setelemattribute(tetrahedron* ptr, int attnum, REAL value);
1556 inline REAL* get_polar(tetrahedron* ptr);
1557 inline REAL get_volume(tetrahedron* ptr);
1558 inline REAL volumebound(tetrahedron* ptr);
1559 inline void setvolumebound(tetrahedron* ptr, REAL value);
1560 inline int elemindex(tetrahedron* ptr);
1561 inline void setelemindex(tetrahedron* ptr, int value);
1562 inline int elemmarker(tetrahedron* ptr);
1563 inline void setelemmarker(tetrahedron* ptr, int value);
1564 inline void infect(triface& t);
1565 inline void uninfect(triface& t);
1566 inline bool infected(triface& t);
1567 inline void marktest(triface& t);
1568 inline void unmarktest(triface& t);
1569 inline bool marktested(triface& t);
1570 inline void markface(triface& t);
1571 inline void unmarkface(triface& t);
1572 inline bool facemarked(triface& t);
1573 inline void markedge(triface& t);
1574 inline void unmarkedge(triface& t);
1575 inline bool edgemarked(triface& t);
1576 inline void marktest2(triface& t);
1577 inline void unmarktest2(triface& t);
1578 inline bool marktest2ed(triface& t);
1579 inline int elemcounter(triface& t);
1580 inline void setelemcounter(triface& t, int value);
1581 inline void increaseelemcounter(triface& t);
1582 inline void decreaseelemcounter(triface& t);
1583 inline bool ishulltet(triface& t);
1584 inline bool isdeadtet(triface& t);
1585
1586 // Primitives for subfaces and subsegments.
1587 inline void sdecode(shellface sptr, face& s);
1588 inline shellface sencode(face& s);
1589 inline shellface sencode2(shellface *sh, int shver);
1590 inline void spivot(face& s1, face& s2);
1591 inline void spivotself(face& s);
1592 inline void sbond(face& s1, face& s2);
1593 inline void sbond1(face& s1, face& s2);
1594 inline void sdissolve(face& s);
1595 inline point sorg(face& s);
1596 inline point sdest(face& s);
1597 inline point sapex(face& s);
1598 inline void setsorg(face& s, point pointptr);
1599 inline void setsdest(face& s, point pointptr);
1600 inline void setsapex(face& s, point pointptr);
1601 inline void sesym(face& s1, face& s2);
1602 inline void sesymself(face& s);
1603 inline void senext(face& s1, face& s2);
1604 inline void senextself(face& s);
1605 inline void senext2(face& s1, face& s2);
1606 inline void senext2self(face& s);
1607 inline REAL areabound(face& s);
1608 inline void setareabound(face& s, REAL value);
1609 inline int shellmark(face& s);
1610 inline void setshellmark(face& s, int value);
1611 inline void sinfect(face& s);
1612 inline void suninfect(face& s);
1613 inline bool sinfected(face& s);
1614 inline void smarktest(face& s);
1615 inline void sunmarktest(face& s);
1616 inline bool smarktested(face& s);
1617 inline void smarktest2(face& s);
1618 inline void sunmarktest2(face& s);
1619 inline bool smarktest2ed(face& s);
1620 inline void smarktest3(face& s);
1621 inline void sunmarktest3(face& s);
1622 inline bool smarktest3ed(face& s);
1623 inline void setfacetindex(face& f, int value);
1624 inline int getfacetindex(face& f);
1625 inline bool isdeadsh(face& s);
1626
1627 // Primitives for interacting tetrahedra and subfaces.
1628 inline void tsbond(triface& t, face& s);
1629 inline void tsdissolve(triface& t);
1630 inline void stdissolve(face& s);
1631 inline void tspivot(triface& t, face& s);
1632 inline void stpivot(face& s, triface& t);
1633
1634 // Primitives for interacting tetrahedra and segments.
1635 inline void tssbond1(triface& t, face& seg);
1636 inline void sstbond1(face& s, triface& t);
1637 inline void tssdissolve1(triface& t);
1638 inline void sstdissolve1(face& s);
1639 inline void tsspivot1(triface& t, face& s);
1640 inline void sstpivot1(face& s, triface& t);
1641
1642 // Primitives for interacting subfaces and segments.
1643 inline void ssbond(face& s, face& edge);
1644 inline void ssbond1(face& s, face& edge);
1645 inline void ssdissolve(face& s);
1646 inline void sspivot(face& s, face& edge);
1647
1648 // Primitives for points.
1649 inline int pointmark(point pt);
1650 inline void setpointmark(point pt, int value);
1651 inline enum verttype pointtype(point pt);
1652 inline void setpointtype(point pt, enum verttype value);
1653 inline int pointgeomtag(point pt);
1654 inline void setpointgeomtag(point pt, int value);
1655 inline REAL pointgeomuv(point pt, int i);
1656 inline void setpointgeomuv(point pt, int i, REAL value);
1657 inline void pinfect(point pt);
1658 inline void puninfect(point pt);
1659 inline bool pinfected(point pt);
1660 inline void pmarktest(point pt);
1661 inline void punmarktest(point pt);
1662 inline bool pmarktested(point pt);
1663 inline void pmarktest2(point pt);
1664 inline void punmarktest2(point pt);
1665 inline bool pmarktest2ed(point pt);
1666 inline void pmarktest3(point pt);
1667 inline void punmarktest3(point pt);
1668 inline bool pmarktest3ed(point pt);
1669 inline tetrahedron point2tet(point pt);
1670 inline void setpoint2tet(point pt, tetrahedron value);
1671 inline shellface point2sh(point pt);
1672 inline void setpoint2sh(point pt, shellface value);
1673 inline point point2ppt(point pt);
1674 inline void setpoint2ppt(point pt, point value);
1675 inline tetrahedron point2bgmtet(point pt);
1676 inline void setpoint2bgmtet(point pt, tetrahedron value);
1677 inline void setpointinsradius(point pt, REAL value);
1678 inline REAL getpointinsradius(point pt);
1679 inline bool issteinerpoint(point pt);
1680
1681 // Advanced primitives.
1682 inline void point2tetorg(point pt, triface& t);
1683 inline void point2shorg(point pa, face& s);
1684 inline point farsorg(face& seg);
1685 inline point farsdest(face& seg);
1686
1687//============================================================================//
1688// //
1689// Memory managment //
1690// //
1691//============================================================================//
1692
1693 void tetrahedrondealloc(tetrahedron*);
1694 tetrahedron *tetrahedrontraverse();
1695 tetrahedron *alltetrahedrontraverse();
1696 void shellfacedealloc(memorypool*, shellface*);
1697 shellface *shellfacetraverse(memorypool*);
1698 void pointdealloc(point);
1699 point pointtraverse();
1700
1701 void makeindex2pointmap(point*&);
1702 void makepoint2submap(memorypool*, int*&, face*&);
1703 void maketetrahedron(triface*);
1704 void maketetrahedron2(triface*, point, point, point, point);
1705 void makeshellface(memorypool*, face*);
1706 void makepoint(point*, enum verttype);
1707
1708 void initializepools();
1709
1710//============================================================================//
1711// //
1712// Advanced geometric predicates and calculations //
1713// //
1714// the routine insphere_s() implements a simplified symbolic perturbation //
1715// scheme from Edelsbrunner, et al [*]. Hence the point-in-sphere test never //
1716// returns a zero. The idea is to perturb the weights of vertices in 4D. //
1717// //
1718// The routine tri_edge_test() determines whether or not a triangle and an //
1719// edge intersect in 3D. If they do cross, their intersection type is also //
1720// reported. This test is a combination of n 3D orientation tests (3 < n < 9).//
1721// It uses the robust orient3d() test to make the branch decisions. //
1722// //
1723// There are several routines to calculate geometrical quantities, e.g., //
1724// circumcenters, angles, dihedral angles, face normals, face areas, etc. //
1725// They are implemented using floating-point arithmetics. //
1726// //
1727//============================================================================//
1728
1729 // Symbolic perturbations (robust)
1730 REAL insphere_s(REAL*, REAL*, REAL*, REAL*, REAL*);
1731 REAL orient4d_s(REAL*, REAL*, REAL*, REAL*, REAL*,
1732 REAL, REAL, REAL, REAL, REAL);
1733
1734 // An embedded 2-dimensional geometric predicate (non-robust)
1735 REAL incircle3d(point pa, point pb, point pc, point pd);
1736
1737 // Triangle-edge intersection test (robust)
1738 int tri_edge_2d(point, point, point, point, point, point, int, int*, int*);
1739 int tri_edge_tail(point,point,point,point,point,point,REAL,REAL,int,int*,int*);
1740 int tri_edge_test(point, point, point, point, point, point, int, int*, int*);
1741
1742 // Triangle-triangle intersection test (robust)
1743 int tri_edge_inter_tail(point, point, point, point, point, REAL, REAL);
1744 int tri_tri_inter(point, point, point, point, point, point);
1745
1746 // Linear algebra functions
1747 inline REAL dot(REAL* v1, REAL* v2);
1748 inline void cross(REAL* v1, REAL* v2, REAL* n);
1749 bool lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N);
1750 void lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N);
1751
1752 // Geometric calculations (non-robust)
1753 REAL orient3dfast(REAL *pa, REAL *pb, REAL *pc, REAL *pd);
1754 inline REAL norm2(REAL x, REAL y, REAL z);
1755 inline REAL distance(REAL* p1, REAL* p2);
1756 inline REAL distance2(REAL* p1, REAL* p2);
1757 void facenormal(point pa, point pb, point pc, REAL *n, int pivot, REAL *lav);
1758 REAL facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2);
1759 REAL triarea(REAL* pa, REAL* pb, REAL* pc);
1760 REAL interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n);
1761 REAL cos_interiorangle(REAL* o, REAL* p1, REAL* p2);
1762 void projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj);
1763 void projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj);
1764 bool circumsphere(REAL*, REAL*, REAL*, REAL*, REAL* cent, REAL* radius);
1765 bool orthosphere(REAL*,REAL*,REAL*,REAL*,REAL,REAL,REAL,REAL,REAL*,REAL*);
1766 void planelineint(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*);
1767 int linelineint(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*);
1768 REAL tetprismvol(REAL* pa, REAL* pb, REAL* pc, REAL* pd);
1769 bool calculateabovepoint(arraypool*, point*, point*, point*);
1770 void calculateabovepoint4(point, point, point, point);
1771
1772//============================================================================//
1773// //
1774// Local mesh transformations //
1775// //
1776// A local transformation replaces a set of tetrahedra with another set that //
1777// partitions the same space and boundaries. //
1778// //
1779// In 3D, the most straightforward local transformations are the elementary //
1780// flips performed within the convex hull of five vertices: 2-to-3, 3-to-2, //
1781// 1-to-4, and 4-to-1 flips. The numbers indicate the number of tetrahedra //
1782// before and after each flip. The 1-to-4 and 4-to-1 flip involve inserting //
1783// or deleting a vertex, respectively. //
1784// //
1785// There are complex local transformations that are a combination of element- //
1786// ary flips. For example, a 4-to-4 flip, which replaces two coplanar edges, //
1787// combines a 2-to-3 flip and a 3-to-2 flip. Note that the first 2-to-3 flip //
1788// will temporarily create a degenerate tetrahedron removed immediately by //
1789// the followed 3-to-2 flip. More generally, an n-to-m flip, where n > 3, //
1790// m = (n - 2) * 2, which removes an edge, can be done by first performing a //
1791// sequence of (n - 3) 2-to-3 flips followed by a 3-to-2 flip. //
1792// //
1793// The routines flip23(), flip32(), and flip41() perform the three elementray //
1794// flips. The flip14() is available inside the routine insertpoint(). //
1795// //
1796// The routines flipnm() and flipnm_post() implement a generalized edge flip //
1797// algorithm that uses elementary flips. //
1798// //
1799// The routine insertpoint() implements the Bowyer-Watson's cavity algorithm //
1800// to insert a vertex. It works for arbitrary tetrahedralization, either //
1801// Delaunay, or constrained Delaunay, or non-Delaunay. //
1802// //
1803//============================================================================//
1804
1805 void flippush(badface*&, triface*);
1806
1807 // The elementary flips.
1808 void flip23(triface*, int, flipconstraints* fc);
1809 void flip32(triface*, int, flipconstraints* fc);
1810 void flip41(triface*, int, flipconstraints* fc);
1811
1812 // A generalized edge flip.
1813 int flipnm(triface*, int n, int level, int, flipconstraints* fc);
1814 int flipnm_post(triface*, int n, int nn, int, flipconstraints* fc);
1815
1816 // Point insertion.
1817 int insertpoint(point, triface*, face*, face*, insertvertexflags*);
1818 void insertpoint_abort(face*, insertvertexflags*);
1819
1820//============================================================================//
1821// //
1822// Delaunay tetrahedralization //
1823// //
1824// The routine incrementaldelaunay() implemented two incremental algorithms //
1825// for constructing Delaunay tetrahedralizations (DTs): the Bowyer-Watson //
1826// (B-W) algorithm and the incremental flip algorithm of Edelsbrunner and //
1827// Shah, "Incremental topological flipping works for regular triangulation," //
1828// Algorithmica, 15:233-241, 1996. //
1829// //
1830// The routine incrementalflip() implements the flip algorithm of [Edelsbrun- //
1831// ner and Shah, 1996]. It flips a queue of locally non-Delaunay faces (in //
1832// arbitrary order). The success is guaranteed when the Delaunay tetrahedra- //
1833// lization is constructed incrementally by adding one vertex at a time. //
1834// //
1835// The routine locate() finds a tetrahedron contains a new point in current //
1836// DT. It uses a simple stochastic walk algorithm: starting from an arbitrary //
1837// tetrahedron in DT, it finds the destination by visit one tetrahedron at a //
1838// time, randomly chooses a tetrahedron if there are more than one choices. //
1839// This algorithm terminates due to Edelsbrunner's acyclic theorem. //
1840// //
1841// Choose a good starting tetrahedron is crucial to the speed of the walk. //
1842// TetGen initially uses the "jump-and-walk" algorithm of Muecke, E.P., Saias,//
1843// I., and Zhu, B. "Fast Randomized Point Location Without Preprocessing." In //
1844// Proceedings of the 12th ACM Symposium on Computational Geometry, 274-283, //
1845// 1996. It first randomly samples several tetrahedra in the DT and then //
1846// choosing the closet one to start walking. //
1847// //
1848// The above algorithm slows download dramatically as the number of points //
1849// grows -- reported in Amenta, N., Choi, S. and Rote, G., "Incremental //
1850// construction con {BRIO}," In Proceedings of 19th ACM Symposium on Computa- //
1851// tional Geometry, 211-219, 2003. On the other hand, Liu and Snoeyink showed //
1852// that the point location could be made in constant time if the points are //
1853// pre-sorted so that the nearby points in space have nearby indices, then //
1854// adding the points in this order. They sorted the points along the 3D //
1855// Hilbert curve. //
1856// //
1857// The routine hilbert_sort3() sorts a set of 3D points along the 3D Hilbert //
1858// curve. It recursively splits a point set according to the Hilbert indices //
1859// mapped to the subboxes of the bounding box of the point set. The Hilbert //
1860// indices is calculated by Butz's algorithm in 1971. An excellent exposition //
1861// of this algorithm can be found in the paper of Hamilton, C., "Compact //
1862// Hilbert Indices", Technical Report CS-2006-07, Computer Science, Dalhousie //
1863// University, 2006 (the Section 2). My implementation also referenced Steven //
1864// Witham's performance of "Hilbert walk" (hopefully, it is still available //
1865// at http://www.tiac.net/~sw/2008/10/Hilbert/). //
1866// //
1867// TetGen sorts the points using the method in the paper of Boissonnat,J.-D., //
1868// Devillers, O. and Hornus, S. "Incremental Construction of the Delaunay //
1869// Triangulation and the Delaunay Graph in Medium Dimension," In Proceedings //
1870// of the 25th ACM Symposium on Computational Geometry, 2009. It first //
1871// randomly sorts the points into subgroups using the Biased Randomized //
1872// Insertion Ordering (BRIO) of Amenta et al 2003, then sorts the points in //
1873// each subgroup along the 3D Hilbert curve. Inserting points in this order //
1874// ensure a randomized "sprinkling" of the points over the domain, while //
1875// sorting of each subset provides locality. //
1876// //
1877//============================================================================//
1878
1879 void transfernodes();
1880
1881 // Point sorting.
1882 int transgc[8][3][8], tsb1mod3[8];
1883 void hilbert_init(int n);
1884 int hilbert_split(point* vertexarray, int arraysize, int gc0, int gc1,
1885 REAL, REAL, REAL, REAL, REAL, REAL);
1886 void hilbert_sort3(point* vertexarray, int arraysize, int e, int d,
1887 REAL, REAL, REAL, REAL, REAL, REAL, int depth);
1888 void brio_multiscale_sort(point*,int,int threshold,REAL ratio,int* depth);
1889
1890 // Point location.
1891 unsigned long randomnation(unsigned int choices);
1892 void randomsample(point searchpt, triface *searchtet);
1893 enum locateresult locate(point searchpt, triface *searchtet, int chkencflag = 0);
1894
1895 // Incremental Delaunay construction.
1896 enum locateresult locate_dt(point searchpt, triface *searchtet);
1897 int insert_vertex_bw(point, triface*, insertvertexflags*);
1898 void initialdelaunay(point pa, point pb, point pc, point pd);
1899 void incrementaldelaunay(clock_t&);
1900
1901//============================================================================//
1902// //
1903// Surface triangulation //
1904// //
1905//============================================================================//
1906
1907 void flipshpush(face*);
1908 void flip22(face*, int, int);
1909 void flip31(face*, int);
1910 long lawsonflip();
1911 int sinsertvertex(point newpt, face*, face*, int iloc, int bowywat, int);
1912 int sremovevertex(point delpt, face*, face*, int lawson);
1913
1914 enum locateresult slocate(point, face*, int, int, int);
1915 enum interresult sscoutsegment(face*, point, int, int, int);
1916 void scarveholes(int, REAL*);
1917 int triangulate(int, arraypool*, arraypool*, int, REAL*);
1918
1919 void unifysegments();
1920 void identifyinputedges(point*);
1921 void mergefacets();
1922 void meshsurface();
1923
1924
1925//============================================================================//
1926// //
1927// Constrained Delaunay tetrahedralization //
1928// //
1929// A constrained Delaunay tetrahedralization (CDT) is a variation of a Delau- //
1930// nay tetrahedralization (DT) that respects the boundary of a 3D PLC (mesh //
1931// domain). A crucial difference between a CDT and a DT is that triangles in //
1932// the PLC's polygons are not required to be locally Delaunay, which frees //
1933// the CDT to respect the PLC's polygons better. CDTs have optimal properties //
1934// similar to those of DTs. //
1935// //
1936// Steiner Points and Steiner CDTs. It is well-known that even a simple 3D //
1937// polyhedron may not have a tetrahedralization which only uses its vertices. //
1938// Some extra points, so-called "Steiner points" are needed to form a tetrah- //
1939// edralization of such polyhedron. A Steiner CDT of a 3D PLC is a CDT //
1940// containing Steiner points. TetGen generates Steiner CDTs. //
1941// //
1942// The routine constraineddelaunay() creates a (Steiner) CDT of the PLC //
1943// (including Steiner points). It has two steps, (1) segment recovery and (2) //
1944// facet (polygon) recovery. //
1945// //
1946// The routine delaunizesegments() implements the segment recovery algorithm //
1947// of Si, H., and Gaertner, K. "Meshing Piecewise Linear Complexes by //
1948// Constrained Delaunay Tetrahedralizations," In Proceedings of the 14th //
1949// International Meshing Roundtable, 147--163, 2005. It adds Steiner points //
1950// into non-Delaunay segments until all subsegments appear together in a DT. //
1951// The running time of this algorithm is proportional to the number of //
1952// Steiner points. //
1953// //
1954// There are two incremental facet recovery algorithms: the cavity re- //
1955// triangulation algorithm of Si, H., and Gaertner, K. "3D Boundary Recovery //
1956// by Constrained Delaunay Tetrahedralization," International Journal for //
1957// Numerical Methods in Engineering, 85:1341-1364, 2011, and the flip //
1958// algorithm of Shewchuk, J. "Updating and Constructing Constrained Delaunay //
1959// and Constrained Regular Triangulations by Flips." In Proceedings of the //
1960// 19th ACM Symposium on Computational Geometry, 86-95, 2003. //
1961// //
1962// Although no Steiner point is needed in step (2), a facet with non-coplanar //
1963// vertices might need Steiner points. It is discussed in the paper of Si, H.,//
1964// and Shewchuk, J., "Incrementally Constructing and Updating Constrained //
1965// Delaunay Tetrahedralizations with Finite Precision Coordinates." In //
1966// Proceedings of the 21th International Meshing Roundtable, 2012. //
1967// //
1968// Our implementation of the facet recovery algorithms recovers a "missing //
1969// region" at a time. Each missing region is a subset of connected interiors //
1970// of a polygon. The routine formcavity() creates the cavity of crossing //
1971// tetrahedra of the missing region. The cavity re-triangulation algorithm is //
1972// implemented by three subroutines, delaunizecavity(), fillcavity(), and //
1973// carvecavity(). Since it may fail due to non-coplanar vertices, the //
1974// subroutine restorecavity() is used to restore the original cavity. //
1975// //
1976// The routine flipinsertfacet() implements the flip algorithm. The sub- //
1977// routine flipcertify() is used to maintain the priority queue of flips. //
1978// The routine refineregion() is called when the facet recovery algorithm //
1979// fails to recover a missing region. It inserts Steiner points to refine the //
1980// missing region. To avoid inserting Steiner points very close to existing //
1981// segments. The classical encroachment rules of the Delaunay refinement //
1982// algorithm are used to choose the Steiner points. The routine //
1983// constrainedfacets() does the facet recovery by using either the cavity re- //
1984// triangulation algorithm (default) or the flip algorithm. It results in a //
1985// CDT of the (modified) PLC (including Steiner points). //
1986// //
1987//============================================================================//
1988
1989 enum interresult finddirection(triface* searchtet, point endpt);
1990 enum interresult scoutsegment(point, point, face*, triface*, point*,
1991 arraypool*);
1992 int getsteinerptonsegment(face* seg, point refpt, point steinpt);
1993 void delaunizesegments();
1994
1995 int scoutsubface(face* searchsh,triface* searchtet,int shflag);
1996 void formregion(face*, arraypool*, arraypool*, arraypool*);
1997 int scoutcrossedge(triface& crosstet, arraypool*, arraypool*);
1998 bool formcavity(triface*, arraypool*, arraypool*, arraypool*, arraypool*,
1999 arraypool*, arraypool*);
2000 // Facet recovery by cavity re-triangulation [Si and Gaertner 2011].
2001 void delaunizecavity(arraypool*, arraypool*, arraypool*, arraypool*,
2002 arraypool*, arraypool*);
2003 bool fillcavity(arraypool*, arraypool*, arraypool*, arraypool*,
2004 arraypool*, arraypool*, triface* crossedge);
2005 void carvecavity(arraypool*, arraypool*, arraypool*);
2006 void restorecavity(arraypool*, arraypool*, arraypool*, arraypool*);
2007 // Facet recovery by flips [Shewchuk 2003].
2008 void flipcertify(triface *chkface, badface **pqueue, point, point, point);
2009 void flipinsertfacet(arraypool*, arraypool*, arraypool*, arraypool*);
2010
2011 int insertpoint_cdt(point, triface*, face*, face*, insertvertexflags*,
2012 arraypool*, arraypool*, arraypool*, arraypool*,
2013 arraypool*, arraypool*);
2014 void refineregion(face&, arraypool*, arraypool*, arraypool*, arraypool*,
2015 arraypool*, arraypool*);
2016 void constrainedfacets();
2017
2018 void constraineddelaunay(clock_t&);
2019
2020//============================================================================//
2021// //
2022// Constrained tetrahedralizations. //
2023// //
2024//============================================================================//
2025
2026 void sort_2pts(point p1, point p2, point ppt[2]);
2027 void sort_3pts(point p1, point p2, point p3, point ppt[3]);
2028
2029 bool is_collinear_at(point mid, point left, point right);
2030 bool is_segment(point p1, point p2);
2031 bool valid_constrained_f23(triface&, point pd, point pe);
2032 bool valid_constrained_f32(triface*, point pa, point pb);
2033
2034 int checkflipeligibility(int fliptype, point, point, point, point, point,
2035 int level, int edgepivot, flipconstraints* fc);
2036
2037 int removeedgebyflips(triface*, flipconstraints*);
2038 int removefacebyflips(triface*, flipconstraints*);
2039
2040 int recoveredgebyflips(point, point, face*, triface*, int fullsearch, int& idir);
2041 int add_steinerpt_in_schoenhardtpoly(triface*, int, int, int chkencflag);
2042 int add_steinerpt_in_segment(face*, int searchlevel, int& idir);
2043 int add_steinerpt_to_recover_edge(point, point, face*, int, int, int& idir);
2044 int recoversegments(arraypool*, int fullsearch, int steinerflag);
2045
2046 int recoverfacebyflips(point,point,point,face*,triface*,int&,point*,point*);
2047 int recoversubfaces(arraypool*, int steinerflag);
2048
2049 int getvertexstar(int, point searchpt, arraypool*, arraypool*, arraypool*);
2050 int getedge(point, point, triface*);
2051 int reduceedgesatvertex(point startpt, arraypool* endptlist);
2052 int removevertexbyflips(point steinerpt);
2053
2054 int smoothpoint(point smtpt, arraypool*, int ccw, optparameters *opm);
2055 int suppressbdrysteinerpoint(point steinerpt);
2056 int suppresssteinerpoints();
2057
2058 void recoverboundary(clock_t&);
2059
2060//============================================================================//
2061// //
2062// Mesh reconstruction //
2063// //
2064//============================================================================//
2065
2066 void carveholes();
2067
2068 void reconstructmesh();
2069
2070 int search_face(point p0, point p1, point p2, triface &tetloop);
2071 int search_edge(point p0, point p1, triface &tetloop);
2072 int scout_point(point, triface*, int randflag);
2073 REAL getpointmeshsize(point, triface*, int iloc);
2074 void interpolatemeshsize();
2075
2076 void insertconstrainedpoints(point *insertarray, int arylen, int rejflag);
2077 void insertconstrainedpoints(tetgenio *addio);
2078
2079 void collectremovepoints(arraypool *remptlist);
2080 void meshcoarsening();
2081
2082//============================================================================//
2083// //
2084// Mesh refinement //
2085// //
2086// The purpose of mesh refinement is to obtain a tetrahedral mesh with well- //
2087// -shaped tetrahedra and appropriate mesh size. It is necessary to insert //
2088// new Steiner points to achieve this property. The questions are (1) how to //
2089// choose the Steiner points? and (2) how to insert them? //
2090// //
2091// Delaunay refinement is a technique first developed by Chew [1989] and //
2092// Ruppert [1993, 1995] to generate quality triangular meshes in the plane. //
2093// It provides guarantee on the smallest angle of the triangles. Rupper's //
2094// algorithm guarantees that the mesh is size-optimal (to within a constant //
2095// factor) among all meshes with the same quality. //
2096// Shewchuk generalized Ruppert's algorithm into 3D in his PhD thesis //
2097// [Shewchuk 1997]. A short version of his algorithm appears in "Tetrahedral //
2098// Mesh Generation by Delaunay Refinement," In Proceedings of the 14th ACM //
2099// Symposium on Computational Geometry, 86-95, 1998. It guarantees that all //
2100// tetrahedra of the output mesh have a "radius-edge ratio" (equivalent to //
2101// the minimal face angle) bounded. However, it does not remove slivers, a //
2102// type of very flat tetrahedra which can have no small face angles but have //
2103// very small (and large) dihedral angles. Moreover, it may not terminate if //
2104// the input PLC contains "sharp features", e.g., two edges (or two facets) //
2105// meet at an acute angle (or dihedral angle). //
2106// //
2107// TetGen uses the basic Delaunay refinement scheme to insert Steiner points. //
2108// While it always maintains a constrained Delaunay mesh. The algorithm is //
2109// described in Si, H., "Adaptive Constrained Delaunay Mesh Generation," //
2110// International Journal for Numerical Methods in Engineering, 75:856-880. //
2111// This algorithm always terminates and sharp features are easily preserved. //
2112// The mesh has good quality (same as Shewchuk's Delaunay refinement algori- //
2113// thm) in the bulk of the mesh domain. Moreover, it supports the generation //
2114// of adaptive mesh according to a (isotropic) mesh sizing function. //
2115// //
2116//============================================================================//
2117
2118 void makesegmentendpointsmap();
2119 REAL set_ridge_vertex_protecting_ball(point);
2120 REAL get_min_angle_at_ridge_vertex(face* seg);
2121 REAL get_min_diahedral_angle(face* seg);
2122 void create_segment_info_list();
2123
2124 void makefacetverticesmap();
2125 void create_segment_facet_map();
2126
2127 int ridge_vertices_adjacent(point, point);
2128 int facet_ridge_vertex_adjacent(face *, point);
2129 int segsegadjacent(face *, face *);
2130 int segfacetadjacent(face *checkseg, face *checksh);
2131 int facetfacetadjacent(face *, face *);
2132 bool is_sharp_segment(face* seg);
2133 bool does_seg_contain_acute_vertex(face* seg);
2134 bool create_a_shorter_edge(point steinerpt, point nearpt);
2135
2136 void enqueuesubface(memorypool*, face*);
2137 void enqueuetetrahedron(triface*);
2138
2139 bool check_encroachment(point pa, point pb, point checkpt);
2140 bool check_enc_segment(face *chkseg, point *pencpt);
2141 bool get_steiner_on_segment(face* seg, point encpt, point newpt);
2142 bool split_segment(face *splitseg, point encpt, REAL *param, int qflag, int, int*);
2143 void repairencsegs(REAL *param, int qflag, int chkencflag);
2144
2145 bool get_subface_ccent(face *chkfac, REAL *ccent);
2146 bool check_enc_subface(face *chkfac, point *pencpt, REAL *ccent, REAL *radius);
2147 bool check_subface(face *chkfac, REAL *ccent, REAL radius, REAL *param);
2148 void enqueue_subface(face *bface, point encpt, REAL *ccent, REAL *param);
2149 badface* top_subface();
2150 void dequeue_subface();
2151 void parallel_shift(point pa, point pb, point pc, point pt, REAL* ppt);
2152 enum locateresult locate_on_surface(point searchpt, face* searchsh);
2153 bool split_subface(face *splitfac, point encpt, REAL *ccent, REAL*, int, int, int*);
2154 void repairencfacs(REAL *param, int qflag, int chkencflag);
2155
2156 bool check_tetrahedron(triface *chktet, REAL* param, int& qflag);
2157 bool checktet4split(triface *chktet, REAL* param, int& qflag);
2158 enum locateresult locate_point_walk(point searchpt, triface*, int chkencflag);
2159 bool split_tetrahedron(triface*, REAL*, int, int, insertvertexflags &ivf);
2160 void repairbadtets(REAL queratio, int chkencflag);
2161
2162 void delaunayrefinement();
2163
2164//============================================================================//
2165// //
2166// Mesh optimization //
2167// //
2168//============================================================================//
2169
2170 long lawsonflip3d(flipconstraints *fc);
2171 void recoverdelaunay();
2172
2173 int get_seg_laplacian_center(point mesh_vert, REAL target[3]);
2174 int get_surf_laplacian_center(point mesh_vert, REAL target[3]);
2175 int get_laplacian_center(point mesh_vert, REAL target[3]);
2176 bool move_vertex(point mesh_vert, REAL target[3]);
2177 void smooth_vertices();
2178
2179 bool get_tet(point, point, point, point, triface *);
2180 bool get_tetqual(triface *chktet, point oppo_pt, badface *bf);
2181 bool get_tetqual(point, point, point, point, badface *bf);
2182 void enqueue_badtet(badface *bf);
2183 badface* top_badtet();
2184 void dequeue_badtet();
2185
2186 bool add_steinerpt_to_repair(badface *bf, bool bSmooth);
2187 bool flip_edge_to_improve(triface *sliver_edge, REAL& improved_cosmaxd);
2188 bool repair_tet(badface *bf, bool bFlips, bool bSmooth, bool bSteiners);
2189 long repair_badqual_tets(bool bFlips, bool bSmooth, bool bSteiners);
2190 void improve_mesh();
2191
2192//============================================================================//
2193// //
2194// Mesh check and statistics //
2195// //
2196//============================================================================//
2197
2198 // Mesh validations.
2199 int check_mesh(int topoflag);
2200 int check_shells();
2201 int check_segments();
2202 int check_delaunay(int perturb = 1);
2203 int check_regular(int);
2204 int check_conforming(int);
2205
2206 // Mesh statistics.
2207 void printfcomma(unsigned long n);
2208 void qualitystatistics();
2209 void memorystatistics();
2210 void statistics();
2211
2212//============================================================================//
2213// //
2214// Mesh output //
2215// //
2216//============================================================================//
2217
2218 void jettisonnodes();
2219 void highorder();
2220 void indexelements();
2221 void numberedges();
2222 void outnodes(tetgenio*);
2223 void outmetrics(tetgenio*);
2224 void outelements(tetgenio*);
2225 void outfaces(tetgenio*);
2226 void outhullfaces(tetgenio*);
2227 void outsubfaces(tetgenio*);
2228 void outedges(tetgenio*);
2229 void outsubsegments(tetgenio*);
2230 void outneighbors(tetgenio*);
2231 void outvoronoi(tetgenio*);
2232 void outsmesh(char*);
2233 void outmesh2medit(char*);
2234 void outmesh2vtk(char*, int);
2235 void out_surfmesh_vtk(char*, int);
2236 void out_intersected_facets();
2237
2238
2239
2240
2241//============================================================================//
2242// //
2243// Constructor & destructor //
2244// //
2245//============================================================================//
2246
2247 void initializetetgenmesh()
2248 {
2249 in = addin = NULL;
2250 b = NULL;
2251 bgm = NULL;
2252
2253 tetrahedrons = subfaces = subsegs = points = NULL;
2254 tet2segpool = tet2subpool = NULL;
2255 dummypoint = NULL;
2256
2257 badtetrahedrons = badsubfacs = badsubsegs = NULL;
2258 split_segments_pool = split_subfaces_pool = NULL;
2259 unsplit_badtets = unsplit_subfaces = unsplit_segments = NULL;
2260 check_tets_list = NULL;
2261 badqual_tets_pool = NULL;
2262
2263 stack_enc_segments = stack_enc_subfaces = NULL;
2264
2265 flippool = NULL;
2266 flipstack = unflip_queue_front = unflip_queue_tail = NULL;
2267 later_unflip_queue = unflipqueue = NULL;
2268
2269 cavetetlist = cavebdrylist = caveoldtetlist = NULL;
2270 cave_oldtet_list = NULL;
2271 cavetetshlist = cavetetseglist = cavetetvertlist = NULL;
2272 caveencshlist = caveencseglist = NULL;
2273 caveshlist = caveshbdlist = cavesegshlist = NULL;
2274
2275 subsegstack = subfacstack = subvertstack = NULL;
2276 skipped_segment_list = skipped_facet_list = NULL;
2277
2278 encseglist = encshlist = NULL;
2279
2280 number_of_facets = 0;
2281 idx2facetlist = NULL;
2282 facetverticeslist = NULL;
2283 idx_segment_facet_list = NULL;
2284 segment_facet_list = NULL;
2285 idx_ridge_vertex_facet_list = NULL;
2286 ridge_vertex_facet_list = NULL;
2287
2288 segmentendpointslist_length = 0;
2289 segmentendpointslist = NULL;
2290 segment_info_list = NULL;
2291 idx_segment_ridge_vertex_list = NULL;
2292 segment_ridge_vertex_list = NULL;
2293
2294 subdomains = 0;
2295 subdomain_markers = NULL;
2296
2297 numpointattrib = numelemattrib = 0;
2298 sizeoftensor = 0;
2299 pointmtrindex = 0;
2300 pointparamindex = 0;
2301 pointmarkindex = 0;
2302 point2simindex = 0;
2303 pointinsradiusindex = 0;
2304 elemattribindex = 0;
2305 polarindex = 0;
2306 volumeboundindex = 0;
2307 shmarkindex = 0;
2308 areaboundindex = 0;
2309 checksubsegflag = 0;
2310 checksubfaceflag = 0;
2311 boundary_recovery_flag = 0;
2312 checkconstraints = 0;
2313 nonconvex = 0;
2314 autofliplinklevel = 1;
2315 useinsertradius = 0;
2316 samples = 0l;
2317 randomseed = 1l;
2318 minfaceang = minfacetdihed = PI;
2319 cos_facet_separate_ang_tol = cos(179.9/180.*PI);
2320 cos_collinear_ang_tol = cos(179.9/180.*PI);
2321 tetprism_vol_sum = 0.0;
2322 longest = minedgelength = 0.0;
2323 xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
2324
2325 smallest_insradius = 1.e+30;
2326 big_radius_edge_ratio = 100.0;
2327 elem_limit = 0;
2328 insert_point_count = 0l;
2329 report_refine_progress = 0l;
2330 last_point_count = 0l;
2331 last_insertion_count = 0l;
2332
2333 insegments = 0l;
2334 hullsize = 0l;
2335 meshedges = meshhulledges = 0l;
2336 steinerleft = -1;
2337 dupverts = 0l;
2338 unuverts = 0l;
2339 duplicated_facets_count = 0l;
2340 nonregularcount = 0l;
2341 st_segref_count = st_facref_count = st_volref_count = 0l;
2342 fillregioncount = cavitycount = cavityexpcount = 0l;
2343 flip14count = flip26count = flipn2ncount = 0l;
2344 flip23count = flip32count = flip44count = flip41count = 0l;
2345 flip22count = flip31count = 0l;
2346 recover_delaunay_count = 0l;
2347 opt_flips_count = opt_collapse_count = opt_smooth_count = 0l;
2348 totalworkmemory = 0l;
2349
2350 } // tetgenmesh()
2351
2352 void freememory()
2353 {
2354 if (bgm != NULL) {
2355 delete bgm;
2356 }
2357
2358 if (points != (memorypool *) NULL) {
2359 delete points;
2360 delete [] dummypoint;
2361 }
2362 if (tetrahedrons != (memorypool *) NULL) {
2363 delete tetrahedrons;
2364 }
2365 if (subfaces != (memorypool *) NULL) {
2366 delete subfaces;
2367 delete subsegs;
2368 }
2369 if (tet2segpool != NULL) {
2370 delete tet2segpool;
2371 delete tet2subpool;
2372 }
2373
2374 if (badtetrahedrons) {
2375 delete badtetrahedrons;
2376 }
2377 if (badsubfacs) {
2378 delete badsubfacs;
2379 }
2380 if (badsubsegs) {
2381 delete badsubsegs;
2382 }
2383 if (unsplit_badtets) {
2384 delete unsplit_badtets;
2385 }
2386 if (check_tets_list) {
2387 delete check_tets_list;
2388 }
2389
2390 if (flippool != NULL) {
2391 delete flippool;
2392 delete later_unflip_queue;
2393 delete unflipqueue;
2394 }
2395
2396 if (cavetetlist != NULL) {
2397 delete cavetetlist;
2398 delete cavebdrylist;
2399 delete caveoldtetlist;
2400 delete cavetetvertlist;
2401 delete cave_oldtet_list;
2402 }
2403
2404 if (caveshlist != NULL) {
2405 delete caveshlist;
2406 delete caveshbdlist;
2407 delete cavesegshlist;
2408 delete cavetetshlist;
2409 delete cavetetseglist;
2410 delete caveencshlist;
2411 delete caveencseglist;
2412 }
2413
2414 if (subsegstack != NULL) {
2415 delete subsegstack;
2416 delete subfacstack;
2417 delete subvertstack;
2418 }
2419
2420 if (idx2facetlist != NULL) {
2421 delete [] idx2facetlist;
2422 delete [] facetverticeslist;
2423 delete [] idx_segment_facet_list;
2424 delete [] segment_facet_list;
2425 delete [] idx_ridge_vertex_facet_list;
2426 delete [] ridge_vertex_facet_list;
2427 }
2428
2429 if (segmentendpointslist != NULL) {
2430 delete [] segmentendpointslist;
2431 delete [] idx_segment_ridge_vertex_list;
2432 delete [] segment_ridge_vertex_list;
2433 }
2434
2435 if (segment_info_list != NULL) {
2436 delete [] segment_info_list;
2437 }
2438
2439 if (subdomain_markers != NULL) {
2440 delete [] subdomain_markers;
2441 }
2442
2443 initializetetgenmesh();
2444 }
2445
2446 tetgenmesh()
2447 {
2448 initializetetgenmesh();
2449 }
2450
2451 ~tetgenmesh()
2452 {
2453 freememory();
2454 } // ~tetgenmesh()
2455
2456}; // End of class tetgenmesh.
2457
2458//============================================================================//
2459// //
2460// tetrahedralize() Interface for using TetGen's library to generate //
2461// Delaunay tetrahedralizations, constrained Delaunay //
2462// tetrahedralizations, quality tetrahedral meshes. //
2463// //
2464// 'in' is an object of 'tetgenio' containing a PLC or a previously generated //
2465// tetrahedral mesh you want to refine. 'out' is another object of 'tetgenio'//
2466// for returing the generated tetrahedral mesh. If it is a NULL pointer, the //
2467// output mesh is saved to file(s). If 'bgmin' != NULL, it contains a back- //
2468// ground mesh defining a mesh size function. //
2469// //
2470//============================================================================//
2471
2472void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
2473 tetgenio *addin = NULL, tetgenio *bgmin = NULL);
2474
2475#ifdef TETLIBRARY
2476void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
2477 tetgenio *addin = NULL, tetgenio *bgmin = NULL);
2478
2479#endif // #ifdef TETLIBRARY
2480
2481//============================================================================//
2482// //
2483// terminatetetgen() Terminate TetGen with a given exit code. //
2484// //
2485//============================================================================//
2486
2487
2488inline void terminatetetgen(tetgenmesh *m, int x)
2489{
2490#ifdef TETLIBRARY
2491 throw x;
2492#else
2493 switch (x) {
2494 case 1: // Out of memory.
2495 printf("Error: Out of memory.\n");
2496 break;
2497 case 2: // Encounter an internal error.
2498 printf("Please report this bug to Hang.Si@wias-berlin.de. Include\n");
2499 printf(" the message above, your input data set, and the exact\n");
2500 printf(" command line you used to run this program, thank you.\n");
2501 break;
2502 case 3:
2503 printf("The input surface mesh contain self-intersections. Program stopped.\n");
2504 //printf("Hint: use -d option to detect all self-intersections.\n");
2505 break;
2506 case 4:
2507 printf("A very small input feature size was detected. Program stopped.\n");
2508 if (m) {
2509 printf("Hint: use -T option to set a smaller tolerance. Current is %g\n",
2510 m->b->epsilon);
2511 }
2512 break;
2513 case 5:
2514 printf("Two very close input facets were detected. Program stopped.\n");
2515 printf("Hint: use -Y option to avoid adding Steiner points in boundary.\n");
2516 break;
2517 case 10:
2518 printf("An input error was detected. Program stopped.\n");
2519 break;
2520 case 200:
2521 printf("Boundary contains Steiner points (-YY option). Program stopped.\n");
2522 break;
2523 } // switch (x)
2524 exit(x);
2525#endif // #ifdef TETLIBRARY
2526}
2527
2528//============================================================================//
2529// //
2530// Primitives for tetrahedra //
2531// //
2532//============================================================================//
2533
2534// encode() compress a handle into a single pointer. It relies on the
2535// assumption that all addresses of tetrahedra are aligned to sixteen-
2536// byte boundaries, so that the last four significant bits are zero.
2537
2538inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
2539 return (tetrahedron) ((uintptr_t) (t).tet | (uintptr_t) (t).ver);
2540}
2541
2542inline tetgenmesh::tetrahedron tetgenmesh::encode2(tetrahedron* ptr, int ver) {
2543 return (tetrahedron) ((uintptr_t) (ptr) | (uintptr_t) (ver));
2544}
2545
2546// decode() converts a pointer to a handle. The version is extracted from
2547// the four least significant bits of the pointer.
2548
2549inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
2550 (t).ver = (int) ((uintptr_t) (ptr) & (uintptr_t) 15);
2551 (t).tet = (tetrahedron *) ((uintptr_t) (ptr) ^ (uintptr_t) (t).ver);
2552}
2553
2554inline tetgenmesh::tetrahedron* tetgenmesh::decode_tet_only(tetrahedron ptr)
2555{
2556 return (tetrahedron *) ((((uintptr_t) ptr) >> 4) << 4);
2557}
2558
2559inline int tetgenmesh::decode_ver_only(tetrahedron ptr)
2560{
2561 return (int) ((uintptr_t) (ptr) & (uintptr_t) 15);
2562}
2563
2564// bond() connects two tetrahedra together. (t1,v1) and (t2,v2) must
2565// refer to the same face and the same edge.
2566
2567inline void tetgenmesh::bond(triface& t1, triface& t2) {
2568 t1.tet[t1.ver & 3] = encode2(t2.tet, bondtbl[t1.ver][t2.ver]);
2569 t2.tet[t2.ver & 3] = encode2(t1.tet, bondtbl[t2.ver][t1.ver]);
2570}
2571
2572
2573// dissolve() a bond (from one side).
2574
2575inline void tetgenmesh::dissolve(triface& t) {
2576 t.tet[t.ver & 3] = NULL;
2577}
2578
2579// enext() finds the next edge (counterclockwise) in the same face.
2580
2581inline void tetgenmesh::enext(triface& t1, triface& t2) {
2582 t2.tet = t1.tet;
2583 t2.ver = enexttbl[t1.ver]; // (t1.ver + 4) % 12;
2584}
2585
2586inline void tetgenmesh::enextself(triface& t) {
2587 t.ver = enexttbl[t.ver]; // (t.ver + 4) % 12;
2588}
2589
2590// eprev() finds the next edge (clockwise) in the same face.
2591
2592inline void tetgenmesh::eprev(triface& t1, triface& t2) {
2593 t2.tet = t1.tet;
2594 t2.ver = eprevtbl[t1.ver]; // (t1.ver + 8) % 12;
2595}
2596
2597inline void tetgenmesh::eprevself(triface& t) {
2598 t.ver = eprevtbl[t.ver]; // (t.ver + 8) % 12;
2599}
2600
2601// esym() finds the reversed edge. It is in the other face of the
2602// same tetrahedron.
2603
2604inline void tetgenmesh::esym(triface& t1, triface& t2) {
2605 (t2).tet = (t1).tet;
2606 (t2).ver = esymtbl[(t1).ver];
2607}
2608
2609inline void tetgenmesh::esymself(triface& t) {
2610 (t).ver = esymtbl[(t).ver];
2611}
2612
2613// enextesym() finds the reversed edge of the next edge. It is in the other
2614// face of the same tetrahedron. It is the combination esym() * enext().
2615
2616inline void tetgenmesh::enextesym(triface& t1, triface& t2) {
2617 t2.tet = t1.tet;
2618 t2.ver = enextesymtbl[t1.ver];
2619}
2620
2621inline void tetgenmesh::enextesymself(triface& t) {
2622 t.ver = enextesymtbl[t.ver];
2623}
2624
2625// eprevesym() finds the reversed edge of the previous edge.
2626
2627inline void tetgenmesh::eprevesym(triface& t1, triface& t2) {
2628 t2.tet = t1.tet;
2629 t2.ver = eprevesymtbl[t1.ver];
2630}
2631
2632inline void tetgenmesh::eprevesymself(triface& t) {
2633 t.ver = eprevesymtbl[t.ver];
2634}
2635
2636// eorgoppo() Finds the opposite face of the origin of the current edge.
2637// Return the opposite edge of the current edge.
2638
2639inline void tetgenmesh::eorgoppo(triface& t1, triface& t2) {
2640 t2.tet = t1.tet;
2641 t2.ver = eorgoppotbl[t1.ver];
2642}
2643
2644inline void tetgenmesh::eorgoppoself(triface& t) {
2645 t.ver = eorgoppotbl[t.ver];
2646}
2647
2648// edestoppo() Finds the opposite face of the destination of the current
2649// edge. Return the opposite edge of the current edge.
2650
2651inline void tetgenmesh::edestoppo(triface& t1, triface& t2) {
2652 t2.tet = t1.tet;
2653 t2.ver = edestoppotbl[t1.ver];
2654}
2655
2656inline void tetgenmesh::edestoppoself(triface& t) {
2657 t.ver = edestoppotbl[t.ver];
2658}
2659
2660// fsym() finds the adjacent tetrahedron at the same face and the same edge.
2661
2662inline void tetgenmesh::fsym(triface& t1, triface& t2) {
2663 decode((t1).tet[(t1).ver & 3], t2);
2664 t2.ver = fsymtbl[t1.ver][t2.ver];
2665}
2666
2667
2668#define fsymself(t) \
2669 t1ver = (t).ver; \
2670 decode((t).tet[(t).ver & 3], (t));\
2671 (t).ver = fsymtbl[t1ver][(t).ver]
2672
2673// fnext() finds the next face while rotating about an edge according to
2674// a right-hand rule. The face is in the adjacent tetrahedron. It is
2675// the combination: fsym() * esym().
2676
2677inline void tetgenmesh::fnext(triface& t1, triface& t2) {
2678 decode(t1.tet[facepivot1[t1.ver]], t2);
2679 t2.ver = facepivot2[t1.ver][t2.ver];
2680}
2681
2682
2683#define fnextself(t) \
2684 t1ver = (t).ver; \
2685 decode((t).tet[facepivot1[(t).ver]], (t)); \
2686 (t).ver = facepivot2[t1ver][(t).ver]
2687
2688
2689// The following primtives get or set the origin, destination, face apex,
2690// or face opposite of an ordered tetrahedron.
2691
2692inline tetgenmesh::point tetgenmesh::org(triface& t) {
2693 return (point) (t).tet[orgpivot[(t).ver]];
2694}
2695
2696inline tetgenmesh::point tetgenmesh:: dest(triface& t) {
2697 return (point) (t).tet[destpivot[(t).ver]];
2698}
2699
2700inline tetgenmesh::point tetgenmesh:: apex(triface& t) {
2701 return (point) (t).tet[apexpivot[(t).ver]];
2702}
2703
2704inline tetgenmesh::point tetgenmesh:: oppo(triface& t) {
2705 return (point) (t).tet[oppopivot[(t).ver]];
2706}
2707
2708inline void tetgenmesh:: setorg(triface& t, point p) {
2709 (t).tet[orgpivot[(t).ver]] = (tetrahedron) (p);
2710}
2711
2712inline void tetgenmesh:: setdest(triface& t, point p) {
2713 (t).tet[destpivot[(t).ver]] = (tetrahedron) (p);
2714}
2715
2716inline void tetgenmesh:: setapex(triface& t, point p) {
2717 (t).tet[apexpivot[(t).ver]] = (tetrahedron) (p);
2718}
2719
2720inline void tetgenmesh:: setoppo(triface& t, point p) {
2721 (t).tet[oppopivot[(t).ver]] = (tetrahedron) (p);
2722}
2723
2724#define setvertices(t, torg, tdest, tapex, toppo) \
2725 (t).tet[orgpivot[(t).ver]] = (tetrahedron) (torg);\
2726 (t).tet[destpivot[(t).ver]] = (tetrahedron) (tdest); \
2727 (t).tet[apexpivot[(t).ver]] = (tetrahedron) (tapex); \
2728 (t).tet[oppopivot[(t).ver]] = (tetrahedron) (toppo)
2729
2730
2731inline REAL* tetgenmesh::get_polar(tetrahedron* ptr)
2732{
2733 return &(((REAL *) (ptr))[polarindex]);
2734}
2735inline REAL tetgenmesh::get_volume(tetrahedron* ptr)
2736{
2737 return ((REAL *) (ptr))[polarindex + 4];
2738}
2739
2740// Check or set a tetrahedron's attributes.
2741
2742inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
2743 return ((REAL *) (ptr))[elemattribindex + attnum];
2744}
2745
2746inline void tetgenmesh::setelemattribute(tetrahedron* ptr, int attnum,
2747 REAL value) {
2748 ((REAL *) (ptr))[elemattribindex + attnum] = value;
2749}
2750
2751// Check or set a tetrahedron's maximum volume bound.
2752
2753inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
2754 return ((REAL *) (ptr))[volumeboundindex];
2755}
2756
2757inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
2758 ((REAL *) (ptr))[volumeboundindex] = value;
2759}
2760
2761// Get or set a tetrahedron's index (only used for output).
2762// These two routines use the reserved slot ptr[10].
2763
2764inline int tetgenmesh::elemindex(tetrahedron* ptr) {
2765 int *iptr = (int *) &(ptr[10]);
2766 return iptr[0];
2767}
2768
2769inline void tetgenmesh::setelemindex(tetrahedron* ptr, int value) {
2770 int *iptr = (int *) &(ptr[10]);
2771 iptr[0] = value;
2772}
2773
2774// Get or set a tetrahedron's marker.
2775// Set 'value = 0' cleans all the face/edge flags.
2776
2777inline int tetgenmesh::elemmarker(tetrahedron* ptr) {
2778 return ((int *) (ptr))[elemmarkerindex];
2779}
2780
2781inline void tetgenmesh::setelemmarker(tetrahedron* ptr, int value) {
2782 ((int *) (ptr))[elemmarkerindex] = value;
2783}
2784
2785// infect(), infected(), uninfect() -- primitives to flag or unflag a
2786// tetrahedron. The last bit of the element marker is flagged (1)
2787// or unflagged (0).
2788
2789inline void tetgenmesh::infect(triface& t) {
2790 ((int *) (t.tet))[elemmarkerindex] |= 1;
2791}
2792
2793inline void tetgenmesh::uninfect(triface& t) {
2794 ((int *) (t.tet))[elemmarkerindex] &= ~1;
2795}
2796
2797inline bool tetgenmesh::infected(triface& t) {
2798 return (((int *) (t.tet))[elemmarkerindex] & 1) != 0;
2799}
2800
2801// marktest(), marktested(), unmarktest() -- primitives to flag or unflag a
2802// tetrahedron. Use the second lowerest bit of the element marker.
2803
2804inline void tetgenmesh::marktest(triface& t) {
2805 ((int *) (t.tet))[elemmarkerindex] |= 2;
2806}
2807
2808inline void tetgenmesh::unmarktest(triface& t) {
2809 ((int *) (t.tet))[elemmarkerindex] &= ~2;
2810}
2811
2812inline bool tetgenmesh::marktested(triface& t) {
2813 return (((int *) (t.tet))[elemmarkerindex] & 2) != 0;
2814}
2815
2816// markface(), unmarkface(), facemarked() -- primitives to flag or unflag a
2817// face of a tetrahedron. From the last 3rd to 6th bits are used for
2818// face markers, e.g., the last third bit corresponds to loc = 0.
2819
2820inline void tetgenmesh::markface(triface& t) {
2821 ((int *) (t.tet))[elemmarkerindex] |= (4 << (t.ver & 3));
2822}
2823
2824inline void tetgenmesh::unmarkface(triface& t) {
2825 ((int *) (t.tet))[elemmarkerindex] &= ~(4 << (t.ver & 3));
2826}
2827
2828inline bool tetgenmesh::facemarked(triface& t) {
2829 return (((int *) (t.tet))[elemmarkerindex] & (4 << (t.ver & 3))) != 0;
2830}
2831
2832// markedge(), unmarkedge(), edgemarked() -- primitives to flag or unflag an
2833// edge of a tetrahedron. From the last 7th to 12th bits are used for
2834// edge markers, e.g., the last 7th bit corresponds to the 0th edge, etc.
2835// Remark: The last 7th bit is marked by 2^6 = 64.
2836
2837inline void tetgenmesh::markedge(triface& t) {
2838 ((int *) (t.tet))[elemmarkerindex] |= (int) (64 << ver2edge[(t).ver]);
2839}
2840
2841inline void tetgenmesh::unmarkedge(triface& t) {
2842 ((int *) (t.tet))[elemmarkerindex] &= ~(int) (64 << ver2edge[(t).ver]);
2843}
2844
2845inline bool tetgenmesh::edgemarked(triface& t) {
2846 return (((int *) (t.tet))[elemmarkerindex] &
2847 (int) (64 << ver2edge[(t).ver])) != 0;
2848}
2849
2850// marktest2(), unmarktest2(), marktest2ed() -- primitives to flag and unflag
2851// a tetrahedron. The 13th bit (2^12 = 4096) is used for this flag.
2852
2853inline void tetgenmesh::marktest2(triface& t) {
2854 ((int *) (t.tet))[elemmarkerindex] |= (int) (4096);
2855}
2856
2857inline void tetgenmesh::unmarktest2(triface& t) {
2858 ((int *) (t.tet))[elemmarkerindex] &= ~(int) (4096);
2859}
2860
2861inline bool tetgenmesh::marktest2ed(triface& t) {
2862 return (((int *) (t.tet))[elemmarkerindex] & (int) (4096)) != 0;
2863}
2864
2865// elemcounter(), setelemcounter() -- primitives to read or ser a (small)
2866// integer counter in this tet. It is saved from the 16th bit. On 32 bit
2867// system, the range of the counter is [0, 2^15 = 32768].
2868
2869inline int tetgenmesh::elemcounter(triface& t) {
2870 return (((int *) (t.tet))[elemmarkerindex]) >> 16;
2871}
2872
2873inline void tetgenmesh::setelemcounter(triface& t, int value) {
2874 int c = ((int *) (t.tet))[elemmarkerindex];
2875 // Clear the old counter while keep the other flags.
2876 c &= 65535; // sum_{i=0^15} 2^i
2877 c |= (value << 16);
2878 ((int *) (t.tet))[elemmarkerindex] = c;
2879}
2880
2881inline void tetgenmesh::increaseelemcounter(triface& t) {
2882 int c = elemcounter(t);
2883 setelemcounter(t, c + 1);
2884}
2885
2886inline void tetgenmesh::decreaseelemcounter(triface& t) {
2887 int c = elemcounter(t);
2888 setelemcounter(t, c - 1);
2889}
2890
2891// ishulltet() tests if t is a hull tetrahedron.
2892
2893inline bool tetgenmesh::ishulltet(triface& t) {
2894 return (point) (t).tet[7] == dummypoint;
2895}
2896
2897// isdeadtet() tests if t is a tetrahedron is dead.
2898
2899inline bool tetgenmesh::isdeadtet(triface& t) {
2900 return ((t.tet == NULL) || (t.tet[4] == NULL));
2901}
2902
2903//============================================================================//
2904// //
2905// Primitives for subfaces and subsegments //
2906// //
2907//============================================================================//
2908
2909// Each subface contains three pointers to its neighboring subfaces, with
2910// edge versions. To save memory, both information are kept in a single
2911// pointer. To make this possible, all subfaces are aligned to eight-byte
2912// boundaries, so that the last three bits of each pointer are zeros. An
2913// edge version (in the range 0 to 5) is compressed into the last three
2914// bits of each pointer by 'sencode()'. 'sdecode()' decodes a pointer,
2915// extracting an edge version and a pointer to the beginning of a subface.
2916
2917inline void tetgenmesh::sdecode(shellface sptr, face& s) {
2918 s.shver = (int) ((uintptr_t) (sptr) & (uintptr_t) 7);
2919 s.sh = (shellface *) ((uintptr_t) (sptr) ^ (uintptr_t) (s.shver));
2920}
2921
2922inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
2923 return (shellface) ((uintptr_t) s.sh | (uintptr_t) s.shver);
2924}
2925
2926inline tetgenmesh::shellface tetgenmesh::sencode2(shellface *sh, int shver) {
2927 return (shellface) ((uintptr_t) sh | (uintptr_t) shver);
2928}
2929
2930// sbond() bonds two subfaces (s1) and (s2) together. s1 and s2 must refer
2931// to the same edge. No requirement is needed on their orientations.
2932
2933inline void tetgenmesh::sbond(face& s1, face& s2)
2934{
2935 s1.sh[s1.shver >> 1] = sencode(s2);
2936 s2.sh[s2.shver >> 1] = sencode(s1);
2937}
2938
2939// sbond1() bonds s1 <== s2, i.e., after bonding, s1 is pointing to s2,
2940// but s2 is not pointing to s1. s1 and s2 must refer to the same edge.
2941// No requirement is needed on their orientations.
2942
2943inline void tetgenmesh::sbond1(face& s1, face& s2)
2944{
2945 s1.sh[s1.shver >> 1] = sencode(s2);
2946}
2947
2948// Dissolve a subface bond (from one side). Note that the other subface
2949// will still think it's connected to this subface.
2950
2951inline void tetgenmesh::sdissolve(face& s)
2952{
2953 s.sh[s.shver >> 1] = NULL;
2954}
2955
2956// spivot() finds the adjacent subface (s2) for a given subface (s1).
2957// s1 and s2 share at the same edge.
2958
2959inline void tetgenmesh::spivot(face& s1, face& s2)
2960{
2961 shellface sptr = s1.sh[s1.shver >> 1];
2962 sdecode(sptr, s2);
2963}
2964
2965inline void tetgenmesh::spivotself(face& s)
2966{
2967 shellface sptr = s.sh[s.shver >> 1];
2968 sdecode(sptr, s);
2969}
2970
2971// These primitives determine or set the origin, destination, or apex
2972// of a subface with respect to the edge version.
2973
2974inline tetgenmesh::point tetgenmesh::sorg(face& s)
2975{
2976 return (point) s.sh[sorgpivot[s.shver]];
2977}
2978
2979inline tetgenmesh::point tetgenmesh::sdest(face& s)
2980{
2981 return (point) s.sh[sdestpivot[s.shver]];
2982}
2983
2984inline tetgenmesh::point tetgenmesh::sapex(face& s)
2985{
2986 return (point) s.sh[sapexpivot[s.shver]];
2987}
2988
2989inline void tetgenmesh::setsorg(face& s, point pointptr)
2990{
2991 s.sh[sorgpivot[s.shver]] = (shellface) pointptr;
2992}
2993
2994inline void tetgenmesh::setsdest(face& s, point pointptr)
2995{
2996 s.sh[sdestpivot[s.shver]] = (shellface) pointptr;
2997}
2998
2999inline void tetgenmesh::setsapex(face& s, point pointptr)
3000{
3001 s.sh[sapexpivot[s.shver]] = (shellface) pointptr;
3002}
3003
3004#define setshvertices(s, pa, pb, pc)\
3005 setsorg(s, pa);\
3006 setsdest(s, pb);\
3007 setsapex(s, pc)
3008
3009// sesym() reserves the direction of the lead edge.
3010
3011inline void tetgenmesh::sesym(face& s1, face& s2)
3012{
3013 s2.sh = s1.sh;
3014 s2.shver = (s1.shver ^ 1); // Inverse the last bit.
3015}
3016
3017inline void tetgenmesh::sesymself(face& s)
3018{
3019 s.shver ^= 1;
3020}
3021
3022// senext() finds the next edge (counterclockwise) in the same orientation
3023// of this face.
3024
3025inline void tetgenmesh::senext(face& s1, face& s2)
3026{
3027 s2.sh = s1.sh;
3028 s2.shver = snextpivot[s1.shver];
3029}
3030
3031inline void tetgenmesh::senextself(face& s)
3032{
3033 s.shver = snextpivot[s.shver];
3034}
3035
3036inline void tetgenmesh::senext2(face& s1, face& s2)
3037{
3038 s2.sh = s1.sh;
3039 s2.shver = snextpivot[snextpivot[s1.shver]];
3040}
3041
3042inline void tetgenmesh::senext2self(face& s)
3043{
3044 s.shver = snextpivot[snextpivot[s.shver]];
3045}
3046
3047
3048// Check or set a subface's maximum area bound.
3049
3050inline REAL tetgenmesh::areabound(face& s)
3051{
3052 return ((REAL *) (s.sh))[areaboundindex];
3053}
3054
3055inline void tetgenmesh::setareabound(face& s, REAL value)
3056{
3057 ((REAL *) (s.sh))[areaboundindex] = value;
3058}
3059
3060// These two primitives read or set a shell marker. Shell markers are used
3061// to hold user boundary information.
3062
3063inline int tetgenmesh::shellmark(face& s)
3064{
3065 return ((int *) (s.sh))[shmarkindex];
3066}
3067
3068inline void tetgenmesh::setshellmark(face& s, int value)
3069{
3070 ((int *) (s.sh))[shmarkindex] = value;
3071}
3072
3073
3074
3075// sinfect(), sinfected(), suninfect() -- primitives to flag or unflag a
3076// subface. The last bit of ((int *) ((s).sh))[shmarkindex+1] is flagged.
3077
3078inline void tetgenmesh::sinfect(face& s)
3079{
3080 ((int *) ((s).sh))[shmarkindex+1] =
3081 (((int *) ((s).sh))[shmarkindex+1] | (int) 1);
3082}
3083
3084inline void tetgenmesh::suninfect(face& s)
3085{
3086 ((int *) ((s).sh))[shmarkindex+1] =
3087 (((int *) ((s).sh))[shmarkindex+1] & ~(int) 1);
3088}
3089
3090// Test a subface for viral infection.
3091
3092inline bool tetgenmesh::sinfected(face& s)
3093{
3094 return (((int *) ((s).sh))[shmarkindex+1] & (int) 1) != 0;
3095}
3096
3097// smarktest(), smarktested(), sunmarktest() -- primitives to flag or unflag
3098// a subface. The last 2nd bit of the integer is flagged.
3099
3100inline void tetgenmesh::smarktest(face& s)
3101{
3102 ((int *) ((s).sh))[shmarkindex+1] =
3103 (((int *)((s).sh))[shmarkindex+1] | (int) 2);
3104}
3105
3106inline void tetgenmesh::sunmarktest(face& s)
3107{
3108 ((int *) ((s).sh))[shmarkindex+1] =
3109 (((int *)((s).sh))[shmarkindex+1] & ~(int)2);
3110}
3111
3112inline bool tetgenmesh::smarktested(face& s)
3113{
3114 return ((((int *) ((s).sh))[shmarkindex+1] & (int) 2) != 0);
3115}
3116
3117// smarktest2(), smarktest2ed(), sunmarktest2() -- primitives to flag or
3118// unflag a subface. The last 3rd bit of the integer is flagged.
3119
3120inline void tetgenmesh::smarktest2(face& s)
3121{
3122 ((int *) ((s).sh))[shmarkindex+1] =
3123 (((int *)((s).sh))[shmarkindex+1] | (int) 4);
3124}
3125
3126inline void tetgenmesh::sunmarktest2(face& s)
3127{
3128 ((int *) ((s).sh))[shmarkindex+1] =
3129 (((int *)((s).sh))[shmarkindex+1] & ~(int)4);
3130}
3131
3132inline bool tetgenmesh::smarktest2ed(face& s)
3133{
3134 return ((((int *) ((s).sh))[shmarkindex+1] & (int) 4) != 0);
3135}
3136
3137// The last 4th bit of ((int *) ((s).sh))[shmarkindex+1] is flagged.
3138
3139inline void tetgenmesh::smarktest3(face& s)
3140{
3141 ((int *) ((s).sh))[shmarkindex+1] =
3142 (((int *)((s).sh))[shmarkindex+1] | (int) 8);
3143}
3144
3145inline void tetgenmesh::sunmarktest3(face& s)
3146{
3147 ((int *) ((s).sh))[shmarkindex+1] =
3148 (((int *)((s).sh))[shmarkindex+1] & ~(int)8);
3149}
3150
3151inline bool tetgenmesh::smarktest3ed(face& s)
3152{
3153 return ((((int *) ((s).sh))[shmarkindex+1] & (int) 8) != 0);
3154}
3155
3156
3157// Each facet has a unique index (automatically indexed). Starting from '0'.
3158// We save this index in the same field of the shell type.
3159
3160inline void tetgenmesh::setfacetindex(face& s, int value)
3161{
3162 ((int *) (s.sh))[shmarkindex + 2] = value;
3163}
3164
3165inline int tetgenmesh::getfacetindex(face& s)
3166{
3167 return ((int *) (s.sh))[shmarkindex + 2];
3168}
3169
3170// Tests if the subface (subsegment) s is dead.
3171
3172inline bool tetgenmesh::isdeadsh(face& s) {
3173 return ((s.sh == NULL) || (s.sh[3] == NULL));
3174}
3175
3176//============================================================================//
3177// //
3178// Primitives for interacting between tetrahedra and subfaces //
3179// //
3180//============================================================================//
3181
3182// tsbond() bond a tetrahedron (t) and a subface (s) together.
3183// Note that t and s must be the same face and the same edge. Moreover,
3184// t and s have the same orientation.
3185// Since the edge number in t and in s can be any number in {0,1,2}. We bond
3186// the edge in s which corresponds to t's 0th edge, and vice versa.
3187
3188inline void tetgenmesh::tsbond(triface& t, face& s)
3189{
3190 if ((t).tet[9] == NULL) {
3191 // Allocate space for this tet.
3192 (t).tet[9] = (tetrahedron) tet2subpool->alloc();
3193 // Initialize.
3194 for (int i = 0; i < 4; i++) {
3195 ((shellface *) (t).tet[9])[i] = NULL;
3196 }
3197 }
3198 // Bond t <== s.
3199 ((shellface *) (t).tet[9])[(t).ver & 3] =
3200 sencode2((s).sh, tsbondtbl[t.ver][s.shver]);
3201 // Bond s <== t.
3202 s.sh[9 + ((s).shver & 1)] =
3203 (shellface) encode2((t).tet, stbondtbl[t.ver][s.shver]);
3204}
3205
3206// tspivot() finds a subface (s) abutting on the given tetrahdera (t).
3207// Return s.sh = NULL if there is no subface at t. Otherwise, return
3208// the subface s, and s and t must be at the same edge wth the same
3209// orientation.
3210
3211inline void tetgenmesh::tspivot(triface& t, face& s)
3212{
3213 if ((t).tet[9] == NULL) {
3214 (s).sh = NULL;
3215 return;
3216 }
3217 // Get the attached subface s.
3218 sdecode(((shellface *) (t).tet[9])[(t).ver & 3], (s));
3219 (s).shver = tspivottbl[t.ver][s.shver];
3220}
3221
3222// Quickly check if the handle (t, v) is a subface.
3223#define issubface(t) \
3224 ((t).tet[9] && ((t).tet[9])[(t).ver & 3])
3225
3226// stpivot() finds a tetrahedron (t) abutting a given subface (s).
3227// Return the t (if it exists) with the same edge and the same
3228// orientation of s.
3229
3230inline void tetgenmesh::stpivot(face& s, triface& t)
3231{
3232 decode((tetrahedron) s.sh[9 + (s.shver & 1)], t);
3233 if ((t).tet == NULL) {
3234 return;
3235 }
3236 (t).ver = stpivottbl[t.ver][s.shver];
3237}
3238
3239// Quickly check if this subface is attached to a tetrahedron.
3240
3241#define isshtet(s) \
3242 ((s).sh[9 + ((s).shver & 1)])
3243
3244// tsdissolve() dissolve a bond (from the tetrahedron side).
3245
3246inline void tetgenmesh::tsdissolve(triface& t)
3247{
3248 if ((t).tet[9] != NULL) {
3249 ((shellface *) (t).tet[9])[(t).ver & 3] = NULL;
3250 }
3251}
3252
3253// stdissolve() dissolve a bond (from the subface side).
3254
3255inline void tetgenmesh::stdissolve(face& s)
3256{
3257 (s).sh[9] = NULL;
3258 (s).sh[10] = NULL;
3259}
3260
3261//============================================================================//
3262// //
3263// Primitives for interacting between subfaces and segments //
3264// //
3265//============================================================================//
3266
3267// ssbond() bond a subface to a subsegment.
3268
3269inline void tetgenmesh::ssbond(face& s, face& edge)
3270{
3271 s.sh[6 + (s.shver >> 1)] = sencode(edge);
3272 edge.sh[0] = sencode(s);
3273}
3274
3275inline void tetgenmesh::ssbond1(face& s, face& edge)
3276{
3277 s.sh[6 + (s.shver >> 1)] = sencode(edge);
3278 //edge.sh[0] = sencode(s);
3279}
3280
3281// ssdisolve() dissolve a bond (from the subface side)
3282
3283inline void tetgenmesh::ssdissolve(face& s)
3284{
3285 s.sh[6 + (s.shver >> 1)] = NULL;
3286}
3287
3288// sspivot() finds a subsegment abutting a subface.
3289
3290inline void tetgenmesh::sspivot(face& s, face& edge)
3291{
3292 sdecode((shellface) s.sh[6 + (s.shver >> 1)], edge);
3293}
3294
3295// Quickly check if the edge is a subsegment.
3296
3297#define isshsubseg(s) \
3298 ((s).sh[6 + ((s).shver >> 1)])
3299
3300//============================================================================//
3301// //
3302// Primitives for interacting between tetrahedra and segments //
3303// //
3304//============================================================================//
3305
3306inline void tetgenmesh::tssbond1(triface& t, face& s)
3307{
3308 if ((t).tet[8] == NULL) {
3309 // Allocate space for this tet.
3310 (t).tet[8] = (tetrahedron) tet2segpool->alloc();
3311 // Initialization.
3312 for (int i = 0; i < 6; i++) {
3313 ((shellface *) (t).tet[8])[i] = NULL;
3314 }
3315 }
3316 ((shellface *) (t).tet[8])[ver2edge[(t).ver]] = sencode((s));
3317}
3318
3319inline void tetgenmesh::sstbond1(face& s, triface& t)
3320{
3321 ((tetrahedron *) (s).sh)[9] = encode(t);
3322}
3323
3324inline void tetgenmesh::tssdissolve1(triface& t)
3325{
3326 if ((t).tet[8] != NULL) {
3327 ((shellface *) (t).tet[8])[ver2edge[(t).ver]] = NULL;
3328 }
3329}
3330
3331inline void tetgenmesh::sstdissolve1(face& s)
3332{
3333 ((tetrahedron *) (s).sh)[9] = NULL;
3334}
3335
3336inline void tetgenmesh::tsspivot1(triface& t, face& s)
3337{
3338 if ((t).tet[8] != NULL) {
3339 sdecode(((shellface *) (t).tet[8])[ver2edge[(t).ver]], s);
3340 } else {
3341 (s).sh = NULL;
3342 }
3343}
3344
3345// Quickly check whether 't' is a segment or not.
3346
3347#define issubseg(t) \
3348 ((t).tet[8] && ((t).tet[8])[ver2edge[(t).ver]])
3349
3350inline void tetgenmesh::sstpivot1(face& s, triface& t)
3351{
3352 decode((tetrahedron) s.sh[9], t);
3353}
3354
3355//============================================================================//
3356// //
3357// Primitives for points //
3358// //
3359//============================================================================//
3360
3361inline int tetgenmesh::pointmark(point pt) {
3362 return ((int *) (pt))[pointmarkindex];
3363}
3364
3365inline void tetgenmesh::setpointmark(point pt, int value) {
3366 ((int *) (pt))[pointmarkindex] = value;
3367}
3368
3369
3370// These two primitives set and read the type of the point.
3371
3372inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
3373 return (enum verttype) (((int *) (pt))[pointmarkindex + 1] >> (int) 8);
3374}
3375
3376inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
3377 ((int *) (pt))[pointmarkindex + 1] =
3378 ((int) value << 8) + (((int *) (pt))[pointmarkindex + 1] & (int) 255);
3379}
3380
3381// pinfect(), puninfect(), pinfected() -- primitives to flag or unflag
3382// a point. The last bit of the integer '[pointindex+1]' is flagged.
3383
3384inline void tetgenmesh::pinfect(point pt) {
3385 ((int *) (pt))[pointmarkindex + 1] |= (int) 1;
3386}
3387
3388inline void tetgenmesh::puninfect(point pt) {
3389 ((int *) (pt))[pointmarkindex + 1] &= ~(int) 1;
3390}
3391
3392inline bool tetgenmesh::pinfected(point pt) {
3393 return (((int *) (pt))[pointmarkindex + 1] & (int) 1) != 0;
3394}
3395
3396// pmarktest(), punmarktest(), pmarktested() -- more primitives to
3397// flag or unflag a point.
3398
3399inline void tetgenmesh::pmarktest(point pt) {
3400 ((int *) (pt))[pointmarkindex + 1] |= (int) 2;
3401}
3402
3403inline void tetgenmesh::punmarktest(point pt) {
3404 ((int *) (pt))[pointmarkindex + 1] &= ~(int) 2;
3405}
3406
3407inline bool tetgenmesh::pmarktested(point pt) {
3408 return (((int *) (pt))[pointmarkindex + 1] & (int) 2) != 0;
3409}
3410
3411inline void tetgenmesh::pmarktest2(point pt) {
3412 ((int *) (pt))[pointmarkindex + 1] |= (int) 4;
3413}
3414
3415inline void tetgenmesh::punmarktest2(point pt) {
3416 ((int *) (pt))[pointmarkindex + 1] &= ~(int) 4;
3417}
3418
3419inline bool tetgenmesh::pmarktest2ed(point pt) {
3420 return (((int *) (pt))[pointmarkindex + 1] & (int) 4) != 0;
3421}
3422
3423inline void tetgenmesh::pmarktest3(point pt) {
3424 ((int *) (pt))[pointmarkindex + 1] |= (int) 8;
3425}
3426
3427inline void tetgenmesh::punmarktest3(point pt) {
3428 ((int *) (pt))[pointmarkindex + 1] &= ~(int) 8;
3429}
3430
3431inline bool tetgenmesh::pmarktest3ed(point pt) {
3432 return (((int *) (pt))[pointmarkindex + 1] & (int) 8) != 0;
3433}
3434
3435// Read and set the geometry tag of the point (used by -s option).
3436
3437inline int tetgenmesh::pointgeomtag(point pt) {
3438 return ((int *) (pt))[pointmarkindex + 2];
3439}
3440
3441inline void tetgenmesh::setpointgeomtag(point pt, int value) {
3442 ((int *) (pt))[pointmarkindex + 2] = value;
3443}
3444
3445// Read and set the u,v coordinates of the point (used by -s option).
3446
3447inline REAL tetgenmesh::pointgeomuv(point pt, int i) {
3448 return pt[pointparamindex + i];
3449}
3450
3451inline void tetgenmesh::setpointgeomuv(point pt, int i, REAL value) {
3452 pt[pointparamindex + i] = value;
3453}
3454
3455
3456
3457// These following primitives set and read a pointer to a tetrahedron
3458// a subface/subsegment, a point, or a tet of background mesh.
3459
3460inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
3461 return ((tetrahedron *) (pt))[point2simindex];
3462}
3463
3464inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
3465 ((tetrahedron *) (pt))[point2simindex] = value;
3466}
3467
3468inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
3469 return (point) ((tetrahedron *) (pt))[point2simindex + 1];
3470}
3471
3472inline void tetgenmesh::setpoint2ppt(point pt, point value) {
3473 ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
3474}
3475
3476inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
3477 return (shellface) ((tetrahedron *) (pt))[point2simindex + 2];
3478}
3479
3480inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
3481 ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
3482}
3483
3484
3485inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
3486 return ((tetrahedron *) (pt))[point2simindex + 3];
3487}
3488
3489inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
3490 ((tetrahedron *) (pt))[point2simindex + 3] = value;
3491}
3492
3493
3494// The primitives for saving and getting the insertion radius.
3495inline void tetgenmesh::setpointinsradius(point pt, REAL value)
3496{
3497 pt[pointinsradiusindex] = value;
3498}
3499
3500inline REAL tetgenmesh::getpointinsradius(point pt)
3501{
3502 return pt[pointinsradiusindex];
3503}
3504
3505inline bool tetgenmesh::issteinerpoint(point pt) {
3506 return (pointtype(pt) == FREESEGVERTEX) || (pointtype(pt) == FREEFACETVERTEX)
3507 || (pointtype(pt) == FREEVOLVERTEX);
3508}
3509
3510// point2tetorg() Get the tetrahedron whose origin is the point.
3511
3512inline void tetgenmesh::point2tetorg(point pa, triface& searchtet)
3513{
3514 decode(point2tet(pa), searchtet);
3515 if ((point) searchtet.tet[4] == pa) {
3516 searchtet.ver = 11;
3517 } else if ((point) searchtet.tet[5] == pa) {
3518 searchtet.ver = 3;
3519 } else if ((point) searchtet.tet[6] == pa) {
3520 searchtet.ver = 7;
3521 } else {
3522 searchtet.ver = 0;
3523 }
3524}
3525
3526// point2shorg() Get the subface/segment whose origin is the point.
3527
3528inline void tetgenmesh::point2shorg(point pa, face& searchsh)
3529{
3530 sdecode(point2sh(pa), searchsh);
3531 if ((point) searchsh.sh[3] == pa) {
3532 searchsh.shver = 0;
3533 } else if ((point) searchsh.sh[4] == pa) {
3534 searchsh.shver = (searchsh.sh[5] != NULL ? 2 : 1);
3535 } else {
3536 searchsh.shver = 4;
3537 }
3538}
3539
3540// farsorg() Return the origin of the subsegment.
3541// farsdest() Return the destination of the subsegment.
3542
3543inline tetgenmesh::point tetgenmesh::farsorg(face& s)
3544{
3545 face travesh, neighsh;
3546
3547 travesh = s;
3548 while (1) {
3549 senext2(travesh, neighsh);
3550 spivotself(neighsh);
3551 if (neighsh.sh == NULL) break;
3552 if (sorg(neighsh) != sorg(travesh)) sesymself(neighsh);
3553 senext2(neighsh, travesh);
3554 }
3555 return sorg(travesh);
3556}
3557
3558inline tetgenmesh::point tetgenmesh::farsdest(face& s)
3559{
3560 face travesh, neighsh;
3561
3562 travesh = s;
3563 while (1) {
3564 senext(travesh, neighsh);
3565 spivotself(neighsh);
3566 if (neighsh.sh == NULL) break;
3567 if (sdest(neighsh) != sdest(travesh)) sesymself(neighsh);
3568 senext(neighsh, travesh);
3569 }
3570 return sdest(travesh);
3571}
3572
3574// //
3575// Linear algebra operators. //
3576// //
3578
3579// dot() returns the dot product: v1 dot v2.
3580inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
3581{
3582 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
3583}
3584
3585// cross() computes the cross product: n = v1 cross v2.
3586inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
3587{
3588 n[0] = v1[1] * v2[2] - v2[1] * v1[2];
3589 n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
3590 n[2] = v1[0] * v2[1] - v2[0] * v1[1];
3591}
3592
3593// distance() computes the Euclidean distance between two points.
3594inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
3595{
3596 return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
3597 (p2[1] - p1[1]) * (p2[1] - p1[1]) +
3598 (p2[2] - p1[2]) * (p2[2] - p1[2]));
3599}
3600
3601inline REAL tetgenmesh::distance2(REAL* p1, REAL* p2)
3602{
3603 return norm2(p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);
3604}
3605
3606inline REAL tetgenmesh::norm2(REAL x, REAL y, REAL z)
3607{
3608 return (x) * (x) + (y) * (y) + (z) * (z);
3609}
3610
3611
3612
3613#endif // #ifndef tetgenH
3614
Definition tetgen.h:615
Definition tetgen.h:109
Definition tetgen.h:1050
Definition tetgen.h:1144
Definition tetgen.h:1021
Definition tetgen.h:1225
Definition tetgen.h:1171
Definition tetgen.h:1102
Definition tetgen.h:1287
Definition tetgen.h:1010
Definition tetgen.h:883
bool split_subface(face *splitfac, point encpt, REAL *ccent, REAL *, int, int, int *)
//
Definition tetgen.cxx:27704
Definition tetgen.h:126
Definition tetgen.h:160
Definition tetgen.h:118
Definition tetgen.h:140
Definition tetgen.h:152