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