Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
triangle.cpp
Go to the documentation of this file.
1/*****************************************************************************/
2/* */
3/* 888888888 ,o, / 888 */
4/* 888 88o88o " o8888o 88o8888o o88888o 888 o88888o */
5/* 888 888 888 88b 888 888 888 888 888 d888 88b */
6/* 888 888 888 o88^o888 888 888 "88888" 888 8888oo888 */
7/* 888 888 888 C888 888 888 888 / 888 q888 */
8/* 888 888 888 "88o^888 888 888 Cb 888 "88oooo" */
9/* "8oo8D */
10/* */
11/* A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator. */
12/* (triangle.c) */
13/* */
14/* Version 1.6 */
15/* July 28, 2005 */
16/* */
17/* Jonathan Richard Shewchuk */
18/* 2360 Woolsey #H */
19/* Berkeley, California 94705-1927 */
20/* jrs@cs.berkeley.edu */
21/* */
22/* This program may be freely redistributed under the condition that the */
23/* copyright notices (including this entire header and the copyright */
24/* notice printed when the `-h' switch is selected) are not removed, and */
25/* no compensation is received. Private, research, and institutional */
26/* use is free. You may distribute modified versions of this code UNDER */
27/* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */
28/* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */
29/* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */
30/* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */
31/* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */
32/* WITH THE AUTHOR. (If you are not directly supplying this code to a */
33/* customer, and you are instead telling them how they can obtain it for */
34/* free, then you are not required to make any arrangement with me.) */
35/* */
36/* Hypertext instructions for Triangle are available on the Web at */
37/* */
38/* http://www.cs.cmu.edu/~quake/triangle.html */
39/* */
40/* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */
41/* whatsoever. This code is provided "as-is". Use at your own risk. */
42/* */
43/* Some of the references listed below are marked with an asterisk. [*] */
44/* These references are available for downloading from the Web page */
45/* */
46/* http://www.cs.cmu.edu/~quake/triangle.research.html */
47/* */
48/* Three papers discussing aspects of Triangle are available. A short */
49/* overview appears in "Triangle: Engineering a 2D Quality Mesh */
50/* Generator and Delaunay Triangulator," in Applied Computational */
51/* Geometry: Towards Geometric Engineering, Ming C. Lin and Dinesh */
52/* Manocha, editors, Lecture Notes in Computer Science volume 1148, */
53/* pages 203-222, Springer-Verlag, Berlin, May 1996 (from the First ACM */
54/* Workshop on Applied Computational Geometry). [*] */
55/* */
56/* The algorithms are discussed in the greatest detail in "Delaunay */
57/* Refinement Algorithms for Triangular Mesh Generation," Computational */
58/* Geometry: Theory and Applications 22(1-3):21-74, May 2002. [*] */
59/* */
60/* More detail about the data structures may be found in my dissertation: */
61/* "Delaunay Refinement Mesh Generation," Ph.D. thesis, Technical Report */
62/* CMU-CS-97-137, School of Computer Science, Carnegie Mellon University, */
63/* Pittsburgh, Pennsylvania, 18 May 1997. [*] */
64/* */
65/* Triangle was created as part of the Quake Project in the School of */
66/* Computer Science at Carnegie Mellon University. For further */
67/* information, see Hesheng Bao, Jacobo Bielak, Omar Ghattas, Loukas F. */
68/* Kallivokas, David R. O'Hallaron, Jonathan R. Shewchuk, and Jifeng Xu, */
69/* "Large-scale Simulation of Elastic Wave Propagation in Heterogeneous */
70/* Media on Parallel Computers," Computer Methods in Applied Mechanics */
71/* and Engineering 152(1-2):85-102, 22 January 1998. */
72/* */
73/* Triangle's Delaunay refinement algorithm for quality mesh generation is */
74/* a hybrid of one due to Jim Ruppert, "A Delaunay Refinement Algorithm */
75/* for Quality 2-Dimensional Mesh Generation," Journal of Algorithms */
76/* 18(3):548-585, May 1995 [*], and one due to L. Paul Chew, "Guaranteed- */
77/* Quality Mesh Generation for Curved Surfaces," Proceedings of the Ninth */
78/* Annual Symposium on Computational Geometry (San Diego, California), */
79/* pages 274-280, Association for Computing Machinery, May 1993, */
80/* http://portal.acm.org/citation.cfm?id=161150 . */
81/* */
82/* The Delaunay refinement algorithm has been modified so that it meshes */
83/* domains with small input angles well, as described in Gary L. Miller, */
84/* Steven E. Pav, and Noel J. Walkington, "When and Why Ruppert's */
85/* Algorithm Works," Twelfth International Meshing Roundtable, pages */
86/* 91-102, Sandia National Laboratories, September 2003. [*] */
87/* */
88/* My implementation of the divide-and-conquer and incremental Delaunay */
89/* triangulation algorithms follows closely the presentation of Guibas */
90/* and Stolfi, even though I use a triangle-based data structure instead */
91/* of their quad-edge data structure. (In fact, I originally implemented */
92/* Triangle using the quad-edge data structure, but the switch to a */
93/* triangle-based data structure sped Triangle by a factor of two.) The */
94/* mesh manipulation primitives and the two aforementioned Delaunay */
95/* triangulation algorithms are described by Leonidas J. Guibas and Jorge */
96/* Stolfi, "Primitives for the Manipulation of General Subdivisions and */
97/* the Computation of Voronoi Diagrams," ACM Transactions on Graphics */
98/* 4(2):74-123, April 1985, http://portal.acm.org/citation.cfm?id=282923 .*/
99/* */
100/* Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai */
101/* Lee and Bruce J. Schachter, "Two Algorithms for Constructing the */
102/* Delaunay Triangulation," International Journal of Computer and */
103/* Information Science 9(3):219-242, 1980. Triangle's improvement of the */
104/* divide-and-conquer algorithm by alternating between vertical and */
105/* horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and- */
106/* Conquer Algorithm for Constructing Delaunay Triangulations," */
107/* Algorithmica 2(2):137-151, 1987. */
108/* */
109/* The incremental insertion algorithm was first proposed by C. L. Lawson, */
110/* "Software for C1 Surface Interpolation," in Mathematical Software III, */
111/* John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977. */
112/* For point location, I use the algorithm of Ernst P. Mucke, Isaac */
113/* Saias, and Binhai Zhu, "Fast Randomized Point Location Without */
114/* Preprocessing in Two- and Three-Dimensional Delaunay Triangulations," */
115/* Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
116/* ACM, May 1996. [*] If I were to randomize the order of vertex */
117/* insertion (I currently don't bother), their result combined with the */
118/* result of Kenneth L. Clarkson and Peter W. Shor, "Applications of */
119/* Random Sampling in Computational Geometry II," Discrete & */
120/* Computational Geometry 4(1):387-421, 1989, would yield an expected */
121/* O(n^{4/3}) bound on running time. */
122/* */
123/* The O(n log n) sweepline Delaunay triangulation algorithm is taken from */
124/* Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams", */
125/* Algorithmica 2(2):153-174, 1987. A random sample of edges on the */
126/* boundary of the triangulation are maintained in a splay tree for the */
127/* purpose of point location. Splay trees are described by Daniel */
128/* Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
129/* Trees," Journal of the ACM 32(3):652-686, July 1985, */
130/* http://portal.acm.org/citation.cfm?id=3835 . */
131/* */
132/* The algorithms for exact computation of the signs of determinants are */
133/* described in Jonathan Richard Shewchuk, "Adaptive Precision Floating- */
134/* Point Arithmetic and Fast Robust Geometric Predicates," Discrete & */
135/* Computational Geometry 18(3):305-363, October 1997. (Also available */
136/* as Technical Report CMU-CS-96-140, School of Computer Science, */
137/* Carnegie Mellon University, Pittsburgh, Pennsylvania, May 1996.) [*] */
138/* An abbreviated version appears as Jonathan Richard Shewchuk, "Robust */
139/* Adaptive Floating-Point Geometric Predicates," Proceedings of the */
140/* Twelfth Annual Symposium on Computational Geometry, ACM, May 1996. [*] */
141/* Many of the ideas for my exact arithmetic routines originate with */
142/* Douglas M. Priest, "Algorithms for Arbitrary Precision Floating Point */
143/* Arithmetic," Tenth Symposium on Computer Arithmetic, pp. 132-143, IEEE */
144/* Computer Society Press, 1991. [*] Many of the ideas for the correct */
145/* evaluation of the signs of determinants are taken from Steven Fortune */
146/* and Christopher J. Van Wyk, "Efficient Exact Arithmetic for Computa- */
147/* tional Geometry," Proceedings of the Ninth Annual Symposium on */
148/* Computational Geometry, ACM, pp. 163-172, May 1993, and from Steven */
149/* Fortune, "Numerical Stability of Algorithms for 2D Delaunay Triangu- */
150/* lations," International Journal of Computational Geometry & Applica- */
151/* tions 5(1-2):193-213, March-June 1995. */
152/* */
153/* The method of inserting new vertices off-center (not precisely at the */
154/* circumcenter of every poor-quality triangle) is from Alper Ungor, */
155/* "Off-centers: A New Type of Steiner Points for Computing Size-Optimal */
156/* Quality-Guaranteed Delaunay Triangulations," Proceedings of LATIN */
157/* 2004 (Buenos Aires, Argentina), April 2004. */
158/* */
159/* For definitions of and results involving Delaunay triangulations, */
160/* constrained and conforming versions thereof, and other aspects of */
161/* triangular mesh generation, see the excellent survey by Marshall Bern */
162/* and David Eppstein, "Mesh Generation and Optimal Triangulation," in */
163/* Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang, */
164/* editors, World Scientific, Singapore, pp. 23-90, 1992. [*] */
165/* */
166/* The time for incrementally adding PSLG (planar straight line graph) */
167/* segments to create a constrained Delaunay triangulation is probably */
168/* O(t^2) per segment in the worst case and O(t) per segment in the */
169/* common case, where t is the number of triangles that intersect the */
170/* segment before it is inserted. This doesn't count point location, */
171/* which can be much more expensive. I could improve this to O(d log d) */
172/* time, but d is usually quite small, so it's not worth the bother. */
173/* (This note does not apply when the -s switch is used, invoking a */
174/* different method is used to insert segments.) */
175/* */
176/* The time for deleting a vertex from a Delaunay triangulation is O(d^2) */
177/* in the worst case and O(d) in the common case, where d is the degree */
178/* of the vertex being deleted. I could improve this to O(d log d) time, */
179/* but d is usually quite small, so it's not worth the bother. */
180/* */
181/* Ruppert's Delaunay refinement algorithm typically generates triangles */
182/* at a linear rate (constant time per triangle) after the initial */
183/* triangulation is formed. There may be pathological cases where */
184/* quadratic time is required, but these never arise in practice. */
185/* */
186/* The geometric predicates (circumcenter calculations, segment */
187/* intersection formulae, etc.) appear in my "Lecture Notes on Geometric */
188/* Robustness" at http://www.cs.berkeley.edu/~jrs/mesh . */
189/* */
190/* If you make any improvements to this code, please please please let me */
191/* know, so that I may obtain the improvements. Even if you don't change */
192/* the code, I'd still love to hear what it's being used for. */
193/* */
194/*****************************************************************************/
195
196/* For single precision (which will save some memory and reduce paging), */
197/* define the symbol SINGLE by using the -DSINGLE compiler switch or by */
198/* writing "#define SINGLE" below. */
199/* */
200/* For double precision (which will allow you to refine meshes to a smaller */
201/* edge length), leave SINGLE undefined. */
202/* */
203/* Double precision uses more memory, but improves the resolution of the */
204/* meshes you can generate with Triangle. It also reduces the likelihood */
205/* of a floating exception due to overflow. Finally, it is much faster */
206/* than single precision on 64-bit architectures like the DEC Alpha. I */
207/* recommend double precision unless you want to generate a mesh for which */
208/* you do not have enough memory. */
209
210/* #define SINGLE */
211
212//#ifdef SINGLE
213//#define REAL float
214//#else /* not SINGLE */
215//#define REAL double
216//#endif /* not SINGLE */
217
218# define TRILIBRARY // use Triangle as a library
219//# define ANSI_DECLARATORS // use ANSI_DECLARATORS
220
221/* If yours is not a Unix system, define the NO_TIMER compiler switch to */
222/* remove the Unix-specific timing code. */
223
224/* #define NO_TIMER */
225
226/* To insert lots of self-checks for internal errors, define the SELF_CHECK */
227/* symbol. This will slow down the program significantly. It is best to */
228/* define the symbol using the -DSELF_CHECK compiler switch, but you could */
229/* write "#define SELF_CHECK" below. If you are modifying this code, I */
230/* recommend you turn self-checks on until your work is debugged. */
231
232/* #define SELF_CHECK */
233
234/* To compile Triangle as a callable object library (triangle.o), define the */
235/* TRILIBRARY symbol. Read the file triangle.h for details on how to call */
236/* the procedure triangulate() that results. */
237
238/* #define TRILIBRARY */
239
240/* It is possible to generate a smaller version of Triangle using one or */
241/* both of the following symbols. Define the REDUCED symbol to eliminate */
242/* all features that are primarily of research interest; specifically, the */
243/* -i, -F, -s, and -C switches. Define the CDT_ONLY symbol to eliminate */
244/* all meshing algorithms above and beyond constrained Delaunay */
245/* triangulation; specifically, the -r, -q, -a, -u, -D, -S, and -s */
246/* switches. These reductions are most likely to be useful when */
247/* generating an object library (triangle.o) by defining the TRILIBRARY */
248/* symbol. */
249
250/* #define REDUCED */
251/* #define CDT_ONLY */
252
253/* On some machines, my exact arithmetic routines might be defeated by the */
254/* use of internal extended precision floating-point registers. The best */
255/* way to solve this problem is to set the floating-point registers to use */
256/* single or double precision internally. On 80x86 processors, this may */
257/* be accomplished by setting the CPU86 symbol for the Microsoft C */
258/* compiler, or the LINUX symbol for the gcc compiler running on Linux. */
259/* */
260/* An inferior solution is to declare certain values as `volatile', thus */
261/* forcing them to be stored to memory and rounded off. Unfortunately, */
262/* this solution might slow Triangle down quite a bit. To use volatile */
263/* values, write "#define INEXACT volatile" below. Normally, however, */
264/* INEXACT should be defined to be nothing. ("#define INEXACT".) */
265/* */
266/* For more discussion, see http://www.cs.cmu.edu/~quake/robust.pc.html . */
267/* For yet more discussion, see Section 5 of my paper, "Adaptive Precision */
268/* Floating-Point Arithmetic and Fast Robust Geometric Predicates" (also */
269/* available as Section 6.6 of my dissertation). */
270
271/* #define CPU86 */
272/* #define LINUX */
273
274#define INEXACT /* Nothing */
275/* #define INEXACT volatile */
276
277/* Maximum number of characters in a file name (including the null). */
278
279#define FILENAMESIZE 2048
280
281/* Maximum number of characters in a line read from a file (including the */
282/* null). */
283
284#define INPUTLINESIZE 1024
285
286/* For efficiency, a variety of data structures are allocated in bulk. The */
287/* following constants determine how many of each structure is allocated */
288/* at once. */
289
290#define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */
291#define SUBSEGPERBLOCK 508 /* Number of subsegments allocated at once. */
292#define VERTEXPERBLOCK 4092 /* Number of vertices allocated at once. */
293#define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */
294/* Number of encroached subsegments allocated at once. */
295#define BADSUBSEGPERBLOCK 252
296/* Number of skinny triangles allocated at once. */
297#define BADTRIPERBLOCK 4092
298/* Number of flipped triangles allocated at once. */
299#define FLIPSTACKERPERBLOCK 252
300/* Number of splay tree nodes allocated at once. */
301#define SPLAYNODEPERBLOCK 508
302
303/* The vertex types. A DEADVERTEX has been deleted entirely. An */
304/* UNDEADVERTEX is not part of the mesh, but is written to the output */
305/* .node file and affects the node indexing in the other output files. */
306
307#define INPUTVERTEX 0
308#define SEGMENTVERTEX 1
309#define FREEVERTEX 2
310#define DEADVERTEX -32768
311#define UNDEADVERTEX -32767
312
313/* The next line is used to outsmart some very stupid compilers. If your */
314/* compiler is smarter, feel free to replace the "int" with "void". */
315/* Not that it matters. */
316
317#define VOID int
318
319/* Two constants for algorithms based on random sampling. Both constants */
320/* have been chosen empirically to optimize their respective algorithms. */
321
322/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */
323/* how large a random sample of triangles to inspect. */
324
325#define SAMPLEFACTOR 11
326
327/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
328/* of boundary edges should be maintained in the splay tree for point */
329/* location on the front. */
330
331#define SAMPLERATE 10
332
333/* A number that speaks for itself, every kissable digit. */
334
335#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
336
337/* Another fave. */
338
339#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
340
341/* And here's one for those of you who are intimidated by math. */
342
343#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
344
345#include <stdio.h>
346#include <stdlib.h>
347#include <string.h>
348#include <math.h>
349#ifndef NO_TIMER
350#include <sys/time.h>
351#endif /* not NO_TIMER */
352#ifdef CPU86
353#include <float.h>
354#endif /* CPU86 */
355#ifdef LINUX
356#include <fpu_control.h>
357#endif /* LINUX */
358#ifdef TRILIBRARY
359#include "triangle.h"
360#endif /* TRILIBRARY */
361
362/* A few forward declarations. */
363
364#ifndef TRILIBRARY
365char *readline();
366char *findfield();
367#endif /* not TRILIBRARY */
368
369/* Labels that signify the result of point location. The result of a */
370/* search indicates that the point falls in the interior of a triangle, on */
371/* an edge, on a vertex, or outside the mesh. */
372
374
375/* Labels that signify the result of vertex insertion. The result indicates */
376/* that the vertex was inserted with complete success, was inserted but */
377/* encroaches upon a subsegment, was not inserted because it lies on a */
378/* segment, or was not inserted because another vertex occupies the same */
379/* location. */
380
383
384/* Labels that signify the result of direction finding. The result */
385/* indicates that a segment connecting the two query points falls within */
386/* the direction triangle, along the left edge of the direction triangle, */
387/* or along the right edge of the direction triangle. */
388
390
391/*****************************************************************************/
392/* */
393/* The basic mesh data structures */
394/* */
395/* There are three: vertices, triangles, and subsegments (abbreviated */
396/* `subseg'). These three data structures, linked by pointers, comprise */
397/* the mesh. A vertex simply represents a mesh vertex and its properties. */
398/* A triangle is a triangle. A subsegment is a special data structure used */
399/* to represent an impenetrable edge of the mesh (perhaps on the outer */
400/* boundary, on the boundary of a hole, or part of an internal boundary */
401/* separating two triangulated regions). Subsegments represent boundaries, */
402/* defined by the user, that triangles may not lie across. */
403/* */
404/* A triangle consists of a list of three vertices, a list of three */
405/* adjoining triangles, a list of three adjoining subsegments (when */
406/* segments exist), an arbitrary number of optional user-defined */
407/* floating-point attributes, and an optional area constraint. The latter */
408/* is an upper bound on the permissible area of each triangle in a region, */
409/* used for mesh refinement. */
410/* */
411/* For a triangle on a boundary of the mesh, some or all of the neighboring */
412/* triangles may not be present. For a triangle in the interior of the */
413/* mesh, often no neighboring subsegments are present. Such absent */
414/* triangles and subsegments are never represented by NULL pointers; they */
415/* are represented by two special records: `dummytri', the triangle that */
416/* fills "outer space", and `dummysub', the omnipresent subsegment. */
417/* `dummytri' and `dummysub' are used for several reasons; for instance, */
418/* they can be dereferenced and their contents examined without violating */
419/* protected memory. */
420/* */
421/* However, it is important to understand that a triangle includes other */
422/* information as well. The pointers to adjoining vertices, triangles, and */
423/* subsegments are ordered in a way that indicates their geometric relation */
424/* to each other. Furthermore, each of these pointers contains orientation */
425/* information. Each pointer to an adjoining triangle indicates which face */
426/* of that triangle is contacted. Similarly, each pointer to an adjoining */
427/* subsegment indicates which side of that subsegment is contacted, and how */
428/* the subsegment is oriented relative to the triangle. */
429/* */
430/* The data structure representing a subsegment may be thought to be */
431/* abutting the edge of one or two triangle data structures: either */
432/* sandwiched between two triangles, or resting against one triangle on an */
433/* exterior boundary or hole boundary. */
434/* */
435/* A subsegment consists of a list of four vertices--the vertices of the */
436/* subsegment, and the vertices of the segment it is a part of--a list of */
437/* two adjoining subsegments, and a list of two adjoining triangles. One */
438/* of the two adjoining triangles may not be present (though there should */
439/* always be one), and neighboring subsegments might not be present. */
440/* Subsegments also store a user-defined integer "boundary marker". */
441/* Typically, this integer is used to indicate what boundary conditions are */
442/* to be applied at that location in a finite element simulation. */
443/* */
444/* Like triangles, subsegments maintain information about the relative */
445/* orientation of neighboring objects. */
446/* */
447/* Vertices are relatively simple. A vertex is a list of floating-point */
448/* numbers, starting with the x, and y coordinates, followed by an */
449/* arbitrary number of optional user-defined floating-point attributes, */
450/* followed by an integer boundary marker. During the segment insertion */
451/* phase, there is also a pointer from each vertex to a triangle that may */
452/* contain it. Each pointer is not always correct, but when one is, it */
453/* speeds up segment insertion. These pointers are assigned values once */
454/* at the beginning of the segment insertion phase, and are not used or */
455/* updated except during this phase. Edge flipping during segment */
456/* insertion will render some of them incorrect. Hence, don't rely upon */
457/* them for anything. */
458/* */
459/* Other than the exception mentioned above, vertices have no information */
460/* about what triangles, subfacets, or subsegments they are linked to. */
461/* */
462/*****************************************************************************/
463
464/*****************************************************************************/
465/* */
466/* Handles */
467/* */
468/* The oriented triangle (`otri') and oriented subsegment (`osub') data */
469/* structures defined below do not themselves store any part of the mesh. */
470/* The mesh itself is made of `triangle's, `subseg's, and `vertex's. */
471/* */
472/* Oriented triangles and oriented subsegments will usually be referred to */
473/* as "handles." A handle is essentially a pointer into the mesh; it */
474/* allows you to "hold" one particular part of the mesh. Handles are used */
475/* to specify the regions in which one is traversing and modifying the mesh.*/
476/* A single `triangle' may be held by many handles, or none at all. (The */
477/* latter case is not a memory leak, because the triangle is still */
478/* connected to other triangles in the mesh.) */
479/* */
480/* An `otri' is a handle that holds a triangle. It holds a specific edge */
481/* of the triangle. An `osub' is a handle that holds a subsegment. It */
482/* holds either the left or right side of the subsegment. */
483/* */
484/* Navigation about the mesh is accomplished through a set of mesh */
485/* manipulation primitives, further below. Many of these primitives take */
486/* a handle and produce a new handle that holds the mesh near the first */
487/* handle. Other primitives take two handles and glue the corresponding */
488/* parts of the mesh together. The orientation of the handles is */
489/* important. For instance, when two triangles are glued together by the */
490/* bond() primitive, they are glued at the edges on which the handles lie. */
491/* */
492/* Because vertices have no information about which triangles they are */
493/* attached to, I commonly represent a vertex by use of a handle whose */
494/* origin is the vertex. A single handle can simultaneously represent a */
495/* triangle, an edge, and a vertex. */
496/* */
497/*****************************************************************************/
498
499/* The triangle data structure. Each triangle contains three pointers to */
500/* adjoining triangles, plus three pointers to vertices, plus three */
501/* pointers to subsegments (declared below; these pointers are usually */
502/* `dummysub'). It may or may not also contain user-defined attributes */
503/* and/or a floating-point "area constraint." It may also contain extra */
504/* pointers for nodes, when the user asks for high-order elements. */
505/* Because the size and structure of a `triangle' is not decided until */
506/* runtime, I haven't simply declared the type `triangle' as a struct. */
507
508typedef REAL **triangle; /* Really: typedef triangle *triangle */
509
510/* An oriented triangle: includes a pointer to a triangle and orientation. */
511/* The orientation denotes an edge of the triangle. Hence, there are */
512/* three possible orientations. By convention, each edge always points */
513/* counterclockwise about the corresponding triangle. */
514
515struct otri {
517 int orient; /* Ranges from 0 to 2. */
518};
519
520/* The subsegment data structure. Each subsegment contains two pointers to */
521/* adjoining subsegments, plus four pointers to vertices, plus two */
522/* pointers to adjoining triangles, plus one boundary marker, plus one */
523/* segment number. */
524
525typedef REAL **subseg; /* Really: typedef subseg *subseg */
526
527/* An oriented subsegment: includes a pointer to a subsegment and an */
528/* orientation. The orientation denotes a side of the edge. Hence, there */
529/* are two possible orientations. By convention, the edge is always */
530/* directed so that the "side" denoted is the right side of the edge. */
531
532struct osub {
534 int ssorient; /* Ranges from 0 to 1. */
535};
536
537/* The vertex data structure. Each vertex is actually an array of REALs. */
538/* The number of REALs is unknown until runtime. An integer boundary */
539/* marker, and sometimes a pointer to a triangle, is appended after the */
540/* REALs. */
541
542typedef REAL *vertex;
543
544/* A queue used to store encroached subsegments. Each subsegment's vertices */
545/* are stored so that we can check whether a subsegment is still the same. */
546
547struct badsubseg {
548 subseg encsubseg; /* An encroached subsegment. */
549 vertex subsegorg, subsegdest; /* Its two vertices. */
550};
551
552/* A queue used to store bad triangles. The key is the square of the cosine */
553/* of the smallest angle of the triangle. Each triangle's vertices are */
554/* stored so that one can check whether a triangle is still the same. */
555
556struct badtriang {
557 triangle poortri; /* A skinny or too-large triangle. */
558 REAL key; /* cos^2 of smallest (apical) angle. */
559 vertex triangorg, triangdest, triangapex; /* Its three vertices. */
560 struct badtriang *nexttriang; /* Pointer to next bad triangle. */
561};
562
563/* A stack of triangles flipped during the most recent vertex insertion. */
564/* The stack is used to undo the vertex insertion if the vertex encroaches */
565/* upon a subsegment. */
566
568 triangle flippedtri; /* A recently flipped triangle. */
569 struct flipstacker *prevflip; /* Previous flip in the stack. */
570};
571
572/* A node in a heap used to store events for the sweepline Delaunay */
573/* algorithm. Nodes do not point directly to their parents or children in */
574/* the heap. Instead, each node knows its position in the heap, and can */
575/* look up its parent and children in a separate array. The `eventptr' */
576/* points either to a `vertex' or to a triangle (in encoded format, so */
577/* that an orientation is included). In the latter case, the origin of */
578/* the oriented triangle is the apex of a "circle event" of the sweepline */
579/* algorithm. To distinguish site events from circle events, all circle */
580/* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */
581
582struct event {
583 REAL xkey, ykey; /* Coordinates of the event. */
584 VOID *eventptr; /* Can be a vertex or the location of a circle event. */
585 int heapposition; /* Marks this event's position in the heap. */
586};
587
588/* A node in the splay tree. Each node holds an oriented ghost triangle */
589/* that represents a boundary edge of the growing triangulation. When a */
590/* circle event covers two boundary edges with a triangle, so that they */
591/* are no longer boundary edges, those edges are not immediately deleted */
592/* from the tree; rather, they are lazily deleted when they are next */
593/* encountered. (Since only a random sample of boundary edges are kept */
594/* in the tree, lazy deletion is faster.) `keydest' is used to verify */
595/* that a triangle is still the same as when it entered the splay tree; if */
596/* it has been rotated (due to a circle event), it no longer represents a */
597/* boundary edge and should be deleted. */
598
599struct splaynode {
600 struct otri keyedge; /* Lprev of an edge on the front. */
601 vertex keydest; /* Used to verify that splay node is still live. */
602 struct splaynode *lchild, *rchild; /* Children in splay tree. */
603};
604
605/* A type used to allocate memory. firstblock is the first block of items. */
606/* nowblock is the block from which items are currently being allocated. */
607/* nextitem points to the next slab of free memory for an item. */
608/* deaditemstack is the head of a linked list (stack) of deallocated items */
609/* that can be recycled. unallocateditems is the number of items that */
610/* remain to be allocated from nowblock. */
611/* */
612/* Traversal is the process of walking through the entire list of items, and */
613/* is separate from allocation. Note that a traversal will visit items on */
614/* the "deaditemstack" stack as well as live items. pathblock points to */
615/* the block currently being traversed. pathitem points to the next item */
616/* to be traversed. pathitemsleft is the number of items that remain to */
617/* be traversed in pathblock. */
618/* */
619/* alignbytes determines how new records should be aligned in memory. */
620/* itembytes is the length of a record in bytes (after rounding up). */
621/* itemsperblock is the number of items allocated at once in a single */
622/* block. itemsfirstblock is the number of items in the first block, */
623/* which can vary from the others. items is the number of currently */
624/* allocated items. maxitems is the maximum number of items that have */
625/* been allocated at once; it is the current number of items plus the */
626/* number of records kept on deaditemstack. */
627
642
643
644/* Global constants. */
645
646REAL splitter; /* Used to split REAL factors for exact multiplication. */
647REAL epsilon; /* Floating-point machine epsilon. */
652
653/* Random number seed is not constant, but I've made it global anyway. */
654
655unsigned long randomseed; /* Current random number seed. */
656
657
658/* Mesh data structure. Triangle operates on only one mesh, but the mesh */
659/* structure is used (instead of global variables) to allow reentrancy. */
660
661struct mesh {
662
663/* Variables used to allocate memory for triangles, subsegments, vertices, */
664/* viri (triangles being eaten), encroached segments, bad (skinny or too */
665/* large) triangles, and splay tree nodes. */
666
675
676/* Variables that maintain the bad triangle queues. The queues are */
677/* ordered from 4095 (highest priority) to 0 (lowest priority). */
678
679 struct badtriang *queuefront[4096];
680 struct badtriang *queuetail[4096];
681 int nextnonemptyq[4096];
683
684/* Variable that maintains the stack of recently flipped triangles. */
685
687
688/* Other variables. */
689
690 REAL xmin, xmax, ymin, ymax; /* x and y bounds. */
691 REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */
692 int invertices; /* Number of input vertices. */
693 int inelements; /* Number of input triangles. */
694 int insegments; /* Number of input segments. */
695 int holes; /* Number of input holes. */
696 int regions; /* Number of input regions. */
697 int undeads; /* Number of input vertices that don't appear in the mesh. */
698 long edges; /* Number of output edges. */
699 int mesh_dim; /* Dimension (ought to be 2). */
700 int nextras; /* Number of attributes per vertex. */
701 int eextras; /* Number of attributes per triangle. */
702 long hullsize; /* Number of edges in convex hull. */
703 int steinerleft; /* Number of Steiner points not yet used. */
704 int vertexmarkindex; /* Index to find boundary marker of a vertex. */
705 int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */
706 int highorderindex; /* Index to find extra nodes for high-order elements. */
707 int elemattribindex; /* Index to find attributes of a triangle. */
708 int areaboundindex; /* Index to find area bound of a triangle. */
709 int checksegments; /* Are there segments in the triangulation yet? */
710 int checkquality; /* Has quality triangulation begun yet? */
711 int readnodefile; /* Has a .node file been read? */
712 long samples; /* Number of random samples for point location. */
713
714 long incirclecount; /* Number of incircle tests performed. */
715 long counterclockcount; /* Number of counterclockwise tests performed. */
716 long orient3dcount; /* Number of 3D orientation tests performed. */
717 long hyperbolacount; /* Number of right-of-hyperbola tests performed. */
718 long circumcentercount; /* Number of circumcenter calculations performed. */
719 long circletopcount; /* Number of circle top calculations performed. */
720
721/* Triangular bounding box vertices. */
722
724
725/* Pointer to the `triangle' that occupies all of "outer space." */
726
728 triangle *dummytribase; /* Keep base address so we can free() it later. */
729
730/* Pointer to the omnipresent subsegment. Referenced by any triangle or */
731/* subsegment that isn't really connected to a subsegment at that */
732/* location. */
733
735 subseg *dummysubbase; /* Keep base address so we can free() it later. */
736
737/* Pointer to a recently visited triangle. Improves point location if */
738/* proximate vertices are inserted sequentially. */
739
741
742}; /* End of `struct mesh'. */
743
744
745/* Data structure for command line switches and file names. This structure */
746/* is used (instead of global variables) to allow reentrancy. */
747
748struct behavior {
749
750/* Switches for the triangulator. */
751/* poly: -p switch. refine: -r switch. */
752/* quality: -q switch. */
753/* minangle: minimum angle bound, specified after -q switch. */
754/* goodangle: cosine squared of minangle. */
755/* offconstant: constant used to place off-center Steiner points. */
756/* vararea: -a switch without number. */
757/* fixedarea: -a switch with number. */
758/* maxarea: maximum area bound, specified after -a switch. */
759/* usertest: -u switch. */
760/* regionattrib: -A switch. convex: -c switch. */
761/* weighted: 1 for -w switch, 2 for -W switch. jettison: -j switch */
762/* firstnumber: inverse of -z switch. All items are numbered starting */
763/* from `firstnumber'. */
764/* edgesout: -e switch. voronoi: -v switch. */
765/* neighbors: -n switch. geomview: -g switch. */
766/* nobound: -B switch. nopolywritten: -P switch. */
767/* nonodewritten: -N switch. noelewritten: -E switch. */
768/* noiterationnum: -I switch. noholes: -O switch. */
769/* noexact: -X switch. */
770/* order: element order, specified after -o switch. */
771/* nobisect: count of how often -Y switch is selected. */
772/* steiner: maximum number of Steiner points, specified after -S switch. */
773/* incremental: -i switch. sweepline: -F switch. */
774/* dwyer: inverse of -l switch. */
775/* splitseg: -s switch. */
776/* conformdel: -D switch. docheck: -C switch. */
777/* quiet: -Q switch. verbose: count of how often -V switch is selected. */
778/* usesegments: -p, -r, -q, or -c switch; determines whether segments are */
779/* used at all. */
780/* */
781/* Read the instructions to find out the meaning of these switches. */
782
794 int order;
799
800/* Variables for file names. */
801
802#ifndef TRILIBRARY
803 char innodefilename[FILENAMESIZE];
804 char inelefilename[FILENAMESIZE];
805 char inpolyfilename[FILENAMESIZE];
806 char areafilename[FILENAMESIZE];
807 char outnodefilename[FILENAMESIZE];
808 char outelefilename[FILENAMESIZE];
809 char outpolyfilename[FILENAMESIZE];
810 char edgefilename[FILENAMESIZE];
811 char vnodefilename[FILENAMESIZE];
812 char vedgefilename[FILENAMESIZE];
813 char neighborfilename[FILENAMESIZE];
814 char offfilename[FILENAMESIZE];
815#endif /* not TRILIBRARY */
816
817}; /* End of `struct behavior'. */
818
819
820/*****************************************************************************/
821/* */
822/* Mesh manipulation primitives. Each triangle contains three pointers to */
823/* other triangles, with orientations. Each pointer points not to the */
824/* first byte of a triangle, but to one of the first three bytes of a */
825/* triangle. It is necessary to extract both the triangle itself and the */
826/* orientation. To save memory, I keep both pieces of information in one */
827/* pointer. To make this possible, I assume that all triangles are aligned */
828/* to four-byte boundaries. The decode() routine below decodes a pointer, */
829/* extracting an orientation (in the range 0 to 2) and a pointer to the */
830/* beginning of a triangle. The encode() routine compresses a pointer to a */
831/* triangle and an orientation into a single pointer. My assumptions that */
832/* triangles are four-byte-aligned and that the `unsigned long' type is */
833/* long enough to hold a pointer are two of the few kludges in this program.*/
834/* */
835/* Subsegments are manipulated similarly. A pointer to a subsegment */
836/* carries both an address and an orientation in the range 0 to 1. */
837/* */
838/* The other primitives take an oriented triangle or oriented subsegment, */
839/* and return an oriented triangle or oriented subsegment or vertex; or */
840/* they change the connections in the data structure. */
841/* */
842/* Below, triangles and subsegments are denoted by their vertices. The */
843/* triangle abc has origin (org) a, destination (dest) b, and apex (apex) */
844/* c. These vertices occur in counterclockwise order about the triangle. */
845/* The handle abc may simultaneously denote vertex a, edge ab, and triangle */
846/* abc. */
847/* */
848/* Similarly, the subsegment ab has origin (sorg) a and destination (sdest) */
849/* b. If ab is thought to be directed upward (with b directly above a), */
850/* then the handle ab is thought to grasp the right side of ab, and may */
851/* simultaneously denote vertex a and edge ab. */
852/* */
853/* An asterisk (*) denotes a vertex whose identity is unknown. */
854/* */
855/* Given this notation, a partial list of mesh manipulation primitives */
856/* follows. */
857/* */
858/* */
859/* For triangles: */
860/* */
861/* sym: Find the abutting triangle; same edge. */
862/* sym(abc) -> ba* */
863/* */
864/* lnext: Find the next edge (counterclockwise) of a triangle. */
865/* lnext(abc) -> bca */
866/* */
867/* lprev: Find the previous edge (clockwise) of a triangle. */
868/* lprev(abc) -> cab */
869/* */
870/* onext: Find the next edge counterclockwise with the same origin. */
871/* onext(abc) -> ac* */
872/* */
873/* oprev: Find the next edge clockwise with the same origin. */
874/* oprev(abc) -> a*b */
875/* */
876/* dnext: Find the next edge counterclockwise with the same destination. */
877/* dnext(abc) -> *ba */
878/* */
879/* dprev: Find the next edge clockwise with the same destination. */
880/* dprev(abc) -> cb* */
881/* */
882/* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */
883/* rnext(abc) -> *a* */
884/* */
885/* rprev: Find the previous edge (clockwise) of the adjacent triangle. */
886/* rprev(abc) -> b** */
887/* */
888/* org: Origin dest: Destination apex: Apex */
889/* org(abc) -> a destT(abc) -> b apex(abc) -> c */
890/* */
891/* bond: Bond two triangles together at the resepective handles. */
892/* bond(abc, bad) */
893/* */
894/* */
895/* For subsegments: */
896/* */
897/* ssym: Reverse the orientation of a subsegment. */
898/* ssym(ab) -> ba */
899/* */
900/* spivot: Find adjoining subsegment with the same origin. */
901/* spivot(ab) -> a* */
902/* */
903/* snext: Find next subsegment in sequence. */
904/* snext(ab) -> b* */
905/* */
906/* sorg: Origin sdest: Destination */
907/* sorg(ab) -> a sdest(ab) -> b */
908/* */
909/* sbond: Bond two subsegments together at the respective origins. */
910/* sbond(ab, ac) */
911/* */
912/* */
913/* For interacting tetrahedra and subfacets: */
914/* */
915/* tspivot: Find a subsegment abutting a triangle. */
916/* tspivot(abc) -> ba */
917/* */
918/* stpivot: Find a triangle abutting a subsegment. */
919/* stpivot(ab) -> ba* */
920/* */
921/* tsbond: Bond a triangle to a subsegment. */
922/* tsbond(abc, ba) */
923/* */
924/*****************************************************************************/
925
926/********* Mesh manipulation primitives begin here *********/
929
930/* Fast lookup arrays to speed some of the mesh manipulation primitives. */
931
932int plus1mod3[3] = {1, 2, 0};
933int minus1mod3[3] = {2, 0, 1};
934
935/********* Primitives for triangles *********/
936/* */
937/* */
938
939/* decode() converts a pointer to an oriented triangle. The orientation is */
940/* extracted from the two least significant bits of the pointer. */
941
942#define decode(ptr, otri) \
943 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
944 (otri).tri = (triangle *) \
945 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
946
947/* encode() compresses an oriented triangle into a single pointer. It */
948/* relies on the assumption that all triangles are aligned to four-byte */
949/* boundaries, so the two least significant bits of (otri).tri are zero. */
950
951#define encode(otri) \
952 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
953
954/* The following handle manipulation primitives are all described by Guibas */
955/* and Stolfi. However, Guibas and Stolfi use an edge-based data */
956/* structure, whereas I use a triangle-based data structure. */
957
958/* sym() finds the abutting triangle, on the same edge. Note that the edge */
959/* direction is necessarily reversed, because the handle specified by an */
960/* oriented triangle is directed counterclockwise around the triangle. */
961
962#define sym(otri1, otri2) \
963 ptr = (otri1).tri[(otri1).orient]; \
964 decode(ptr, otri2);
965
966#define symself(otri) \
967 ptr = (otri).tri[(otri).orient]; \
968 decode(ptr, otri);
969
970/* lnext() finds the next edge (counterclockwise) of a triangle. */
971
972#define lnext(otri1, otri2) \
973 (otri2).tri = (otri1).tri; \
974 (otri2).orient = plus1mod3[(otri1).orient]
975
976#define lnextself(otri) \
977 (otri).orient = plus1mod3[(otri).orient]
978
979/* lprev() finds the previous edge (clockwise) of a triangle. */
980
981#define lprev(otri1, otri2) \
982 (otri2).tri = (otri1).tri; \
983 (otri2).orient = minus1mod3[(otri1).orient]
984
985#define lprevself(otri) \
986 (otri).orient = minus1mod3[(otri).orient]
987
988/* onext() spins counterclockwise around a vertex; that is, it finds the */
989/* next edge with the same origin in the counterclockwise direction. This */
990/* edge is part of a different triangle. */
991
992#define onext(otri1, otri2) \
993 lprev(otri1, otri2); \
994 symself(otri2);
995
996#define onextself(otri) \
997 lprevself(otri); \
998 symself(otri);
999
1000/* oprev() spins clockwise around a vertex; that is, it finds the next edge */
1001/* with the same origin in the clockwise direction. This edge is part of */
1002/* a different triangle. */
1003
1004#define oprev(otri1, otri2) \
1005 sym(otri1, otri2); \
1006 lnextself(otri2);
1007
1008#define oprevself(otri) \
1009 symself(otri); \
1010 lnextself(otri);
1011
1012/* dnext() spins counterclockwise around a vertex; that is, it finds the */
1013/* next edge with the same destination in the counterclockwise direction. */
1014/* This edge is part of a different triangle. */
1015
1016#define dnext(otri1, otri2) \
1017 sym(otri1, otri2); \
1018 lprevself(otri2);
1019
1020#define dnextself(otri) \
1021 symself(otri); \
1022 lprevself(otri);
1023
1024/* dprev() spins clockwise around a vertex; that is, it finds the next edge */
1025/* with the same destination in the clockwise direction. This edge is */
1026/* part of a different triangle. */
1027
1028#define dprev(otri1, otri2) \
1029 lnext(otri1, otri2); \
1030 symself(otri2);
1031
1032#define dprevself(otri) \
1033 lnextself(otri); \
1034 symself(otri);
1035
1036/* rnext() moves one edge counterclockwise about the adjacent triangle. */
1037/* (It's best understood by reading Guibas and Stolfi. It involves */
1038/* changing triangles twice.) */
1039
1040#define rnext(otri1, otri2) \
1041 sym(otri1, otri2); \
1042 lnextself(otri2); \
1043 symself(otri2);
1044
1045#define rnextself(otri) \
1046 symself(otri); \
1047 lnextself(otri); \
1048 symself(otri);
1049
1050/* rprev() moves one edge clockwise about the adjacent triangle. */
1051/* (It's best understood by reading Guibas and Stolfi. It involves */
1052/* changing triangles twice.) */
1053
1054#define rprev(otri1, otri2) \
1055 sym(otri1, otri2); \
1056 lprevself(otri2); \
1057 symself(otri2);
1058
1059#define rprevself(otri) \
1060 symself(otri); \
1061 lprevself(otri); \
1062 symself(otri);
1063
1064/* These primitives determine or set the origin, destination, or apex of a */
1065/* triangle. */
1066
1067#define org(otri, vertexptr) \
1068 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
1069
1070#define destT(otri, vertexptr) \
1071 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
1072
1073#define apex(otri, vertexptr) \
1074 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
1075
1076#define setorg(otri, vertexptr) \
1077 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1078
1079#define setdest(otri, vertexptr) \
1080 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1081
1082#define setapex(otri, vertexptr) \
1083 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
1084
1085/* Bond two triangles together. */
1086
1087#define bond(otri1, otri2) \
1088 (otri1).tri[(otri1).orient] = encode(otri2); \
1089 (otri2).tri[(otri2).orient] = encode(otri1)
1090
1091/* Dissolve a bond (from one side). Note that the other triangle will still */
1092/* think it's connected to this triangle. Usually, however, the other */
1093/* triangle is being deleted entirely, or bonded to another triangle, so */
1094/* it doesn't matter. */
1095
1096#define dissolve(otri) \
1097 (otri).tri[(otri).orient] = (triangle) m->dummytri
1098
1099/* Copy an oriented triangle. */
1100
1101#define otricopy(otri1, otri2) \
1102 (otri2).tri = (otri1).tri; \
1103 (otri2).orient = (otri1).orient
1104
1105/* Test for equality of oriented triangles. */
1106
1107#define otriequal(otri1, otri2) \
1108 (((otri1).tri == (otri2).tri) && \
1109 ((otri1).orient == (otri2).orient))
1110
1111/* Primitives to infect or cure a triangle with the virus. These rely on */
1112/* the assumption that all subsegments are aligned to four-byte boundaries.*/
1113
1114#define infect(otri) \
1115 (otri).tri[6] = (triangle) \
1116 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
1117
1118#define uninfect(otri) \
1119 (otri).tri[6] = (triangle) \
1120 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
1121
1122/* Test a triangle for viral infection. */
1123
1124#define infected(otri) \
1125 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
1126
1127/* Check or set a triangle's attributes. */
1128
1129#define elemattribute(otri, attnum) \
1130 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
1131
1132#define setelemattribute(otri, attnum, value) \
1133 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
1134
1135/* Check or set a triangle's maximum area bound. */
1136
1137#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
1138
1139#define setareabound(otri, value) \
1140 ((REAL *) (otri).tri)[m->areaboundindex] = value
1141
1142/* Check or set a triangle's deallocation. Its second pointer is set to */
1143/* NULL to indicate that it is not allocated. (Its first pointer is used */
1144/* for the stack of dead items.) Its fourth pointer (its first vertex) */
1145/* is set to NULL in case a `badtriang' structure points to it. */
1146
1147#define deadtri(tria) ((tria)[1] == (triangle) NULL)
1148
1149#define killtri(tria) \
1150 (tria)[1] = (triangle) NULL; \
1151 (tria)[3] = (triangle) NULL
1152
1153/********* Primitives for subsegments *********/
1154/* */
1155/* */
1156
1157/* sdecode() converts a pointer to an oriented subsegment. The orientation */
1158/* is extracted from the least significant bit of the pointer. The two */
1159/* least significant bits (one for orientation, one for viral infection) */
1160/* are masked out to produce the real pointer. */
1161
1162#define sdecode(sptr, osub) \
1163 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
1164 (osub).ss = (subseg *) \
1165 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
1166
1167/* sencode() compresses an oriented subsegment into a single pointer. It */
1168/* relies on the assumption that all subsegments are aligned to two-byte */
1169/* boundaries, so the least significant bit of (osub).ss is zero. */
1170
1171#define sencode(osub) \
1172 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
1173
1174/* ssym() toggles the orientation of a subsegment. */
1175
1176#define ssym(osub1, osub2) \
1177 (osub2).ss = (osub1).ss; \
1178 (osub2).ssorient = 1 - (osub1).ssorient
1179
1180#define ssymself(osub) \
1181 (osub).ssorient = 1 - (osub).ssorient
1182
1183/* spivot() finds the other subsegment (from the same segment) that shares */
1184/* the same origin. */
1185
1186#define spivot(osub1, osub2) \
1187 sptr = (osub1).ss[(osub1).ssorient]; \
1188 sdecode(sptr, osub2)
1189
1190#define spivotself(osub) \
1191 sptr = (osub).ss[(osub).ssorient]; \
1192 sdecode(sptr, osub)
1193
1194/* snext() finds the next subsegment (from the same segment) in sequence; */
1195/* one whose origin is the input subsegment's destination. */
1196
1197#define snext(osub1, osub2) \
1198 sptr = (osub1).ss[1 - (osub1).ssorient]; \
1199 sdecode(sptr, osub2)
1200
1201#define snextself(osub) \
1202 sptr = (osub).ss[1 - (osub).ssorient]; \
1203 sdecode(sptr, osub)
1204
1205/* These primitives determine or set the origin or destination of a */
1206/* subsegment or the segment that includes it. */
1207
1208#define sorg(osub, vertexptr) \
1209 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
1210
1211#define sdest(osub, vertexptr) \
1212 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
1213
1214#define setsorg(osub, vertexptr) \
1215 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
1216
1217#define setsdest(osub, vertexptr) \
1218 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
1219
1220#define segorg(osub, vertexptr) \
1221 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
1222
1223#define segdest(osub, vertexptr) \
1224 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
1225
1226#define setsegorg(osub, vertexptr) \
1227 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
1228
1229#define setsegdest(osub, vertexptr) \
1230 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
1231
1232/* These primitives read or set a boundary marker. Boundary markers are */
1233/* used to hold user-defined tags for setting boundary conditions in */
1234/* finite element solvers. */
1235
1236#define markT(osub) (* (int *) ((osub).ss + 8))
1237
1238#define setmark(osub, value) \
1239 * (int *) ((osub).ss + 8) = value
1240
1241/* Bond two subsegments together. */
1242
1243#define sbond(osub1, osub2) \
1244 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
1245 (osub2).ss[(osub2).ssorient] = sencode(osub1)
1246
1247/* Dissolve a subsegment bond (from one side). Note that the other */
1248/* subsegment will still think it's connected to this subsegment. */
1249
1250#define sdissolve(osub) \
1251 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
1252
1253/* Copy a subsegment. */
1254
1255#define subsegcopy(osub1, osub2) \
1256 (osub2).ss = (osub1).ss; \
1257 (osub2).ssorient = (osub1).ssorient
1258
1259/* Test for equality of subsegments. */
1260
1261#define subsegequal(osub1, osub2) \
1262 (((osub1).ss == (osub2).ss) && \
1263 ((osub1).ssorient == (osub2).ssorient))
1264
1265/* Check or set a subsegment's deallocation. Its second pointer is set to */
1266/* NULL to indicate that it is not allocated. (Its first pointer is used */
1267/* for the stack of dead items.) Its third pointer (its first vertex) */
1268/* is set to NULL in case a `badsubseg' structure points to it. */
1269
1270#define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
1271
1272#define killsubseg(sub) \
1273 (sub)[1] = (subseg) NULL; \
1274 (sub)[2] = (subseg) NULL
1275
1276/********* Primitives for interacting triangles and subsegments *********/
1277/* */
1278/* */
1279
1280/* tspivot() finds a subsegment abutting a triangle. */
1281
1282#define tspivot(otri, osub) \
1283 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
1284 sdecode(sptr, osub)
1285
1286/* stpivot() finds a triangle abutting a subsegment. It requires that the */
1287/* variable `ptr' of type `triangle' be defined. */
1288
1289#define stpivot(osub, otri) \
1290 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
1291 decode(ptr, otri)
1292
1293/* Bond a triangle to a subsegment. */
1294
1295#define tsbond(otri, osub) \
1296 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
1297 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
1298
1299/* Dissolve a bond (from the triangle side). */
1300
1301#define tsdissolve(otri) \
1302 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
1303
1304/* Dissolve a bond (from the subsegment side). */
1305
1306#define stdissolve(osub) \
1307 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
1308
1309/********* Primitives for vertices *********/
1310/* */
1311/* */
1312
1313#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
1314
1315#define setvertexmark(vx, value) \
1316 ((int *) (vx))[m->vertexmarkindex] = value
1317
1318#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
1319
1320#define setvertextype(vx, value) \
1321 ((int *) (vx))[m->vertexmarkindex + 1] = value
1322
1323#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
1324
1325#define setvertex2tri(vx, value) \
1326 ((triangle *) (vx))[m->vertex2triindex] = value
1327
1330/********* Mesh manipulation primitives end here *********/
1331
1332/********* User-defined triangle evaluation routine begins here *********/
1335
1336/*****************************************************************************/
1337/* */
1338/* triunsuitable() Determine if a triangle is unsuitable, and thus must */
1339/* be further refined. */
1340/* */
1341/* You may write your own procedure that decides whether or not a selected */
1342/* triangle is too big (and needs to be refined). There are two ways to do */
1343/* this. */
1344/* */
1345/* (1) Modify the procedure `triunsuitable' below, then recompile */
1346/* Triangle. */
1347/* */
1348/* (2) Define the symbol EXTERNAL_TEST (either by adding the definition */
1349/* to this file, or by using the appropriate compiler switch). This way, */
1350/* you can compile triangle.c separately from your test. Write your own */
1351/* `triunsuitable' procedure in a separate C file (using the same prototype */
1352/* as below). Compile it and link the object code with triangle.o. */
1353/* */
1354/* This procedure returns 1 if the triangle is too large and should be */
1355/* refined; 0 otherwise. */
1356/* */
1357/*****************************************************************************/
1358
1359#ifdef EXTERNAL_TEST
1360
1362
1363#else /* not EXTERNAL_TEST */
1364
1365#ifdef ANSI_DECLARATORS
1367#else /* not ANSI_DECLARATORS */
1369vertex triorg; /* The triangle's origin vertex. */
1370vertex tridest; /* The triangle's destination vertex. */
1371vertex triapex; /* The triangle's apex vertex. */
1372REAL area; /* The area of the triangle. */
1373#endif /* not ANSI_DECLARATORS */
1374
1375{
1376 REAL dxoa, dxda, dxod;
1380
1382 dyoa = triorg[1] - triapex[1];
1384 dyda = tridest[1] - triapex[1];
1386 dyod = triorg[1] - tridest[1];
1387 /* Find the squares of the lengths of the triangle's three edges. */
1388 oalen = dxoa * dxoa + dyoa * dyoa;
1389 dalen = dxda * dxda + dyda * dyda;
1390 odlen = dxod * dxod + dyod * dyod;
1391 /* Find the square of the length of the longest edge. */
1392 maxlen = (dalen > oalen) ? dalen : oalen;
1393 maxlen = (odlen > maxlen) ? odlen : maxlen;
1394
1395 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
1396 return 1;
1397 } else {
1398 return 0;
1399 }
1400}
1401
1402#endif /* not EXTERNAL_TEST */
1403
1406/********* User-defined triangle evaluation routine ends here *********/
1407
1408/********* Memory allocation and program exit wrappers begin here *********/
1411
1412#ifdef ANSI_DECLARATORS
1413void triexit(int status)
1414#else /* not ANSI_DECLARATORS */
1415void triexit(status)
1416int status;
1417#endif /* not ANSI_DECLARATORS */
1418
1419{
1420 exit(status);
1421}
1422
1423#ifdef ANSI_DECLARATORS
1424VOID *trimalloc(int size)
1425#else /* not ANSI_DECLARATORS */
1426VOID *trimalloc(size)
1427int size;
1428#endif /* not ANSI_DECLARATORS */
1429
1430{
1431 VOID *memptr;
1432
1433 memptr = (VOID *) malloc((unsigned int) size);
1434 if (memptr == (VOID *) NULL) {
1435 printf("Error: Out of memory.\n");
1436 triexit(1);
1437 }
1438 return(memptr);
1439}
1440
1441#ifdef ANSI_DECLARATORS
1442void trifree(void *memptr)
1443#else /* not ANSI_DECLARATORS */
1444void trifree(memptr)
1445VOID *memptr;
1446#endif /* not ANSI_DECLARATORS */
1447
1448{
1449 free(memptr);
1450}
1451
1454/********* Memory allocation and program exit wrappers end here *********/
1455
1456/********* User interaction routines begin here *********/
1459
1460/*****************************************************************************/
1461/* */
1462/* syntax() Print list of command line switches. */
1463/* */
1464/*****************************************************************************/
1465
1466#ifndef TRILIBRARY
1467
1469{
1470#ifdef CDT_ONLY
1471#ifdef REDUCED
1472 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
1473#else /* not REDUCED */
1474 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
1475#endif /* not REDUCED */
1476#else /* not CDT_ONLY */
1477#ifdef REDUCED
1478 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
1479#else /* not REDUCED */
1480 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
1481#endif /* not REDUCED */
1482#endif /* not CDT_ONLY */
1483
1484 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
1485#ifndef CDT_ONLY
1486 printf(" -r Refines a previously generated mesh.\n");
1487 printf(
1488 " -q Quality mesh generation. A minimum angle may be specified.\n");
1489 printf(" -a Applies a maximum triangle area constraint.\n");
1490 printf(" -u Applies a user-defined triangle constraint.\n");
1491#endif /* not CDT_ONLY */
1492 printf(
1493 " -A Applies attributes to identify triangles in certain regions.\n");
1494 printf(" -c Encloses the convex hull with segments.\n");
1495#ifndef CDT_ONLY
1496 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
1497#endif /* not CDT_ONLY */
1498/*
1499 printf(" -w Weighted Delaunay triangulation.\n");
1500 printf(" -W Regular triangulation (lower hull of a height field).\n");
1501*/
1502 printf(" -j Jettison unused vertices from output .node file.\n");
1503 printf(" -e Generates an edge list.\n");
1504 printf(" -v Generates a Voronoi diagram.\n");
1505 printf(" -n Generates a list of triangle neighbors.\n");
1506 printf(" -g Generates an .off file for Geomview.\n");
1507 printf(" -B Suppresses output of boundary information.\n");
1508 printf(" -P Suppresses output of .poly file.\n");
1509 printf(" -N Suppresses output of .node file.\n");
1510 printf(" -E Suppresses output of .ele file.\n");
1511 printf(" -I Suppresses mesh iteration numbers.\n");
1512 printf(" -O Ignores holes in .poly file.\n");
1513 printf(" -X Suppresses use of exact arithmetic.\n");
1514 printf(" -z Numbers all items starting from zero (rather than one).\n");
1515 printf(" -o2 Generates second-order subparametric elements.\n");
1516#ifndef CDT_ONLY
1517 printf(" -Y Suppresses boundary segment splitting.\n");
1518 printf(" -S Specifies maximum number of added Steiner points.\n");
1519#endif /* not CDT_ONLY */
1520#ifndef REDUCED
1521 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
1522 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
1523#endif /* not REDUCED */
1524 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
1525#ifndef REDUCED
1526#ifndef CDT_ONLY
1527 printf(
1528 " -s Force segments into mesh by splitting (instead of using CDT).\n");
1529#endif /* not CDT_ONLY */
1530 printf(" -C Check consistency of final mesh.\n");
1531#endif /* not REDUCED */
1532 printf(" -Q Quiet: No terminal output except errors.\n");
1533 printf(" -V Verbose: Detailed information on what I'm doing.\n");
1534 printf(" -h Help: Detailed instructions for Triangle.\n");
1535 triexit(0);
1536}
1537
1538#endif /* not TRILIBRARY */
1539
1540/*****************************************************************************/
1541/* */
1542/* info() Print out complete instructions. */
1543/* */
1544/*****************************************************************************/
1545
1546#ifndef TRILIBRARY
1547
1548void info()
1549{
1550 printf("Triangle\n");
1551 printf(
1552"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
1553 printf("Version 1.6\n\n");
1554 printf(
1555 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
1556 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
1557 printf(
1558"Created as part of the Quake project (tools for earthquake simulation).\n");
1559 printf(
1560"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
1561 printf("There is no warranty whatsoever. Use at your own risk.\n");
1562#ifdef SINGLE
1563 printf("This executable is compiled for single precision arithmetic.\n\n\n");
1564#else /* not SINGLE */
1565 printf("This executable is compiled for double precision arithmetic.\n\n\n");
1566#endif /* not SINGLE */
1567 printf(
1568"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
1569 printf(
1570"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
1571 printf(
1572"high-quality triangular meshes. The latter can be generated with no small\n"
1573);
1574 printf(
1575"or large angles, and are thus suitable for finite element analysis. If no\n"
1576);
1577 printf(
1578"command line switch is specified, your .node input file is read, and the\n");
1579 printf(
1580"Delaunay triangulation is returned in .node and .ele output files. The\n");
1581 printf("command syntax is:\n\n");
1582 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
1583 printf(
1584"Underscores indicate that numbers may optionally follow certain switches.\n");
1585 printf(
1586"Do not leave any space between a switch and its numeric parameter.\n");
1587 printf(
1588"input_file must be a file with extension .node, or extension .poly if the\n");
1589 printf(
1590"-p switch is used. If -r is used, you must supply .node and .ele files,\n");
1591 printf(
1592"and possibly a .poly file and an .area file as well. The formats of these\n"
1593);
1594 printf("files are described below.\n\n");
1595 printf("Command Line Switches:\n\n");
1596 printf(
1597" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
1598);
1599 printf(
1600" vertices, segments, holes, regional attributes, and regional area\n");
1601 printf(
1602" constraints. Generates a constrained Delaunay triangulation (CDT)\n"
1603);
1604 printf(
1605" fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
1606 printf(
1607" constrained Delaunay triangulation (CCDT). If you want a truly\n");
1608 printf(
1609" Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
1610 printf(
1611" well. When -p is not used, Triangle reads a .node file by default.\n"
1612);
1613 printf(
1614" -r Refines a previously generated mesh. The mesh is read from a .node\n"
1615);
1616 printf(
1617" file and an .ele file. If -p is also used, a .poly file is read\n");
1618 printf(
1619" and used to constrain segments in the mesh. If -a is also used\n");
1620 printf(
1621" (with no number following), an .area file is read and used to\n");
1622 printf(
1623" impose area constraints on the mesh. Further details on refinement\n"
1624);
1625 printf(" appear below.\n");
1626 printf(
1627" -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
1628 printf(
1629" Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
1630);
1631 printf(
1632" ensure that all angles are between 20 and 140 degrees. An\n");
1633 printf(
1634" alternative bound on the minimum angle, replacing 20 degrees, may\n");
1635 printf(
1636" be specified after the `q'. The specified angle may include a\n");
1637 printf(
1638" decimal point, but not exponential notation. Note that a bound of\n"
1639);
1640 printf(
1641" theta degrees on the smallest angle also implies a bound of\n");
1642 printf(
1643" (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
1644);
1645 printf(
1646" degrees or smaller, Triangle is mathematically guaranteed to\n");
1647 printf(
1648" terminate (assuming infinite precision arithmetic--Triangle may\n");
1649 printf(
1650" fail to terminate if you run out of precision). In practice,\n");
1651 printf(
1652" Triangle often succeeds for minimum angles up to 34 degrees. For\n");
1653 printf(
1654" some meshes, however, you might need to reduce the minimum angle to\n"
1655);
1656 printf(
1657" avoid problems associated with insufficient floating-point\n");
1658 printf(" precision.\n");
1659 printf(
1660" -a Imposes a maximum triangle area. If a number follows the `a', no\n");
1661 printf(
1662" triangle is generated whose area is larger than that number. If no\n"
1663);
1664 printf(
1665" number is specified, an .area file (if -r is used) or .poly file\n");
1666 printf(
1667" (if -r is not used) specifies a set of maximum area constraints.\n");
1668 printf(
1669" An .area file contains a separate area constraint for each\n");
1670 printf(
1671" triangle, and is useful for refining a finite element mesh based on\n"
1672);
1673 printf(
1674" a posteriori error estimates. A .poly file can optionally contain\n"
1675);
1676 printf(
1677" an area constraint for each segment-bounded region, thereby\n");
1678 printf(
1679" controlling triangle densities in a first triangulation of a PSLG.\n"
1680);
1681 printf(
1682" You can impose both a fixed area constraint and a varying area\n");
1683 printf(
1684" constraint by invoking the -a switch twice, once with and once\n");
1685 printf(
1686" without a number following. Each area specified may include a\n");
1687 printf(" decimal point.\n");
1688 printf(
1689" -u Imposes a user-defined constraint on triangle size. There are two\n"
1690);
1691 printf(
1692" ways to use this feature. One is to edit the triunsuitable()\n");
1693 printf(
1694" procedure in triangle.c to encode any constraint you like, then\n");
1695 printf(
1696" recompile Triangle. The other is to compile triangle.c with the\n");
1697 printf(
1698" EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
1699 printf(
1700" link Triangle with a separate object file that implements\n");
1701 printf(
1702" triunsuitable(). In either case, the -u switch causes the user-\n");
1703 printf(" defined test to be applied to every triangle.\n");
1704 printf(
1705" -A Assigns an additional floating-point attribute to each triangle\n");
1706 printf(
1707" that identifies what segment-bounded region each triangle belongs\n");
1708 printf(
1709" to. Attributes are assigned to regions by the .poly file. If a\n");
1710 printf(
1711" region is not explicitly marked by the .poly file, triangles in\n");
1712 printf(
1713" that region are assigned an attribute of zero. The -A switch has\n");
1714 printf(
1715" an effect only when the -p switch is used and the -r switch is not.\n"
1716);
1717 printf(
1718" -c Creates segments on the convex hull of the triangulation. If you\n");
1719 printf(
1720" are triangulating a vertex set, this switch causes a .poly file to\n"
1721);
1722 printf(
1723" be written, containing all edges of the convex hull. If you are\n");
1724 printf(
1725" triangulating a PSLG, this switch specifies that the whole convex\n");
1726 printf(
1727" hull of the PSLG should be triangulated, regardless of what\n");
1728 printf(
1729" segments the PSLG has. If you do not use this switch when\n");
1730 printf(
1731" triangulating a PSLG, Triangle assumes that you have identified the\n"
1732);
1733 printf(
1734" region to be triangulated by surrounding it with segments of the\n");
1735 printf(
1736" input PSLG. Beware: if you are not careful, this switch can cause\n"
1737);
1738 printf(
1739" the introduction of an extremely thin angle between a PSLG segment\n"
1740);
1741 printf(
1742" and a convex hull segment, which can cause overrefinement (and\n");
1743 printf(
1744" possibly failure if Triangle runs out of precision). If you are\n");
1745 printf(
1746" refining a mesh, the -c switch works differently: it causes a\n");
1747 printf(
1748" .poly file to be written containing the boundary edges of the mesh\n"
1749);
1750 printf(" (useful if no .poly file was read).\n");
1751 printf(
1752" -D Conforming Delaunay triangulation: use this switch if you want to\n"
1753);
1754 printf(
1755" ensure that all the triangles in the mesh are Delaunay, and not\n");
1756 printf(
1757" merely constrained Delaunay; or if you want to ensure that all the\n"
1758);
1759 printf(
1760" Voronoi vertices lie within the triangulation. (Some finite volume\n"
1761);
1762 printf(
1763" methods have this requirement.) This switch invokes Ruppert's\n");
1764 printf(
1765" original algorithm, which splits every subsegment whose diametral\n");
1766 printf(
1767" circle is encroached. It usually increases the number of vertices\n"
1768);
1769 printf(" and triangles.\n");
1770 printf(
1771" -j Jettisons vertices that are not part of the final triangulation\n");
1772 printf(
1773" from the output .node file. By default, Triangle copies all\n");
1774 printf(
1775" vertices in the input .node file to the output .node file, in the\n");
1776 printf(
1777" same order, so their indices do not change. The -j switch prevents\n"
1778);
1779 printf(
1780" duplicated input vertices, or vertices `eaten' by holes, from\n");
1781 printf(
1782" appearing in the output .node file. Thus, if two input vertices\n");
1783 printf(
1784" have exactly the same coordinates, only the first appears in the\n");
1785 printf(
1786" output. If any vertices are jettisoned, the vertex numbering in\n");
1787 printf(
1788" the output .node file differs from that of the input .node file.\n");
1789 printf(
1790" -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
1791 printf(
1792" -v Outputs the Voronoi diagram associated with the triangulation.\n");
1793 printf(
1794" Does not attempt to detect degeneracies, so some Voronoi vertices\n");
1795 printf(
1796" may be duplicated. See the discussion of Voronoi diagrams below.\n");
1797 printf(
1798" -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
1799 printf(" triangle.\n");
1800 printf(
1801" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
1802);
1803 printf(" viewing with the Geometry Center's Geomview package.\n");
1804 printf(
1805" -B No boundary markers in the output .node, .poly, and .edge output\n");
1806 printf(
1807" files. See the detailed discussion of boundary markers below.\n");
1808 printf(
1809" -P No output .poly file. Saves disk space, but you lose the ability\n");
1810 printf(
1811" to maintain constraining segments on later refinements of the mesh.\n"
1812);
1813 printf(" -N No output .node file.\n");
1814 printf(" -E No output .ele file.\n");
1815 printf(
1816" -I No iteration numbers. Suppresses the output of .node and .poly\n");
1817 printf(
1818" files, so your input files won't be overwritten. (If your input is\n"
1819);
1820 printf(
1821" a .poly file only, a .node file is written.) Cannot be used with\n");
1822 printf(
1823" the -r switch, because that would overwrite your input .ele file.\n");
1824 printf(
1825" Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
1826 printf(
1827" using a .node file for input, because no .node file is written, so\n"
1828);
1829 printf(" there is no record of any added Steiner points.\n");
1830 printf(" -O No holes. Ignores the holes in the .poly file.\n");
1831 printf(
1832" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
1833);
1834 printf(
1835" arithmetic for certain tests if it thinks the inexact tests are not\n"
1836);
1837 printf(
1838" accurate enough. Exact arithmetic ensures the robustness of the\n");
1839 printf(
1840" triangulation algorithms, despite floating-point roundoff error.\n");
1841 printf(
1842" Disabling exact arithmetic with the -X switch causes a small\n");
1843 printf(
1844" improvement in speed and creates the possibility that Triangle will\n"
1845);
1846 printf(" fail to produce a valid mesh. Not recommended.\n");
1847 printf(
1848" -z Numbers all items starting from zero (rather than one). Note that\n"
1849);
1850 printf(
1851" this switch is normally overridden by the value used to number the\n"
1852);
1853 printf(
1854" first vertex of the input .node or .poly file. However, this\n");
1855 printf(
1856" switch is useful when calling Triangle from another program.\n");
1857 printf(
1858" -o2 Generates second-order subparametric elements with six nodes each.\n"
1859);
1860 printf(
1861" -Y No new vertices on the boundary. This switch is useful when the\n");
1862 printf(
1863" mesh boundary must be preserved so that it conforms to some\n");
1864 printf(
1865" adjacent mesh. Be forewarned that you will probably sacrifice much\n"
1866);
1867 printf(
1868" of the quality of the mesh; Triangle will try, but the resulting\n");
1869 printf(
1870" mesh may contain poorly shaped triangles. Works well if all the\n");
1871 printf(
1872" boundary vertices are closely spaced. Specify this switch twice\n");
1873 printf(
1874" (`-YY') to prevent all segment splitting, including internal\n");
1875 printf(" boundaries.\n");
1876 printf(
1877" -S Specifies the maximum number of Steiner points (vertices that are\n");
1878 printf(
1879" not in the input, but are added to meet the constraints on minimum\n"
1880);
1881 printf(
1882" angle and maximum area). The default is to allow an unlimited\n");
1883 printf(
1884" number. If you specify this switch with no number after it,\n");
1885 printf(
1886" the limit is set to zero. Triangle always adds vertices at segment\n"
1887);
1888 printf(
1889" intersections, even if it needs to use more vertices than the limit\n"
1890);
1891 printf(
1892" you set. When Triangle inserts segments by splitting (-s), it\n");
1893 printf(
1894" always adds enough vertices to ensure that all the segments of the\n"
1895);
1896 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
1897 printf(
1898" -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
1899 printf(
1900" construct a Delaunay triangulation. Try it if the divide-and-\n");
1901 printf(" conquer algorithm fails.\n");
1902 printf(
1903" -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
1904 printf(
1905" triangulation. Warning: does not use exact arithmetic for all\n");
1906 printf(" calculations. An exact result is not guaranteed.\n");
1907 printf(
1908" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
1909 printf(
1910" default, Triangle alternates between vertical and horizontal cuts,\n"
1911);
1912 printf(
1913" which usually improve the speed except with vertex sets that are\n");
1914 printf(
1915" small or short and wide. This switch is primarily of theoretical\n");
1916 printf(" interest.\n");
1917 printf(
1918" -s Specifies that segments should be forced into the triangulation by\n"
1919);
1920 printf(
1921" recursively splitting them at their midpoints, rather than by\n");
1922 printf(
1923" generating a constrained Delaunay triangulation. Segment splitting\n"
1924);
1925 printf(
1926" is true to Ruppert's original algorithm, but can create needlessly\n"
1927);
1928 printf(
1929" small triangles. This switch is primarily of theoretical interest.\n"
1930);
1931 printf(
1932" -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
1933);
1934 printf(
1935" checking, even if the -X switch is used. Useful if you suspect\n");
1936 printf(" Triangle is buggy.\n");
1937 printf(
1938" -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
1939 printf(" unless an error occurs.\n");
1940 printf(
1941" -V Verbose: Gives detailed information about what Triangle is doing.\n"
1942);
1943 printf(
1944" Add more `V's for increasing amount of detail. `-V' is most\n");
1945 printf(
1946" useful; itgives information on algorithmic progress and much more\n");
1947 printf(
1948" detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
1949 printf(
1950" prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
1951);
1952 printf(" information only a debugger could love.\n");
1953 printf(" -h Help: Displays these instructions.\n");
1954 printf("\n");
1955 printf("Definitions:\n");
1956 printf("\n");
1957 printf(
1958" A Delaunay triangulation of a vertex set is a triangulation whose\n");
1959 printf(
1960" vertices are the vertex set, that covers the convex hull of the vertex\n");
1961 printf(
1962" set. A Delaunay triangulation has the property that no vertex lies\n");
1963 printf(
1964" inside the circumscribing circle (circle that passes through all three\n");
1965 printf(" vertices) of any triangle in the triangulation.\n\n");
1966 printf(
1967" A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
1968 printf(
1969" polygonal cells (some of which may be unbounded, meaning infinitely\n");
1970 printf(
1971" large), where each cell is the set of points in the plane that are closer\n"
1972);
1973 printf(
1974" to some input vertex than to any other input vertex. The Voronoi diagram\n"
1975);
1976 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
1977 printf(
1978" A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
1979 printf(
1980" Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
1981);
1982 printf(
1983" Segments may intersect each other only at their endpoints. The file\n");
1984 printf(" format for PSLGs (.poly files) is described below.\n\n");
1985 printf(
1986" A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
1987 printf(
1988" Delaunay triangulation, but each PSLG segment is present as a single edge\n"
1989);
1990 printf(
1991" of the CDT. (A constrained Delaunay triangulation is not truly a\n");
1992 printf(
1993" Delaunay triangulation, because some of its triangles might not be\n");
1994 printf(
1995" Delaunay.) By definition, a CDT does not have any vertices other than\n");
1996 printf(
1997" those specified in the input PSLG. Depending on context, a CDT might\n");
1998 printf(
1999" cover the convex hull of the PSLG, or it might cover only a segment-\n");
2000 printf(" bounded region (e.g. a polygon).\n\n");
2001 printf(
2002" A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
2003);
2004 printf(
2005" each triangle is truly Delaunay, and each PSLG segment is represented by\n"
2006);
2007 printf(
2008" a linear contiguous sequence of edges of the triangulation. New vertices\n"
2009);
2010 printf(
2011" (not part of the PSLG) may appear, and each input segment may have been\n");
2012 printf(
2013" subdivided into shorter edges (subsegments) by these additional vertices.\n"
2014);
2015 printf(
2016" The new vertices are frequently necessary to maintain the Delaunay\n");
2017 printf(" property while ensuring that every segment is represented.\n\n");
2018 printf(
2019" A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
2020 printf(
2021" triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
2022 printf(" vertices may appear, and input segments may be subdivided into\n");
2023 printf(
2024" subsegments, but not to guarantee that segments are respected; rather, to\n"
2025);
2026 printf(
2027" improve the quality of the triangles. The high-quality meshes produced\n");
2028 printf(
2029" by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
2030 printf(" with the -D switch.\n\n");
2031 printf("File Formats:\n\n");
2032 printf(
2033" All files may contain comments prefixed by the character '#'. Vertices,\n"
2034);
2035 printf(
2036" triangles, edges, holes, and maximum area constraints must be numbered\n");
2037 printf(
2038" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
2039 printf(
2040" input files must be consistent; if the vertices are numbered from 1, so\n");
2041 printf(
2042" must be all other objects. Triangle automatically detects your choice\n");
2043 printf(
2044" while reading the .node (or .poly) file. (When calling Triangle from\n");
2045 printf(
2046" another program, use the -z switch if you wish to number objects from\n");
2047 printf(" zero.) Examples of these file formats are given below.\n\n");
2048 printf(" .node files:\n");
2049 printf(
2050" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2051);
2052 printf(
2053" <# of boundary markers (0 or 1)>\n"
2054);
2055 printf(
2056" Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2057 printf("\n");
2058 printf(
2059" The attributes, which are typically floating-point values of physical\n");
2060 printf(
2061" quantities (such as mass or conductivity) associated with the nodes of\n"
2062);
2063 printf(
2064" a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
2065);
2066 printf(
2067" -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
2068);
2069 printf(" has attributes assigned to it by linear interpolation.\n\n");
2070 printf(
2071" If the fourth entry of the first line is `1', the last column of the\n");
2072 printf(
2073" remainder of the file is assumed to contain boundary markers. Boundary\n"
2074);
2075 printf(
2076" markers are used to identify boundary vertices and vertices resting on\n"
2077);
2078 printf(
2079" PSLG segments; a complete description appears in a section below. The\n"
2080);
2081 printf(
2082" .node file produced by Triangle contains boundary markers in the last\n");
2083 printf(" column unless they are suppressed by the -B switch.\n\n");
2084 printf(" .ele files:\n");
2085 printf(
2086" First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
2087 printf(
2088" Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
2089 printf("\n");
2090 printf(
2091" Nodes are indices into the corresponding .node file. The first three\n");
2092 printf(
2093" nodes are the corner vertices, and are listed in counterclockwise order\n"
2094);
2095 printf(
2096" around each triangle. (The remaining nodes, if any, depend on the type\n"
2097);
2098 printf(" of finite element used.)\n\n");
2099 printf(
2100" The attributes are just like those of .node files. Because there is no\n"
2101);
2102 printf(
2103" simple mapping from input to output triangles, Triangle attempts to\n");
2104 printf(
2105" interpolate attributes, and may cause a lot of diffusion of attributes\n"
2106);
2107 printf(
2108" among nearby triangles as the triangulation is refined. Attributes do\n"
2109);
2110 printf(" not diffuse across segments, so attributes used to identify\n");
2111 printf(" segment-bounded regions remain intact.\n\n");
2112 printf(
2113" In .ele files produced by Triangle, each triangular element has three\n");
2114 printf(
2115" nodes (vertices) unless the -o2 switch is used, in which case\n");
2116 printf(
2117" subparametric quadratic elements with six nodes each are generated.\n");
2118 printf(
2119" The first three nodes are the corners in counterclockwise order, and\n");
2120 printf(
2121" the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
2122 printf(
2123" opposite the first, second, and third vertices, respectively.\n");
2124 printf("\n");
2125 printf(" .poly files:\n");
2126 printf(
2127" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2128);
2129 printf(
2130" <# of boundary markers (0 or 1)>\n"
2131);
2132 printf(
2133" Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2134 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
2135 printf(
2136" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
2137 printf(" One line: <# of holes>\n");
2138 printf(" Following lines: <hole #> <x> <y>\n");
2139 printf(
2140" Optional line: <# of regional attributes and/or area constraints>\n");
2141 printf(
2142" Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
2143 printf("\n");
2144 printf(
2145" A .poly file represents a PSLG, as well as some additional information.\n"
2146);
2147 printf(
2148" The first section lists all the vertices, and is identical to the\n");
2149 printf(
2150" format of .node files. <# of vertices> may be set to zero to indicate\n"
2151);
2152 printf(
2153" that the vertices are listed in a separate .node file; .poly files\n");
2154 printf(
2155" produced by Triangle always have this format. A vertex set represented\n"
2156);
2157 printf(
2158" this way has the advantage that it may easily be triangulated with or\n");
2159 printf(
2160" without segments (depending on whether the -p switch is invoked).\n");
2161 printf("\n");
2162 printf(
2163" The second section lists the segments. Segments are edges whose\n");
2164 printf(
2165" presence in the triangulation is enforced. (Depending on the choice of\n"
2166);
2167 printf(
2168" switches, segment might be subdivided into smaller edges). Each\n");
2169 printf(
2170" segment is specified by listing the indices of its two endpoints. This\n"
2171);
2172 printf(
2173" means that you must include its endpoints in the vertex list. Each\n");
2174 printf(" segment, like each point, may have a boundary marker.\n\n");
2175 printf(
2176" If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
2177);
2178 printf(
2179" Delaunay triangulation (CDT), in which each segment appears as a single\n"
2180);
2181 printf(
2182" edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
2183);
2184 printf(
2185" produces a conforming constrained Delaunay triangulation (CCDT), in\n");
2186 printf(
2187" which segments may be subdivided into smaller edges. If -D is\n");
2188 printf(
2189" selected, Triangle produces a conforming Delaunay triangulation, so\n");
2190 printf(
2191" that every triangle is Delaunay, and not just constrained Delaunay.\n");
2192 printf("\n");
2193 printf(
2194" The third section lists holes (and concavities, if -c is selected) in\n");
2195 printf(
2196" the triangulation. Holes are specified by identifying a point inside\n");
2197 printf(
2198" each hole. After the triangulation is formed, Triangle creates holes\n");
2199 printf(
2200" by eating triangles, spreading out from each hole point until its\n");
2201 printf(
2202" progress is blocked by segments in the PSLG. You must be careful to\n");
2203 printf(
2204" enclose each hole in segments, or your whole triangulation might be\n");
2205 printf(
2206" eaten away. If the two triangles abutting a segment are eaten, the\n");
2207 printf(
2208" segment itself is also eaten. Do not place a hole directly on a\n");
2209 printf(" segment; if you do, Triangle chooses one side of the segment\n");
2210 printf(" arbitrarily.\n\n");
2211 printf(
2212" The optional fourth section lists regional attributes (to be assigned\n");
2213 printf(
2214" to all triangles in a region) and regional constraints on the maximum\n");
2215 printf(
2216" triangle area. Triangle reads this section only if the -A switch is\n");
2217 printf(
2218" used or the -a switch is used without a number following it, and the -r\n"
2219);
2220 printf(
2221" switch is not used. Regional attributes and area constraints are\n");
2222 printf(
2223" propagated in the same manner as holes: you specify a point for each\n");
2224 printf(
2225" attribute and/or constraint, and the attribute and/or constraint\n");
2226 printf(
2227" affects the whole region (bounded by segments) containing the point.\n");
2228 printf(
2229" If two values are written on a line after the x and y coordinate, the\n");
2230 printf(
2231" first such value is assumed to be a regional attribute (but is only\n");
2232 printf(
2233" applied if the -A switch is selected), and the second value is assumed\n"
2234);
2235 printf(
2236" to be a regional area constraint (but is only applied if the -a switch\n"
2237);
2238 printf(
2239" is selected). You may specify just one value after the coordinates,\n");
2240 printf(
2241" which can serve as both an attribute and an area constraint, depending\n"
2242);
2243 printf(
2244" on the choice of switches. If you are using the -A and -a switches\n");
2245 printf(
2246" simultaneously and wish to assign an attribute to some region without\n");
2247 printf(" imposing an area constraint, use a negative maximum area.\n\n");
2248 printf(
2249" When a triangulation is created from a .poly file, you must either\n");
2250 printf(
2251" enclose the entire region to be triangulated in PSLG segments, or\n");
2252 printf(
2253" use the -c switch, which automatically creates extra segments that\n");
2254 printf(
2255" enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
2256);
2257 printf(
2258" Triangle eats all triangles that are not enclosed by segments; if you\n");
2259 printf(
2260" are not careful, your whole triangulation may be eaten away. If you do\n"
2261);
2262 printf(
2263" use the -c switch, you can still produce concavities by the appropriate\n"
2264);
2265 printf(
2266" placement of holes just inside the boundary of the convex hull.\n");
2267 printf("\n");
2268 printf(
2269" An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
2270 printf(
2271" upon segments (except, of course, the endpoints of each segment). You\n"
2272);
2273 printf(
2274" aren't required to make your .poly files ideal, but you should be aware\n"
2275);
2276 printf(
2277" of what can go wrong. Segment intersections are relatively safe--\n");
2278 printf(
2279" Triangle calculates the intersection points for you and adds them to\n");
2280 printf(
2281" the triangulation--as long as your machine's floating-point precision\n");
2282 printf(
2283" doesn't become a problem. You are tempting the fates if you have three\n"
2284);
2285 printf(
2286" segments that cross at the same location, and expect Triangle to figure\n"
2287);
2288 printf(
2289" out where the intersection point is. Thanks to floating-point roundoff\n"
2290);
2291 printf(
2292" error, Triangle will probably decide that the three segments intersect\n"
2293);
2294 printf(
2295" at three different points, and you will find a minuscule triangle in\n");
2296 printf(
2297" your output--unless Triangle tries to refine the tiny triangle, uses\n");
2298 printf(
2299" up the last bit of machine precision, and fails to terminate at all.\n");
2300 printf(
2301" You're better off putting the intersection point in the input files,\n");
2302 printf(
2303" and manually breaking up each segment into two. Similarly, if you\n");
2304 printf(
2305" place a vertex at the middle of a segment, and hope that Triangle will\n"
2306);
2307 printf(
2308" break up the segment at that vertex, you might get lucky. On the other\n"
2309);
2310 printf(
2311" hand, Triangle might decide that the vertex doesn't lie precisely on\n");
2312 printf(
2313" the segment, and you'll have a needle-sharp triangle in your output--or\n"
2314);
2315 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
2316 printf("\n");
2317 printf(
2318" When Triangle reads a .poly file, it also writes a .poly file, which\n");
2319 printf(
2320" includes all the subsegments--the edges that are parts of input\n");
2321 printf(
2322" segments. If the -c switch is used, the output .poly file also\n");
2323 printf(
2324" includes all of the edges on the convex hull. Hence, the output .poly\n"
2325);
2326 printf(
2327" file is useful for finding edges associated with input segments and for\n"
2328);
2329 printf(
2330" setting boundary conditions in finite element simulations. Moreover,\n");
2331 printf(
2332" you will need the output .poly file if you plan to refine the output\n");
2333 printf(
2334" mesh, and don't want segments to be missing in later triangulations.\n");
2335 printf("\n");
2336 printf(" .area files:\n");
2337 printf(" First line: <# of triangles>\n");
2338 printf(" Following lines: <triangle #> <maximum area>\n");
2339 printf("\n");
2340 printf(
2341" An .area file associates with each triangle a maximum area that is used\n"
2342);
2343 printf(
2344" for mesh refinement. As with other file formats, every triangle must\n");
2345 printf(
2346" be represented, and the triangles must be numbered consecutively. A\n");
2347 printf(
2348" triangle may be left unconstrained by assigning it a negative maximum\n");
2349 printf(" area.\n\n");
2350 printf(" .edge files:\n");
2351 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
2352 printf(
2353" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
2354 printf("\n");
2355 printf(
2356" Endpoints are indices into the corresponding .node file. Triangle can\n"
2357);
2358 printf(
2359" produce .edge files (use the -e switch), but cannot read them. The\n");
2360 printf(
2361" optional column of boundary markers is suppressed by the -B switch.\n");
2362 printf("\n");
2363 printf(
2364" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
2365 printf(
2366" infinite ray with only one endpoint. For these edges, a different\n");
2367 printf(" format is used:\n\n");
2368 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
2369 printf(
2370" The `direction' is a floating-point vector that indicates the direction\n"
2371);
2372 printf(" of the infinite ray.\n\n");
2373 printf(" .neigh files:\n");
2374 printf(
2375" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
2376);
2377 printf(
2378" Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
2379 printf("\n");
2380 printf(
2381" Neighbors are indices into the corresponding .ele file. An index of -1\n"
2382);
2383 printf(
2384" indicates no neighbor (because the triangle is on an exterior\n");
2385 printf(
2386" boundary). The first neighbor of triangle i is opposite the first\n");
2387 printf(" corner of triangle i, and so on.\n\n");
2388 printf(
2389" Triangle can produce .neigh files (use the -n switch), but cannot read\n"
2390);
2391 printf(" them.\n\n");
2392 printf("Boundary Markers:\n\n");
2393 printf(
2394" Boundary markers are tags used mainly to identify which output vertices\n");
2395 printf(
2396" and edges are associated with which PSLG segment, and to identify which\n");
2397 printf(
2398" vertices and edges occur on a boundary of the triangulation. A common\n");
2399 printf(
2400" use is to determine where boundary conditions should be applied to a\n");
2401 printf(
2402" finite element mesh. You can prevent boundary markers from being written\n"
2403);
2404 printf(" into files produced by Triangle by using the -B switch.\n\n");
2405 printf(
2406" The boundary marker associated with each segment in an output .poly file\n"
2407);
2408 printf(" and each edge in an output .edge file is chosen as follows:\n");
2409 printf(
2410" - If an output edge is part or all of a PSLG segment with a nonzero\n");
2411 printf(
2412" boundary marker, then the edge is assigned the same marker.\n");
2413 printf(
2414" - Otherwise, if the edge lies on a boundary of the triangulation\n");
2415 printf(
2416" (even the boundary of a hole), then the edge is assigned the marker\n");
2417 printf(" one (1).\n");
2418 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
2419 printf(
2420" The boundary marker associated with each vertex in an output .node file\n");
2421 printf(" is chosen as follows:\n");
2422 printf(
2423" - If a vertex is assigned a nonzero boundary marker in the input file,\n"
2424);
2425 printf(
2426" then it is assigned the same marker in the output .node file.\n");
2427 printf(
2428" - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
2429 printf(
2430" endpoint of the segment) with a nonzero boundary marker, then the\n");
2431 printf(
2432" vertex is assigned the same marker. If the vertex lies on several\n");
2433 printf(" such segments, one of the markers is chosen arbitrarily.\n");
2434 printf(
2435" - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
2436 printf(" then the vertex is assigned the marker one (1).\n");
2437 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
2438 printf("\n");
2439 printf(
2440" If you want Triangle to determine for you which vertices and edges are on\n"
2441);
2442 printf(
2443" the boundary, assign them the boundary marker zero (or use no markers at\n"
2444);
2445 printf(
2446" all) in your input files. In the output files, all boundary vertices,\n");
2447 printf(" edges, and segments will be assigned the value one.\n\n");
2448 printf("Triangulation Iteration Numbers:\n\n");
2449 printf(
2450" Because Triangle can read and refine its own triangulations, input\n");
2451 printf(
2452" and output files have iteration numbers. For instance, Triangle might\n");
2453 printf(
2454" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
2455 printf(
2456" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
2457 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
2458 printf(
2459" their iteration number is zero; hence, Triangle might read the file\n");
2460 printf(
2461" points.node, triangulate it, and produce the files points.1.node and\n");
2462 printf(" points.1.ele.\n\n");
2463 printf(
2464" Iteration numbers allow you to create a sequence of successively finer\n");
2465 printf(
2466" meshes suitable for multigrid methods. They also allow you to produce a\n"
2467);
2468 printf(
2469" sequence of meshes using error estimate-driven mesh refinement.\n");
2470 printf("\n");
2471 printf(
2472" If you're not using refinement or quality meshing, and you don't like\n");
2473 printf(
2474" iteration numbers, use the -I switch to disable them. This switch also\n");
2475 printf(
2476" disables output of .node and .poly files to prevent your input files from\n"
2477);
2478 printf(
2479" being overwritten. (If the input is a .poly file that contains its own\n");
2480 printf(
2481" points, a .node file is written. This can be quite convenient for\n");
2482 printf(" computing CDTs or quality meshes.)\n\n");
2483 printf("Examples of How to Use Triangle:\n\n");
2484 printf(
2485" `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
2486);
2487 printf(
2488" triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
2489 printf(
2490" to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
2491 printf(
2492" instead. (No additional .node file is needed, so none is written.)\n");
2493 printf("\n");
2494 printf(
2495" `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
2496 printf(
2497" object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
2498);
2499 printf(
2500" its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
2501);
2502 printf(
2503" The segments are copied to object.2.poly, and all edges are written to\n");
2504 printf(" object.2.edge.\n\n");
2505 printf(
2506" `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
2507);
2508 printf(
2509" object.node), generates a mesh whose angles are all between 31.5 and 117\n"
2510);
2511 printf(
2512" degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
2513);
2514 printf(
2515" mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
2516 printf(" into multiple subsegments; these are written to object.1.poly.\n");
2517 printf("\n");
2518 printf(
2519" Here is a sample file `box.poly' describing a square with a square hole:\n"
2520);
2521 printf("\n");
2522 printf(
2523" # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
2524);
2525 printf(" 8 2 0 1\n");
2526 printf(" # Outer box has these vertices:\n");
2527 printf(" 1 0 0 0\n");
2528 printf(" 2 0 3 0\n");
2529 printf(" 3 3 0 0\n");
2530 printf(" 4 3 3 33 # A special marker for this vertex.\n");
2531 printf(" # Inner square has these vertices:\n");
2532 printf(" 5 1 1 0\n");
2533 printf(" 6 1 2 0\n");
2534 printf(" 7 2 1 0\n");
2535 printf(" 8 2 2 0\n");
2536 printf(" # Five segments with boundary markers.\n");
2537 printf(" 5 1\n");
2538 printf(" 1 1 2 5 # Left side of outer box.\n");
2539 printf(" # Square hole has these segments:\n");
2540 printf(" 2 5 7 0\n");
2541 printf(" 3 7 8 0\n");
2542 printf(" 4 8 6 10\n");
2543 printf(" 5 6 5 0\n");
2544 printf(" # One hole in the middle of the inner square.\n");
2545 printf(" 1\n");
2546 printf(" 1 1.5 1.5\n");
2547 printf("\n");
2548 printf(
2549" Note that some segments are missing from the outer square, so you must\n");
2550 printf(
2551" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
2552);
2553 printf(
2554" file `box.1.node', with twelve vertices. The last four vertices were\n");
2555 printf(
2556" added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
2557 printf(
2558" from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
2559 printf(
2560" other vertices but 4 have been marked to indicate that they lie on a\n");
2561 printf(" boundary.\n\n");
2562 printf(" 12 2 0 1\n");
2563 printf(" 1 0 0 5\n");
2564 printf(" 2 0 3 5\n");
2565 printf(" 3 3 0 1\n");
2566 printf(" 4 3 3 33\n");
2567 printf(" 5 1 1 1\n");
2568 printf(" 6 1 2 10\n");
2569 printf(" 7 2 1 1\n");
2570 printf(" 8 2 2 10\n");
2571 printf(" 9 0 1.5 5\n");
2572 printf(" 10 1.5 0 1\n");
2573 printf(" 11 3 1.5 1\n");
2574 printf(" 12 1.5 3 1\n");
2575 printf(" # Generated by triangle -pqc box.poly\n");
2576 printf("\n");
2577 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
2578 printf("\n");
2579 printf(" 12 3 0\n");
2580 printf(" 1 5 6 9\n");
2581 printf(" 2 10 3 7\n");
2582 printf(" 3 6 8 12\n");
2583 printf(" 4 9 1 5\n");
2584 printf(" 5 6 2 9\n");
2585 printf(" 6 7 3 11\n");
2586 printf(" 7 11 4 8\n");
2587 printf(" 8 7 5 10\n");
2588 printf(" 9 12 2 6\n");
2589 printf(" 10 8 7 11\n");
2590 printf(" 11 5 1 10\n");
2591 printf(" 12 8 4 12\n");
2592 printf(" # Generated by triangle -pqc box.poly\n\n");
2593 printf(
2594" Here is the output file `box.1.poly'. Note that segments have been added\n"
2595);
2596 printf(
2597" to represent the convex hull, and some segments have been subdivided by\n");
2598 printf(
2599" newly added vertices. Note also that <# of vertices> is set to zero to\n");
2600 printf(" indicate that the vertices should be read from the .node file.\n");
2601 printf("\n");
2602 printf(" 0 2 0 1\n");
2603 printf(" 12 1\n");
2604 printf(" 1 1 9 5\n");
2605 printf(" 2 5 7 1\n");
2606 printf(" 3 8 7 1\n");
2607 printf(" 4 6 8 10\n");
2608 printf(" 5 5 6 1\n");
2609 printf(" 6 3 10 1\n");
2610 printf(" 7 4 11 1\n");
2611 printf(" 8 2 12 1\n");
2612 printf(" 9 9 2 5\n");
2613 printf(" 10 10 1 1\n");
2614 printf(" 11 11 3 1\n");
2615 printf(" 12 12 4 1\n");
2616 printf(" 1\n");
2617 printf(" 1 1.5 1.5\n");
2618 printf(" # Generated by triangle -pqc box.poly\n");
2619 printf("\n");
2620 printf("Refinement and Area Constraints:\n");
2621 printf("\n");
2622 printf(
2623" The -r switch causes a mesh (.node and .ele files) to be read and\n");
2624 printf(
2625" refined. If the -p switch is also used, a .poly file is read and used to\n"
2626);
2627 printf(
2628" specify edges that are constrained and cannot be eliminated (although\n");
2629 printf(
2630" they can be subdivided into smaller edges) by the refinement process.\n");
2631 printf("\n");
2632 printf(
2633" When you refine a mesh, you generally want to impose tighter constraints.\n"
2634);
2635 printf(
2636" One way to accomplish this is to use -q with a larger angle, or -a\n");
2637 printf(
2638" followed by a smaller area than you used to generate the mesh you are\n");
2639 printf(
2640" refining. Another way to do this is to create an .area file, which\n");
2641 printf(
2642" specifies a maximum area for each triangle, and use the -a switch\n");
2643 printf(
2644" (without a number following). Each triangle's area constraint is applied\n"
2645);
2646 printf(
2647" to that triangle. Area constraints tend to diffuse as the mesh is\n");
2648 printf(
2649" refined, so if there are large variations in area constraint between\n");
2650 printf(
2651" adjacent triangles, you may not get the results you want. In that case,\n"
2652);
2653 printf(
2654" consider instead using the -u switch and writing a C procedure that\n");
2655 printf(" determines which triangles are too large.\n\n");
2656 printf(
2657" If you are refining a mesh composed of linear (three-node) elements, the\n"
2658);
2659 printf(
2660" output mesh contains all the nodes present in the input mesh, in the same\n"
2661);
2662 printf(
2663" order, with new nodes added at the end of the .node file. However, the\n");
2664 printf(
2665" refinement is not hierarchical: there is no guarantee that each output\n");
2666 printf(
2667" element is contained in a single input element. Often, an output element\n"
2668);
2669 printf(
2670" can overlap two or three input elements, and some input edges are not\n");
2671 printf(
2672" present in the output mesh. Hence, a sequence of refined meshes forms a\n"
2673);
2674 printf(
2675" hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
2676 printf(
2677" mesh of higher-order elements, the hierarchical property applies only to\n"
2678);
2679 printf(
2680" the nodes at the corners of an element; the midpoint nodes on each edge\n");
2681 printf(" are discarded before the mesh is refined.\n\n");
2682 printf(
2683" Maximum area constraints in .poly files operate differently from those in\n"
2684);
2685 printf(
2686" .area files. A maximum area in a .poly file applies to the whole\n");
2687 printf(
2688" (segment-bounded) region in which a point falls, whereas a maximum area\n");
2689 printf(
2690" in an .area file applies to only one triangle. Area constraints in .poly\n"
2691);
2692 printf(
2693" files are used only when a mesh is first generated, whereas area\n");
2694 printf(
2695" constraints in .area files are used only to refine an existing mesh, and\n"
2696);
2697 printf(
2698" are typically based on a posteriori error estimates resulting from a\n");
2699 printf(" finite element simulation on that mesh.\n\n");
2700 printf(
2701" `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
2702 printf(
2703" refines the triangulation to enforce a 25 degree minimum angle, and then\n"
2704);
2705 printf(
2706" writes the refined triangulation to object.2.node and object.2.ele.\n");
2707 printf("\n");
2708 printf(
2709" `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
2710);
2711 printf(
2712" After reconstructing the mesh and its subsegments, Triangle refines the\n");
2713 printf(
2714" mesh so that no triangle has area greater than 6.2, and furthermore the\n");
2715 printf(
2716" triangles satisfy the maximum area constraints in z.3.area. No angle\n");
2717 printf(
2718" bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
2719);
2720 printf(" z.4.poly.\n\n");
2721 printf(
2722" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
2723 printf(
2724" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
2725 printf(" suitable for multigrid.\n\n");
2726 printf("Convex Hulls and Mesh Boundaries:\n\n");
2727 printf(
2728" If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
2729 printf(
2730" hull as a by-product in the output .poly file if you use the -c switch.\n");
2731 printf(
2732" There are faster algorithms for finding a two-dimensional convex hull\n");
2733 printf(" than triangulation, of course, but this one comes for free.\n\n");
2734 printf(
2735" If the input is an unconstrained mesh (you are using the -r switch but\n");
2736 printf(
2737" not the -p switch), Triangle produces a list of its boundary edges\n");
2738 printf(
2739" (including hole boundaries) as a by-product when you use the -c switch.\n");
2740 printf(
2741" If you also use the -p switch, the output .poly file contains all the\n");
2742 printf(" segments from the input .poly file as well.\n\n");
2743 printf("Voronoi Diagrams:\n\n");
2744 printf(
2745" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
2746 printf(
2747" .v.edge. For example, `triangle -v points' reads points.node, produces\n");
2748 printf(
2749" its Delaunay triangulation in points.1.node and points.1.ele, and\n");
2750 printf(
2751" produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
2752);
2753 printf(
2754" .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
2755 printf(
2756" file contains a list of all Voronoi edges, some of which may be infinite\n"
2757);
2758 printf(
2759" rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
2760 printf(" vertices through Triangle, if so desired.)\n\n");
2761 printf(
2762" This implementation does not use exact arithmetic to compute the Voronoi\n"
2763);
2764 printf(
2765" vertices, and does not check whether neighboring vertices are identical.\n"
2766);
2767 printf(
2768" Be forewarned that if the Delaunay triangulation is degenerate or\n");
2769 printf(
2770" near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
2771 printf(" crossing edges.\n\n");
2772 printf(
2773" The result is a valid Voronoi diagram only if Triangle's output is a true\n"
2774);
2775 printf(
2776" Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
2777 printf(
2778" may contain crossing edges and other pathology) if the output is a CDT or\n"
2779);
2780 printf(
2781" CCDT, or if it has holes or concavities. If the triangulated domain is\n");
2782 printf(
2783" convex and has no holes, you can use -D switch to force Triangle to\n");
2784 printf(
2785" construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
2786 printf(" Voronoi diagram will be valid.\n\n");
2787 printf("Mesh Topology:\n\n");
2788 printf(
2789" You may wish to know which triangles are adjacent to a certain Delaunay\n");
2790 printf(
2791" edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
2792 printf(
2793" Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
2794 printf(
2795" each other. All of this information can be found by cross-referencing\n");
2796 printf(
2797" output files with the recollection that the Delaunay triangulation and\n");
2798 printf(" the Voronoi diagram are planar duals.\n\n");
2799 printf(
2800" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
2801 printf(
2802" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
2803 printf(
2804" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
2805 printf(
2806" vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
2807 printf(" of vertex k of the corresponding .node file.\n\n");
2808 printf(
2809" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
2810 printf(
2811" vertices of the corresponding Voronoi edge. If the endpoints of a\n");
2812 printf(
2813" Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
2814);
2815 printf(
2816" and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
2817);
2818 printf(
2819" respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
2820);
2821 printf(
2822" at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
2823);
2824 printf(
2825" a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
2826);
2827 printf(
2828" adjoin the right and left sides of the corresponding Voronoi edge,\n");
2829 printf(
2830" respectively. To find which Voronoi cells are adjacent to each other,\n");
2831 printf(" just read the list of Delaunay edges.\n\n");
2832 printf(
2833" Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
2834);
2835 printf(
2836" but you can reconstructed it straightforwardly. For instance, to find\n");
2837 printf(
2838" all the edges of Voronoi cell 1, search the output .edge file for every\n");
2839 printf(
2840" edge that has input vertex 1 as an endpoint. The corresponding dual\n");
2841 printf(
2842" edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
2843 printf("\n");
2844 printf(
2845" For each Voronoi vertex, the .neigh file gives a list of the three\n");
2846 printf(
2847" Voronoi vertices attached to it. You might find this more convenient\n");
2848 printf(" than the .v.edge file.\n\n");
2849 printf("Quadratic Elements:\n\n");
2850 printf(
2851" Triangle generates meshes with subparametric quadratic elements if the\n");
2852 printf(
2853" -o2 switch is specified. Quadratic elements have six nodes per element,\n"
2854);
2855 printf(
2856" rather than three. `Subparametric' means that the edges of the triangles\n"
2857);
2858 printf(
2859" are always straight, so that subparametric quadratic elements are\n");
2860 printf(
2861" geometrically identical to linear elements, even though they can be used\n"
2862);
2863 printf(
2864" with quadratic interpolating functions. The three extra nodes of an\n");
2865 printf(
2866" element fall at the midpoints of the three edges, with the fourth, fifth,\n"
2867);
2868 printf(
2869" and sixth nodes appearing opposite the first, second, and third corners\n");
2870 printf(" respectively.\n\n");
2871 printf("Domains with Small Angles:\n\n");
2872 printf(
2873" If two input segments adjoin each other at a small angle, clearly the -q\n"
2874);
2875 printf(
2876" switch cannot remove the small angle. Moreover, Triangle may have no\n");
2877 printf(
2878" choice but to generate additional triangles whose smallest angles are\n");
2879 printf(
2880" smaller than the specified bound. However, these triangles only appear\n");
2881 printf(
2882" between input segments separated by small angles. Moreover, if you\n");
2883 printf(
2884" request a minimum angle of theta degrees, Triangle will generally produce\n"
2885);
2886 printf(
2887" no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
2888);
2889 printf(" the minimum angle.\n\n");
2890 printf("Statistics:\n\n");
2891 printf(
2892" After generating a mesh, Triangle prints a count of entities in the\n");
2893 printf(
2894" output mesh, including the number of vertices, triangles, edges, exterior\n"
2895);
2896 printf(
2897" boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
2898 printf(
2899" including hole boundaries), interior boundary edges (i.e. subsegments of\n"
2900);
2901 printf(
2902" input segments not on the boundary), and total subsegments. If you've\n");
2903 printf(
2904" forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
2905);
2906 printf(
2907" with the -rNEP switches to read the mesh and print the statistics without\n"
2908);
2909 printf(
2910" writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
2911 printf("\n");
2912 printf(
2913" The -V switch produces extended statistics, including a rough estimate\n");
2914 printf(
2915" of memory use, the number of calls to geometric predicates, and\n");
2916 printf(
2917" histograms of the angles and the aspect ratios of the triangles in the\n");
2918 printf(" mesh.\n\n");
2919 printf("Exact Arithmetic:\n\n");
2920 printf(
2921" Triangle uses adaptive exact arithmetic to perform what computational\n");
2922 printf(
2923" geometers call the `orientation' and `incircle' tests. If the floating-\n"
2924);
2925 printf(
2926" point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
2927 printf(
2928" most workstations do), and does not use extended precision internal\n");
2929 printf(
2930" floating-point registers, then your output is guaranteed to be an\n");
2931 printf(
2932" absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
2933);
2934 printf(
2935" error notwithstanding. The word `adaptive' implies that these arithmetic\n"
2936);
2937 printf(
2938" routines compute the result only to the precision necessary to guarantee\n"
2939);
2940 printf(
2941" correctness, so they are usually nearly as fast as their approximate\n");
2942 printf(" counterparts.\n\n");
2943 printf(
2944" May CPUs, including Intel x86 processors, have extended precision\n");
2945 printf(
2946" floating-point registers. These must be reconfigured so their precision\n"
2947);
2948 printf(
2949" is reduced to memory precision. Triangle does this if it is compiled\n");
2950 printf(" correctly. See the makefile for details.\n\n");
2951 printf(
2952" The exact tests can be disabled with the -X switch. On most inputs, this\n"
2953);
2954 printf(
2955" switch reduces the computation time by about eight percent--it's not\n");
2956 printf(
2957" worth the risk. There are rare difficult inputs (having many collinear\n");
2958 printf(
2959" and cocircular vertices), however, for which the difference in speed\n");
2960 printf(
2961" could be a factor of two. Be forewarned that these are precisely the\n");
2962 printf(
2963" inputs most likely to cause errors if you use the -X switch. Hence, the\n"
2964);
2965 printf(" -X switch is not recommended.\n\n");
2966 printf(
2967" Unfortunately, the exact tests don't solve every numerical problem.\n");
2968 printf(
2969" Exact arithmetic is not used to compute the positions of new vertices,\n");
2970 printf(
2971" because the bit complexity of vertex coordinates would grow without\n");
2972 printf(
2973" bound. Hence, segment intersections aren't computed exactly; in very\n");
2974 printf(
2975" unusual cases, roundoff error in computing an intersection point might\n");
2976 printf(
2977" actually lead to an inverted triangle and an invalid triangulation.\n");
2978 printf(
2979" (This is one reason to specify your own intersection points in your .poly\n"
2980);
2981 printf(
2982" files.) Similarly, exact arithmetic is not used to compute the vertices\n"
2983);
2984 printf(" of the Voronoi diagram.\n\n");
2985 printf(
2986" Another pair of problems not solved by the exact arithmetic routines is\n");
2987 printf(
2988" underflow and overflow. If Triangle is compiled for double precision\n");
2989 printf(
2990" arithmetic, I believe that Triangle's geometric predicates work correctly\n"
2991);
2992 printf(
2993" if the exponent of every input coordinate falls in the range [-148, 201].\n"
2994);
2995 printf(
2996" Underflow can silently prevent the orientation and incircle tests from\n");
2997 printf(
2998" being performed exactly, while overflow typically causes a floating\n");
2999 printf(" exception.\n\n");
3000 printf("Calling Triangle from Another Program:\n\n");
3001 printf(" Read the file triangle.h for details.\n\n");
3002 printf("Troubleshooting:\n\n");
3003 printf(" Please read this section before mailing me bugs.\n\n");
3004 printf(" `My output mesh has no triangles!'\n\n");
3005 printf(
3006" If you're using a PSLG, you've probably failed to specify a proper set\n"
3007);
3008 printf(
3009" of bounding segments, or forgotten to use the -c switch. Or you may\n");
3010 printf(
3011" have placed a hole badly, thereby eating all your triangles. To test\n");
3012 printf(" these possibilities, try again with the -c and -O switches.\n");
3013 printf(
3014" Alternatively, all your input vertices may be collinear, in which case\n"
3015);
3016 printf(" you can hardly expect to triangulate them.\n\n");
3017 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
3018 printf(
3019" Bad things can happen when triangles get so small that the distance\n");
3020 printf(
3021" between their vertices isn't much larger than the precision of your\n");
3022 printf(
3023" machine's arithmetic. If you've compiled Triangle for single-precision\n"
3024);
3025 printf(
3026" arithmetic, you might do better by recompiling it for double-precision.\n"
3027);
3028 printf(
3029" Then again, you might just have to settle for more lenient constraints\n"
3030);
3031 printf(
3032" on the minimum angle and the maximum area than you had planned.\n");
3033 printf("\n");
3034 printf(
3035" You can minimize precision problems by ensuring that the origin lies\n");
3036 printf(
3037" inside your vertex set, or even inside the densest part of your\n");
3038 printf(
3039" mesh. If you're triangulating an object whose x-coordinates all fall\n");
3040 printf(
3041" between 6247133 and 6247134, you're not leaving much floating-point\n");
3042 printf(" precision for Triangle to work with.\n\n");
3043 printf(
3044" Precision problems can occur covertly if the input PSLG contains two\n");
3045 printf(
3046" segments that meet (or intersect) at an extremely small angle, or if\n");
3047 printf(
3048" such an angle is introduced by the -c switch. If you don't realize\n");
3049 printf(
3050" that a tiny angle is being formed, you might never discover why\n");
3051 printf(
3052" Triangle is crashing. To check for this possibility, use the -S switch\n"
3053);
3054 printf(
3055" (with an appropriate limit on the number of Steiner points, found by\n");
3056 printf(
3057" trial-and-error) to stop Triangle early, and view the output .poly file\n"
3058);
3059 printf(
3060" with Show Me (described below). Look carefully for regions where dense\n"
3061);
3062 printf(
3063" clusters of vertices are forming and for small angles between segments.\n"
3064);
3065 printf(
3066" Zoom in closely, as such segments might look like a single segment from\n"
3067);
3068 printf(" a distance.\n\n");
3069 printf(
3070" If some of the input values are too large, Triangle may suffer a\n");
3071 printf(
3072" floating exception due to overflow when attempting to perform an\n");
3073 printf(
3074" orientation or incircle test. (Read the section on exact arithmetic\n");
3075 printf(
3076" above.) Again, I recommend compiling Triangle for double (rather\n");
3077 printf(" than single) precision arithmetic.\n\n");
3078 printf(
3079" Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
3080 printf(
3081" -u) with an input that is not segment-bounded--that is, if your input\n");
3082 printf(
3083" is a vertex set, or you're using the -c switch. If the convex hull of\n"
3084);
3085 printf(
3086" your input vertices has collinear vertices on its boundary, an input\n");
3087 printf(
3088" vertex that you think lies on the convex hull might actually lie just\n");
3089 printf(
3090" inside the convex hull. If so, the vertex and the nearby convex hull\n");
3091 printf(
3092" edge form an extremely thin triangle. When Triangle tries to refine\n");
3093 printf(
3094" the mesh to enforce angle and area constraints, Triangle might generate\n"
3095);
3096 printf(
3097" extremely tiny triangles, or it might fail because of insufficient\n");
3098 printf(" floating-point precision.\n\n");
3099 printf(
3100" `The numbering of the output vertices doesn't match the input vertices.'\n"
3101);
3102 printf("\n");
3103 printf(
3104" You may have had duplicate input vertices, or you may have eaten some\n");
3105 printf(
3106" of your input vertices with a hole, or by placing them outside the area\n"
3107);
3108 printf(
3109" enclosed by segments. In any case, you can solve the problem by not\n");
3110 printf(" using the -j switch.\n\n");
3111 printf(
3112" `Triangle executes without incident, but when I look at the resulting\n");
3113 printf(
3114" mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
3115 printf("\n");
3116 printf(
3117" If you select the -X switch, Triangle occasionally makes mistakes due\n");
3118 printf(
3119" to floating-point roundoff error. Although these errors are rare,\n");
3120 printf(
3121" don't use the -X switch. If you still have problems, please report the\n"
3122);
3123 printf(" bug.\n\n");
3124 printf(
3125" `Triangle executes without incident, but when I look at the resulting\n");
3126 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
3127 printf(" inconsistencies.'\n");
3128 printf("\n");
3129 printf(
3130" If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
3131);
3132 printf(
3133" diagram if the domain you are triangulating is convex and free of\n");
3134 printf(
3135" holes, and you use the -D switch to construct a conforming Delaunay\n");
3136 printf(" triangulation (instead of a CDT or CCDT).\n\n");
3137 printf(
3138" Strange things can happen if you've taken liberties with your PSLG. Do\n");
3139 printf(
3140" you have a vertex lying in the middle of a segment? Triangle sometimes\n");
3141 printf(
3142" copes poorly with that sort of thing. Do you want to lay out a collinear\n"
3143);
3144 printf(
3145" row of evenly spaced, segment-connected vertices? Have you simply\n");
3146 printf(
3147" defined one long segment connecting the leftmost vertex to the rightmost\n"
3148);
3149 printf(
3150" vertex, and a bunch of vertices lying along it? This method occasionally\n"
3151);
3152 printf(
3153" works, especially with horizontal and vertical lines, but often it\n");
3154 printf(
3155" doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
3156);
3157 printf(" separate segment. If you don't like it, tough.\n\n");
3158 printf(
3159" Furthermore, if you have segments that intersect other than at their\n");
3160 printf(
3161" endpoints, try not to let the intersections fall extremely close to PSLG\n"
3162);
3163 printf(" vertices or each other.\n\n");
3164 printf(
3165" If you have problems refining a triangulation not produced by Triangle:\n");
3166 printf(
3167" Are you sure the triangulation is geometrically valid? Is it formatted\n");
3168 printf(
3169" correctly for Triangle? Are the triangles all listed so the first three\n"
3170);
3171 printf(
3172" vertices are their corners in counterclockwise order? Are all of the\n");
3173 printf(
3174" triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
3175);
3176 printf(" assumes that it starts with a CDT.\n\n");
3177 printf("Show Me:\n\n");
3178 printf(
3179" Triangle comes with a separate program named `Show Me', whose primary\n");
3180 printf(
3181" purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
3182);
3183 printf(
3184" purpose is to check the validity of your input files, and do so more\n");
3185 printf(
3186" thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
3187 printf(
3188" you have the X Windows system. Sorry, Microsoft Windows users.\n");
3189 printf("\n");
3190 printf("Triangle on the Web:\n");
3191 printf("\n");
3192 printf(" To see an illustrated version of these instructions, check out\n");
3193 printf("\n");
3194 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
3195 printf("\n");
3196 printf("A Brief Plea:\n");
3197 printf("\n");
3198 printf(
3199" If you use Triangle, and especially if you use it to accomplish real\n");
3200 printf(
3201" work, I would like very much to hear from you. A short letter or email\n");
3202 printf(
3203" (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
3204);
3205 printf(
3206" to me. The more people I know are using this program, the more easily I\n"
3207);
3208 printf(
3209" can justify spending time on improvements, which in turn will benefit\n");
3210 printf(
3211" you. Also, I can put you on a list to receive email whenever a new\n");
3212 printf(" version of Triangle is available.\n\n");
3213 printf(
3214" If you use a mesh generated by Triangle in a publication, please include\n"
3215);
3216 printf(
3217" an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
3218);
3219 printf(
3220" If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
3221 printf(
3222" ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
3223 printf(
3224" Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
3225 printf(
3226" Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
3227 printf(
3228" Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
3229 printf(
3230" Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
3231);
3232 printf(" Geometry.)'\n\n");
3233 printf("Research credit:\n\n");
3234 printf(
3235" Of course, I can take credit for only a fraction of the ideas that made\n");
3236 printf(
3237" this mesh generator possible. Triangle owes its existence to the efforts\n"
3238);
3239 printf(
3240" of many fine computational geometers and other researchers, including\n");
3241 printf(
3242" Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
3243);
3244 printf(
3245" Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
3246 printf(
3247" Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
3248 printf(
3249" Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
3250 printf(
3251" Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
3252);
3253 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
3254 printf(
3255" Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
3256 printf(" source code for references.\n\n");
3257 triexit(0);
3258}
3259
3260#endif /* not TRILIBRARY */
3261
3262/*****************************************************************************/
3263/* */
3264/* internalerror() Ask the user to send me the defective product. Exit. */
3265/* */
3266/*****************************************************************************/
3267
3269{
3270 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
3271 printf(" Include the message above, your input data set, and the exact\n");
3272 printf(" command line you used to run Triangle.\n");
3273 triexit(1);
3274}
3275
3276/*****************************************************************************/
3277/* */
3278/* parsecommandline() Read the command line, identify switches, and set */
3279/* up options and file names. */
3280/* */
3281/*****************************************************************************/
3282
3283#ifdef ANSI_DECLARATORS
3284void parsecommandline(int argc,const char **argv, struct behavior *b)
3285#else /* not ANSI_DECLARATORS */
3288char **argv;
3289struct behavior *b;
3290#endif /* not ANSI_DECLARATORS */
3291
3292{
3293#ifdef TRILIBRARY
3294#define STARTINDEX 0
3295#else /* not TRILIBRARY */
3296#define STARTINDEX 1
3297 int increment;
3299#endif /* not TRILIBRARY */
3300 int i, j, k;
3301 char workstring[FILENAMESIZE];
3302
3303 b->poly = b->refine = b->quality = 0;
3304 b->vararea = b->fixedarea = b->usertest = 0;
3305 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
3306 b->firstnumber = 1;
3307 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
3308 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
3309 b->noiterationnum = 0;
3310 b->noholes = b->noexact = 0;
3311 b->incremental = b->sweepline = 0;
3312 b->dwyer = 1;
3313 b->splitseg = 0;
3314 b->docheck = 0;
3315 b->nobisect = 0;
3316 b->conformdel = 0;
3317 b->steiner = -1;
3318 b->order = 1;
3319 b->minangle = 0.0;
3320 b->maxarea = -1.0;
3321 b->quiet = b->verbose = 0;
3322#ifndef TRILIBRARY
3323 b->innodefilename[0] = '\0';
3324#endif /* not TRILIBRARY */
3325
3326 for (i = STARTINDEX; i < argc; i++) {
3327#ifndef TRILIBRARY
3328 if (argv[i][0] == '-') {
3329#endif /* not TRILIBRARY */
3330 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
3331 if (argv[i][j] == 'p') {
3332 b->poly = 1;
3333 }
3334#ifndef CDT_ONLY
3335 if (argv[i][j] == 'r') {
3336 b->refine = 1;
3337 }
3338 if (argv[i][j] == 'q') {
3339 b->quality = 1;
3340 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3341 (argv[i][j + 1] == '.')) {
3342 k = 0;
3343 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3344 (argv[i][j + 1] == '.')) {
3345 j++;
3346 workstring[k] = argv[i][j];
3347 k++;
3348 }
3349 workstring[k] = '\0';
3350 b->minangle = (REAL) strtod(workstring, (char **) NULL);
3351 } else {
3352 b->minangle = 20.0;
3353 }
3354 }
3355 if (argv[i][j] == 'a') {
3356 b->quality = 1;
3357 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3358 (argv[i][j + 1] == '.')) {
3359 b->fixedarea = 1;
3360 k = 0;
3361 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3362 (argv[i][j + 1] == '.')) {
3363 j++;
3364 workstring[k] = argv[i][j];
3365 k++;
3366 }
3367 workstring[k] = '\0';
3368 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
3369 if (b->maxarea <= 0.0) {
3370 printf("Error: Maximum area must be greater than zero.\n");
3371 triexit(1);
3372 }
3373 } else {
3374 b->vararea = 1;
3375 }
3376 }
3377 if (argv[i][j] == 'u') {
3378 b->quality = 1;
3379 b->usertest = 1;
3380 }
3381#endif /* not CDT_ONLY */
3382 if (argv[i][j] == 'A') {
3383 b->regionattrib = 1;
3384 }
3385 if (argv[i][j] == 'c') {
3386 b->convex = 1;
3387 }
3388 if (argv[i][j] == 'w') {
3389 b->weighted = 1;
3390 }
3391 if (argv[i][j] == 'W') {
3392 b->weighted = 2;
3393 }
3394 if (argv[i][j] == 'j') {
3395 b->jettison = 1;
3396 }
3397 if (argv[i][j] == 'z') {
3398 b->firstnumber = 0;
3399 }
3400 if (argv[i][j] == 'e') {
3401 b->edgesout = 1;
3402 }
3403 if (argv[i][j] == 'v') {
3404 b->voronoi = 1;
3405 }
3406 if (argv[i][j] == 'n') {
3407 b->neighbors = 1;
3408 }
3409 if (argv[i][j] == 'g') {
3410 b->geomview = 1;
3411 }
3412 if (argv[i][j] == 'B') {
3413 b->nobound = 1;
3414 }
3415 if (argv[i][j] == 'P') {
3416 b->nopolywritten = 1;
3417 }
3418 if (argv[i][j] == 'N') {
3419 b->nonodewritten = 1;
3420 }
3421 if (argv[i][j] == 'E') {
3422 b->noelewritten = 1;
3423 }
3424#ifndef TRILIBRARY
3425 if (argv[i][j] == 'I') {
3426 b->noiterationnum = 1;
3427 }
3428#endif /* not TRILIBRARY */
3429 if (argv[i][j] == 'O') {
3430 b->noholes = 1;
3431 }
3432 if (argv[i][j] == 'X') {
3433 b->noexact = 1;
3434 }
3435 if (argv[i][j] == 'o') {
3436 if (argv[i][j + 1] == '2') {
3437 j++;
3438 b->order = 2;
3439 }
3440 }
3441#ifndef CDT_ONLY
3442 if (argv[i][j] == 'Y') {
3443 b->nobisect++;
3444 }
3445 if (argv[i][j] == 'S') {
3446 b->steiner = 0;
3447 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
3448 j++;
3449 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
3450 }
3451 }
3452#endif /* not CDT_ONLY */
3453#ifndef REDUCED
3454 if (argv[i][j] == 'i') {
3455 b->incremental = 1;
3456 }
3457 if (argv[i][j] == 'F') {
3458 b->sweepline = 1;
3459 }
3460#endif /* not REDUCED */
3461 if (argv[i][j] == 'l') {
3462 b->dwyer = 0;
3463 }
3464#ifndef REDUCED
3465#ifndef CDT_ONLY
3466 if (argv[i][j] == 's') {
3467 b->splitseg = 1;
3468 }
3469 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
3470 b->quality = 1;
3471 b->conformdel = 1;
3472 }
3473#endif /* not CDT_ONLY */
3474 if (argv[i][j] == 'C') {
3475 b->docheck = 1;
3476 }
3477#endif /* not REDUCED */
3478 if (argv[i][j] == 'Q') {
3479 b->quiet = 1;
3480 }
3481 if (argv[i][j] == 'V') {
3482 b->verbose++;
3483 }
3484#ifndef TRILIBRARY
3485 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
3486 (argv[i][j] == '?')) {
3487 info();
3488 }
3489#endif /* not TRILIBRARY */
3490 }
3491#ifndef TRILIBRARY
3492 } else {
3493 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
3494 b->innodefilename[FILENAMESIZE - 1] = '\0';
3495 }
3496#endif /* not TRILIBRARY */
3497 }
3498#ifndef TRILIBRARY
3499 if (b->innodefilename[0] == '\0') {
3500 syntax();
3501 }
3502 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
3503 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3504 }
3505 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
3506 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3507 b->poly = 1;
3508 }
3509#ifndef CDT_ONLY
3510 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
3511 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
3512 b->refine = 1;
3513 }
3514 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
3515 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3516 b->refine = 1;
3517 b->quality = 1;
3518 b->vararea = 1;
3519 }
3520#endif /* not CDT_ONLY */
3521#endif /* not TRILIBRARY */
3522 b->usesegments = b->poly || b->refine || b->quality || b->convex;
3523 b->goodangle = cos(b->minangle * PI / 180.0);
3524 if (b->goodangle == 1.0) {
3525 b->offconstant = 0.0;
3526 } else {
3527 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
3528 }
3529 b->goodangle *= b->goodangle;
3530 if (b->refine && b->noiterationnum) {
3531 printf(
3532 "Error: You cannot use the -I switch when refining a triangulation.\n");
3533 triexit(1);
3534 }
3535 /* Be careful not to allocate space for element area constraints that */
3536 /* will never be assigned any value (other than the default -1.0). */
3537 if (!b->refine && !b->poly) {
3538 b->vararea = 0;
3539 }
3540 /* Be careful not to add an extra attribute to each element unless the */
3541 /* input supports it (PSLG in, but not refining a preexisting mesh). */
3542 if (b->refine || !b->poly) {
3543 b->regionattrib = 0;
3544 }
3545 /* Regular/weighted triangulations are incompatible with PSLGs */
3546 /* and meshing. */
3547 if (b->weighted && (b->poly || b->quality)) {
3548 b->weighted = 0;
3549 if (!b->quiet) {
3550 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
3551 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
3552 );
3553 }
3554 }
3555 if (b->jettison && b->nonodewritten && !b->quiet) {
3556 printf("Warning: -j and -N switches are somewhat incompatible.\n");
3557 printf(" If any vertices are jettisoned, you will need the output\n");
3558 printf(" .node file to reconstruct the new node indices.");
3559 }
3560
3561#ifndef TRILIBRARY
3562 strcpy(b->inpolyfilename, b->innodefilename);
3563 strcpy(b->inelefilename, b->innodefilename);
3564 strcpy(b->areafilename, b->innodefilename);
3566 strcpy(workstring, b->innodefilename);
3567 j = 1;
3568 while (workstring[j] != '\0') {
3569 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
3570 increment = j + 1;
3571 }
3572 j++;
3573 }
3574 meshnumber = 0;
3575 if (increment > 0) {
3576 j = increment;
3577 do {
3578 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
3579 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
3580 } else {
3581 increment = 0;
3582 }
3583 j++;
3584 } while (workstring[j] != '\0');
3585 }
3586 if (b->noiterationnum) {
3587 strcpy(b->outnodefilename, b->innodefilename);
3588 strcpy(b->outelefilename, b->innodefilename);
3589 strcpy(b->edgefilename, b->innodefilename);
3590 strcpy(b->vnodefilename, b->innodefilename);
3591 strcpy(b->vedgefilename, b->innodefilename);
3592 strcpy(b->neighborfilename, b->innodefilename);
3593 strcpy(b->offfilename, b->innodefilename);
3594 strcat(b->outnodefilename, ".node");
3595 strcat(b->outelefilename, ".ele");
3596 strcat(b->edgefilename, ".edge");
3597 strcat(b->vnodefilename, ".v.node");
3598 strcat(b->vedgefilename, ".v.edge");
3599 strcat(b->neighborfilename, ".neigh");
3600 strcat(b->offfilename, ".off");
3601 } else if (increment == 0) {
3602 strcpy(b->outnodefilename, b->innodefilename);
3603 strcpy(b->outpolyfilename, b->innodefilename);
3604 strcpy(b->outelefilename, b->innodefilename);
3605 strcpy(b->edgefilename, b->innodefilename);
3606 strcpy(b->vnodefilename, b->innodefilename);
3607 strcpy(b->vedgefilename, b->innodefilename);
3608 strcpy(b->neighborfilename, b->innodefilename);
3609 strcpy(b->offfilename, b->innodefilename);
3610 strcat(b->outnodefilename, ".1.node");
3611 strcat(b->outpolyfilename, ".1.poly");
3612 strcat(b->outelefilename, ".1.ele");
3613 strcat(b->edgefilename, ".1.edge");
3614 strcat(b->vnodefilename, ".1.v.node");
3615 strcat(b->vedgefilename, ".1.v.edge");
3616 strcat(b->neighborfilename, ".1.neigh");
3617 strcat(b->offfilename, ".1.off");
3618 } else {
3619 workstring[increment] = '%';
3620 workstring[increment + 1] = 'd';
3621 workstring[increment + 2] = '\0';
3622 sprintf(b->outnodefilename, workstring, meshnumber + 1);
3623 strcpy(b->outpolyfilename, b->outnodefilename);
3624 strcpy(b->outelefilename, b->outnodefilename);
3625 strcpy(b->edgefilename, b->outnodefilename);
3626 strcpy(b->vnodefilename, b->outnodefilename);
3627 strcpy(b->vedgefilename, b->outnodefilename);
3628 strcpy(b->neighborfilename, b->outnodefilename);
3629 strcpy(b->offfilename, b->outnodefilename);
3630 strcat(b->outnodefilename, ".node");
3631 strcat(b->outpolyfilename, ".poly");
3632 strcat(b->outelefilename, ".ele");
3633 strcat(b->edgefilename, ".edge");
3634 strcat(b->vnodefilename, ".v.node");
3635 strcat(b->vedgefilename, ".v.edge");
3636 strcat(b->neighborfilename, ".neigh");
3637 strcat(b->offfilename, ".off");
3638 }
3639 strcat(b->innodefilename, ".node");
3640 strcat(b->inpolyfilename, ".poly");
3641 strcat(b->inelefilename, ".ele");
3642 strcat(b->areafilename, ".area");
3643#endif /* not TRILIBRARY */
3644}
3645
3648/********* User interaction routines begin here *********/
3649
3650/********* Debugging routines begin here *********/
3653
3654/*****************************************************************************/
3655/* */
3656/* printtriangle() Print out the details of an oriented triangle. */
3657/* */
3658/* I originally wrote this procedure to simplify debugging; it can be */
3659/* called directly from the debugger, and presents information about an */
3660/* oriented triangle in digestible form. It's also used when the */
3661/* highest level of verbosity (`-VVV') is specified. */
3662/* */
3663/*****************************************************************************/
3664
3665#ifdef ANSI_DECLARATORS
3666void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
3667#else /* not ANSI_DECLARATORS */
3668void printtriangle(m, b, t)
3669struct mesh *m;
3670struct behavior *b;
3671struct otri *t;
3672#endif /* not ANSI_DECLARATORS */
3673
3674{
3675 struct otri printtri;
3678
3679 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
3680 t->orient);
3681 decode(t->tri[0], printtri);
3682 if (printtri.tri == m->dummytri) {
3683 printf(" [0] = Outer space\n");
3684 } else {
3685 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
3686 printtri.orient);
3687 }
3688 decode(t->tri[1], printtri);
3689 if (printtri.tri == m->dummytri) {
3690 printf(" [1] = Outer space\n");
3691 } else {
3692 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
3693 printtri.orient);
3694 }
3695 decode(t->tri[2], printtri);
3696 if (printtri.tri == m->dummytri) {
3697 printf(" [2] = Outer space\n");
3698 } else {
3699 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
3700 printtri.orient);
3701 }
3702
3703 org(*t, printvertex);
3704 if (printvertex == (vertex) NULL)
3705 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
3706 else
3707 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
3708 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
3709 printvertex[0], printvertex[1]);
3710 destT(*t, printvertex);
3711 if (printvertex == (vertex) NULL)
3712 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
3713 else
3714 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
3715 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
3716 printvertex[0], printvertex[1]);
3717 apex(*t, printvertex);
3718 if (printvertex == (vertex) NULL)
3719 printf(" Apex [%d] = NULL\n", t->orient + 3);
3720 else
3721 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
3722 t->orient + 3, (unsigned long) printvertex,
3723 printvertex[0], printvertex[1]);
3724
3725 if (b->usesegments) {
3726 sdecode(t->tri[6], printsh);
3727 if (printsh.ss != m->dummysub) {
3728 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
3729 printsh.ssorient);
3730 }
3731 sdecode(t->tri[7], printsh);
3732 if (printsh.ss != m->dummysub) {
3733 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
3734 printsh.ssorient);
3735 }
3736 sdecode(t->tri[8], printsh);
3737 if (printsh.ss != m->dummysub) {
3738 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
3739 printsh.ssorient);
3740 }
3741 }
3742
3743 if (b->vararea) {
3744 printf(" Area constraint: %.4g\n", areabound(*t));
3745 }
3746}
3747
3748/*****************************************************************************/
3749/* */
3750/* printsubseg() Print out the details of an oriented subsegment. */
3751/* */
3752/* I originally wrote this procedure to simplify debugging; it can be */
3753/* called directly from the debugger, and presents information about an */
3754/* oriented subsegment in digestible form. It's also used when the highest */
3755/* level of verbosity (`-VVV') is specified. */
3756/* */
3757/*****************************************************************************/
3758
3759#ifdef ANSI_DECLARATORS
3760void printsubseg(struct mesh *m, struct behavior* /*b*/, struct osub *s)
3761#else /* not ANSI_DECLARATORS */
3762void printsubseg(m, b, s)
3763struct mesh *m;
3764struct behavior *b;
3765struct osub *s;
3766#endif /* not ANSI_DECLARATORS */
3767
3768{
3769 struct osub printsh;
3770 struct otri printtri;
3772
3773 printf("subsegment x%lx with orientation %d and mark %d:\n",
3774 (unsigned long) s->ss, s->ssorient, markT(*s));
3775 sdecode(s->ss[0], printsh);
3776 if (printsh.ss == m->dummysub) {
3777 printf(" [0] = No subsegment\n");
3778 } else {
3779 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
3780 printsh.ssorient);
3781 }
3782 sdecode(s->ss[1], printsh);
3783 if (printsh.ss == m->dummysub) {
3784 printf(" [1] = No subsegment\n");
3785 } else {
3786 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
3787 printsh.ssorient);
3788 }
3789
3790 sorg(*s, printvertex);
3791 if (printvertex == (vertex) NULL)
3792 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
3793 else
3794 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
3795 2 + s->ssorient, (unsigned long) printvertex,
3796 printvertex[0], printvertex[1]);
3797 sdest(*s, printvertex);
3798 if (printvertex == (vertex) NULL)
3799 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
3800 else
3801 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
3802 3 - s->ssorient, (unsigned long) printvertex,
3803 printvertex[0], printvertex[1]);
3804
3805 decode(s->ss[6], printtri);
3806 if (printtri.tri == m->dummytri) {
3807 printf(" [6] = Outer space\n");
3808 } else {
3809 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
3810 printtri.orient);
3811 }
3812 decode(s->ss[7], printtri);
3813 if (printtri.tri == m->dummytri) {
3814 printf(" [7] = Outer space\n");
3815 } else {
3816 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
3817 printtri.orient);
3818 }
3819
3820 segorg(*s, printvertex);
3821 if (printvertex == (vertex) NULL)
3822 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
3823 else
3824 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
3825 4 + s->ssorient, (unsigned long) printvertex,
3826 printvertex[0], printvertex[1]);
3827 segdest(*s, printvertex);
3828 if (printvertex == (vertex) NULL)
3829 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
3830 else
3831 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
3832 5 - s->ssorient, (unsigned long) printvertex,
3833 printvertex[0], printvertex[1]);
3834}
3835
3838/********* Debugging routines end here *********/
3839
3840/********* Memory management routines begin here *********/
3843
3844/*****************************************************************************/
3845/* */
3846/* poolzero() Set all of a pool's fields to zero. */
3847/* */
3848/* This procedure should never be called on a pool that has any memory */
3849/* allocated to it, as that memory would leak. */
3850/* */
3851/*****************************************************************************/
3852
3853#ifdef ANSI_DECLARATORS
3854void poolzero(struct memorypool *pool)
3855#else /* not ANSI_DECLARATORS */
3856void poolzero(pool)
3857struct memorypool *pool;
3858#endif /* not ANSI_DECLARATORS */
3859
3860{
3861 pool->firstblock = (VOID **) NULL;
3862 pool->nowblock = (VOID **) NULL;
3863 pool->nextitem = (VOID *) NULL;
3864 pool->deaditemstack = (VOID *) NULL;
3865 pool->pathblock = (VOID **) NULL;
3866 pool->pathitem = (VOID *) NULL;
3867 pool->alignbytes = 0;
3868 pool->itembytes = 0;
3869 pool->itemsperblock = 0;
3870 pool->itemsfirstblock = 0;
3871 pool->items = 0;
3872 pool->maxitems = 0;
3873 pool->unallocateditems = 0;
3874 pool->pathitemsleft = 0;
3875}
3876
3877/*****************************************************************************/
3878/* */
3879/* poolrestart() Deallocate all items in a pool. */
3880/* */
3881/* The pool is returned to its starting state, except that no memory is */
3882/* freed to the operating system. Rather, the previously allocated blocks */
3883/* are ready to be reused. */
3884/* */
3885/*****************************************************************************/
3886
3887#ifdef ANSI_DECLARATORS
3888void poolrestart(struct memorypool *pool)
3889#else /* not ANSI_DECLARATORS */
3890void poolrestart(pool)
3891struct memorypool *pool;
3892#endif /* not ANSI_DECLARATORS */
3893
3894{
3895 unsigned long alignptr;
3896
3897 pool->items = 0;
3898 pool->maxitems = 0;
3899
3900 /* Set the currently active block. */
3901 pool->nowblock = pool->firstblock;
3902 /* Find the first item in the pool. Increment by the size of (VOID *). */
3903 alignptr = (unsigned long) (pool->nowblock + 1);
3904 /* Align the item on an `alignbytes'-byte boundary. */
3905 pool->nextitem = (VOID *)
3906 (alignptr + (unsigned long) pool->alignbytes -
3907 (alignptr % (unsigned long) pool->alignbytes));
3908 /* There are lots of unallocated items left in this block. */
3909 pool->unallocateditems = pool->itemsfirstblock;
3910 /* The stack of deallocated items is empty. */
3911 pool->deaditemstack = (VOID *) NULL;
3912}
3913
3914/*****************************************************************************/
3915/* */
3916/* poolinit() Initialize a pool of memory for allocation of items. */
3917/* */
3918/* This routine initializes the machinery for allocating items. A `pool' */
3919/* is created whose records have size at least `bytecount'. Items will be */
3920/* allocated in `itemcount'-item blocks. Each item is assumed to be a */
3921/* collection of words, and either pointers or floating-point values are */
3922/* assumed to be the "primary" word type. (The "primary" word type is used */
3923/* to determine alignment of items.) If `alignment' isn't zero, all items */
3924/* will be `alignment'-byte aligned in memory. `alignment' must be either */
3925/* a multiple or a factor of the primary word size; powers of two are safe. */
3926/* `alignment' is normally used to create a few unused bits at the bottom */
3927/* of each item's pointer, in which information may be stored. */
3928/* */
3929/* Don't change this routine unless you understand it. */
3930/* */
3931/*****************************************************************************/
3932
3933#ifdef ANSI_DECLARATORS
3934void poolinit(struct memorypool *pool, int bytecount, int itemcount,
3935 int firstitemcount, int alignment)
3936#else /* not ANSI_DECLARATORS */
3937void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
3938struct memorypool *pool;
3939int bytecount;
3940int itemcount;
3941int firstitemcount;
3942int alignment;
3943#endif /* not ANSI_DECLARATORS */
3944
3945{
3946 /* Find the proper alignment, which must be at least as large as: */
3947 /* - The parameter `alignment'. */
3948 /* - sizeof(VOID *), so the stack of dead items can be maintained */
3949 /* without unaligned accesses. */
3950 if (alignment > int(sizeof(VOID *))) {
3951 pool->alignbytes = alignment;
3952 } else {
3953 pool->alignbytes = sizeof(VOID *);
3954 }
3955 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
3956 pool->alignbytes;
3957 pool->itemsperblock = itemcount;
3958 if (firstitemcount == 0) {
3959 pool->itemsfirstblock = itemcount;
3960 } else {
3961 pool->itemsfirstblock = firstitemcount;
3962 }
3963
3964 /* Allocate a block of items. Space for `itemsfirstblock' items and one */
3965 /* pointer (to point to the next block) are allocated, as well as space */
3966 /* to ensure alignment of the items. */
3967 pool->firstblock = (VOID **)
3968 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
3969 pool->alignbytes);
3970 /* Set the next block pointer to NULL. */
3971 *(pool->firstblock) = (VOID *) NULL;
3972 poolrestart(pool);
3973}
3974
3975/*****************************************************************************/
3976/* */
3977/* pooldeinit() Free to the operating system all memory taken by a pool. */
3978/* */
3979/*****************************************************************************/
3980
3981#ifdef ANSI_DECLARATORS
3982void pooldeinit(struct memorypool *pool)
3983#else /* not ANSI_DECLARATORS */
3984void pooldeinit(pool)
3985struct memorypool *pool;
3986#endif /* not ANSI_DECLARATORS */
3987
3988{
3989 while (pool->firstblock != (VOID **) NULL) {
3990 pool->nowblock = (VOID **) *(pool->firstblock);
3991 trifree((VOID *) pool->firstblock);
3992 pool->firstblock = pool->nowblock;
3993 }
3994}
3995
3996/*****************************************************************************/
3997/* */
3998/* poolalloc() Allocate space for an item. */
3999/* */
4000/*****************************************************************************/
4001
4002#ifdef ANSI_DECLARATORS
4003VOID *poolalloc(struct memorypool *pool)
4004#else /* not ANSI_DECLARATORS */
4005VOID *poolalloc(pool)
4006struct memorypool *pool;
4007#endif /* not ANSI_DECLARATORS */
4008
4009{
4010 VOID *newitem;
4011 VOID **newblock;
4012 unsigned long alignptr;
4013
4014 /* First check the linked list of dead items. If the list is not */
4015 /* empty, allocate an item from the list rather than a fresh one. */
4016 if (pool->deaditemstack != (VOID *) NULL) {
4017 newitem = pool->deaditemstack; /* Take first item in list. */
4018 pool->deaditemstack = * (VOID **) pool->deaditemstack;
4019 } else {
4020 /* Check if there are any free items left in the current block. */
4021 if (pool->unallocateditems == 0) {
4022 /* Check if another block must be allocated. */
4023 if (*(pool->nowblock) == (VOID *) NULL) {
4024 /* Allocate a new block of items, pointed to by the previous block. */
4025 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
4026 (int) sizeof(VOID *) +
4027 pool->alignbytes);
4028 *(pool->nowblock) = (VOID *) newblock;
4029 /* The next block pointer is NULL. */
4030 *newblock = (VOID *) NULL;
4031 }
4032
4033 /* Move to the new block. */
4034 pool->nowblock = (VOID **) *(pool->nowblock);
4035 /* Find the first item in the block. */
4036 /* Increment by the size of (VOID *). */
4037 alignptr = (unsigned long) (pool->nowblock + 1);
4038 /* Align the item on an `alignbytes'-byte boundary. */
4039 pool->nextitem = (VOID *)
4040 (alignptr + (unsigned long) pool->alignbytes -
4041 (alignptr % (unsigned long) pool->alignbytes));
4042 /* There are lots of unallocated items left in this block. */
4043 pool->unallocateditems = pool->itemsperblock;
4044 }
4045
4046 /* Allocate a new item. */
4047 newitem = pool->nextitem;
4048 /* Advance `nextitem' pointer to next free item in block. */
4049 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
4050 pool->unallocateditems--;
4051 pool->maxitems++;
4052 }
4053 pool->items++;
4054 return newitem;
4055}
4056
4057/*****************************************************************************/
4058/* */
4059/* pooldealloc() Deallocate space for an item. */
4060/* */
4061/* The deallocated space is stored in a queue for later reuse. */
4062/* */
4063/*****************************************************************************/
4064
4065#ifdef ANSI_DECLARATORS
4066void pooldealloc(struct memorypool *pool, VOID *dyingitem)
4067#else /* not ANSI_DECLARATORS */
4068void pooldealloc(pool, dyingitem)
4069struct memorypool *pool;
4070VOID *dyingitem;
4071#endif /* not ANSI_DECLARATORS */
4072
4073{
4074 /* Push freshly killed item onto stack. */
4075 *((VOID **) dyingitem) = pool->deaditemstack;
4076 pool->deaditemstack = dyingitem;
4077 pool->items--;
4078}
4079
4080/*****************************************************************************/
4081/* */
4082/* traversalinit() Prepare to traverse the entire list of items. */
4083/* */
4084/* This routine is used in conjunction with traverse(). */
4085/* */
4086/*****************************************************************************/
4087
4088#ifdef ANSI_DECLARATORS
4089void traversalinit(struct memorypool *pool)
4090#else /* not ANSI_DECLARATORS */
4091void traversalinit(pool)
4092struct memorypool *pool;
4093#endif /* not ANSI_DECLARATORS */
4094
4095{
4096 unsigned long alignptr;
4097
4098 /* Begin the traversal in the first block. */
4099 pool->pathblock = pool->firstblock;
4100 /* Find the first item in the block. Increment by the size of (VOID *). */
4101 alignptr = (unsigned long) (pool->pathblock + 1);
4102 /* Align with item on an `alignbytes'-byte boundary. */
4103 pool->pathitem = (VOID *)
4104 (alignptr + (unsigned long) pool->alignbytes -
4105 (alignptr % (unsigned long) pool->alignbytes));
4106 /* Set the number of items left in the current block. */
4107 pool->pathitemsleft = pool->itemsfirstblock;
4108}
4109
4110/*****************************************************************************/
4111/* */
4112/* traverse() Find the next item in the list. */
4113/* */
4114/* This routine is used in conjunction with traversalinit(). Be forewarned */
4115/* that this routine successively returns all items in the list, including */
4116/* deallocated ones on the deaditemqueue. It's up to you to figure out */
4117/* which ones are actually dead. Why? I don't want to allocate extra */
4118/* space just to demarcate dead items. It can usually be done more */
4119/* space-efficiently by a routine that knows something about the structure */
4120/* of the item. */
4121/* */
4122/*****************************************************************************/
4123
4124#ifdef ANSI_DECLARATORS
4125VOID *traverse(struct memorypool *pool)
4126#else /* not ANSI_DECLARATORS */
4127VOID *traverse(pool)
4128struct memorypool *pool;
4129#endif /* not ANSI_DECLARATORS */
4130
4131{
4132 VOID *newitem;
4133 unsigned long alignptr;
4134
4135 /* Stop upon exhausting the list of items. */
4136 if (pool->pathitem == pool->nextitem) {
4137 return (VOID *) NULL;
4138 }
4139
4140 /* Check whether any untraversed items remain in the current block. */
4141 if (pool->pathitemsleft == 0) {
4142 /* Find the next block. */
4143 pool->pathblock = (VOID **) *(pool->pathblock);
4144 /* Find the first item in the block. Increment by the size of (VOID *). */
4145 alignptr = (unsigned long) (pool->pathblock + 1);
4146 /* Align with item on an `alignbytes'-byte boundary. */
4147 pool->pathitem = (VOID *)
4148 (alignptr + (unsigned long) pool->alignbytes -
4149 (alignptr % (unsigned long) pool->alignbytes));
4150 /* Set the number of items left in the current block. */
4151 pool->pathitemsleft = pool->itemsperblock;
4152 }
4153
4154 newitem = pool->pathitem;
4155 /* Find the next item in the block. */
4156 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
4157 pool->pathitemsleft--;
4158 return newitem;
4159}
4160
4161/*****************************************************************************/
4162/* */
4163/* dummyinit() Initialize the triangle that fills "outer space" and the */
4164/* omnipresent subsegment. */
4165/* */
4166/* The triangle that fills "outer space," called `dummytri', is pointed to */
4167/* by every triangle and subsegment on a boundary (be it outer or inner) of */
4168/* the triangulation. Also, `dummytri' points to one of the triangles on */
4169/* the convex hull (until the holes and concavities are carved), making it */
4170/* possible to find a starting triangle for point location. */
4171/* */
4172/* The omnipresent subsegment, `dummysub', is pointed to by every triangle */
4173/* or subsegment that doesn't have a full complement of real subsegments */
4174/* to point to. */
4175/* */
4176/* `dummytri' and `dummysub' are generally required to fulfill only a few */
4177/* invariants: their vertices must remain NULL and `dummytri' must always */
4178/* be bonded (at offset zero) to some triangle on the convex hull of the */
4179/* mesh, via a boundary edge. Otherwise, the connections of `dummytri' and */
4180/* `dummysub' may change willy-nilly. This makes it possible to avoid */
4181/* writing a good deal of special-case code (in the edge flip, for example) */
4182/* for dealing with the boundary of the mesh, places where no subsegment is */
4183/* present, and so forth. Other entities are frequently bonded to */
4184/* `dummytri' and `dummysub' as if they were real mesh entities, with no */
4185/* harm done. */
4186/* */
4187/*****************************************************************************/
4188
4189#ifdef ANSI_DECLARATORS
4190void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
4191 int subsegbytes)
4192#else /* not ANSI_DECLARATORS */
4194struct mesh *m;
4195struct behavior *b;
4196int trianglebytes;
4198#endif /* not ANSI_DECLARATORS */
4199
4200{
4201 unsigned long alignptr;
4202
4203 /* Set up `dummytri', the `triangle' that occupies "outer space." */
4204 m->dummytribase = (triangle *) trimalloc(trianglebytes +
4205 m->triangles.alignbytes);
4206 /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
4207 alignptr = (unsigned long) m->dummytribase;
4208 m->dummytri = (triangle *)
4209 (alignptr + (unsigned long) m->triangles.alignbytes -
4210 (alignptr % (unsigned long) m->triangles.alignbytes));
4211 /* Initialize the three adjoining triangles to be "outer space." These */
4212 /* will eventually be changed by various bonding operations, but their */
4213 /* values don't really matter, as long as they can legally be */
4214 /* dereferenced. */
4215 m->dummytri[0] = (triangle) m->dummytri;
4216 m->dummytri[1] = (triangle) m->dummytri;
4217 m->dummytri[2] = (triangle) m->dummytri;
4218 /* Three NULL vertices. */
4219 m->dummytri[3] = (triangle) NULL;
4220 m->dummytri[4] = (triangle) NULL;
4221 m->dummytri[5] = (triangle) NULL;
4222
4223 if (b->usesegments) {
4224 /* Set up `dummysub', the omnipresent subsegment pointed to by any */
4225 /* triangle side or subsegment end that isn't attached to a real */
4226 /* subsegment. */
4227 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
4228 m->subsegs.alignbytes);
4229 /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
4230 alignptr = (unsigned long) m->dummysubbase;
4231 m->dummysub = (subseg *)
4232 (alignptr + (unsigned long) m->subsegs.alignbytes -
4233 (alignptr % (unsigned long) m->subsegs.alignbytes));
4234 /* Initialize the two adjoining subsegments to be the omnipresent */
4235 /* subsegment. These will eventually be changed by various bonding */
4236 /* operations, but their values don't really matter, as long as they */
4237 /* can legally be dereferenced. */
4238 m->dummysub[0] = (subseg) m->dummysub;
4239 m->dummysub[1] = (subseg) m->dummysub;
4240 /* Four NULL vertices. */
4241 m->dummysub[2] = (subseg) NULL;
4242 m->dummysub[3] = (subseg) NULL;
4243 m->dummysub[4] = (subseg) NULL;
4244 m->dummysub[5] = (subseg) NULL;
4245 /* Initialize the two adjoining triangles to be "outer space." */
4246 m->dummysub[6] = (subseg) m->dummytri;
4247 m->dummysub[7] = (subseg) m->dummytri;
4248 /* Set the boundary marker to zero. */
4249 * (int *) (m->dummysub + 8) = 0;
4250
4251 /* Initialize the three adjoining subsegments of `dummytri' to be */
4252 /* the omnipresent subsegment. */
4253 m->dummytri[6] = (triangle) m->dummysub;
4254 m->dummytri[7] = (triangle) m->dummysub;
4255 m->dummytri[8] = (triangle) m->dummysub;
4256 }
4257}
4258
4259/*****************************************************************************/
4260/* */
4261/* initializevertexpool() Calculate the size of the vertex data structure */
4262/* and initialize its memory pool. */
4263/* */
4264/* This routine also computes the `vertexmarkindex' and `vertex2triindex' */
4265/* indices used to find values within each vertex. */
4266/* */
4267/*****************************************************************************/
4268
4269#ifdef ANSI_DECLARATORS
4270void initializevertexpool(struct mesh *m, struct behavior *b)
4271#else /* not ANSI_DECLARATORS */
4273struct mesh *m;
4274struct behavior *b;
4275#endif /* not ANSI_DECLARATORS */
4276
4277{
4278 int vertexsize;
4279
4280 /* The index within each vertex at which the boundary marker is found, */
4281 /* followed by the vertex type. Ensure the vertex marker is aligned to */
4282 /* a sizeof(int)-byte address. */
4283 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
4284 sizeof(int) - 1) /
4285 sizeof(int);
4286 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
4287 if (b->poly) {
4288 /* The index within each vertex at which a triangle pointer is found. */
4289 /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
4290 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
4291 sizeof(triangle);
4292 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
4293 }
4294
4295 /* Initialize the pool of vertices. */
4296 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
4297 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
4298 sizeof(REAL));
4299}
4300
4301/*****************************************************************************/
4302/* */
4303/* initializetrisubpools() Calculate the sizes of the triangle and */
4304/* subsegment data structures and initialize */
4305/* their memory pools. */
4306/* */
4307/* This routine also computes the `highorderindex', `elemattribindex', and */
4308/* `areaboundindex' indices used to find values within each triangle. */
4309/* */
4310/*****************************************************************************/
4311
4312#ifdef ANSI_DECLARATORS
4313void initializetrisubpools(struct mesh *m, struct behavior *b)
4314#else /* not ANSI_DECLARATORS */
4316struct mesh *m;
4317struct behavior *b;
4318#endif /* not ANSI_DECLARATORS */
4319
4320{
4321 int trisize;
4322
4323 /* The index within each triangle at which the extra nodes (above three) */
4324 /* associated with high order elements are found. There are three */
4325 /* pointers to other triangles, three pointers to corners, and possibly */
4326 /* three pointers to subsegments before the extra nodes. */
4327 m->highorderindex = 6 + (b->usesegments * 3);
4328 /* The number of bytes occupied by a triangle. */
4329 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
4330 sizeof(triangle);
4331 /* The index within each triangle at which its attributes are found, */
4332 /* where the index is measured in REALs. */
4333 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
4334 /* The index within each triangle at which the maximum area constraint */
4335 /* is found, where the index is measured in REALs. Note that if the */
4336 /* `regionattrib' flag is set, an additional attribute will be added. */
4337 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
4338 /* If triangle attributes or an area bound are needed, increase the number */
4339 /* of bytes occupied by a triangle. */
4340 if (b->vararea) {
4341 trisize = (m->areaboundindex + 1) * sizeof(REAL);
4342 } else if (m->eextras + b->regionattrib > 0) {
4343 trisize = m->areaboundindex * sizeof(REAL);
4344 }
4345 /* If a Voronoi diagram or triangle neighbor graph is requested, make */
4346 /* sure there's room to store an integer index in each triangle. This */
4347 /* integer index can occupy the same space as the subsegment pointers */
4348 /* or attributes or area constraint or extra nodes. */
4349 if ((b->voronoi || b->neighbors) &&
4350 (trisize < int(6 * sizeof(triangle) + sizeof(int)))) {
4351 trisize = 6 * sizeof(triangle) + sizeof(int);
4352 }
4353
4354 /* Having determined the memory size of a triangle, initialize the pool. */
4355 poolinit(&m->triangles, trisize, TRIPERBLOCK,
4356 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
4357 TRIPERBLOCK, 4);
4358
4359 if (b->usesegments) {
4360 /* Initialize the pool of subsegments. Take into account all eight */
4361 /* pointers and one boundary marker. */
4362 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
4363 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
4364
4365 /* Initialize the "outer space" triangle and omnipresent subsegment. */
4366 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
4367 } else {
4368 /* Initialize the "outer space" triangle. */
4369 dummyinit(m, b, m->triangles.itembytes, 0);
4370 }
4371}
4372
4373/*****************************************************************************/
4374/* */
4375/* triangledealloc() Deallocate space for a triangle, marking it dead. */
4376/* */
4377/*****************************************************************************/
4378
4379#ifdef ANSI_DECLARATORS
4381#else /* not ANSI_DECLARATORS */
4383struct mesh *m;
4385#endif /* not ANSI_DECLARATORS */
4386
4387{
4388 /* Mark the triangle as dead. This makes it possible to detect dead */
4389 /* triangles when traversing the list of all triangles. */
4390 killtri(dyingtriangle);
4391 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
4392}
4393
4394/*****************************************************************************/
4395/* */
4396/* triangletraverse() Traverse the triangles, skipping dead ones. */
4397/* */
4398/*****************************************************************************/
4399
4400#ifdef ANSI_DECLARATORS
4402#else /* not ANSI_DECLARATORS */
4404struct mesh *m;
4405#endif /* not ANSI_DECLARATORS */
4406
4407{
4409
4410 do {
4411 newtriangle = (triangle *) traverse(&m->triangles);
4412 if (newtriangle == (triangle *) NULL) {
4413 return (triangle *) NULL;
4414 }
4415 } while (deadtri(newtriangle)); /* Skip dead ones. */
4417}
4418
4419/*****************************************************************************/
4420/* */
4421/* subsegdealloc() Deallocate space for a subsegment, marking it dead. */
4422/* */
4423/*****************************************************************************/
4424
4425#ifdef ANSI_DECLARATORS
4427#else /* not ANSI_DECLARATORS */
4429struct mesh *m;
4431#endif /* not ANSI_DECLARATORS */
4432
4433{
4434 /* Mark the subsegment as dead. This makes it possible to detect dead */
4435 /* subsegments when traversing the list of all subsegments. */
4436 killsubseg(dyingsubseg);
4437 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
4438}
4439
4440/*****************************************************************************/
4441/* */
4442/* subsegtraverse() Traverse the subsegments, skipping dead ones. */
4443/* */
4444/*****************************************************************************/
4445
4446#ifdef ANSI_DECLARATORS
4448#else /* not ANSI_DECLARATORS */
4450struct mesh *m;
4451#endif /* not ANSI_DECLARATORS */
4452
4453{
4455
4456 do {
4457 newsubseg = (subseg *) traverse(&m->subsegs);
4458 if (newsubseg == (subseg *) NULL) {
4459 return (subseg *) NULL;
4460 }
4461 } while (deadsubseg(newsubseg)); /* Skip dead ones. */
4463}
4464
4465/*****************************************************************************/
4466/* */
4467/* vertexdealloc() Deallocate space for a vertex, marking it dead. */
4468/* */
4469/*****************************************************************************/
4470
4471#ifdef ANSI_DECLARATORS
4473#else /* not ANSI_DECLARATORS */
4475struct mesh *m;
4477#endif /* not ANSI_DECLARATORS */
4478
4479{
4480 /* Mark the vertex as dead. This makes it possible to detect dead */
4481 /* vertices when traversing the list of all vertices. */
4482 setvertextype(dyingvertex, DEADVERTEX);
4483 pooldealloc(&m->vertices, (VOID *) dyingvertex);
4484}
4485
4486/*****************************************************************************/
4487/* */
4488/* vertextraverse() Traverse the vertices, skipping dead ones. */
4489/* */
4490/*****************************************************************************/
4491
4492#ifdef ANSI_DECLARATORS
4494#else /* not ANSI_DECLARATORS */
4496struct mesh *m;
4497#endif /* not ANSI_DECLARATORS */
4498
4499{
4501
4502 do {
4503 newvertex = (vertex) traverse(&m->vertices);
4504 if (newvertex == (vertex) NULL) {
4505 return (vertex) NULL;
4506 }
4507 } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */
4509}
4510
4511/*****************************************************************************/
4512/* */
4513/* badsubsegdealloc() Deallocate space for a bad subsegment, marking it */
4514/* dead. */
4515/* */
4516/*****************************************************************************/
4517
4518#ifndef CDT_ONLY
4519
4520#ifdef ANSI_DECLARATORS
4522#else /* not ANSI_DECLARATORS */
4524struct mesh *m;
4526#endif /* not ANSI_DECLARATORS */
4527
4528{
4529 /* Set subsegment's origin to NULL. This makes it possible to detect dead */
4530 /* badsubsegs when traversing the list of all badsubsegs . */
4531 dyingseg->subsegorg = (vertex) NULL;
4532 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
4533}
4534
4535#endif /* not CDT_ONLY */
4536
4537/*****************************************************************************/
4538/* */
4539/* badsubsegtraverse() Traverse the bad subsegments, skipping dead ones. */
4540/* */
4541/*****************************************************************************/
4542
4543#ifndef CDT_ONLY
4544
4545#ifdef ANSI_DECLARATORS
4547#else /* not ANSI_DECLARATORS */
4549struct mesh *m;
4550#endif /* not ANSI_DECLARATORS */
4551
4552{
4553 struct badsubseg *newseg;
4554
4555 do {
4556 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
4557 if (newseg == (struct badsubseg *) NULL) {
4558 return (struct badsubseg *) NULL;
4559 }
4560 } while (newseg->subsegorg == (vertex) NULL); /* Skip dead ones. */
4561 return newseg;
4562}
4563
4564#endif /* not CDT_ONLY */
4565
4566/*****************************************************************************/
4567/* */
4568/* getvertex() Get a specific vertex, by number, from the list. */
4569/* */
4570/* The first vertex is number 'firstnumber'. */
4571/* */
4572/* Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */
4573/* is large). I don't care to take the trouble to make it work in constant */
4574/* time. */
4575/* */
4576/*****************************************************************************/
4577
4578#ifdef ANSI_DECLARATORS
4579vertex getvertex(struct mesh *m, struct behavior *b, int number)
4580#else /* not ANSI_DECLARATORS */
4582struct mesh *m;
4583struct behavior *b;
4585#endif /* not ANSI_DECLARATORS */
4586
4587{
4588 VOID **getblock;
4590 unsigned long alignptr;
4592
4593 getblock = m->vertices.firstblock;
4594 current = b->firstnumber;
4595
4596 /* Find the right block. */
4597 if (current + m->vertices.itemsfirstblock <= number) {
4598 getblock = (VOID **) *getblock;
4599 current += m->vertices.itemsfirstblock;
4600 while (current + m->vertices.itemsperblock <= number) {
4601 getblock = (VOID **) *getblock;
4602 current += m->vertices.itemsperblock;
4603 }
4604 }
4605
4606 /* Now find the right vertex. */
4607 alignptr = (unsigned long) (getblock + 1);
4608 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
4609 (alignptr % (unsigned long) m->vertices.alignbytes));
4610 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
4611}
4612
4613/*****************************************************************************/
4614/* */
4615/* triangledeinit() Free all remaining allocated memory. */
4616/* */
4617/*****************************************************************************/
4618
4619#ifdef ANSI_DECLARATORS
4620void triangledeinit(struct mesh *m, struct behavior *b)
4621#else /* not ANSI_DECLARATORS */
4622void triangledeinit(m, b)
4623struct mesh *m;
4624struct behavior *b;
4625#endif /* not ANSI_DECLARATORS */
4626
4627{
4628 pooldeinit(&m->triangles);
4629 trifree((VOID *) m->dummytribase);
4630 if (b->usesegments) {
4631 pooldeinit(&m->subsegs);
4632 trifree((VOID *) m->dummysubbase);
4633 }
4634 pooldeinit(&m->vertices);
4635#ifndef CDT_ONLY
4636 if (b->quality) {
4637 pooldeinit(&m->badsubsegs);
4638 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
4639 pooldeinit(&m->badtriangles);
4640 pooldeinit(&m->flipstackers);
4641 }
4642 }
4643#endif /* not CDT_ONLY */
4644}
4645
4648/********* Memory management routines end here *********/
4649
4650/********* Constructors begin here *********/
4653
4654/*****************************************************************************/
4655/* */
4656/* maketriangle() Create a new triangle with orientation zero. */
4657/* */
4658/*****************************************************************************/
4659
4660#ifdef ANSI_DECLARATORS
4661void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
4662#else /* not ANSI_DECLARATORS */
4663void maketriangle(m, b, newotri)
4664struct mesh *m;
4665struct behavior *b;
4667#endif /* not ANSI_DECLARATORS */
4668
4669{
4670 int i;
4671
4672 newotri->tri = (triangle *) poolalloc(&m->triangles);
4673 /* Initialize the three adjoining triangles to be "outer space". */
4674 newotri->tri[0] = (triangle) m->dummytri;
4675 newotri->tri[1] = (triangle) m->dummytri;
4676 newotri->tri[2] = (triangle) m->dummytri;
4677 /* Three NULL vertices. */
4678 newotri->tri[3] = (triangle) NULL;
4679 newotri->tri[4] = (triangle) NULL;
4680 newotri->tri[5] = (triangle) NULL;
4681 if (b->usesegments) {
4682 /* Initialize the three adjoining subsegments to be the omnipresent */
4683 /* subsegment. */
4684 newotri->tri[6] = (triangle) m->dummysub;
4685 newotri->tri[7] = (triangle) m->dummysub;
4686 newotri->tri[8] = (triangle) m->dummysub;
4687 }
4688 for (i = 0; i < m->eextras; i++) {
4689 setelemattribute(*newotri, i, 0.0);
4690 }
4691 if (b->vararea) {
4692 setareabound(*newotri, -1.0);
4693 }
4694
4695 newotri->orient = 0;
4696}
4697
4698/*****************************************************************************/
4699/* */
4700/* makesubseg() Create a new subsegment with orientation zero. */
4701/* */
4702/*****************************************************************************/
4703
4704#ifdef ANSI_DECLARATORS
4705void makesubseg(struct mesh *m, struct osub *newsubseg)
4706#else /* not ANSI_DECLARATORS */
4707void makesubseg(m, newsubseg)
4708struct mesh *m;
4709struct osub *newsubseg;
4710#endif /* not ANSI_DECLARATORS */
4711
4712{
4713 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
4714 /* Initialize the two adjoining subsegments to be the omnipresent */
4715 /* subsegment. */
4716 newsubseg->ss[0] = (subseg) m->dummysub;
4717 newsubseg->ss[1] = (subseg) m->dummysub;
4718 /* Four NULL vertices. */
4719 newsubseg->ss[2] = (subseg) NULL;
4720 newsubseg->ss[3] = (subseg) NULL;
4721 newsubseg->ss[4] = (subseg) NULL;
4722 newsubseg->ss[5] = (subseg) NULL;
4723 /* Initialize the two adjoining triangles to be "outer space." */
4724 newsubseg->ss[6] = (subseg) m->dummytri;
4725 newsubseg->ss[7] = (subseg) m->dummytri;
4726 /* Set the boundary marker to zero. */
4727 setmark(*newsubseg, 0);
4728
4729 newsubseg->ssorient = 0;
4730}
4731
4734/********* Constructors end here *********/
4735
4736/********* Geometric primitives begin here *********/
4739
4740/* The adaptive exact arithmetic geometric predicates implemented herein are */
4741/* described in detail in my paper, "Adaptive Precision Floating-Point */
4742/* Arithmetic and Fast Robust Geometric Predicates." See the header for a */
4743/* full citation. */
4744
4745/* Which of the following two methods of finding the absolute values is */
4746/* fastest is compiler-dependent. A few compilers can inline and optimize */
4747/* the fabs() call; but most will incur the overhead of a function call, */
4748/* which is disastrously slow. A faster way on IEEE machines might be to */
4749/* mask the appropriate bit, but that's difficult to do in C without */
4750/* forcing the value to be stored to memory (rather than be kept in the */
4751/* register to which the optimizer assigned it). */
4752
4753#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
4754/* #define Absolute(a) fabs(a) */
4755
4756/* Many of the operations are broken up into two pieces, a main part that */
4757/* performs an approximate operation, and a "tail" that computes the */
4758/* roundoff error of that operation. */
4759/* */
4760/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */
4761/* Split(), and Two_Product() are all implemented as described in the */
4762/* reference. Each of these macros requires certain variables to be */
4763/* defined in the calling routine. The variables `bvirt', `c', `abig', */
4764/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */
4765/* they store the result of an operation that may incur roundoff error. */
4766/* The input parameter `x' (or the highest numbered `x_' parameter) must */
4767/* also be declared `INEXACT'. */
4768
4769#define Fast_Two_Sum_Tail(a, b, x, y) \
4770 bvirt = x - a; \
4771 y = b - bvirt
4772
4773#define Fast_Two_Sum(a, b, x, y) \
4774 x = (REAL) (a + b); \
4775 Fast_Two_Sum_Tail(a, b, x, y)
4776
4777#define Two_Sum_Tail(a, b, x, y) \
4778 bvirt = (REAL) (x - a); \
4779 avirt = x - bvirt; \
4780 bround = b - bvirt; \
4781 around = a - avirt; \
4782 y = around + bround
4783
4784#define Two_Sum(a, b, x, y) \
4785 x = (REAL) (a + b); \
4786 Two_Sum_Tail(a, b, x, y)
4787
4788#define Two_Diff_Tail(a, b, x, y) \
4789 bvirt = (REAL) (a - x); \
4790 avirt = x + bvirt; \
4791 bround = bvirt - b; \
4792 around = a - avirt; \
4793 y = around + bround
4794
4795#define Two_Diff(a, b, x, y) \
4796 x = (REAL) (a - b); \
4797 Two_Diff_Tail(a, b, x, y)
4798
4799#define Split(a, ahi, alo) \
4800 c = (REAL) (splitter * a); \
4801 abig = (REAL) (c - a); \
4802 ahi = c - abig; \
4803 alo = a - ahi
4804
4805#define Two_Product_Tail(a, b, x, y) \
4806 Split(a, ahi, alo); \
4807 Split(b, bhi, blo); \
4808 err1 = x - (ahi * bhi); \
4809 err2 = err1 - (alo * bhi); \
4810 err3 = err2 - (ahi * blo); \
4811 y = (alo * blo) - err3
4812
4813#define Two_Product(a, b, x, y) \
4814 x = (REAL) (a * b); \
4815 Two_Product_Tail(a, b, x, y)
4816
4817/* Two_Product_Presplit() is Two_Product() where one of the inputs has */
4818/* already been split. Avoids redundant splitting. */
4819
4820#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
4821 x = (REAL) (a * b); \
4822 Split(a, ahi, alo); \
4823 err1 = x - (ahi * bhi); \
4824 err2 = err1 - (alo * bhi); \
4825 err3 = err2 - (ahi * blo); \
4826 y = (alo * blo) - err3
4827
4828/* Square() can be done more quickly than Two_Product(). */
4829
4830#define Square_Tail(a, x, y) \
4831 Split(a, ahi, alo); \
4832 err1 = x - (ahi * ahi); \
4833 err3 = err1 - ((ahi + ahi) * alo); \
4834 y = (alo * alo) - err3
4835
4836#define Square(a, x, y) \
4837 x = (REAL) (a * a); \
4838 Square_Tail(a, x, y)
4839
4840/* Macros for summing expansions of various fixed lengths. These are all */
4841/* unrolled versions of Expansion_Sum(). */
4842
4843#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
4844 Two_Sum(a0, b , _i, x0); \
4845 Two_Sum(a1, _i, x2, x1)
4846
4847#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
4848 Two_Diff(a0, b , _i, x0); \
4849 Two_Sum( a1, _i, x2, x1)
4850
4851#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
4852 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
4853 Two_One_Sum(_j, _0, b1, x3, x2, x1)
4854
4855#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
4856 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
4857 Two_One_Diff(_j, _0, b1, x3, x2, x1)
4858
4859/* Macro for multiplying a two-component expansion by a single component. */
4860
4861#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
4862 Split(b, bhi, blo); \
4863 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
4864 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
4865 Two_Sum(_i, _0, _k, x1); \
4866 Fast_Two_Sum(_j, _k, x3, x2)
4867
4868/*****************************************************************************/
4869/* */
4870/* exactinit() Initialize the variables used for exact arithmetic. */
4871/* */
4872/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
4873/* floating-point arithmetic. `epsilon' bounds the relative roundoff */
4874/* error. It is used for floating-point error analysis. */
4875/* */
4876/* `splitter' is used to split floating-point numbers into two half- */
4877/* length significands for exact multiplication. */
4878/* */
4879/* I imagine that a highly optimizing compiler might be too smart for its */
4880/* own good, and somehow cause this routine to fail, if it pretends that */
4881/* floating-point arithmetic is too much like real arithmetic. */
4882/* */
4883/* Don't change this routine unless you fully understand it. */
4884/* */
4885/*****************************************************************************/
4886
4888{
4889 REAL half;
4890 REAL check, lastcheck;
4891 int every_other;
4892#ifdef LINUX
4893 int cword;
4894#endif /* LINUX */
4895
4896#ifdef CPU86
4897#ifdef SINGLE
4898 _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */
4899#else /* not SINGLE */
4900 _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */
4901#endif /* not SINGLE */
4902#endif /* CPU86 */
4903#ifdef LINUX
4904#ifdef SINGLE
4905 /* cword = 4223; */
4906 cword = 4210; /* set FPU control word for single precision */
4907#else /* not SINGLE */
4908 /* cword = 4735; */
4909 cword = 4722; /* set FPU control word for double precision */
4910#endif /* not SINGLE */
4911 _FPU_SETCW(cword);
4912#endif /* LINUX */
4913
4914 every_other = 1;
4915 half = 0.5;
4916 epsilon = 1.0;
4917 splitter = 1.0;
4918 check = 1.0;
4919 /* Repeatedly divide `epsilon' by two until it is too small to add to */
4920 /* one without causing roundoff. (Also check if the sum is equal to */
4921 /* the previous sum, for machines that round up instead of using exact */
4922 /* rounding. Not that these routines will work on such machines.) */
4923 do {
4924 lastcheck = check;
4925 epsilon *= half;
4926 if (every_other) {
4927 splitter *= 2.0;
4928 }
4929 every_other = !every_other;
4930 check = 1.0 + epsilon;
4931 } while ((check != 1.0) && (check != lastcheck));
4932 splitter += 1.0;
4933 /* Error bounds for orientation and incircle tests. */
4934 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
4935 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
4936 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
4937 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
4938 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
4939 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
4940 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
4941 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
4942 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
4943 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
4944}
4945
4946/*****************************************************************************/
4947/* */
4948/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
4949/* components from the output expansion. */
4950/* */
4951/* Sets h = e + f. See my Robust Predicates paper for details. */
4952/* */
4953/* If round-to-even is used (as with IEEE 754), maintains the strongly */
4954/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
4955/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
4956/* properties. */
4957/* */
4958/*****************************************************************************/
4959
4960#ifdef ANSI_DECLARATORS
4961int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
4962#else /* not ANSI_DECLARATORS */
4963int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */
4965REAL *e;
4966int flen;
4967REAL *f;
4968REAL *h;
4969#endif /* not ANSI_DECLARATORS */
4970
4971{
4972 REAL Q;
4973 INEXACT REAL Qnew;
4974 INEXACT REAL hh;
4975 INEXACT REAL bvirt;
4978 REAL enow, fnow;
4979
4980 enow = e[0];
4981 fnow = f[0];
4982 eindex = findex = 0;
4983 if ((fnow > enow) == (fnow > -enow)) {
4984 Q = enow;
4985 enow = e[++eindex];
4986 } else {
4987 Q = fnow;
4988 fnow = f[++findex];
4989 }
4990 hindex = 0;
4991 if ((eindex < elen) && (findex < flen)) {
4992 if ((fnow > enow) == (fnow > -enow)) {
4993 Fast_Two_Sum(enow, Q, Qnew, hh);
4994 enow = e[++eindex];
4995 } else {
4996 Fast_Two_Sum(fnow, Q, Qnew, hh);
4997 fnow = f[++findex];
4998 }
4999 Q = Qnew;
5000 if (hh != 0.0) {
5001 h[hindex++] = hh;
5002 }
5003 while ((eindex < elen) && (findex < flen)) {
5004 if ((fnow > enow) == (fnow > -enow)) {
5005 Two_Sum(Q, enow, Qnew, hh);
5006 enow = e[++eindex];
5007 } else {
5008 Two_Sum(Q, fnow, Qnew, hh);
5009 fnow = f[++findex];
5010 }
5011 Q = Qnew;
5012 if (hh != 0.0) {
5013 h[hindex++] = hh;
5014 }
5015 }
5016 }
5017 while (eindex < elen) {
5018 Two_Sum(Q, enow, Qnew, hh);
5019 enow = e[++eindex];
5020 Q = Qnew;
5021 if (hh != 0.0) {
5022 h[hindex++] = hh;
5023 }
5024 }
5025 while (findex < flen) {
5026 Two_Sum(Q, fnow, Qnew, hh);
5027 fnow = f[++findex];
5028 Q = Qnew;
5029 if (hh != 0.0) {
5030 h[hindex++] = hh;
5031 }
5032 }
5033 if ((Q != 0.0) || (hindex == 0)) {
5034 h[hindex++] = Q;
5035 }
5036 return hindex;
5037}
5038
5039/*****************************************************************************/
5040/* */
5041/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */
5042/* eliminating zero components from the */
5043/* output expansion. */
5044/* */
5045/* Sets h = be. See my Robust Predicates paper for details. */
5046/* */
5047/* Maintains the nonoverlapping property. If round-to-even is used (as */
5048/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
5049/* properties as well. (That is, if e has one of these properties, so */
5050/* will h.) */
5051/* */
5052/*****************************************************************************/
5053
5054#ifdef ANSI_DECLARATORS
5055int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
5056#else /* not ANSI_DECLARATORS */
5057int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */
5058int elen;
5059REAL *e;
5060REAL b;
5061REAL *h;
5062#endif /* not ANSI_DECLARATORS */
5063
5064{
5065 INEXACT REAL Q, sum;
5066 REAL hh;
5067 INEXACT REAL product1;
5069 int eindex, hindex;
5070 REAL enow;
5071 INEXACT REAL bvirt;
5072 REAL avirt, bround, around;
5073 INEXACT REAL c;
5074 INEXACT REAL abig;
5075 REAL ahi, alo, bhi, blo;
5077
5080 hindex = 0;
5081 if (hh != 0) {
5082 h[hindex++] = hh;
5083 }
5084 for (eindex = 1; eindex < elen; eindex++) {
5085 enow = e[eindex];
5087 Two_Sum(Q, product0, sum, hh);
5088 if (hh != 0) {
5089 h[hindex++] = hh;
5090 }
5091 Fast_Two_Sum(product1, sum, Q, hh);
5092 if (hh != 0) {
5093 h[hindex++] = hh;
5094 }
5095 }
5096 if ((Q != 0.0) || (hindex == 0)) {
5097 h[hindex++] = Q;
5098 }
5099 return hindex;
5100}
5101
5102/*****************************************************************************/
5103/* */
5104/* estimate() Produce a one-word estimate of an expansion's value. */
5105/* */
5106/* See my Robust Predicates paper for details. */
5107/* */
5108/*****************************************************************************/
5109
5110#ifdef ANSI_DECLARATORS
5111REAL estimate(int elen, REAL *e)
5112#else /* not ANSI_DECLARATORS */
5113REAL estimate(elen, e)
5114int elen;
5115REAL *e;
5116#endif /* not ANSI_DECLARATORS */
5117
5118{
5119 REAL Q;
5120 int eindex;
5121
5122 Q = e[0];
5123 for (eindex = 1; eindex < elen; eindex++) {
5124 Q += e[eindex];
5125 }
5126 return Q;
5127}
5128
5129/*****************************************************************************/
5130/* */
5131/* counterclockwise() Return a positive value if the points pa, pb, and */
5132/* pc occur in counterclockwise order; a negative */
5133/* value if they occur in clockwise order; and zero */
5134/* if they are collinear. The result is also a rough */
5135/* approximation of twice the signed area of the */
5136/* triangle defined by the three points. */
5137/* */
5138/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5139/* result returned is the determinant of a matrix. This determinant is */
5140/* computed adaptively, in the sense that exact arithmetic is used only to */
5141/* the degree it is needed to ensure that the returned value has the */
5142/* correct sign. Hence, this function is usually quite fast, but will run */
5143/* more slowly when the input points are collinear or nearly so. */
5144/* */
5145/* See my Robust Predicates paper for details. */
5146/* */
5147/*****************************************************************************/
5148
5149#ifdef ANSI_DECLARATORS
5151#else /* not ANSI_DECLARATORS */
5154vertex pb;
5155vertex pc;
5157#endif /* not ANSI_DECLARATORS */
5158
5159{
5160 INEXACT REAL acx, acy, bcx, bcy;
5162 INEXACT REAL detleft, detright;
5165 REAL B[4], C1[8], C2[12], D[16];
5166 INEXACT REAL B3;
5168 REAL u[4];
5169 INEXACT REAL u3;
5170 INEXACT REAL s1, t1;
5171 REAL s0, t0;
5172
5173 INEXACT REAL bvirt;
5174 REAL avirt, bround, around;
5175 INEXACT REAL c;
5176 INEXACT REAL abig;
5177 REAL ahi, alo, bhi, blo;
5178 REAL err1, err2, err3;
5179 INEXACT REAL _i, _j;
5180 REAL _0;
5181
5182 acx = (REAL) (pa[0] - pc[0]);
5183 bcx = (REAL) (pb[0] - pc[0]);
5184 acy = (REAL) (pa[1] - pc[1]);
5185 bcy = (REAL) (pb[1] - pc[1]);
5186
5189
5191 B3, B[2], B[1], B[0]);
5192 B[3] = B3;
5193
5194 det = estimate(4, B);
5196 if ((det >= errbound) || (-det >= errbound)) {
5197 return det;
5198 }
5199
5204
5205 if ((acxtail == 0.0) && (acytail == 0.0)
5206 && (bcxtail == 0.0) && (bcytail == 0.0)) {
5207 return det;
5208 }
5209
5210 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
5211 det += (acx * bcytail + bcy * acxtail)
5212 - (acy * bcxtail + bcx * acytail);
5213 if ((det >= errbound) || (-det >= errbound)) {
5214 return det;
5215 }
5216
5219 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5220 u[3] = u3;
5222
5225 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5226 u[3] = u3;
5228
5231 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5232 u[3] = u3;
5234
5235 return(D[Dlength - 1]);
5236}
5237
5238#ifdef ANSI_DECLARATORS
5239REAL counterclockwise(struct mesh *m, struct behavior *b,
5241#else /* not ANSI_DECLARATORS */
5242REAL counterclockwise(m, b, pa, pb, pc)
5243struct mesh *m;
5244struct behavior *b;
5245vertex pa;
5246vertex pb;
5247vertex pc;
5248#endif /* not ANSI_DECLARATORS */
5249
5250{
5251 REAL detleft, detright, det;
5252 REAL detsum, errbound;
5253
5254 m->counterclockcount++;
5255
5256 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
5257 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
5258 det = detleft - detright;
5259
5260 if (b->noexact) {
5261 return det;
5262 }
5263
5264 if (detleft > 0.0) {
5265 if (detright <= 0.0) {
5266 return det;
5267 } else {
5269 }
5270 } else if (detleft < 0.0) {
5271 if (detright >= 0.0) {
5272 return det;
5273 } else {
5274 detsum = -detleft - detright;
5275 }
5276 } else {
5277 return det;
5278 }
5279
5281 if ((det >= errbound) || (-det >= errbound)) {
5282 return det;
5283 }
5284
5286}
5287
5288/*****************************************************************************/
5289/* */
5290/* incircle() Return a positive value if the point pd lies inside the */
5291/* circle passing through pa, pb, and pc; a negative value if */
5292/* it lies outside; and zero if the four points are cocircular.*/
5293/* The points pa, pb, and pc must be in counterclockwise */
5294/* order, or the sign of the result will be reversed. */
5295/* */
5296/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5297/* result returned is the determinant of a matrix. This determinant is */
5298/* computed adaptively, in the sense that exact arithmetic is used only to */
5299/* the degree it is needed to ensure that the returned value has the */
5300/* correct sign. Hence, this function is usually quite fast, but will run */
5301/* more slowly when the input points are cocircular or nearly so. */
5302/* */
5303/* See my Robust Predicates paper for details. */
5304/* */
5305/*****************************************************************************/
5306
5307#ifdef ANSI_DECLARATORS
5309#else /* not ANSI_DECLARATORS */
5311vertex pa;
5312vertex pb;
5313vertex pc;
5314vertex pd;
5316#endif /* not ANSI_DECLARATORS */
5317
5318{
5319 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
5320 REAL det, errbound;
5321
5324 REAL bc[4], ca[4], ab[4];
5325 INEXACT REAL bc3, ca3, ab3;
5326 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
5328 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
5330 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
5332 REAL abdet[64];
5334 REAL fin1[1152], fin2[1152];
5337
5341 REAL aa[4], bb[4], cc[4];
5342 INEXACT REAL aa3, bb3, cc3;
5343 INEXACT REAL ti1, tj1;
5344 REAL ti0, tj0;
5345 REAL u[4], v[4];
5346 INEXACT REAL u3, v3;
5347 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
5348 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
5351 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
5353 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
5355 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
5357 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
5359 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
5361 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
5362 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
5364 REAL abt[8], bct[8], cat[8];
5366 REAL abtt[4], bctt[4], catt[4];
5368 INEXACT REAL abtt3, bctt3, catt3;
5370
5371 INEXACT REAL bvirt;
5372 REAL avirt, bround, around;
5373 INEXACT REAL c;
5374 INEXACT REAL abig;
5375 REAL ahi, alo, bhi, blo;
5376 REAL err1, err2, err3;
5377 INEXACT REAL _i, _j;
5378 REAL _0;
5379
5380 adx = (REAL) (pa[0] - pd[0]);
5381 bdx = (REAL) (pb[0] - pd[0]);
5382 cdx = (REAL) (pc[0] - pd[0]);
5383 ady = (REAL) (pa[1] - pd[1]);
5384 bdy = (REAL) (pb[1] - pd[1]);
5385 cdy = (REAL) (pc[1] - pd[1]);
5386
5390 bc[3] = bc3;
5396
5400 ca[3] = ca3;
5406
5410 ab[3] = ab3;
5416
5419
5422 if ((det >= errbound) || (-det >= errbound)) {
5423 return det;
5424 }
5425
5432 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
5433 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
5434 return det;
5435 }
5436
5438 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
5439 - (bdy * cdxtail + cdx * bdytail))
5440 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
5441 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
5442 - (cdy * adxtail + adx * cdytail))
5443 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
5444 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
5445 - (ady * bdxtail + bdx * adytail))
5446 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
5447 if ((det >= errbound) || (-det >= errbound)) {
5448 return det;
5449 }
5450
5451 finnow = fin1;
5452 finother = fin2;
5453
5454 if ((bdxtail != 0.0) || (bdytail != 0.0)
5455 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5456 Square(adx, adxadx1, adxadx0);
5457 Square(ady, adyady1, adyady0);
5458 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
5459 aa[3] = aa3;
5460 }
5461 if ((cdxtail != 0.0) || (cdytail != 0.0)
5462 || (adxtail != 0.0) || (adytail != 0.0)) {
5463 Square(bdx, bdxbdx1, bdxbdx0);
5464 Square(bdy, bdybdy1, bdybdy0);
5465 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
5466 bb[3] = bb3;
5467 }
5468 if ((adxtail != 0.0) || (adytail != 0.0)
5469 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5470 Square(cdx, cdxcdx1, cdxcdx0);
5471 Square(cdy, cdycdy1, cdycdy0);
5472 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
5473 cc[3] = cc3;
5474 }
5475
5590
5591 if ((adxtail != 0.0) || (adytail != 0.0)) {
5592 if ((bdxtail != 0.0) || (bdytail != 0.0)
5593 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5596 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5597 u[3] = u3;
5598 negate = -bdy;
5600 negate = -bdytail;
5602 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5603 v[3] = v3;
5605
5608 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
5609 bctt[3] = bctt3;
5610 bcttlen = 4;
5611 } else {
5612 bct[0] = 0.0;
5613 bctlen = 1;
5614 bctt[0] = 0.0;
5615 bcttlen = 1;
5616 }
5617
5618 if (adxtail != 0.0) {
5622 temp32a);
5626 temp48, finother);
5628 if (bdytail != 0.0) {
5631 temp16a);
5633 temp16a, finother);
5635 }
5636 if (cdytail != 0.0) {
5639 temp16a);
5641 temp16a, finother);
5643 }
5644
5646 temp32a);
5649 temp16a);
5651 temp16b);
5657 temp64, finother);
5659 }
5660 if (adytail != 0.0) {
5664 temp32a);
5668 temp48, finother);
5670
5671
5673 temp32a);
5676 temp16a);
5678 temp16b);
5684 temp64, finother);
5686 }
5687 }
5688 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
5689 if ((cdxtail != 0.0) || (cdytail != 0.0)
5690 || (adxtail != 0.0) || (adytail != 0.0)) {
5693 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5694 u[3] = u3;
5695 negate = -cdy;
5697 negate = -cdytail;
5699 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5700 v[3] = v3;
5702
5705 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
5706 catt[3] = catt3;
5707 cattlen = 4;
5708 } else {
5709 cat[0] = 0.0;
5710 catlen = 1;
5711 catt[0] = 0.0;
5712 cattlen = 1;
5713 }
5714
5715 if (bdxtail != 0.0) {
5719 temp32a);
5723 temp48, finother);
5725 if (cdytail != 0.0) {
5728 temp16a);
5730 temp16a, finother);
5732 }
5733 if (adytail != 0.0) {
5736 temp16a);
5738 temp16a, finother);
5740 }
5741
5743 temp32a);
5746 temp16a);
5748 temp16b);
5754 temp64, finother);
5756 }
5757 if (bdytail != 0.0) {
5761 temp32a);
5765 temp48, finother);
5767
5768
5770 temp32a);
5773 temp16a);
5775 temp16b);
5781 temp64, finother);
5783 }
5784 }
5785 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
5786 if ((adxtail != 0.0) || (adytail != 0.0)
5787 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5790 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5791 u[3] = u3;
5792 negate = -ady;
5794 negate = -adytail;
5796 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5797 v[3] = v3;
5799
5802 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
5803 abtt[3] = abtt3;
5804 abttlen = 4;
5805 } else {
5806 abt[0] = 0.0;
5807 abtlen = 1;
5808 abtt[0] = 0.0;
5809 abttlen = 1;
5810 }
5811
5812 if (cdxtail != 0.0) {
5816 temp32a);
5820 temp48, finother);
5822 if (adytail != 0.0) {
5825 temp16a);
5827 temp16a, finother);
5829 }
5830 if (bdytail != 0.0) {
5833 temp16a);
5835 temp16a, finother);
5837 }
5838
5840 temp32a);
5843 temp16a);
5845 temp16b);
5851 temp64, finother);
5853 }
5854 if (cdytail != 0.0) {
5858 temp32a);
5862 temp48, finother);
5864
5865
5867 temp32a);
5870 temp16a);
5872 temp16b);
5878 temp64, finother);
5880 }
5881 }
5882
5883 return finnow[finlength - 1];
5884}
5885
5886#ifdef ANSI_DECLARATORS
5887REAL incircle(struct mesh *m, struct behavior *b,
5889#else /* not ANSI_DECLARATORS */
5890REAL incircle(m, b, pa, pb, pc, pd)
5891struct mesh *m;
5892struct behavior *b;
5893vertex pa;
5894vertex pb;
5895vertex pc;
5896vertex pd;
5897#endif /* not ANSI_DECLARATORS */
5898
5899{
5900 REAL adx, bdx, cdx, ady, bdy, cdy;
5903 REAL det;
5904 REAL permanent, errbound;
5905
5906 m->incirclecount++;
5907
5908 adx = pa[0] - pd[0];
5909 bdx = pb[0] - pd[0];
5910 cdx = pc[0] - pd[0];
5911 ady = pa[1] - pd[1];
5912 bdy = pb[1] - pd[1];
5913 cdy = pc[1] - pd[1];
5914
5915 bdxcdy = bdx * cdy;
5916 cdxbdy = cdx * bdy;
5917 alift = adx * adx + ady * ady;
5918
5919 cdxady = cdx * ady;
5920 adxcdy = adx * cdy;
5921 blift = bdx * bdx + bdy * bdy;
5922
5923 adxbdy = adx * bdy;
5924 bdxady = bdx * ady;
5925 clift = cdx * cdx + cdy * cdy;
5926
5927 det = alift * (bdxcdy - cdxbdy)
5928 + blift * (cdxady - adxcdy)
5929 + clift * (adxbdy - bdxady);
5930
5931 if (b->noexact) {
5932 return det;
5933 }
5934
5935 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
5936 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
5937 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
5939 if ((det > errbound) || (-det > errbound)) {
5940 return det;
5941 }
5942
5944}
5945
5946/*****************************************************************************/
5947/* */
5948/* orient3d() Return a positive value if the point pd lies below the */
5949/* plane passing through pa, pb, and pc; "below" is defined so */
5950/* that pa, pb, and pc appear in counterclockwise order when */
5951/* viewed from above the plane. Returns a negative value if */
5952/* pd lies above the plane. Returns zero if the points are */
5953/* coplanar. The result is also a rough approximation of six */
5954/* times the signed volume of the tetrahedron defined by the */
5955/* four points. */
5956/* */
5957/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5958/* result returned is the determinant of a matrix. This determinant is */
5959/* computed adaptively, in the sense that exact arithmetic is used only to */
5960/* the degree it is needed to ensure that the returned value has the */
5961/* correct sign. Hence, this function is usually quite fast, but will run */
5962/* more slowly when the input points are coplanar or nearly so. */
5963/* */
5964/* See my Robust Predicates paper for details. */
5965/* */
5966/*****************************************************************************/
5967
5968#ifdef ANSI_DECLARATORS
5970 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
5971 REAL permanent)
5972#else /* not ANSI_DECLARATORS */
5973REAL orient3dadapt(pa, pb, pc, pd,
5975vertex pa;
5976vertex pb;
5977vertex pc;
5978vertex pd;
5979REAL aheight;
5980REAL bheight;
5981REAL cheight;
5982REAL dheight;
5983REAL permanent;
5984#endif /* not ANSI_DECLARATORS */
5985
5986{
5987 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
5988 REAL det, errbound;
5989
5990 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5992 REAL bc[4], ca[4], ab[4];
5993 INEXACT REAL bc3, ca3, ab3;
5994 REAL adet[8], bdet[8], cdet[8];
5995 int alen, blen, clen;
5996 REAL abdet[16];
5997 int ablen;
5998 REAL *finnow, *finother, *finswap;
5999 REAL fin1[192], fin2[192];
6000 int finlength;
6001
6002 REAL adxtail, bdxtail, cdxtail;
6003 REAL adytail, bdytail, cdytail;
6005 INEXACT REAL at_blarge, at_clarge;
6006 INEXACT REAL bt_clarge, bt_alarge;
6007 INEXACT REAL ct_alarge, ct_blarge;
6008 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
6018 REAL bct[8], cat[8], abt[8];
6019 int bctlen, catlen, abtlen;
6024 REAL u[4], v[12], w[16];
6025 INEXACT REAL u3;
6027 REAL negate;
6028
6029 INEXACT REAL bvirt;
6030 REAL avirt, bround, around;
6031 INEXACT REAL c;
6032 INEXACT REAL abig;
6033 REAL ahi, alo, bhi, blo;
6034 REAL err1, err2, err3;
6035 INEXACT REAL _i, _j, _k;
6036 REAL _0;
6037
6038 adx = (REAL) (pa[0] - pd[0]);
6039 bdx = (REAL) (pb[0] - pd[0]);
6040 cdx = (REAL) (pc[0] - pd[0]);
6041 ady = (REAL) (pa[1] - pd[1]);
6042 bdy = (REAL) (pb[1] - pd[1]);
6043 cdy = (REAL) (pc[1] - pd[1]);
6047
6051 bc[3] = bc3;
6053
6057 ca[3] = ca3;
6059
6063 ab[3] = ab3;
6065
6068
6071 if ((det >= errbound) || (-det >= errbound)) {
6072 return det;
6073 }
6074
6075 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
6076 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
6077 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
6078 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
6079 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
6080 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
6084
6085 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
6086 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
6087 (adheighttail == 0.0) &&
6088 (bdheighttail == 0.0) &&
6089 (cdheighttail == 0.0)) {
6090 return det;
6091 }
6092
6094 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
6095 (bdy * cdxtail + cdx * bdytail)) +
6096 adheighttail * (bdx * cdy - bdy * cdx)) +
6097 (bdheight * ((cdx * adytail + ady * cdxtail) -
6098 (cdy * adxtail + adx * cdytail)) +
6099 bdheighttail * (cdx * ady - cdy * adx)) +
6100 (cdheight * ((adx * bdytail + bdy * adxtail) -
6101 (ady * bdxtail + bdx * adytail)) +
6102 cdheighttail * (adx * bdy - ady * bdx));
6103 if ((det >= errbound) || (-det >= errbound)) {
6104 return det;
6105 }
6106
6107 finnow = fin1;
6108 finother = fin2;
6109
6110 if (adxtail == 0.0) {
6111 if (adytail == 0.0) {
6112 at_b[0] = 0.0;
6113 at_blen = 1;
6114 at_c[0] = 0.0;
6115 at_clen = 1;
6116 } else {
6117 negate = -adytail;
6119 at_b[1] = at_blarge;
6120 at_blen = 2;
6122 at_c[1] = at_clarge;
6123 at_clen = 2;
6124 }
6125 } else {
6126 if (adytail == 0.0) {
6128 at_b[1] = at_blarge;
6129 at_blen = 2;
6130 negate = -adxtail;
6132 at_c[1] = at_clarge;
6133 at_clen = 2;
6134 } else {
6138 at_blarge, at_b[2], at_b[1], at_b[0]);
6139 at_b[3] = at_blarge;
6140 at_blen = 4;
6144 at_clarge, at_c[2], at_c[1], at_c[0]);
6145 at_c[3] = at_clarge;
6146 at_clen = 4;
6147 }
6148 }
6149 if (bdxtail == 0.0) {
6150 if (bdytail == 0.0) {
6151 bt_c[0] = 0.0;
6152 bt_clen = 1;
6153 bt_a[0] = 0.0;
6154 bt_alen = 1;
6155 } else {
6156 negate = -bdytail;
6158 bt_c[1] = bt_clarge;
6159 bt_clen = 2;
6161 bt_a[1] = bt_alarge;
6162 bt_alen = 2;
6163 }
6164 } else {
6165 if (bdytail == 0.0) {
6167 bt_c[1] = bt_clarge;
6168 bt_clen = 2;
6169 negate = -bdxtail;
6171 bt_a[1] = bt_alarge;
6172 bt_alen = 2;
6173 } else {
6177 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
6178 bt_c[3] = bt_clarge;
6179 bt_clen = 4;
6183 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
6184 bt_a[3] = bt_alarge;
6185 bt_alen = 4;
6186 }
6187 }
6188 if (cdxtail == 0.0) {
6189 if (cdytail == 0.0) {
6190 ct_a[0] = 0.0;
6191 ct_alen = 1;
6192 ct_b[0] = 0.0;
6193 ct_blen = 1;
6194 } else {
6195 negate = -cdytail;
6197 ct_a[1] = ct_alarge;
6198 ct_alen = 2;
6200 ct_b[1] = ct_blarge;
6201 ct_blen = 2;
6202 }
6203 } else {
6204 if (cdytail == 0.0) {
6206 ct_a[1] = ct_alarge;
6207 ct_alen = 2;
6208 negate = -cdxtail;
6210 ct_b[1] = ct_blarge;
6211 ct_blen = 2;
6212 } else {
6216 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
6217 ct_a[3] = ct_alarge;
6218 ct_alen = 4;
6222 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
6223 ct_b[3] = ct_blarge;
6224 ct_blen = 4;
6225 }
6226 }
6227
6231 finother);
6233
6237 finother);
6239
6243 finother);
6245
6264
6265 if (adxtail != 0.0) {
6266 if (bdytail != 0.0) {
6268 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
6269 u[3] = u3;
6271 finother);
6273 if (cdheighttail != 0.0) {
6274 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
6275 u3, u[2], u[1], u[0]);
6276 u[3] = u3;
6278 finother);
6280 }
6281 }
6282 if (cdytail != 0.0) {
6283 negate = -adxtail;
6285 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
6286 u[3] = u3;
6288 finother);
6290 if (bdheighttail != 0.0) {
6291 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
6292 u3, u[2], u[1], u[0]);
6293 u[3] = u3;
6295 finother);
6297 }
6298 }
6299 }
6300 if (bdxtail != 0.0) {
6301 if (cdytail != 0.0) {
6303 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
6304 u[3] = u3;
6306 finother);
6308 if (adheighttail != 0.0) {
6309 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
6310 u3, u[2], u[1], u[0]);
6311 u[3] = u3;
6313 finother);
6315 }
6316 }
6317 if (adytail != 0.0) {
6318 negate = -bdxtail;
6320 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
6321 u[3] = u3;
6323 finother);
6325 if (cdheighttail != 0.0) {
6326 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
6327 u3, u[2], u[1], u[0]);
6328 u[3] = u3;
6330 finother);
6332 }
6333 }
6334 }
6335 if (cdxtail != 0.0) {
6336 if (adytail != 0.0) {
6338 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
6339 u[3] = u3;
6341 finother);
6343 if (bdheighttail != 0.0) {
6344 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
6345 u3, u[2], u[1], u[0]);
6346 u[3] = u3;
6348 finother);
6350 }
6351 }
6352 if (bdytail != 0.0) {
6353 negate = -cdxtail;
6355 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
6356 u[3] = u3;
6358 finother);
6360 if (adheighttail != 0.0) {
6361 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
6362 u3, u[2], u[1], u[0]);
6363 u[3] = u3;
6365 finother);
6367 }
6368 }
6369 }
6370
6371 if (adheighttail != 0.0) {
6374 finother);
6376 }
6377 if (bdheighttail != 0.0) {
6380 finother);
6382 }
6383 if (cdheighttail != 0.0) {
6386 finother);
6388 }
6389
6390 return finnow[finlength - 1];
6391}
6392
6393#ifdef ANSI_DECLARATORS
6394REAL orient3d(struct mesh *m, struct behavior *b,
6396 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
6397#else /* not ANSI_DECLARATORS */
6399struct mesh *m;
6400struct behavior *b;
6401vertex pa;
6402vertex pb;
6403vertex pc;
6404vertex pd;
6405REAL aheight;
6406REAL bheight;
6407REAL cheight;
6408REAL dheight;
6409#endif /* not ANSI_DECLARATORS */
6410
6411{
6412 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6414 REAL det;
6415 REAL permanent, errbound;
6416
6417 m->orient3dcount++;
6418
6419 adx = pa[0] - pd[0];
6420 bdx = pb[0] - pd[0];
6421 cdx = pc[0] - pd[0];
6422 ady = pa[1] - pd[1];
6423 bdy = pb[1] - pd[1];
6424 cdy = pc[1] - pd[1];
6428
6429 bdxcdy = bdx * cdy;
6430 cdxbdy = cdx * bdy;
6431
6432 cdxady = cdx * ady;
6433 adxcdy = adx * cdy;
6434
6435 adxbdy = adx * bdy;
6436 bdxady = bdx * ady;
6437
6438 det = adheight * (bdxcdy - cdxbdy)
6439 + bdheight * (cdxady - adxcdy)
6440 + cdheight * (adxbdy - bdxady);
6441
6442 if (b->noexact) {
6443 return det;
6444 }
6445
6446 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
6447 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
6448 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
6450 if ((det > errbound) || (-det > errbound)) {
6451 return det;
6452 }
6453
6455 permanent);
6456}
6457
6458/*****************************************************************************/
6459/* */
6460/* nonregular() Return a positive value if the point pd is incompatible */
6461/* with the circle or plane passing through pa, pb, and pc */
6462/* (meaning that pd is inside the circle or below the */
6463/* plane); a negative value if it is compatible; and zero if */
6464/* the four points are cocircular/coplanar. The points pa, */
6465/* pb, and pc must be in counterclockwise order, or the sign */
6466/* of the result will be reversed. */
6467/* */
6468/* If the -w switch is used, the points are lifted onto the parabolic */
6469/* lifting map, then they are dropped according to their weights, then the */
6470/* 3D orientation test is applied. If the -W switch is used, the points' */
6471/* heights are already provided, so the 3D orientation test is applied */
6472/* directly. If neither switch is used, the incircle test is applied. */
6473/* */
6474/*****************************************************************************/
6475
6476#ifdef ANSI_DECLARATORS
6477REAL nonregular(struct mesh *m, struct behavior *b,
6479#else /* not ANSI_DECLARATORS */
6480REAL nonregular(m, b, pa, pb, pc, pd)
6481struct mesh *m;
6482struct behavior *b;
6483vertex pa;
6484vertex pb;
6485vertex pc;
6486vertex pd;
6487#endif /* not ANSI_DECLARATORS */
6488
6489{
6490 if (b->weighted == 0) {
6491 return incircle(m, b, pa, pb, pc, pd);
6492 } else if (b->weighted == 1) {
6493 return orient3d(m, b, pa, pb, pc, pd,
6494 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
6495 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
6496 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
6497 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
6498 } else {
6499 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
6500 }
6501}
6502
6503/*****************************************************************************/
6504/* */
6505/* findcircumcenter() Find the circumcenter of a triangle. */
6506/* */
6507/* The result is returned both in terms of x-y coordinates and xi-eta */
6508/* (barycentric) coordinates. The xi-eta coordinate system is defined in */
6509/* terms of the triangle: the origin of the triangle is the origin of the */
6510/* coordinate system; the destination of the triangle is one unit along the */
6511/* xi axis; and the apex of the triangle is one unit along the eta axis. */
6512/* This procedure also returns the square of the length of the triangle's */
6513/* shortest edge. */
6514/* */
6515/*****************************************************************************/
6516
6517#ifdef ANSI_DECLARATORS
6518void findcircumcenter(struct mesh *m, struct behavior *b,
6520 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
6521#else /* not ANSI_DECLARATORS */
6522void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
6523 offcenter)
6524struct mesh *m;
6525struct behavior *b;
6530REAL *xi;
6531REAL *eta;
6533#endif /* not ANSI_DECLARATORS */
6534
6535{
6536 REAL xdo, ydo, xao, yao;
6539 REAL dx, dy, dxoff, dyoff;
6540
6541 m->circumcentercount++;
6542
6543 /* Compute the circumcenter of the triangle. */
6544 xdo = tdest[0] - torg[0];
6545 ydo = tdest[1] - torg[1];
6546 xao = tapex[0] - torg[0];
6547 yao = tapex[1] - torg[1];
6548 dodist = xdo * xdo + ydo * ydo;
6549 aodist = xao * xao + yao * yao;
6550 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
6551 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
6552 if (b->noexact) {
6553 denominator = 0.5 / (xdo * yao - xao * ydo);
6554 } else {
6555 /* Use the counterclockwise() routine to ensure a positive (and */
6556 /* reasonably accurate) result, avoiding any possibility of */
6557 /* division by zero. */
6559 /* Don't count the above as an orientation test. */
6560 m->counterclockcount--;
6561 }
6562 dx = (yao * dodist - ydo * aodist) * denominator;
6563 dy = (xdo * aodist - xao * dodist) * denominator;
6564
6565 /* Find the (squared) length of the triangle's shortest edge. This */
6566 /* serves as a conservative estimate of the insertion radius of the */
6567 /* circumcenter's parent. The estimate is used to ensure that */
6568 /* the algorithm terminates even if very small angles appear in */
6569 /* the input PSLG. */
6570 if ((dodist < aodist) && (dodist < dadist)) {
6571 if (offcenter && (b->offconstant > 0.0)) {
6572 /* Find the position of the off-center, as described by Alper Ungor. */
6573 dxoff = 0.5 * xdo - b->offconstant * ydo;
6574 dyoff = 0.5 * ydo + b->offconstant * xdo;
6575 /* If the off-center is closer to the origin than the */
6576 /* circumcenter, use the off-center instead. */
6577 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6578 dx = dxoff;
6579 dy = dyoff;
6580 }
6581 }
6582 } else if (aodist < dadist) {
6583 if (offcenter && (b->offconstant > 0.0)) {
6584 dxoff = 0.5 * xao + b->offconstant * yao;
6585 dyoff = 0.5 * yao - b->offconstant * xao;
6586 /* If the off-center is closer to the origin than the */
6587 /* circumcenter, use the off-center instead. */
6588 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6589 dx = dxoff;
6590 dy = dyoff;
6591 }
6592 }
6593 } else {
6594 if (offcenter && (b->offconstant > 0.0)) {
6595 dxoff = 0.5 * (tapex[0] - tdest[0]) -
6596 b->offconstant * (tapex[1] - tdest[1]);
6597 dyoff = 0.5 * (tapex[1] - tdest[1]) +
6598 b->offconstant * (tapex[0] - tdest[0]);
6599 /* If the off-center is closer to the destination than the */
6600 /* circumcenter, use the off-center instead. */
6601 if (dxoff * dxoff + dyoff * dyoff <
6602 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
6603 dx = xdo + dxoff;
6604 dy = ydo + dyoff;
6605 }
6606 }
6607 }
6608
6609 circumcenter[0] = torg[0] + dx;
6610 circumcenter[1] = torg[1] + dy;
6611
6612 /* To interpolate vertex attributes for the new vertex inserted at */
6613 /* the circumcenter, define a coordinate system with a xi-axis, */
6614 /* directed from the triangle's origin to its destination, and */
6615 /* an eta-axis, directed from its origin to its apex. */
6616 /* Calculate the xi and eta coordinates of the circumcenter. */
6617 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
6618 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
6619}
6620
6623/********* Geometric primitives end here *********/
6624
6625/*****************************************************************************/
6626/* */
6627/* triangleinit() Initialize some variables. */
6628/* */
6629/*****************************************************************************/
6630
6631#ifdef ANSI_DECLARATORS
6632void triangleinit(struct mesh *m)
6633#else /* not ANSI_DECLARATORS */
6634void triangleinit(m)
6635struct mesh *m;
6636#endif /* not ANSI_DECLARATORS */
6637
6638{
6639 poolzero(&m->vertices);
6640 poolzero(&m->triangles);
6641 poolzero(&m->subsegs);
6642 poolzero(&m->viri);
6643 poolzero(&m->badsubsegs);
6644 poolzero(&m->badtriangles);
6645 poolzero(&m->flipstackers);
6646 poolzero(&m->splaynodes);
6647
6648 m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */
6649 m->undeads = 0; /* No eliminated input vertices yet. */
6650 m->samples = 1; /* Point location should take at least one sample. */
6651 m->checksegments = 0; /* There are no segments in the triangulation yet. */
6652 m->checkquality = 0; /* The quality triangulation stage has not begun. */
6653 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
6654 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
6655 randomseed = 1;
6656
6657 exactinit(); /* Initialize exact arithmetic constants. */
6658}
6659
6660/*****************************************************************************/
6661/* */
6662/* randomnation() Generate a random number between 0 and `choices' - 1. */
6663/* */
6664/* This is a simple linear congruential random number generator. Hence, it */
6665/* is a bad random number generator, but good enough for most randomized */
6666/* geometric algorithms. */
6667/* */
6668/*****************************************************************************/
6669
6670#ifdef ANSI_DECLARATORS
6671unsigned long randomnation(unsigned int choices)
6672#else /* not ANSI_DECLARATORS */
6673unsigned long randomnation(choices)
6674unsigned int choices;
6675#endif /* not ANSI_DECLARATORS */
6676
6677{
6678 randomseed = (randomseed * 1366l + 150889l) % 714025l;
6679 return randomseed / (714025l / choices + 1);
6680}
6681
6682/********* Mesh quality testing routines begin here *********/
6685
6686/*****************************************************************************/
6687/* */
6688/* checkmesh() Test the mesh for topological consistency. */
6689/* */
6690/*****************************************************************************/
6691
6692#ifndef REDUCED
6693
6694#ifdef ANSI_DECLARATORS
6695void checkmesh(struct mesh *m, struct behavior *b)
6696#else /* not ANSI_DECLARATORS */
6697void checkmesh(m, b)
6698struct mesh *m;
6699struct behavior *b;
6700#endif /* not ANSI_DECLARATORS */
6701
6702{
6703 struct otri triangleloop;
6709 triangle ptr; /* Temporary variable used by sym(). */
6710
6711 /* Temporarily turn on exact arithmetic if it's off. */
6712 saveexact = b->noexact;
6713 b->noexact = 0;
6714 if (!b->quiet) {
6715 printf(" Checking consistency of mesh...\n");
6716 }
6717 horrors = 0;
6718 /* Run through the list of triangles, checking each one. */
6719 traversalinit(&m->triangles);
6721 while (triangleloop.tri != (triangle *) NULL) {
6722 /* Check all three edges of the triangle. */
6723 for (triangleloop.orient = 0; triangleloop.orient < 3;
6724 triangleloop.orient++) {
6727 if (triangleloop.orient == 0) { /* Only test for inversion once. */
6728 /* Test if the triangle is flat or inverted. */
6730 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
6731 printf(" !! !! Inverted ");
6733 horrors++;
6734 }
6735 }
6736 /* Find the neighboring triangle on this edge. */
6738 if (oppotri.tri != m->dummytri) {
6739 /* Check that the triangle's neighbor knows it's a neighbor. */
6741 if ((triangleloop.tri != oppooppotri.tri)
6742 || (triangleloop.orient != oppooppotri.orient)) {
6743 printf(" !! !! Asymmetric triangle-triangle bond:\n");
6744 if (triangleloop.tri == oppooppotri.tri) {
6745 printf(" (Right triangle, wrong orientation)\n");
6746 }
6747 printf(" First ");
6749 printf(" Second (nonreciprocating) ");
6751 horrors++;
6752 }
6753 /* Check that both triangles agree on the identities */
6754 /* of their shared vertices. */
6757 if ((triorg != oppodest) || (tridest != oppoorg)) {
6758 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
6759 );
6760 printf(" First mismatched ");
6762 printf(" Second mismatched ");
6764 horrors++;
6765 }
6766 }
6767 }
6769 }
6770 if (horrors == 0) {
6771 if (!b->quiet) {
6772 printf(" In my studied opinion, the mesh appears to be consistent.\n");
6773 }
6774 } else if (horrors == 1) {
6775 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
6776 } else {
6777 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
6778 }
6779 /* Restore the status of exact arithmetic. */
6780 b->noexact = saveexact;
6781}
6782
6783#endif /* not REDUCED */
6784
6785/*****************************************************************************/
6786/* */
6787/* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */
6788/* */
6789/*****************************************************************************/
6790
6791#ifndef REDUCED
6792
6793#ifdef ANSI_DECLARATORS
6794void checkdelaunay(struct mesh *m, struct behavior *b)
6795#else /* not ANSI_DECLARATORS */
6796void checkdelaunay(m, b)
6797struct mesh *m;
6798struct behavior *b;
6799#endif /* not ANSI_DECLARATORS */
6800
6801{
6802 struct otri triangleloop;
6808 int horrors;
6809 int saveexact;
6810 triangle ptr; /* Temporary variable used by sym(). */
6811 subseg sptr; /* Temporary variable used by tspivot(). */
6812
6813 /* Temporarily turn on exact arithmetic if it's off. */
6814 saveexact = b->noexact;
6815 b->noexact = 0;
6816 if (!b->quiet) {
6817 printf(" Checking Delaunay property of mesh...\n");
6818 }
6819 horrors = 0;
6820 /* Run through the list of triangles, checking each one. */
6821 traversalinit(&m->triangles);
6823 while (triangleloop.tri != (triangle *) NULL) {
6824 /* Check all three edges of the triangle. */
6825 for (triangleloop.orient = 0; triangleloop.orient < 3;
6826 triangleloop.orient++) {
6832 /* Only test that the edge is locally Delaunay if there is an */
6833 /* adjoining triangle whose pointer is larger (to ensure that */
6834 /* each pair isn't tested twice). */
6835 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
6836 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
6837 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
6838 (triorg != m->infvertex3) &&
6839 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
6840 (tridest != m->infvertex3) &&
6841 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
6842 (triapex != m->infvertex3) &&
6843 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
6844 (oppoapex != m->infvertex3);
6845 if (m->checksegments && shouldbedelaunay) {
6846 /* If a subsegment separates the triangles, then the edge is */
6847 /* constrained, so no local Delaunay test should be done. */
6849 if (opposubseg.ss != m->dummysub){
6850 shouldbedelaunay = 0;
6851 }
6852 }
6853 if (shouldbedelaunay) {
6854 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
6855 if (!b->weighted) {
6856 printf(" !! !! Non-Delaunay pair of triangles:\n");
6857 printf(" First non-Delaunay ");
6859 printf(" Second non-Delaunay ");
6860 } else {
6861 printf(" !! !! Non-regular pair of triangles:\n");
6862 printf(" First non-regular ");
6864 printf(" Second non-regular ");
6865 }
6867 horrors++;
6868 }
6869 }
6870 }
6872 }
6873 if (horrors == 0) {
6874 if (!b->quiet) {
6875 printf(
6876 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
6877 }
6878 } else if (horrors == 1) {
6879 printf(
6880 " !! !! !! !! Precisely one terrifying transgression identified.\n");
6881 } else {
6882 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
6883 }
6884 /* Restore the status of exact arithmetic. */
6885 b->noexact = saveexact;
6886}
6887
6888#endif /* not REDUCED */
6889
6890/*****************************************************************************/
6891/* */
6892/* enqueuebadtriang() Add a bad triangle data structure to the end of a */
6893/* queue. */
6894/* */
6895/* The queue is actually a set of 4096 queues. I use multiple queues to */
6896/* give priority to smaller angles. I originally implemented a heap, but */
6897/* the queues are faster by a larger margin than I'd suspected. */
6898/* */
6899/*****************************************************************************/
6900
6901#ifndef CDT_ONLY
6902
6903#ifdef ANSI_DECLARATORS
6904void enqueuebadtriang(struct mesh *m, struct behavior *b,
6905 struct badtriang *badtri)
6906#else /* not ANSI_DECLARATORS */
6907void enqueuebadtriang(m, b, badtri)
6908struct mesh *m;
6909struct behavior *b;
6911#endif /* not ANSI_DECLARATORS */
6912
6913{
6914 REAL length, multiplier;
6918 int i;
6919
6920 if (b->verbose > 2) {
6921 printf(" Queueing bad triangle:\n");
6922 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
6923 badtri->triangorg[0], badtri->triangorg[1],
6924 badtri->triangdest[0], badtri->triangdest[1],
6925 badtri->triangapex[0], badtri->triangapex[1]);
6926 }
6927
6928 /* Determine the appropriate queue to put the bad triangle into. */
6929 /* Recall that the key is the square of its shortest edge length. */
6930 if (badtri->key >= 1.0) {
6931 length = badtri->key;
6932 posexponent = 1;
6933 } else {
6934 /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */
6935 /* fact and use the reciprocal of `badtri->key', which is > 1.0. */
6936 length = 1.0 / badtri->key;
6937 posexponent = 0;
6938 }
6939 /* `length' is approximately 2.0 to what exponent? The following code */
6940 /* determines the answer in time logarithmic in the exponent. */
6941 exponent = 0;
6942 while (length > 2.0) {
6943 /* Find an approximation by repeated squaring of two. */
6944 expincrement = 1;
6945 multiplier = 0.5;
6946 while (length * multiplier * multiplier > 1.0) {
6947 expincrement *= 2;
6949 }
6950 /* Reduce the value of `length', then iterate if necessary. */
6952 length *= multiplier;
6953 }
6954 /* `length' is approximately squareroot(2.0) to what exponent? */
6955 exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
6956 /* `exponent' is now in the range 0...2047 for IEEE double precision. */
6957 /* Choose a queue in the range 0...4095. The shortest edges have the */
6958 /* highest priority (queue 4095). */
6960 queuenumber = 2047 - exponent;
6961 } else {
6962 queuenumber = 2048 + exponent;
6963 }
6964
6965 /* Are we inserting into an empty queue? */
6966 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
6967 /* Yes, we are inserting into an empty queue. */
6968 /* Will this become the highest-priority queue? */
6969 if (queuenumber > m->firstnonemptyq) {
6970 /* Yes, this is the highest-priority queue. */
6971 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
6972 m->firstnonemptyq = queuenumber;
6973 } else {
6974 /* No, this is not the highest-priority queue. */
6975 /* Find the queue with next higher priority. */
6976 i = queuenumber + 1;
6977 while (m->queuefront[i] == (struct badtriang *) NULL) {
6978 i++;
6979 }
6980 /* Mark the newly nonempty queue as following a higher-priority queue. */
6981 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
6982 m->nextnonemptyq[i] = queuenumber;
6983 }
6984 /* Put the bad triangle at the beginning of the (empty) queue. */
6985 m->queuefront[queuenumber] = badtri;
6986 } else {
6987 /* Add the bad triangle to the end of an already nonempty queue. */
6988 m->queuetail[queuenumber]->nexttriang = badtri;
6989 }
6990 /* Maintain a pointer to the last triangle of the queue. */
6991 m->queuetail[queuenumber] = badtri;
6992 /* Newly enqueued bad triangle has no successor in the queue. */
6993 badtri->nexttriang = (struct badtriang *) NULL;
6994}
6995
6996#endif /* not CDT_ONLY */
6997
6998/*****************************************************************************/
6999/* */
7000/* enqueuebadtri() Add a bad triangle to the end of a queue. */
7001/* */
7002/* Allocates a badtriang data structure for the triangle, then passes it to */
7003/* enqueuebadtriang(). */
7004/* */
7005/*****************************************************************************/
7006
7007#ifndef CDT_ONLY
7008
7009#ifdef ANSI_DECLARATORS
7010void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
7012#else /* not ANSI_DECLARATORS */
7014struct mesh *m;
7015struct behavior *b;
7016struct otri *enqtri;
7017REAL minedge;
7021#endif /* not ANSI_DECLARATORS */
7022
7023{
7024 struct badtriang *newbad;
7025
7026 /* Allocate space for the bad triangle. */
7027 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
7028 newbad->poortri = encode(*enqtri);
7030 newbad->triangapex = enqapex;
7031 newbad->triangorg = enqorg;
7032 newbad->triangdest = enqdest;
7034}
7035
7036#endif /* not CDT_ONLY */
7037
7038/*****************************************************************************/
7039/* */
7040/* dequeuebadtriang() Remove a triangle from the front of the queue. */
7041/* */
7042/*****************************************************************************/
7043
7044#ifndef CDT_ONLY
7045
7046#ifdef ANSI_DECLARATORS
7048#else /* not ANSI_DECLARATORS */
7050struct mesh *m;
7051#endif /* not ANSI_DECLARATORS */
7052
7053{
7054 struct badtriang *result;
7055
7056 /* If no queues are nonempty, return NULL. */
7057 if (m->firstnonemptyq < 0) {
7058 return (struct badtriang *) NULL;
7059 }
7060 /* Find the first triangle of the highest-priority queue. */
7061 result = m->queuefront[m->firstnonemptyq];
7062 /* Remove the triangle from the queue. */
7063 m->queuefront[m->firstnonemptyq] = result->nexttriang;
7064 /* If this queue is now empty, note the new highest-priority */
7065 /* nonempty queue. */
7066 if (result == m->queuetail[m->firstnonemptyq]) {
7067 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
7068 }
7069 return result;
7070}
7071
7072#endif /* not CDT_ONLY */
7073
7074/*****************************************************************************/
7075/* */
7076/* checkseg4encroach() Check a subsegment to see if it is encroached; add */
7077/* it to the list if it is. */
7078/* */
7079/* A subsegment is encroached if there is a vertex in its diametral lens. */
7080/* For Ruppert's algorithm (-D switch), the "diametral lens" is the */
7081/* diametral circle. For Chew's algorithm (default), the diametral lens is */
7082/* just big enough to enclose two isosceles triangles whose bases are the */
7083/* subsegment. Each of the two isosceles triangles has two angles equal */
7084/* to `b->minangle'. */
7085/* */
7086/* Chew's algorithm does not require diametral lenses at all--but they save */
7087/* time. Any vertex inside a subsegment's diametral lens implies that the */
7088/* triangle adjoining the subsegment will be too skinny, so it's only a */
7089/* matter of time before the encroaching vertex is deleted by Chew's */
7090/* algorithm. It's faster to simply not insert the doomed vertex in the */
7091/* first place, which is why I use diametral lenses with Chew's algorithm. */
7092/* */
7093/* Returns a nonzero value if the subsegment is encroached. */
7094/* */
7095/*****************************************************************************/
7096
7097#ifndef CDT_ONLY
7098
7099#ifdef ANSI_DECLARATORS
7100int checkseg4encroach(struct mesh *m, struct behavior *b,
7101 struct osub *testsubseg)
7102#else /* not ANSI_DECLARATORS */
7104struct mesh *m;
7105struct behavior *b;
7107#endif /* not ANSI_DECLARATORS */
7108
7109{
7110 struct otri neighbortri;
7117 triangle ptr; /* Temporary variable used by stpivot(). */
7118
7119 encroached = 0;
7120 sides = 0;
7121
7122 sorg(*testsubseg, eorg);
7123 sdest(*testsubseg, edest);
7124 /* Check one neighbor of the subsegment. */
7125 stpivot(*testsubseg, neighbortri);
7126 /* Does the neighbor exist, or is this a boundary edge? */
7127 if (neighbortri.tri != m->dummytri) {
7128 sides++;
7129 /* Find a vertex opposite this subsegment. */
7130 apex(neighbortri, eapex);
7131 /* Check whether the apex is in the diametral lens of the subsegment */
7132 /* (the diametral circle if `conformdel' is set). A dot product */
7133 /* of two sides of the triangle is used to check whether the angle */
7134 /* at the apex is greater than (180 - 2 `minangle') degrees (for */
7135 /* lenses; 90 degrees for diametral circles). */
7136 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7137 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7138 if (dotproduct < 0.0) {
7139 if (b->conformdel ||
7141 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7142 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7143 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7144 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7145 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7146 encroached = 1;
7147 }
7148 }
7149 }
7150 /* Check the other neighbor of the subsegment. */
7151 ssym(*testsubseg, testsym);
7152 stpivot(testsym, neighbortri);
7153 /* Does the neighbor exist, or is this a boundary edge? */
7154 if (neighbortri.tri != m->dummytri) {
7155 sides++;
7156 /* Find the other vertex opposite this subsegment. */
7157 apex(neighbortri, eapex);
7158 /* Check whether the apex is in the diametral lens of the subsegment */
7159 /* (or the diametral circle, if `conformdel' is set). */
7160 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7161 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7162 if (dotproduct < 0.0) {
7163 if (b->conformdel ||
7165 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7166 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7167 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7168 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7169 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7170 encroached += 2;
7171 }
7172 }
7173 }
7174
7175 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
7176 if (b->verbose > 2) {
7177 printf(
7178 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
7179 eorg[0], eorg[1], edest[0], edest[1]);
7180 }
7181 /* Add the subsegment to the list of encroached subsegments. */
7182 /* Be sure to get the orientation right. */
7183 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
7184 if (encroached == 1) {
7185 encroachedseg->encsubseg = sencode(*testsubseg);
7186 encroachedseg->subsegorg = eorg;
7187 encroachedseg->subsegdest = edest;
7188 } else {
7189 encroachedseg->encsubseg = sencode(testsym);
7190 encroachedseg->subsegorg = edest;
7191 encroachedseg->subsegdest = eorg;
7192 }
7193 }
7194
7195 return encroached;
7196}
7197
7198#endif /* not CDT_ONLY */
7199
7200/*****************************************************************************/
7201/* */
7202/* testtriangle() Test a triangle for quality and size. */
7203/* */
7204/* Tests a triangle to see if it satisfies the minimum angle condition and */
7205/* the maximum area condition. Triangles that aren't up to spec are added */
7206/* to the bad triangle queue. */
7207/* */
7208/*****************************************************************************/
7209
7210#ifndef CDT_ONLY
7211
7212#ifdef ANSI_DECLARATORS
7213void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
7214#else /* not ANSI_DECLARATORS */
7215void testtriangle(m, b, testtri)
7216struct mesh *m;
7217struct behavior *b;
7219#endif /* not ANSI_DECLARATORS */
7220
7221{
7222 struct otri tri1, tri2;
7231 REAL angle;
7232 REAL area;
7234 subseg sptr; /* Temporary variable used by tspivot(). */
7235 triangle ptr; /* Temporary variable used by oprev() and dnext(). */
7236
7237 org(*testtri, torg);
7238 destT(*testtri, tdest);
7239 apex(*testtri, tapex);
7240 dxod = torg[0] - tdest[0];
7241 dyod = torg[1] - tdest[1];
7242 dxda = tdest[0] - tapex[0];
7243 dyda = tdest[1] - tapex[1];
7244 dxao = tapex[0] - torg[0];
7245 dyao = tapex[1] - torg[1];
7246 dxod2 = dxod * dxod;
7247 dyod2 = dyod * dyod;
7248 dxda2 = dxda * dxda;
7249 dyda2 = dyda * dyda;
7250 dxao2 = dxao * dxao;
7251 dyao2 = dyao * dyao;
7252 /* Find the lengths of the triangle's three edges. */
7253 apexlen = dxod2 + dyod2;
7254 orglen = dxda2 + dyda2;
7255 destlen = dxao2 + dyao2;
7256
7257 if ((apexlen < orglen) && (apexlen < destlen)) {
7258 /* The edge opposite the apex is shortest. */
7259 minedge = apexlen;
7260 /* Find the square of the cosine of the angle at the apex. */
7261 angle = dxda * dxao + dyda * dyao;
7262 angle = angle * angle / (orglen * destlen);
7263 base1 = torg;
7264 base2 = tdest;
7265 otricopy(*testtri, tri1);
7266 } else if (orglen < destlen) {
7267 /* The edge opposite the origin is shortest. */
7268 minedge = orglen;
7269 /* Find the square of the cosine of the angle at the origin. */
7270 angle = dxod * dxao + dyod * dyao;
7271 angle = angle * angle / (apexlen * destlen);
7272 base1 = tdest;
7273 base2 = tapex;
7274 lnext(*testtri, tri1);
7275 } else {
7276 /* The edge opposite the destination is shortest. */
7277 minedge = destlen;
7278 /* Find the square of the cosine of the angle at the destination. */
7279 angle = dxod * dxda + dyod * dyda;
7280 angle = angle * angle / (apexlen * orglen);
7281 base1 = tapex;
7282 base2 = torg;
7283 lprev(*testtri, tri1);
7284 }
7285
7286 if (b->vararea || b->fixedarea || b->usertest) {
7287 /* Check whether the area is larger than permitted. */
7288 area = 0.5 * (dxod * dyda - dyod * dxda);
7289 if (b->fixedarea && (area > b->maxarea)) {
7290 /* Add this triangle to the list of bad triangles. */
7292 return;
7293 }
7294
7295 /* Nonpositive area constraints are treated as unconstrained. */
7296 if ((b->vararea) && (area > areabound(*testtri)) &&
7297 (areabound(*testtri) > 0.0)) {
7298 /* Add this triangle to the list of bad triangles. */
7300 return;
7301 }
7302
7303 if (b->usertest) {
7304 /* Check whether the user thinks this triangle is too large. */
7305 if (triunsuitable(torg, tdest, tapex, area)) {
7307 return;
7308 }
7309 }
7310 }
7311
7312 /* Check whether the angle is smaller than permitted. */
7313 if (angle > b->goodangle) {
7314 /* Use the rules of Miller, Pav, and Walkington to decide that certain */
7315 /* triangles should not be split, even if they have bad angles. */
7316 /* A skinny triangle is not split if its shortest edge subtends a */
7317 /* small input angle, and both endpoints of the edge lie on a */
7318 /* concentric circular shell. For convenience, I make a small */
7319 /* adjustment to that rule: I check if the endpoints of the edge */
7320 /* both lie in segment interiors, equidistant from the apex where */
7321 /* the two segments meet. */
7322 /* First, check if both points lie in segment interiors. */
7323 if ((vertextype(base1) == SEGMENTVERTEX) &&
7324 (vertextype(base2) == SEGMENTVERTEX)) {
7325 /* Check if both points lie in a common segment. If they do, the */
7326 /* skinny triangle is enqueued to be split as usual. */
7327 tspivot(tri1, testsub);
7328 if (testsub.ss == m->dummysub) {
7329 /* No common segment. Find a subsegment that contains `torg'. */
7330 otricopy(tri1, tri2);
7331 do {
7332 oprevself(tri1);
7333 tspivot(tri1, testsub);
7334 } while (testsub.ss == m->dummysub);
7335 /* Find the endpoints of the containing segment. */
7336 segorg(testsub, org1);
7337 segdest(testsub, dest1);
7338 /* Find a subsegment that contains `tdest'. */
7339 do {
7340 dnextself(tri2);
7341 tspivot(tri2, testsub);
7342 } while (testsub.ss == m->dummysub);
7343 /* Find the endpoints of the containing segment. */
7344 segorg(testsub, org2);
7345 segdest(testsub, dest2);
7346 /* Check if the two containing segments have an endpoint in common. */
7347 joinvertex = (vertex) NULL;
7348 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
7349 joinvertex = dest1;
7350 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
7351 joinvertex = org1;
7352 }
7353 if (joinvertex != (vertex) NULL) {
7354 /* Compute the distance from the common endpoint (of the two */
7355 /* segments) to each of the endpoints of the shortest edge. */
7356 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
7357 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
7358 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
7359 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
7360 /* If the two distances are equal, don't split the triangle. */
7361 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
7362 /* Return now to avoid enqueueing the bad triangle. */
7363 return;
7364 }
7365 }
7366 }
7367 }
7368
7369 /* Add this triangle to the list of bad triangles. */
7371 }
7372}
7373
7374#endif /* not CDT_ONLY */
7375
7378/********* Mesh quality testing routines end here *********/
7379
7380/********* Point location routines begin here *********/
7383
7384/*****************************************************************************/
7385/* */
7386/* makevertexmap() Construct a mapping from vertices to triangles to */
7387/* improve the speed of point location for segment */
7388/* insertion. */
7389/* */
7390/* Traverses all the triangles, and provides each corner of each triangle */
7391/* with a pointer to that triangle. Of course, pointers will be */
7392/* overwritten by other pointers because (almost) each vertex is a corner */
7393/* of several triangles, but in the end every vertex will point to some */
7394/* triangle that contains it. */
7395/* */
7396/*****************************************************************************/
7397
7398#ifdef ANSI_DECLARATORS
7399void makevertexmap(struct mesh *m, struct behavior *b)
7400#else /* not ANSI_DECLARATORS */
7401void makevertexmap(m, b)
7402struct mesh *m;
7403struct behavior *b;
7404#endif /* not ANSI_DECLARATORS */
7405
7406{
7407 struct otri triangleloop;
7408 vertex triorg;
7409
7410 if (b->verbose) {
7411 printf(" Constructing mapping from vertices to triangles.\n");
7412 }
7413 traversalinit(&m->triangles);
7415 while (triangleloop.tri != (triangle *) NULL) {
7416 /* Check all three vertices of the triangle. */
7417 for (triangleloop.orient = 0; triangleloop.orient < 3;
7418 triangleloop.orient++) {
7421 }
7423 }
7424}
7425
7426/*****************************************************************************/
7427/* */
7428/* preciselocate() Find a triangle or edge containing a given point. */
7429/* */
7430/* Begins its search from `searchtri'. It is important that `searchtri' */
7431/* be a handle with the property that `searchpoint' is strictly to the left */
7432/* of the edge denoted by `searchtri', or is collinear with that edge and */
7433/* does not intersect that edge. (In particular, `searchpoint' should not */
7434/* be the origin or destination of that edge.) */
7435/* */
7436/* These conditions are imposed because preciselocate() is normally used in */
7437/* one of two situations: */
7438/* */
7439/* (1) To try to find the location to insert a new point. Normally, we */
7440/* know an edge that the point is strictly to the left of. In the */
7441/* incremental Delaunay algorithm, that edge is a bounding box edge. */
7442/* In Ruppert's Delaunay refinement algorithm for quality meshing, */
7443/* that edge is the shortest edge of the triangle whose circumcenter */
7444/* is being inserted. */
7445/* */
7446/* (2) To try to find an existing point. In this case, any edge on the */
7447/* convex hull is a good starting edge. You must screen out the */
7448/* possibility that the vertex sought is an endpoint of the starting */
7449/* edge before you call preciselocate(). */
7450/* */
7451/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7452/* */
7453/* This implementation differs from that given by Guibas and Stolfi. It */
7454/* walks from triangle to triangle, crossing an edge only if `searchpoint' */
7455/* is on the other side of the line containing that edge. After entering */
7456/* a triangle, there are two edges by which one can leave that triangle. */
7457/* If both edges are valid (`searchpoint' is on the other side of both */
7458/* edges), one of the two is chosen by drawing a line perpendicular to */
7459/* the entry edge (whose endpoints are `forg' and `fdest') passing through */
7460/* `fapex'. Depending on which side of this perpendicular `searchpoint' */
7461/* falls on, an exit edge is chosen. */
7462/* */
7463/* This implementation is empirically faster than the Guibas and Stolfi */
7464/* point location routine (which I originally used), which tends to spiral */
7465/* in toward its target. */
7466/* */
7467/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7468/* is a handle whose origin is the existing vertex. */
7469/* */
7470/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7471/* handle whose primary edge is the edge on which the point lies. */
7472/* */
7473/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7474/* `searchtri' is a handle on the triangle that contains the point. */
7475/* */
7476/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7477/* handle whose primary edge the point is to the right of. This might */
7478/* occur when the circumcenter of a triangle falls just slightly outside */
7479/* the mesh due to floating-point roundoff error. It also occurs when */
7480/* seeking a hole or region point that a foolish user has placed outside */
7481/* the mesh. */
7482/* */
7483/* If `stopatsubsegment' is nonzero, the search will stop if it tries to */
7484/* walk through a subsegment, and will return OUTSIDE. */
7485/* */
7486/* WARNING: This routine is designed for convex triangulations, and will */
7487/* not generally work after the holes and concavities have been carved. */
7488/* However, it can still be used to find the circumcenter of a triangle, as */
7489/* long as the search is begun from the triangle in question. */
7490/* */
7491/*****************************************************************************/
7492
7493#ifdef ANSI_DECLARATORS
7496 int stopatsubsegment)
7497#else /* not ANSI_DECLARATORS */
7499struct mesh *m;
7500struct behavior *b;
7502struct otri *searchtri;
7504#endif /* not ANSI_DECLARATORS */
7505
7506{
7507 struct otri backtracktri;
7512 triangle ptr; /* Temporary variable used by sym(). */
7513 subseg sptr; /* Temporary variable used by tspivot(). */
7514
7515 if (b->verbose > 2) {
7516 printf(" Searching for point (%.12g, %.12g).\n",
7517 searchpoint[0], searchpoint[1]);
7518 }
7519 /* Where are we? */
7520 org(*searchtri, forg);
7522 apex(*searchtri, fapex);
7523 while (1) {
7524 if (b->verbose > 2) {
7525 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7526 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
7527 }
7528 /* Check whether the apex is the point we seek. */
7529 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
7531 return ONVERTEX;
7532 }
7533 /* Does the point lie on the other side of the line defined by the */
7534 /* triangle edge opposite the triangle's destination? */
7536 /* Does the point lie on the other side of the line defined by the */
7537 /* triangle edge opposite the triangle's origin? */
7539 if (destorient > 0.0) {
7540 if (orgorient > 0.0) {
7541 /* Move left if the inner product of (fapex - searchpoint) and */
7542 /* (fdest - forg) is positive. This is equivalent to drawing */
7543 /* a line perpendicular to the line (forg, fdest) and passing */
7544 /* through `fapex', and determining which side of this line */
7545 /* `searchpoint' falls on. */
7546 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
7547 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
7548 } else {
7549 moveleft = 1;
7550 }
7551 } else {
7552 if (orgorient > 0.0) {
7553 moveleft = 0;
7554 } else {
7555 /* The point we seek must be on the boundary of or inside this */
7556 /* triangle. */
7557 if (destorient == 0.0) {
7559 return ONEDGE;
7560 }
7561 if (orgorient == 0.0) {
7563 return ONEDGE;
7564 }
7565 return INTRIANGLE;
7566 }
7567 }
7568
7569 /* Move to another triangle. Leave a trace `backtracktri' in case */
7570 /* floating-point roundoff or some such bogey causes us to walk */
7571 /* off a boundary of the triangulation. */
7572 if (moveleft) {
7573 lprev(*searchtri, backtracktri);
7574 fdest = fapex;
7575 } else {
7576 lnext(*searchtri, backtracktri);
7577 forg = fapex;
7578 }
7579 sym(backtracktri, *searchtri);
7580
7581 if (m->checksegments && stopatsubsegment) {
7582 /* Check for walking through a subsegment. */
7583 tspivot(backtracktri, checkedge);
7584 if (checkedge.ss != m->dummysub) {
7585 /* Go back to the last triangle. */
7586 otricopy(backtracktri, *searchtri);
7587 return OUTSIDE;
7588 }
7589 }
7590 /* Check for walking right out of the triangulation. */
7591 if (searchtri->tri == m->dummytri) {
7592 /* Go back to the last triangle. */
7593 otricopy(backtracktri, *searchtri);
7594 return OUTSIDE;
7595 }
7596
7597 apex(*searchtri, fapex);
7598 }
7599}
7600
7601/*****************************************************************************/
7602/* */
7603/* locate() Find a triangle or edge containing a given point. */
7604/* */
7605/* Searching begins from one of: the input `searchtri', a recently */
7606/* encountered triangle `recenttri', or from a triangle chosen from a */
7607/* random sample. The choice is made by determining which triangle's */
7608/* origin is closest to the point we are searching for. Normally, */
7609/* `searchtri' should be a handle on the convex hull of the triangulation. */
7610/* */
7611/* Details on the random sampling method can be found in the Mucke, Saias, */
7612/* and Zhu paper cited in the header of this code. */
7613/* */
7614/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7615/* */
7616/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7617/* is a handle whose origin is the existing vertex. */
7618/* */
7619/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7620/* handle whose primary edge is the edge on which the point lies. */
7621/* */
7622/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7623/* `searchtri' is a handle on the triangle that contains the point. */
7624/* */
7625/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7626/* handle whose primary edge the point is to the right of. This might */
7627/* occur when the circumcenter of a triangle falls just slightly outside */
7628/* the mesh due to floating-point roundoff error. It also occurs when */
7629/* seeking a hole or region point that a foolish user has placed outside */
7630/* the mesh. */
7631/* */
7632/* WARNING: This routine is designed for convex triangulations, and will */
7633/* not generally work after the holes and concavities have been carved. */
7634/* */
7635/*****************************************************************************/
7636
7637#ifdef ANSI_DECLARATORS
7638enum locateresult locate(struct mesh *m, struct behavior *b,
7640#else /* not ANSI_DECLARATORS */
7642struct mesh *m;
7643struct behavior *b;
7645struct otri *searchtri;
7646#endif /* not ANSI_DECLARATORS */
7647
7648{
7649 VOID **sampleblock;
7652 vertex torg, tdest;
7653 unsigned long alignptr;
7655 REAL ahead;
7658 triangle ptr; /* Temporary variable used by sym(). */
7659
7660 if (b->verbose > 2) {
7661 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
7662 searchpoint[0], searchpoint[1]);
7663 }
7664 /* Record the distance from the suggested starting triangle to the */
7665 /* point we seek. */
7666 org(*searchtri, torg);
7667 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7668 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7669 if (b->verbose > 2) {
7670 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
7671 torg[0], torg[1]);
7672 }
7673
7674 /* If a recently encountered triangle has been recorded and has not been */
7675 /* deallocated, test it as a good starting point. */
7676 if (m->recenttri.tri != (triangle *) NULL) {
7677 if (!deadtri(m->recenttri.tri)) {
7678 org(m->recenttri, torg);
7679 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7680 otricopy(m->recenttri, *searchtri);
7681 return ONVERTEX;
7682 }
7683 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7684 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7685 if (dist < searchdist) {
7686 otricopy(m->recenttri, *searchtri);
7687 searchdist = dist;
7688 if (b->verbose > 2) {
7689 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
7690 torg[0], torg[1]);
7691 }
7692 }
7693 }
7694 }
7695
7696 /* The number of random samples taken is proportional to the cube root of */
7697 /* the number of triangles in the mesh. The next bit of code assumes */
7698 /* that the number of triangles increases monotonically (or at least */
7699 /* doesn't decrease enough to matter). */
7700 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
7701 m->triangles.items) {
7702 m->samples++;
7703 }
7704
7705 /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */
7706 /* from each block of triangles (except the first)--until we meet the */
7707 /* sample quota. The ceiling means that blocks at the end might be */
7708 /* neglected, but I don't care. */
7709 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
7710 /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */
7711 /* from the first block of triangles. */
7712 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
7713 m->triangles.maxitems + 1;
7714 totalsamplesleft = m->samples;
7715 population = m->triangles.itemsfirstblock;
7716 totalpopulation = m->triangles.maxitems;
7717 sampleblock = m->triangles.firstblock;
7718 sampletri.orient = 0;
7719 while (totalsamplesleft > 0) {
7720 /* If we're in the last block, `population' needs to be corrected. */
7723 }
7724 /* Find a pointer to the first triangle in the block. */
7725 alignptr = (unsigned long) (sampleblock + 1);
7726 firsttri = (char *) (alignptr +
7727 (unsigned long) m->triangles.alignbytes -
7728 (alignptr %
7729 (unsigned long) m->triangles.alignbytes));
7730
7731 /* Choose `samplesleft' randomly sampled triangles in this block. */
7732 do {
7733 sampletri.tri = (triangle *) (firsttri +
7734 (randomnation((unsigned int) population) *
7735 m->triangles.itembytes));
7736 if (!deadtri(sampletri.tri)) {
7737 org(sampletri, torg);
7738 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7739 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7740 if (dist < searchdist) {
7742 searchdist = dist;
7743 if (b->verbose > 2) {
7744 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
7745 torg[0], torg[1]);
7746 }
7747 }
7748 }
7749
7750 samplesleft--;
7752 } while ((samplesleft > 0) && (totalsamplesleft > 0));
7753
7754 if (totalsamplesleft > 0) {
7755 sampleblock = (VOID **) *sampleblock;
7758 population = TRIPERBLOCK;
7759 }
7760 }
7761
7762 /* Where are we? */
7763 org(*searchtri, torg);
7765 /* Check the starting triangle's vertices. */
7766 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7767 return ONVERTEX;
7768 }
7769 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
7771 return ONVERTEX;
7772 }
7773 /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
7775 if (ahead < 0.0) {
7776 /* Turn around so that `searchpoint' is to the left of the */
7777 /* edge specified by `searchtri'. */
7779 } else if (ahead == 0.0) {
7780 /* Check if `searchpoint' is between `torg' and `tdest'. */
7781 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
7782 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
7783 return ONEDGE;
7784 }
7785 }
7787}
7788
7791/********* Point location routines end here *********/
7792
7793/********* Mesh transformation routines begin here *********/
7796
7797/*****************************************************************************/
7798/* */
7799/* insertsubseg() Create a new subsegment and insert it between two */
7800/* triangles. */
7801/* */
7802/* The new subsegment is inserted at the edge described by the handle */
7803/* `tri'. Its vertices are properly initialized. The marker `subsegmark' */
7804/* is applied to the subsegment and, if appropriate, its vertices. */
7805/* */
7806/*****************************************************************************/
7807
7808#ifdef ANSI_DECLARATORS
7809void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
7810 int subsegmark)
7811#else /* not ANSI_DECLARATORS */
7812void insertsubseg(m, b, tri, subsegmark)
7813struct mesh *m;
7814struct behavior *b;
7815struct otri *tri; /* Edge at which to insert the new subsegment. */
7816int subsegmark; /* Marker for the new subsegment. */
7817#endif /* not ANSI_DECLARATORS */
7818
7819{
7820 struct otri oppotri;
7821 struct osub newsubseg;
7823 triangle ptr; /* Temporary variable used by sym(). */
7824 subseg sptr; /* Temporary variable used by tspivot(). */
7825
7826 org(*tri, triorg);
7827 destT(*tri, tridest);
7828 /* Mark vertices if possible. */
7829 if (vertexmark(triorg) == 0) {
7831 }
7832 if (vertexmark(tridest) == 0) {
7834 }
7835 /* Check if there's already a subsegment here. */
7837 if (newsubseg.ss == m->dummysub) {
7838 /* Make new subsegment and initialize its vertices. */
7840 setsorg(newsubseg, tridest);
7841 setsdest(newsubseg, triorg);
7842 setsegorg(newsubseg, tridest);
7843 setsegdest(newsubseg, triorg);
7844 /* Bond new subsegment to the two triangles it is sandwiched between. */
7845 /* Note that the facing triangle `oppotri' might be equal to */
7846 /* `dummytri' (outer space), but the new subsegment is bonded to it */
7847 /* all the same. */
7848 tsbond(*tri, newsubseg);
7849 sym(*tri, oppotri);
7850 ssymself(newsubseg);
7851 tsbond(oppotri, newsubseg);
7852 setmark(newsubseg, subsegmark);
7853 if (b->verbose > 2) {
7854 printf(" Inserting new ");
7855 printsubseg(m, b, &newsubseg);
7856 }
7857 } else {
7858 if (markT(newsubseg) == 0) {
7859 setmark(newsubseg, subsegmark);
7860 }
7861 }
7862}
7863
7864/*****************************************************************************/
7865/* */
7866/* Terminology */
7867/* */
7868/* A "local transformation" replaces a small set of triangles with another */
7869/* set of triangles. This may or may not involve inserting or deleting a */
7870/* vertex. */
7871/* */
7872/* The term "casing" is used to describe the set of triangles that are */
7873/* attached to the triangles being transformed, but are not transformed */
7874/* themselves. Think of the casing as a fixed hollow structure inside */
7875/* which all the action happens. A "casing" is only defined relative to */
7876/* a single transformation; each occurrence of a transformation will */
7877/* involve a different casing. */
7878/* */
7879/*****************************************************************************/
7880
7881/*****************************************************************************/
7882/* */
7883/* flip() Transform two triangles to two different triangles by flipping */
7884/* an edge counterclockwise within a quadrilateral. */
7885/* */
7886/* Imagine the original triangles, abc and bad, oriented so that the */
7887/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
7888/* and the vertex a on the right. The vertex c lies below the edge, and */
7889/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
7890/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
7891/* */
7892/* The triangles abc and bad are deleted and replaced by the triangles cdb */
7893/* and dca. The triangles that represent abc and bad are NOT deallocated; */
7894/* they are reused for dca and cdb, respectively. Hence, any handles that */
7895/* may have held the original triangles are still valid, although not */
7896/* directed as they were before. */
7897/* */
7898/* Upon completion of this routine, the `flipedge' handle holds the edge */
7899/* dc of triangle dca, and is directed down, from vertex d to vertex c. */
7900/* (Hence, the two triangles have rotated counterclockwise.) */
7901/* */
7902/* WARNING: This transformation is geometrically valid only if the */
7903/* quadrilateral adbc is convex. Furthermore, this transformation is */
7904/* valid only if there is not a subsegment between the triangles abc and */
7905/* bad. This routine does not check either of these preconditions, and */
7906/* it is the responsibility of the calling routine to ensure that they are */
7907/* met. If they are not, the streets shall be filled with wailing and */
7908/* gnashing of teeth. */
7909/* */
7910/*****************************************************************************/
7911
7912#ifdef ANSI_DECLARATORS
7913void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
7914#else /* not ANSI_DECLARATORS */
7915void flip(m, b, flipedge)
7916struct mesh *m;
7917struct behavior *b;
7918struct otri *flipedge; /* Handle for the triangle abc. */
7919#endif /* not ANSI_DECLARATORS */
7920
7921{
7922 struct otri botleft, botright;
7923 struct otri topleft, topright;
7924 struct otri top;
7925 struct otri botlcasing, botrcasing;
7926 struct otri toplcasing, toprcasing;
7927 struct osub botlsubseg, botrsubseg;
7928 struct osub toplsubseg, toprsubseg;
7931 triangle ptr; /* Temporary variable used by sym(). */
7932 subseg sptr; /* Temporary variable used by tspivot(). */
7933
7934 /* Identify the vertices of the quadrilateral. */
7938 sym(*flipedge, top);
7939#ifdef SELF_CHECK
7940 if (top.tri == m->dummytri) {
7941 printf("Internal error in flip(): Attempt to flip on boundary.\n");
7943 return;
7944 }
7945 if (m->checksegments) {
7946 tspivot(*flipedge, toplsubseg);
7947 if (toplsubseg.ss != m->dummysub) {
7948 printf("Internal error in flip(): Attempt to flip a segment.\n");
7950 return;
7951 }
7952 }
7953#endif /* SELF_CHECK */
7955
7956 /* Identify the casing of the quadrilateral. */
7957 lprev(top, topleft);
7958 sym(topleft, toplcasing);
7961 lnext(*flipedge, botleft);
7962 sym(botleft, botlcasing);
7965 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
7966 bond(topleft, botlcasing);
7967 bond(botleft, botrcasing);
7969 bond(topright, toplcasing);
7970
7971 if (m->checksegments) {
7972 /* Check for subsegments and rebond them to the quadrilateral. */
7973 tspivot(topleft, toplsubseg);
7974 tspivot(botleft, botlsubseg);
7977 if (toplsubseg.ss == m->dummysub) {
7978 tsdissolve(topright);
7979 } else {
7980 tsbond(topright, toplsubseg);
7981 }
7982 if (botlsubseg.ss == m->dummysub) {
7983 tsdissolve(topleft);
7984 } else {
7985 tsbond(topleft, botlsubseg);
7986 }
7987 if (botrsubseg.ss == m->dummysub) {
7988 tsdissolve(botleft);
7989 } else {
7990 tsbond(botleft, botrsubseg);
7991 }
7992 if (toprsubseg.ss == m->dummysub) {
7993 tsdissolve(botright);
7994 } else {
7995 tsbond(botright, toprsubseg);
7996 }
7997 }
7998
7999 /* New vertex assignments for the rotated quadrilateral. */
8006 if (b->verbose > 2) {
8007 printf(" Edge flip results in left ");
8008 printtriangle(m, b, &top);
8009 printf(" and right ");
8011 }
8012}
8013
8014/*****************************************************************************/
8015/* */
8016/* unflip() Transform two triangles to two different triangles by */
8017/* flipping an edge clockwise within a quadrilateral. Reverses */
8018/* the flip() operation so that the data structures representing */
8019/* the triangles are back where they were before the flip(). */
8020/* */
8021/* Imagine the original triangles, abc and bad, oriented so that the */
8022/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
8023/* and the vertex a on the right. The vertex c lies below the edge, and */
8024/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
8025/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
8026/* */
8027/* The triangles abc and bad are deleted and replaced by the triangles cdb */
8028/* and dca. The triangles that represent abc and bad are NOT deallocated; */
8029/* they are reused for cdb and dca, respectively. Hence, any handles that */
8030/* may have held the original triangles are still valid, although not */
8031/* directed as they were before. */
8032/* */
8033/* Upon completion of this routine, the `flipedge' handle holds the edge */
8034/* cd of triangle cdb, and is directed up, from vertex c to vertex d. */
8035/* (Hence, the two triangles have rotated clockwise.) */
8036/* */
8037/* WARNING: This transformation is geometrically valid only if the */
8038/* quadrilateral adbc is convex. Furthermore, this transformation is */
8039/* valid only if there is not a subsegment between the triangles abc and */
8040/* bad. This routine does not check either of these preconditions, and */
8041/* it is the responsibility of the calling routine to ensure that they are */
8042/* met. If they are not, the streets shall be filled with wailing and */
8043/* gnashing of teeth. */
8044/* */
8045/*****************************************************************************/
8046
8047#ifdef ANSI_DECLARATORS
8048void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
8049#else /* not ANSI_DECLARATORS */
8050void unflip(m, b, flipedge)
8051struct mesh *m;
8052struct behavior *b;
8053struct otri *flipedge; /* Handle for the triangle abc. */
8054#endif /* not ANSI_DECLARATORS */
8055
8056{
8057 struct otri botleft, botright;
8058 struct otri topleft, topright;
8059 struct otri top;
8060 struct otri botlcasing, botrcasing;
8061 struct otri toplcasing, toprcasing;
8062 struct osub botlsubseg, botrsubseg;
8063 struct osub toplsubseg, toprsubseg;
8066 triangle ptr; /* Temporary variable used by sym(). */
8067 subseg sptr; /* Temporary variable used by tspivot(). */
8068
8069 /* Identify the vertices of the quadrilateral. */
8073 sym(*flipedge, top);
8074#ifdef SELF_CHECK
8075 if (top.tri == m->dummytri) {
8076 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
8078 return;
8079 }
8080 if (m->checksegments) {
8081 tspivot(*flipedge, toplsubseg);
8082 if (toplsubseg.ss != m->dummysub) {
8083 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
8085 return;
8086 }
8087 }
8088#endif /* SELF_CHECK */
8089 apex(top, farvertex);
8090
8091 /* Identify the casing of the quadrilateral. */
8092 lprev(top, topleft);
8093 sym(topleft, toplcasing);
8094 lnext(top, topright);
8096 lnext(*flipedge, botleft);
8097 sym(botleft, botlcasing);
8100 /* Rotate the quadrilateral one-quarter turn clockwise. */
8101 bond(topleft, toprcasing);
8102 bond(botleft, toplcasing);
8103 bond(botright, botlcasing);
8105
8106 if (m->checksegments) {
8107 /* Check for subsegments and rebond them to the quadrilateral. */
8108 tspivot(topleft, toplsubseg);
8109 tspivot(botleft, botlsubseg);
8112 if (toplsubseg.ss == m->dummysub) {
8113 tsdissolve(botleft);
8114 } else {
8115 tsbond(botleft, toplsubseg);
8116 }
8117 if (botlsubseg.ss == m->dummysub) {
8118 tsdissolve(botright);
8119 } else {
8120 tsbond(botright, botlsubseg);
8121 }
8122 if (botrsubseg.ss == m->dummysub) {
8123 tsdissolve(topright);
8124 } else {
8125 tsbond(topright, botrsubseg);
8126 }
8127 if (toprsubseg.ss == m->dummysub) {
8128 tsdissolve(topleft);
8129 } else {
8130 tsbond(topleft, toprsubseg);
8131 }
8132 }
8133
8134 /* New vertex assignments for the rotated quadrilateral. */
8141 if (b->verbose > 2) {
8142 printf(" Edge unflip results in left ");
8144 printf(" and right ");
8145 printtriangle(m, b, &top);
8146 }
8147}
8148
8149/*****************************************************************************/
8150/* */
8151/* insertvertex() Insert a vertex into a Delaunay triangulation, */
8152/* performing flips as necessary to maintain the Delaunay */
8153/* property. */
8154/* */
8155/* The point `insertvertex' is located. If `searchtri.tri' is not NULL, */
8156/* the search for the containing triangle begins from `searchtri'. If */
8157/* `searchtri.tri' is NULL, a full point location procedure is called. */
8158/* If `insertvertex' is found inside a triangle, the triangle is split into */
8159/* three; if `insertvertex' lies on an edge, the edge is split in two, */
8160/* thereby splitting the two adjacent triangles into four. Edge flips are */
8161/* used to restore the Delaunay property. If `insertvertex' lies on an */
8162/* existing vertex, no action is taken, and the value DUPLICATEVERTEX is */
8163/* returned. On return, `searchtri' is set to a handle whose origin is the */
8164/* existing vertex. */
8165/* */
8166/* Normally, the parameter `splitseg' is set to NULL, implying that no */
8167/* subsegment should be split. In this case, if `insertvertex' is found to */
8168/* lie on a segment, no action is taken, and the value VIOLATINGVERTEX is */
8169/* returned. On return, `searchtri' is set to a handle whose primary edge */
8170/* is the violated subsegment. */
8171/* */
8172/* If the calling routine wishes to split a subsegment by inserting a */
8173/* vertex in it, the parameter `splitseg' should be that subsegment. In */
8174/* this case, `searchtri' MUST be the triangle handle reached by pivoting */
8175/* from that subsegment; no point location is done. */
8176/* */
8177/* `segmentflaws' and `triflaws' are flags that indicate whether or not */
8178/* there should be checks for the creation of encroached subsegments or bad */
8179/* quality triangles. If a newly inserted vertex encroaches upon */
8180/* subsegments, these subsegments are added to the list of subsegments to */
8181/* be split if `segmentflaws' is set. If bad triangles are created, these */
8182/* are added to the queue if `triflaws' is set. */
8183/* */
8184/* If a duplicate vertex or violated segment does not prevent the vertex */
8185/* from being inserted, the return value will be ENCROACHINGVERTEX if the */
8186/* vertex encroaches upon a subsegment (and checking is enabled), or */
8187/* SUCCESSFULVERTEX otherwise. In either case, `searchtri' is set to a */
8188/* handle whose origin is the newly inserted vertex. */
8189/* */
8190/* insertvertex() does not use flip() for reasons of speed; some */
8191/* information can be reused from edge flip to edge flip, like the */
8192/* locations of subsegments. */
8193/* */
8194/*****************************************************************************/
8195
8196#ifdef ANSI_DECLARATORS
8198 vertex newvertex, struct otri *searchtri,
8199 struct osub *splitseg,
8200 int segmentflaws, int triflaws)
8201#else /* not ANSI_DECLARATORS */
8204struct mesh *m;
8205struct behavior *b;
8207struct otri *searchtri;
8208struct osub *splitseg;
8209int segmentflaws;
8211#endif /* not ANSI_DECLARATORS */
8212
8213{
8214 struct otri horiz;
8215 struct otri top;
8216 struct otri botleft, botright;
8217 struct otri topleft, topright;
8218 struct otri newbotleft, newbotright;
8220 struct otri botlcasing, botrcasing;
8221 struct otri toplcasing, toprcasing;
8222 struct otri testtri;
8223 struct osub botlsubseg, botrsubseg;
8224 struct osub toplsubseg, toprsubseg;
8228 struct osub newsubseg;
8229 struct badsubseg *encroached;
8235 REAL area;
8240 int enq;
8241 int i;
8242 triangle ptr; /* Temporary variable used by sym(). */
8243 subseg sptr; /* Temporary variable used by spivot() and tspivot(). */
8244
8245 if (b->verbose > 1) {
8246 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
8247 }
8248
8249 if (splitseg == (struct osub *) NULL) {
8250 /* Find the location of the vertex to be inserted. Check if a good */
8251 /* starting triangle has already been provided by the caller. */
8252 if (searchtri->tri == m->dummytri) {
8253 /* Find a boundary triangle. */
8254 horiz.tri = m->dummytri;
8255 horiz.orient = 0;
8256 symself(horiz);
8257 /* Search for a triangle containing `newvertex'. */
8258 intersect = locate(m, b, newvertex, &horiz);
8259 } else {
8260 /* Start searching from the triangle provided by the caller. */
8261 otricopy(*searchtri, horiz);
8262 intersect = preciselocate(m, b, newvertex, &horiz, 1);
8263 }
8264 } else {
8265 /* The calling routine provides the subsegment in which */
8266 /* the vertex is inserted. */
8267 otricopy(*searchtri, horiz);
8268 intersect = ONEDGE;
8269 }
8270
8272 /* There's already a vertex there. Return in `searchtri' a triangle */
8273 /* whose origin is the existing vertex. */
8274 otricopy(horiz, *searchtri);
8275 otricopy(horiz, m->recenttri);
8276 return DUPLICATEVERTEX;
8277 }
8278 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
8279 /* The vertex falls on an edge or boundary. */
8280 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
8281 /* Check whether the vertex falls on a subsegment. */
8282 tspivot(horiz, brokensubseg);
8283 if (brokensubseg.ss != m->dummysub) {
8284 /* The vertex falls on a subsegment, and hence will not be inserted. */
8285 if (segmentflaws) {
8286 enq = b->nobisect != 2;
8287 if (enq && (b->nobisect == 1)) {
8288 /* This subsegment may be split only if it is an */
8289 /* internal boundary. */
8290 sym(horiz, testtri);
8291 enq = testtri.tri != m->dummytri;
8292 }
8293 if (enq) {
8294 /* Add the subsegment to the list of encroached subsegments. */
8295 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
8296 encroached->encsubseg = sencode(brokensubseg);
8297 sorg(brokensubseg, encroached->subsegorg);
8298 sdest(brokensubseg, encroached->subsegdest);
8299 if (b->verbose > 2) {
8300 printf(
8301 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
8302 encroached->subsegorg[0], encroached->subsegorg[1],
8303 encroached->subsegdest[0], encroached->subsegdest[1]);
8304 }
8305 }
8306 }
8307 /* Return a handle whose primary edge contains the vertex, */
8308 /* which has not been inserted. */
8309 otricopy(horiz, *searchtri);
8310 otricopy(horiz, m->recenttri);
8311 return VIOLATINGVERTEX;
8312 }
8313 }
8314
8315 /* Insert the vertex on an edge, dividing one triangle into two (if */
8316 /* the edge lies on a boundary) or two triangles into four. */
8317 lprev(horiz, botright);
8319 sym(horiz, topright);
8320 /* Is there a second triangle? (Or does this edge lie on a boundary?) */
8321 mirrorflag = topright.tri != m->dummytri;
8322 if (mirrorflag) {
8326 } else {
8327 /* Splitting a boundary edge increases the number of boundary edges. */
8328 m->hullsize++;
8329 }
8331
8332 /* Set the vertices of changed and new triangles. */
8333 org(horiz, rightvertex);
8334 destT(horiz, leftvertex);
8335 apex(horiz, botvertex);
8339 setorg(horiz, newvertex);
8340 for (i = 0; i < m->eextras; i++) {
8341 /* Set the element attributes of a new triangle. */
8342 setelemattribute(newbotright, i, elemattribute(botright, i));
8343 }
8344 if (b->vararea) {
8345 /* Set the area constraint of a new triangle. */
8346 setareabound(newbotright, areabound(botright));
8347 }
8348 if (mirrorflag) {
8354 for (i = 0; i < m->eextras; i++) {
8355 /* Set the element attributes of another new triangle. */
8356 setelemattribute(newtopright, i, elemattribute(topright, i));
8357 }
8358 if (b->vararea) {
8359 /* Set the area constraint of another new triangle. */
8360 setareabound(newtopright, areabound(topright));
8361 }
8362 }
8363
8364 /* There may be subsegments that need to be bonded */
8365 /* to the new triangle(s). */
8366 if (m->checksegments) {
8368 if (botrsubseg.ss != m->dummysub) {
8369 tsdissolve(botright);
8370 tsbond(newbotright, botrsubseg);
8371 }
8372 if (mirrorflag) {
8374 if (toprsubseg.ss != m->dummysub) {
8375 tsdissolve(topright);
8376 tsbond(newtopright, toprsubseg);
8377 }
8378 }
8379 }
8380
8381 /* Bond the new triangle(s) to the surrounding triangles. */
8386 if (mirrorflag) {
8392 }
8393
8394 if (splitseg != (struct osub *) NULL) {
8395 /* Split the subsegment into two. */
8396 setsdest(*splitseg, newvertex);
8397 segorg(*splitseg, segmentorg);
8398 segdest(*splitseg, segmentdest);
8399 ssymself(*splitseg);
8400 spivot(*splitseg, rightsubseg);
8401 insertsubseg(m, b, &newbotright, markT(*splitseg));
8403 setsegorg(newsubseg, segmentorg);
8404 setsegdest(newsubseg, segmentdest);
8405 sbond(*splitseg, newsubseg);
8406 ssymself(newsubseg);
8407 sbond(newsubseg, rightsubseg);
8408 ssymself(*splitseg);
8409 /* Transfer the subsegment's boundary marker to the vertex */
8410 /* if required. */
8411 if (vertexmark(newvertex) == 0) {
8413 }
8414 }
8415
8416 if (m->checkquality) {
8417 poolrestart(&m->flipstackers);
8418 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8419 m->lastflip->flippedtri = encode(horiz);
8420 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
8421 }
8422
8423#ifdef SELF_CHECK
8425 printf("Internal error in insertvertex():\n");
8426 printf(
8427 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
8428 }
8429 if (mirrorflag) {
8431 printf("Internal error in insertvertex():\n");
8432 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
8433 }
8435 printf("Internal error in insertvertex():\n");
8436 printf(
8437 " Clockwise triangle after edge vertex insertion (top right).\n");
8438 }
8440 printf("Internal error in insertvertex():\n");
8441 printf(
8442 " Clockwise triangle after edge vertex insertion (top left).\n");
8443 }
8444 }
8446 printf("Internal error in insertvertex():\n");
8447 printf(
8448 " Clockwise triangle after edge vertex insertion (bottom left).\n");
8449 }
8451 printf("Internal error in insertvertex():\n");
8452 printf(
8453 " Clockwise triangle after edge vertex insertion (bottom right).\n");
8454 }
8455#endif /* SELF_CHECK */
8456 if (b->verbose > 2) {
8457 printf(" Updating bottom left ");
8459 if (mirrorflag) {
8460 printf(" Updating top left ");
8462 printf(" Creating top right ");
8464 }
8465 printf(" Creating bottom right ");
8467 }
8468
8469 /* Position `horiz' on the first edge to check for */
8470 /* the Delaunay property. */
8471 lnextself(horiz);
8472 } else {
8473 /* Insert the vertex in a triangle, splitting it into three. */
8474 lnext(horiz, botleft);
8476 sym(botleft, botlcasing);
8478 maketriangle(m, b, &newbotleft);
8480
8481 /* Set the vertices of changed and new triangles. */
8485 setorg(newbotleft, leftvertex);
8486 setdest(newbotleft, botvertex);
8487 setapex(newbotleft, newvertex);
8492 for (i = 0; i < m->eextras; i++) {
8493 /* Set the element attributes of the new triangles. */
8494 attrib = elemattribute(horiz, i);
8495 setelemattribute(newbotleft, i, attrib);
8496 setelemattribute(newbotright, i, attrib);
8497 }
8498 if (b->vararea) {
8499 /* Set the area constraint of the new triangles. */
8500 area = areabound(horiz);
8501 setareabound(newbotleft, area);
8502 setareabound(newbotright, area);
8503 }
8504
8505 /* There may be subsegments that need to be bonded */
8506 /* to the new triangles. */
8507 if (m->checksegments) {
8508 tspivot(botleft, botlsubseg);
8509 if (botlsubseg.ss != m->dummysub) {
8510 tsdissolve(botleft);
8511 tsbond(newbotleft, botlsubseg);
8512 }
8514 if (botrsubseg.ss != m->dummysub) {
8515 tsdissolve(botright);
8516 tsbond(newbotright, botrsubseg);
8517 }
8518 }
8519
8520 /* Bond the new triangles to the surrounding triangles. */
8521 bond(newbotleft, botlcasing);
8523 lnextself(newbotleft);
8525 bond(newbotleft, newbotright);
8526 lnextself(newbotleft);
8527 bond(botleft, newbotleft);
8530
8531 if (m->checkquality) {
8532 poolrestart(&m->flipstackers);
8533 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8534 m->lastflip->flippedtri = encode(horiz);
8535 m->lastflip->prevflip = (struct flipstacker *) NULL;
8536 }
8537
8538#ifdef SELF_CHECK
8540 printf("Internal error in insertvertex():\n");
8541 printf(" Clockwise triangle prior to vertex insertion.\n");
8542 }
8544 printf("Internal error in insertvertex():\n");
8545 printf(" Clockwise triangle after vertex insertion (top).\n");
8546 }
8548 printf("Internal error in insertvertex():\n");
8549 printf(" Clockwise triangle after vertex insertion (left).\n");
8550 }
8552 printf("Internal error in insertvertex():\n");
8553 printf(" Clockwise triangle after vertex insertion (right).\n");
8554 }
8555#endif /* SELF_CHECK */
8556 if (b->verbose > 2) {
8557 printf(" Updating top ");
8558 printtriangle(m, b, &horiz);
8559 printf(" Creating left ");
8560 printtriangle(m, b, &newbotleft);
8561 printf(" Creating right ");
8563 }
8564 }
8565
8566 /* The insertion is successful by default, unless an encroached */
8567 /* subsegment is found. */
8569 /* Circle around the newly inserted vertex, checking each edge opposite */
8570 /* it for the Delaunay property. Non-Delaunay edges are flipped. */
8571 /* `horiz' is always the edge being checked. `first' marks where to */
8572 /* stop circling. */
8573 org(horiz, first);
8575 destT(horiz, leftvertex);
8576 /* Circle until finished. */
8577 while (1) {
8578 /* By default, the edge will be flipped. */
8579 doflip = 1;
8580
8581 if (m->checksegments) {
8582 /* Check for a subsegment, which cannot be flipped. */
8583 tspivot(horiz, checksubseg);
8584 if (checksubseg.ss != m->dummysub) {
8585 /* The edge is a subsegment and cannot be flipped. */
8586 doflip = 0;
8587#ifndef CDT_ONLY
8588 if (segmentflaws) {
8589 /* Does the new vertex encroach upon this subsegment? */
8590 if (checkseg4encroach(m, b, &checksubseg)) {
8592 }
8593 }
8594#endif /* not CDT_ONLY */
8595 }
8596 }
8597
8598 if (doflip) {
8599 /* Check if the edge is a boundary edge. */
8600 sym(horiz, top);
8601 if (top.tri == m->dummytri) {
8602 /* The edge is a boundary edge and cannot be flipped. */
8603 doflip = 0;
8604 } else {
8605 /* Find the vertex on the other side of the edge. */
8606 apex(top, farvertex);
8607 /* In the incremental Delaunay triangulation algorithm, any of */
8608 /* `leftvertex', `rightvertex', and `farvertex' could be vertices */
8609 /* of the triangular bounding box. These vertices must be */
8610 /* treated as if they are infinitely distant, even though their */
8611 /* "coordinates" are not. */
8612 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
8613 (leftvertex == m->infvertex3)) {
8614 /* `leftvertex' is infinitely distant. Check the convexity of */
8615 /* the boundary of the triangulation. 'farvertex' might be */
8616 /* infinite as well, but trust me, this same condition should */
8617 /* be applied. */
8619 > 0.0;
8620 } else if ((rightvertex == m->infvertex1) ||
8621 (rightvertex == m->infvertex2) ||
8622 (rightvertex == m->infvertex3)) {
8623 /* `rightvertex' is infinitely distant. Check the convexity of */
8624 /* the boundary of the triangulation. 'farvertex' might be */
8625 /* infinite as well, but trust me, this same condition should */
8626 /* be applied. */
8628 > 0.0;
8629 } else if ((farvertex == m->infvertex1) ||
8630 (farvertex == m->infvertex2) ||
8631 (farvertex == m->infvertex3)) {
8632 /* `farvertex' is infinitely distant and cannot be inside */
8633 /* the circumcircle of the triangle `horiz'. */
8634 doflip = 0;
8635 } else {
8636 /* Test whether the edge is locally Delaunay. */
8638 farvertex) > 0.0;
8639 }
8640 if (doflip) {
8641 /* We made it! Flip the edge `horiz' by rotating its containing */
8642 /* quadrilateral (the two triangles adjacent to `horiz'). */
8643 /* Identify the casing of the quadrilateral. */
8644 lprev(top, topleft);
8645 sym(topleft, toplcasing);
8646 lnext(top, topright);
8648 lnext(horiz, botleft);
8649 sym(botleft, botlcasing);
8650 lprev(horiz, botright);
8652 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
8653 bond(topleft, botlcasing);
8654 bond(botleft, botrcasing);
8656 bond(topright, toplcasing);
8657 if (m->checksegments) {
8658 /* Check for subsegments and rebond them to the quadrilateral. */
8659 tspivot(topleft, toplsubseg);
8660 tspivot(botleft, botlsubseg);
8663 if (toplsubseg.ss == m->dummysub) {
8664 tsdissolve(topright);
8665 } else {
8666 tsbond(topright, toplsubseg);
8667 }
8668 if (botlsubseg.ss == m->dummysub) {
8669 tsdissolve(topleft);
8670 } else {
8671 tsbond(topleft, botlsubseg);
8672 }
8673 if (botrsubseg.ss == m->dummysub) {
8674 tsdissolve(botleft);
8675 } else {
8676 tsbond(botleft, botrsubseg);
8677 }
8678 if (toprsubseg.ss == m->dummysub) {
8679 tsdissolve(botright);
8680 } else {
8681 tsbond(botright, toprsubseg);
8682 }
8683 }
8684 /* New vertex assignments for the rotated quadrilateral. */
8685 setorg(horiz, farvertex);
8686 setdest(horiz, newvertex);
8687 setapex(horiz, rightvertex);
8691 for (i = 0; i < m->eextras; i++) {
8692 /* Take the average of the two triangles' attributes. */
8693 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
8694 setelemattribute(top, i, attrib);
8695 setelemattribute(horiz, i, attrib);
8696 }
8697 if (b->vararea) {
8698 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
8699 area = -1.0;
8700 } else {
8701 /* Take the average of the two triangles' area constraints. */
8702 /* This prevents small area constraints from migrating a */
8703 /* long, long way from their original location due to flips. */
8704 area = 0.5 * (areabound(top) + areabound(horiz));
8705 }
8706 setareabound(top, area);
8707 setareabound(horiz, area);
8708 }
8709
8710 if (m->checkquality) {
8711 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8712 newflip->flippedtri = encode(horiz);
8713 newflip->prevflip = m->lastflip;
8714 m->lastflip = newflip;
8715 }
8716
8717#ifdef SELF_CHECK
8718 if (newvertex != (vertex) NULL) {
8720 0.0) {
8721 printf("Internal error in insertvertex():\n");
8722 printf(" Clockwise triangle prior to edge flip (bottom).\n");
8723 }
8724 /* The following test has been removed because constrainededge() */
8725 /* sometimes generates inverted triangles that insertvertex() */
8726 /* removes. */
8727/*
8728 if (counterclockwise(m, b, rightvertex, farvertex, leftvertex) <
8729 0.0) {
8730 printf("Internal error in insertvertex():\n");
8731 printf(" Clockwise triangle prior to edge flip (top).\n");
8732 }
8733*/
8735 0.0) {
8736 printf("Internal error in insertvertex():\n");
8737 printf(" Clockwise triangle after edge flip (left).\n");
8738 }
8740 0.0) {
8741 printf("Internal error in insertvertex():\n");
8742 printf(" Clockwise triangle after edge flip (right).\n");
8743 }
8744 }
8745#endif /* SELF_CHECK */
8746 if (b->verbose > 2) {
8747 printf(" Edge flip results in left ");
8748 lnextself(topleft);
8749 printtriangle(m, b, &topleft);
8750 printf(" and right ");
8751 printtriangle(m, b, &horiz);
8752 }
8753 /* On the next iterations, consider the two edges that were */
8754 /* exposed (this is, are now visible to the newly inserted */
8755 /* vertex) by the edge flip. */
8756 lprevself(horiz);
8758 }
8759 }
8760 }
8761 if (!doflip) {
8762 /* The handle `horiz' is accepted as locally Delaunay. */
8763#ifndef CDT_ONLY
8764 if (triflaws) {
8765 /* Check the triangle `horiz' for quality. */
8766 testtriangle(m, b, &horiz);
8767 }
8768#endif /* not CDT_ONLY */
8769 /* Look for the next edge around the newly inserted vertex. */
8770 lnextself(horiz);
8771 sym(horiz, testtri);
8772 /* Check for finishing a complete revolution about the new vertex, or */
8773 /* falling outside of the triangulation. The latter will happen */
8774 /* when a vertex is inserted at a boundary. */
8775 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
8776 /* We're done. Return a triangle whose origin is the new vertex. */
8777 lnext(horiz, *searchtri);
8778 lnext(horiz, m->recenttri);
8779 return success;
8780 }
8781 /* Finish finding the next edge around the newly inserted vertex. */
8782 lnext(testtri, horiz);
8784 destT(horiz, leftvertex);
8785 }
8786 }
8787}
8788
8789/*****************************************************************************/
8790/* */
8791/* triangulatepolygon() Find the Delaunay triangulation of a polygon that */
8792/* has a certain "nice" shape. This includes the */
8793/* polygons that result from deletion of a vertex or */
8794/* insertion of a segment. */
8795/* */
8796/* This is a conceptually difficult routine. The starting assumption is */
8797/* that we have a polygon with n sides. n - 1 of these sides are currently */
8798/* represented as edges in the mesh. One side, called the "base", need not */
8799/* be. */
8800/* */
8801/* Inside the polygon is a structure I call a "fan", consisting of n - 1 */
8802/* triangles that share a common origin. For each of these triangles, the */
8803/* edge opposite the origin is one of the sides of the polygon. The */
8804/* primary edge of each triangle is the edge directed from the origin to */
8805/* the destination; note that this is not the same edge that is a side of */
8806/* the polygon. `firstedge' is the primary edge of the first triangle. */
8807/* From there, the triangles follow in counterclockwise order about the */
8808/* polygon, until `lastedge', the primary edge of the last triangle. */
8809/* `firstedge' and `lastedge' are probably connected to other triangles */
8810/* beyond the extremes of the fan, but their identity is not important, as */
8811/* long as the fan remains connected to them. */
8812/* */
8813/* Imagine the polygon oriented so that its base is at the bottom. This */
8814/* puts `firstedge' on the far right, and `lastedge' on the far left. */
8815/* The right vertex of the base is the destination of `firstedge', and the */
8816/* left vertex of the base is the apex of `lastedge'. */
8817/* */
8818/* The challenge now is to find the right sequence of edge flips to */
8819/* transform the fan into a Delaunay triangulation of the polygon. Each */
8820/* edge flip effectively removes one triangle from the fan, committing it */
8821/* to the polygon. The resulting polygon has one fewer edge. If `doflip' */
8822/* is set, the final flip will be performed, resulting in a fan of one */
8823/* (useless?) triangle. If `doflip' is not set, the final flip is not */
8824/* performed, resulting in a fan of two triangles, and an unfinished */
8825/* triangular polygon that is not yet filled out with a single triangle. */
8826/* On completion of the routine, `lastedge' is the last remaining triangle, */
8827/* or the leftmost of the last two. */
8828/* */
8829/* Although the flips are performed in the order described above, the */
8830/* decisions about what flips to perform are made in precisely the reverse */
8831/* order. The recursive triangulatepolygon() procedure makes a decision, */
8832/* uses up to two recursive calls to triangulate the "subproblems" */
8833/* (polygons with fewer edges), and then performs an edge flip. */
8834/* */
8835/* The "decision" it makes is which vertex of the polygon should be */
8836/* connected to the base. This decision is made by testing every possible */
8837/* vertex. Once the best vertex is found, the two edges that connect this */
8838/* vertex to the base become the bases for two smaller polygons. These */
8839/* are triangulated recursively. Unfortunately, this approach can take */
8840/* O(n^2) time not only in the worst case, but in many common cases. It's */
8841/* rarely a big deal for vertex deletion, where n is rarely larger than */
8842/* ten, but it could be a big deal for segment insertion, especially if */
8843/* there's a lot of long segments that each cut many triangles. I ought to */
8844/* code a faster algorithm some day. */
8845/* */
8846/* The `edgecount' parameter is the number of sides of the polygon, */
8847/* including its base. `triflaws' is a flag that determines whether the */
8848/* new triangles should be tested for quality, and enqueued if they are */
8849/* bad. */
8850/* */
8851/*****************************************************************************/
8852
8853#ifdef ANSI_DECLARATORS
8854void triangulatepolygon(struct mesh *m, struct behavior *b,
8855 struct otri *firstedge, struct otri *lastedge,
8856 int edgecount, int doflip, int triflaws)
8857#else /* not ANSI_DECLARATORS */
8859struct mesh *m;
8860struct behavior *b;
8861struct otri *firstedge;
8862struct otri *lastedge;
8863int edgecount;
8864int doflip;
8865int triflaws;
8866#endif /* not ANSI_DECLARATORS */
8867
8868{
8869 struct otri testtri;
8876 int i;
8877 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8878
8879 /* Identify the base vertices. */
8882 if (b->verbose > 2) {
8883 printf(" Triangulating interior polygon at edge\n");
8884 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
8886 }
8887 /* Find the best vertex to connect the base to. */
8888 onext(*firstedge, besttri);
8891 bestnumber = 1;
8892 for (i = 2; i <= edgecount - 2; i++) {
8893 onextself(testtri);
8895 /* Is this a better vertex? */
8897 testvertex) > 0.0) {
8900 bestnumber = i;
8901 }
8902 }
8903 if (b->verbose > 2) {
8904 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
8905 bestvertex[1]);
8906 }
8907 if (bestnumber > 1) {
8908 /* Recursively triangulate the smaller polygon on the right. */
8911 triflaws);
8912 }
8913 if (bestnumber < edgecount - 2) {
8914 /* Recursively triangulate the smaller polygon on the left. */
8917 triflaws);
8918 /* Find `besttri' again; it may have been lost to edge flips. */
8920 }
8921 if (doflip) {
8922 /* Do one final edge flip. */
8923 flip(m, b, &besttri);
8924#ifndef CDT_ONLY
8925 if (triflaws) {
8926 /* Check the quality of the newly committed triangle. */
8928 testtriangle(m, b, &testtri);
8929 }
8930#endif /* not CDT_ONLY */
8931 }
8932 /* Return the base triangle. */
8934}
8935
8936/*****************************************************************************/
8937/* */
8938/* deletevertex() Delete a vertex from a Delaunay triangulation, ensuring */
8939/* that the triangulation remains Delaunay. */
8940/* */
8941/* The origin of `deltri' is deleted. The union of the triangles adjacent */
8942/* to this vertex is a polygon, for which the Delaunay triangulation is */
8943/* found. Two triangles are removed from the mesh. */
8944/* */
8945/* Only interior vertices that do not lie on segments or boundaries may be */
8946/* deleted. */
8947/* */
8948/*****************************************************************************/
8949
8950#ifndef CDT_ONLY
8951
8952#ifdef ANSI_DECLARATORS
8953void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
8954#else /* not ANSI_DECLARATORS */
8955void deletevertex(m, b, deltri)
8956struct mesh *m;
8957struct behavior *b;
8958struct otri *deltri;
8959#endif /* not ANSI_DECLARATORS */
8960
8961{
8962 struct otri countingtri;
8963 struct otri firstedge, lastedge;
8965 struct otri lefttri, righttri;
8966 struct otri leftcasing, rightcasing;
8967 struct osub leftsubseg, rightsubseg;
8970 int edgecount;
8971 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8972 subseg sptr; /* Temporary variable used by tspivot(). */
8973
8974 org(*deltri, delvertex);
8975 if (b->verbose > 1) {
8976 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
8977 }
8979
8980 /* Count the degree of the vertex being deleted. */
8981 onext(*deltri, countingtri);
8982 edgecount = 1;
8983 while (!otriequal(*deltri, countingtri)) {
8984#ifdef SELF_CHECK
8985 if (countingtri.tri == m->dummytri) {
8986 printf("Internal error in deletevertex():\n");
8987 printf(" Attempt to delete boundary vertex.\n");
8988 internalerror();
8989 }
8990#endif /* SELF_CHECK */
8991 edgecount++;
8992 onextself(countingtri);
8993 }
8994
8995#ifdef SELF_CHECK
8996 if (edgecount < 3) {
8997 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
8998 edgecount);
8999 internalerror();
9000 }
9001#endif /* SELF_CHECK */
9002 if (edgecount > 3) {
9003 /* Triangulate the polygon defined by the union of all triangles */
9004 /* adjacent to the vertex being deleted. Check the quality of */
9005 /* the resulting triangles. */
9006 onext(*deltri, firstedge);
9009 !b->nobisect);
9010 }
9011 /* Splice out two triangles. */
9013 dnext(*deltri, lefttri);
9014 sym(lefttri, leftcasing);
9017 bond(*deltri, leftcasing);
9019 tspivot(lefttri, leftsubseg);
9020 if (leftsubseg.ss != m->dummysub) {
9021 tsbond(*deltri, leftsubseg);
9022 }
9024 if (rightsubseg.ss != m->dummysub) {
9025 tsbond(deltriright, rightsubseg);
9026 }
9027
9028 /* Set the new origin of `deltri' and check its quality. */
9029 org(lefttri, neworg);
9030 setorg(*deltri, neworg);
9031 if (!b->nobisect) {
9033 }
9034
9035 /* Delete the two spliced-out triangles. */
9036 triangledealloc(m, lefttri.tri);
9038}
9039
9040#endif /* not CDT_ONLY */
9041
9042/*****************************************************************************/
9043/* */
9044/* undovertex() Undo the most recent vertex insertion. */
9045/* */
9046/* Walks through the list of transformations (flips and a vertex insertion) */
9047/* in the reverse of the order in which they were done, and undoes them. */
9048/* The inserted vertex is removed from the triangulation and deallocated. */
9049/* Two triangles (possibly just one) are also deallocated. */
9050/* */
9051/*****************************************************************************/
9052
9053#ifndef CDT_ONLY
9054
9055#ifdef ANSI_DECLARATORS
9056void undovertex(struct mesh *m, struct behavior *b)
9057#else /* not ANSI_DECLARATORS */
9058void undovertex(m, b)
9059struct mesh *m;
9060struct behavior *b;
9061#endif /* not ANSI_DECLARATORS */
9062
9063{
9064 struct otri fliptri;
9065 struct otri botleft, botright, topright;
9066 struct otri botlcasing, botrcasing, toprcasing;
9068 struct osub botlsubseg, botrsubseg, toprsubseg;
9070 triangle ptr; /* Temporary variable used by sym(). */
9071 subseg sptr; /* Temporary variable used by tspivot(). */
9072
9073 /* Walk through the list of transformations (flips and a vertex insertion) */
9074 /* in the reverse of the order in which they were done, and undo them. */
9075 while (m->lastflip != (struct flipstacker *) NULL) {
9076 /* Find a triangle involved in the last unreversed transformation. */
9077 decode(m->lastflip->flippedtri, fliptri);
9078
9079 /* We are reversing one of three transformations: a trisection of one */
9080 /* triangle into three (by inserting a vertex in the triangle), a */
9081 /* bisection of two triangles into four (by inserting a vertex in an */
9082 /* edge), or an edge flip. */
9083 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
9084 /* Restore a triangle that was split into three triangles, */
9085 /* so it is again one triangle. */
9086 dprev(fliptri, botleft);
9087 lnextself(botleft);
9088 onext(fliptri, botright);
9090 sym(botleft, botlcasing);
9092 destT(botleft, botvertex);
9093
9096 bond(fliptri, botlcasing);
9097 tspivot(botleft, botlsubseg);
9098 tsbond(fliptri, botlsubseg);
9102 tsbond(fliptri, botrsubseg);
9103
9104 /* Delete the two spliced-out triangles. */
9105 triangledealloc(m, botleft.tri);
9107 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
9108 /* Restore two triangles that were split into four triangles, */
9109 /* so they are again two triangles. */
9115
9119 tsbond(gluetri, botrsubseg);
9120
9121 /* Delete the spliced-out triangle. */
9123
9125 if (gluetri.tri != m->dummytri) {
9127 dnext(gluetri, topright);
9129
9133 tsbond(gluetri, toprsubseg);
9134
9135 /* Delete the spliced-out triangle. */
9137 }
9138
9139 /* This is the end of the list, sneakily encoded. */
9140 m->lastflip->prevflip = (struct flipstacker *) NULL;
9141 } else {
9142 /* Undo an edge flip. */
9143 unflip(m, b, &fliptri);
9144 }
9145
9146 /* Go on and process the next transformation. */
9147 m->lastflip = m->lastflip->prevflip;
9148 }
9149}
9150
9151#endif /* not CDT_ONLY */
9152
9155/********* Mesh transformation routines end here *********/
9156
9157/********* Divide-and-conquer Delaunay triangulation begins here *********/
9160
9161/*****************************************************************************/
9162/* */
9163/* The divide-and-conquer bounding box */
9164/* */
9165/* I originally implemented the divide-and-conquer and incremental Delaunay */
9166/* triangulations using the edge-based data structure presented by Guibas */
9167/* and Stolfi. Switching to a triangle-based data structure doubled the */
9168/* speed. However, I had to think of a few extra tricks to maintain the */
9169/* elegance of the original algorithms. */
9170/* */
9171/* The "bounding box" used by my variant of the divide-and-conquer */
9172/* algorithm uses one triangle for each edge of the convex hull of the */
9173/* triangulation. These bounding triangles all share a common apical */
9174/* vertex, which is represented by NULL and which represents nothing. */
9175/* The bounding triangles are linked in a circular fan about this NULL */
9176/* vertex, and the edges on the convex hull of the triangulation appear */
9177/* opposite the NULL vertex. You might find it easiest to imagine that */
9178/* the NULL vertex is a point in 3D space behind the center of the */
9179/* triangulation, and that the bounding triangles form a sort of cone. */
9180/* */
9181/* This bounding box makes it easy to represent degenerate cases. For */
9182/* instance, the triangulation of two vertices is a single edge. This edge */
9183/* is represented by two bounding box triangles, one on each "side" of the */
9184/* edge. These triangles are also linked together in a fan about the NULL */
9185/* vertex. */
9186/* */
9187/* The bounding box also makes it easy to traverse the convex hull, as the */
9188/* divide-and-conquer algorithm needs to do. */
9189/* */
9190/*****************************************************************************/
9191
9192/*****************************************************************************/
9193/* */
9194/* vertexsort() Sort an array of vertices by x-coordinate, using the */
9195/* y-coordinate as a secondary key. */
9196/* */
9197/* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */
9198/* the usual quicksort mistakes. */
9199/* */
9200/*****************************************************************************/
9201
9202#ifdef ANSI_DECLARATORS
9204#else /* not ANSI_DECLARATORS */
9208#endif /* not ANSI_DECLARATORS */
9209
9210{
9211 int left, right;
9215
9216 if (arraysize == 2) {
9217 /* Recursive base case. */
9218 if ((sortarray[0][0] > sortarray[1][0]) ||
9219 ((sortarray[0][0] == sortarray[1][0]) &&
9220 (sortarray[0][1] > sortarray[1][1]))) {
9221 temp = sortarray[1];
9222 sortarray[1] = sortarray[0];
9223 sortarray[0] = temp;
9224 }
9225 return;
9226 }
9227 /* Choose a random pivot to split the array. */
9228 pivot = (int) randomnation((unsigned int) arraysize);
9229 pivotx = sortarray[pivot][0];
9230 pivoty = sortarray[pivot][1];
9231 /* Split the array. */
9232 left = -1;
9234 while (left < right) {
9235 /* Search for a vertex whose x-coordinate is too large for the left. */
9236 do {
9237 left++;
9238 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
9239 ((sortarray[left][0] == pivotx) &&
9240 (sortarray[left][1] < pivoty))));
9241 /* Search for a vertex whose x-coordinate is too small for the right. */
9242 do {
9243 right--;
9244 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
9245 ((sortarray[right][0] == pivotx) &&
9246 (sortarray[right][1] > pivoty))));
9247 if (left < right) {
9248 /* Swap the left and right vertices. */
9249 temp = sortarray[left];
9251 sortarray[right] = temp;
9252 }
9253 }
9254 if (left > 1) {
9255 /* Recursively sort the left subset. */
9257 }
9258 if (right < arraysize - 2) {
9259 /* Recursively sort the right subset. */
9261 }
9262}
9263
9264/*****************************************************************************/
9265/* */
9266/* vertexmedian() An order statistic algorithm, almost. Shuffles an */
9267/* array of vertices so that the first `median' vertices */
9268/* occur lexicographically before the remaining vertices. */
9269/* */
9270/* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */
9271/* if axis == 1. Very similar to the vertexsort() procedure, but runs in */
9272/* randomized linear time. */
9273/* */
9274/*****************************************************************************/
9275
9276#ifdef ANSI_DECLARATORS
9278#else /* not ANSI_DECLARATORS */
9281int arraysize;
9282int median;
9284#endif /* not ANSI_DECLARATORS */
9285
9286{
9287 int left, right;
9288 int pivot;
9290 vertex temp;
9291
9292 if (arraysize == 2) {
9293 /* Recursive base case. */
9294 if ((sortarray[0][axis] > sortarray[1][axis]) ||
9295 ((sortarray[0][axis] == sortarray[1][axis]) &&
9296 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
9297 temp = sortarray[1];
9298 sortarray[1] = sortarray[0];
9299 sortarray[0] = temp;
9300 }
9301 return;
9302 }
9303 /* Choose a random pivot to split the array. */
9304 pivot = (int) randomnation((unsigned int) arraysize);
9306 pivot2 = sortarray[pivot][1 - axis];
9307 /* Split the array. */
9308 left = -1;
9309 right = arraysize;
9310 while (left < right) {
9311 /* Search for a vertex whose x-coordinate is too large for the left. */
9312 do {
9313 left++;
9314 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
9315 ((sortarray[left][axis] == pivot1) &&
9316 (sortarray[left][1 - axis] < pivot2))));
9317 /* Search for a vertex whose x-coordinate is too small for the right. */
9318 do {
9319 right--;
9320 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
9321 ((sortarray[right][axis] == pivot1) &&
9322 (sortarray[right][1 - axis] > pivot2))));
9323 if (left < right) {
9324 /* Swap the left and right vertices. */
9325 temp = sortarray[left];
9327 sortarray[right] = temp;
9328 }
9329 }
9330 /* Unlike in vertexsort(), at most one of the following */
9331 /* conditionals is true. */
9332 if (left > median) {
9333 /* Recursively shuffle the left subset. */
9335 }
9336 if (right < median - 1) {
9337 /* Recursively shuffle the right subset. */
9339 median - right - 1, axis);
9340 }
9341}
9342
9343/*****************************************************************************/
9344/* */
9345/* alternateaxes() Sorts the vertices as appropriate for the divide-and- */
9346/* conquer algorithm with alternating cuts. */
9347/* */
9348/* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */
9349/* For the base case, subsets containing only two or three vertices are */
9350/* always sorted by x-coordinate. */
9351/* */
9352/*****************************************************************************/
9353
9354#ifdef ANSI_DECLARATORS
9356#else /* not ANSI_DECLARATORS */
9359int arraysize;
9360int axis;
9361#endif /* not ANSI_DECLARATORS */
9362
9363{
9364 int divider;
9365
9367 if (arraysize <= 3) {
9368 /* Recursive base case: subsets of two or three vertices will be */
9369 /* handled specially, and should always be sorted by x-coordinate. */
9370 axis = 0;
9371 }
9372 /* Partition with a horizontal or vertical cut. */
9374 /* Recursively partition the subsets with a cross cut. */
9375 if (arraysize - divider >= 2) {
9376 if (divider >= 2) {
9378 }
9380 }
9381}
9382
9383/*****************************************************************************/
9384/* */
9385/* mergehulls() Merge two adjacent Delaunay triangulations into a */
9386/* single Delaunay triangulation. */
9387/* */
9388/* This is similar to the algorithm given by Guibas and Stolfi, but uses */
9389/* a triangle-based, rather than edge-based, data structure. */
9390/* */
9391/* The algorithm walks up the gap between the two triangulations, knitting */
9392/* them together. As they are merged, some of their bounding triangles */
9393/* are converted into real triangles of the triangulation. The procedure */
9394/* pulls each hull's bounding triangles apart, then knits them together */
9395/* like the teeth of two gears. The Delaunay property determines, at each */
9396/* step, whether the next "tooth" is a bounding triangle of the left hull */
9397/* or the right. When a bounding triangle becomes real, its apex is */
9398/* changed from NULL to a real vertex. */
9399/* */
9400/* Only two new triangles need to be allocated. These become new bounding */
9401/* triangles at the top and bottom of the seam. They are used to connect */
9402/* the remaining bounding triangles (those that have not been converted */
9403/* into real triangles) into a single fan. */
9404/* */
9405/* On entry, `farleft' and `innerleft' are bounding triangles of the left */
9406/* triangulation. The origin of `farleft' is the leftmost vertex, and */
9407/* the destination of `innerleft' is the rightmost vertex of the */
9408/* triangulation. Similarly, `innerright' and `farright' are bounding */
9409/* triangles of the right triangulation. The origin of `innerright' and */
9410/* destination of `farright' are the leftmost and rightmost vertices. */
9411/* */
9412/* On completion, the origin of `farleft' is the leftmost vertex of the */
9413/* merged triangulation, and the destination of `farright' is the rightmost */
9414/* vertex. */
9415/* */
9416/*****************************************************************************/
9417
9418#ifdef ANSI_DECLARATORS
9419void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
9420 struct otri *innerleft, struct otri *innerright,
9421 struct otri *farright, int axis)
9422#else /* not ANSI_DECLARATORS */
9424struct mesh *m;
9425struct behavior *b;
9426struct otri *farleft;
9427struct otri *innerleft;
9428struct otri *innerright;
9429struct otri *farright;
9430int axis;
9431#endif /* not ANSI_DECLARATORS */
9432
9433{
9434 struct otri leftcand, rightcand;
9437 struct otri sidecasing, topcasing, outercasing;
9438 struct otri checkedge;
9451 triangle ptr; /* Temporary variable used by sym(). */
9452
9457 /* Special treatment for horizontal cuts. */
9458 if (b->dwyer && (axis == 1)) {
9463 /* The pointers to the extremal vertices are shifted to point to the */
9464 /* topmost and bottommost vertex of each hull, rather than the */
9465 /* leftmost and rightmost vertices. */
9466 while (farleftapex[1] < farleftpt[1]) {
9468 symself(*farleft);
9471 }
9474 while (checkvertex[1] > innerleftdest[1]) {
9480 }
9481 while (innerrightapex[1] < innerrightorg[1]) {
9486 }
9489 while (checkvertex[1] > farrightpt[1]) {
9495 }
9496 }
9497 /* Find a line tangent to and below both hulls. */
9498 do {
9499 changemade = 0;
9500 /* Make innerleftdest the "bottommost" vertex of the left hull. */
9509 /* Make innerrightorg the "bottommost" vertex of the right hull. */
9518 } while (changemade);
9519 /* Find the two candidates to be the next "gear tooth." */
9520 sym(*innerleft, leftcand);
9521 sym(*innerright, rightcand);
9522 /* Create the bottom new bounding triangle. */
9524 /* Connect it to the bounding boxes of the left and right triangulations. */
9531 /* Apex is intentionally left NULL. */
9532 if (b->verbose > 2) {
9533 printf(" Creating base bounding ");
9535 }
9536 /* Fix the extreme triangles if necessary. */
9540 }
9545 /* The vertices of the current knitting edge. */
9548 /* The candidate vertices for knitting. */
9549 apex(leftcand, upperleft);
9550 apex(rightcand, upperright);
9551 /* Walk up the gap between the two triangulations, knitting them together. */
9552 while (1) {
9553 /* Have we reached the top? (This isn't quite the right question, */
9554 /* because even though the left triangulation might seem finished now, */
9555 /* moving up on the right triangulation might reveal a new vertex of */
9556 /* the left triangulation. And vice-versa.) */
9558 0.0;
9560 <= 0.0;
9561 if (leftfinished && rightfinished) {
9562 /* Create the top new bounding triangle. */
9566 /* Apex is intentionally left NULL. */
9567 /* Connect it to the bounding boxes of the two triangulations. */
9570 bond(nextedge, rightcand);
9572 bond(nextedge, leftcand);
9573 if (b->verbose > 2) {
9574 printf(" Creating top bounding ");
9576 }
9577 /* Special treatment for horizontal cuts. */
9578 if (b->dwyer && (axis == 1)) {
9585 /* The pointers to the extremal vertices are restored to the */
9586 /* leftmost and rightmost vertices (rather than topmost and */
9587 /* bottommost). */
9588 while (checkvertex[0] < farleftpt[0]) {
9594 }
9595 while (farrightapex[0] > farrightpt[0]) {
9597 symself(*farright);
9600 }
9601 }
9602 return;
9603 }
9604 /* Consider eliminating edges from the left triangulation. */
9605 if (!leftfinished) {
9606 /* What vertex would be exposed if an edge were deleted? */
9607 lprev(leftcand, nextedge);
9610 /* If nextapex is NULL, then no vertex would be exposed; the */
9611 /* triangulation would have been eaten right through. */
9612 if (nextapex != (vertex) NULL) {
9613 /* Check whether the edge is Delaunay. */
9615 0.0;
9616 while (badedge) {
9617 /* Eliminate the edge with an edge flip. As a result, the */
9618 /* left triangulation will have one more boundary triangle. */
9620 sym(nextedge, topcasing);
9622 sym(nextedge, sidecasing);
9623 bond(nextedge, topcasing);
9624 bond(leftcand, sidecasing);
9625 lnextself(leftcand);
9626 sym(leftcand, outercasing);
9629 /* Correct the vertices to reflect the edge flip. */
9630 setorg(leftcand, lowerleft);
9631 setdest(leftcand, NULL);
9632 setapex(leftcand, nextapex);
9633 setorg(nextedge, NULL);
9636 /* Consider the newly exposed vertex. */
9638 /* What vertex would be exposed if another edge were deleted? */
9639 otricopy(sidecasing, nextedge);
9641 if (nextapex != (vertex) NULL) {
9642 /* Check whether the edge is Delaunay. */
9644 nextapex) > 0.0;
9645 } else {
9646 /* Avoid eating right through the triangulation. */
9647 badedge = 0;
9648 }
9649 }
9650 }
9651 }
9652 /* Consider eliminating edges from the right triangulation. */
9653 if (!rightfinished) {
9654 /* What vertex would be exposed if an edge were deleted? */
9655 lnext(rightcand, nextedge);
9658 /* If nextapex is NULL, then no vertex would be exposed; the */
9659 /* triangulation would have been eaten right through. */
9660 if (nextapex != (vertex) NULL) {
9661 /* Check whether the edge is Delaunay. */
9663 0.0;
9664 while (badedge) {
9665 /* Eliminate the edge with an edge flip. As a result, the */
9666 /* right triangulation will have one more boundary triangle. */
9668 sym(nextedge, topcasing);
9670 sym(nextedge, sidecasing);
9671 bond(nextedge, topcasing);
9672 bond(rightcand, sidecasing);
9673 lprevself(rightcand);
9674 sym(rightcand, outercasing);
9677 /* Correct the vertices to reflect the edge flip. */
9678 setorg(rightcand, NULL);
9679 setdest(rightcand, lowerright);
9680 setapex(rightcand, nextapex);
9682 setdest(nextedge, NULL);
9684 /* Consider the newly exposed vertex. */
9686 /* What vertex would be exposed if another edge were deleted? */
9687 otricopy(sidecasing, nextedge);
9689 if (nextapex != (vertex) NULL) {
9690 /* Check whether the edge is Delaunay. */
9692 nextapex) > 0.0;
9693 } else {
9694 /* Avoid eating right through the triangulation. */
9695 badedge = 0;
9696 }
9697 }
9698 }
9699 }
9700 if (leftfinished || (!rightfinished &&
9702 0.0))) {
9703 /* Knit the triangulations, adding an edge from `lowerleft' */
9704 /* to `upperright'. */
9705 bond(baseedge, rightcand);
9706 lprev(rightcand, baseedge);
9709 sym(baseedge, rightcand);
9710 apex(rightcand, upperright);
9711 } else {
9712 /* Knit the triangulations, adding an edge from `upperleft' */
9713 /* to `lowerright'. */
9714 bond(baseedge, leftcand);
9715 lnext(leftcand, baseedge);
9718 sym(baseedge, leftcand);
9719 apex(leftcand, upperleft);
9720 }
9721 if (b->verbose > 2) {
9722 printf(" Connecting ");
9724 }
9725 }
9726}
9727
9728/*****************************************************************************/
9729/* */
9730/* divconqrecurse() Recursively form a Delaunay triangulation by the */
9731/* divide-and-conquer method. */
9732/* */
9733/* Recursively breaks down the problem into smaller pieces, which are */
9734/* knitted together by mergehulls(). The base cases (problems of two or */
9735/* three vertices) are handled specially here. */
9736/* */
9737/* On completion, `farleft' and `farright' are bounding triangles such that */
9738/* the origin of `farleft' is the leftmost vertex (breaking ties by */
9739/* choosing the highest leftmost vertex), and the destination of */
9740/* `farright' is the rightmost vertex (breaking ties by choosing the */
9741/* lowest rightmost vertex). */
9742/* */
9743/*****************************************************************************/
9744
9745#ifdef ANSI_DECLARATORS
9747 int vertices, int axis,
9748 struct otri *farleft, struct otri *farright)
9749#else /* not ANSI_DECLARATORS */
9751struct mesh *m;
9752struct behavior *b;
9754int vertices;
9755int axis;
9756struct otri *farleft;
9757struct otri *farright;
9758#endif /* not ANSI_DECLARATORS */
9759
9760{
9761 struct otri midtri, tri1, tri2, tri3;
9762 struct otri innerleft, innerright;
9763 REAL area;
9764 int divider;
9765
9766 if (b->verbose > 2) {
9767 printf(" Triangulating %d vertices.\n", vertices);
9768 }
9769 if (vertices == 2) {
9770 /* The triangulation of two vertices is an edge. An edge is */
9771 /* represented by two bounding triangles. */
9773 setorg(*farleft, sortarray[0]);
9775 /* The apex is intentionally left NULL. */
9779 /* The apex is intentionally left NULL. */
9780 bond(*farleft, *farright);
9783 bond(*farleft, *farright);
9786 bond(*farleft, *farright);
9787 if (b->verbose > 2) {
9788 printf(" Creating ");
9790 printf(" Creating ");
9792 }
9793 /* Ensure that the origin of `farleft' is sortarray[0]. */
9795 return;
9796 } else if (vertices == 3) {
9797 /* The triangulation of three vertices is either a triangle (with */
9798 /* three bounding triangles) or two edges (with four bounding */
9799 /* triangles). In either case, four triangles are created. */
9800 maketriangle(m, b, &midtri);
9801 maketriangle(m, b, &tri1);
9802 maketriangle(m, b, &tri2);
9803 maketriangle(m, b, &tri3);
9805 if (area == 0.0) {
9806 /* Three collinear vertices; the triangulation is two edges. */
9807 setorg(midtri, sortarray[0]);
9808 setdest(midtri, sortarray[1]);
9809 setorg(tri1, sortarray[1]);
9810 setdest(tri1, sortarray[0]);
9811 setorg(tri2, sortarray[2]);
9812 setdest(tri2, sortarray[1]);
9813 setorg(tri3, sortarray[1]);
9814 setdest(tri3, sortarray[2]);
9815 /* All apices are intentionally left NULL. */
9816 bond(midtri, tri1);
9817 bond(tri2, tri3);
9818 lnextself(midtri);
9819 lprevself(tri1);
9820 lnextself(tri2);
9821 lprevself(tri3);
9822 bond(midtri, tri3);
9823 bond(tri1, tri2);
9824 lnextself(midtri);
9825 lprevself(tri1);
9826 lnextself(tri2);
9827 lprevself(tri3);
9828 bond(midtri, tri1);
9829 bond(tri2, tri3);
9830 /* Ensure that the origin of `farleft' is sortarray[0]. */
9831 otricopy(tri1, *farleft);
9832 /* Ensure that the destination of `farright' is sortarray[2]. */
9833 otricopy(tri2, *farright);
9834 } else {
9835 /* The three vertices are not collinear; the triangulation is one */
9836 /* triangle, namely `midtri'. */
9837 setorg(midtri, sortarray[0]);
9838 setdest(tri1, sortarray[0]);
9839 setorg(tri3, sortarray[0]);
9840 /* Apices of tri1, tri2, and tri3 are left NULL. */
9841 if (area > 0.0) {
9842 /* The vertices are in counterclockwise order. */
9843 setdest(midtri, sortarray[1]);
9844 setorg(tri1, sortarray[1]);
9845 setdest(tri2, sortarray[1]);
9846 setapex(midtri, sortarray[2]);
9847 setorg(tri2, sortarray[2]);
9848 setdest(tri3, sortarray[2]);
9849 } else {
9850 /* The vertices are in clockwise order. */
9851 setdest(midtri, sortarray[2]);
9852 setorg(tri1, sortarray[2]);
9853 setdest(tri2, sortarray[2]);
9854 setapex(midtri, sortarray[1]);
9855 setorg(tri2, sortarray[1]);
9856 setdest(tri3, sortarray[1]);
9857 }
9858 /* The topology does not depend on how the vertices are ordered. */
9859 bond(midtri, tri1);
9860 lnextself(midtri);
9861 bond(midtri, tri2);
9862 lnextself(midtri);
9863 bond(midtri, tri3);
9864 lprevself(tri1);
9865 lnextself(tri2);
9866 bond(tri1, tri2);
9867 lprevself(tri1);
9868 lprevself(tri3);
9869 bond(tri1, tri3);
9870 lnextself(tri2);
9871 lprevself(tri3);
9872 bond(tri2, tri3);
9873 /* Ensure that the origin of `farleft' is sortarray[0]. */
9874 otricopy(tri1, *farleft);
9875 /* Ensure that the destination of `farright' is sortarray[2]. */
9876 if (area > 0.0) {
9877 otricopy(tri2, *farright);
9878 } else {
9880 }
9881 }
9882 if (b->verbose > 2) {
9883 printf(" Creating ");
9884 printtriangle(m, b, &midtri);
9885 printf(" Creating ");
9886 printtriangle(m, b, &tri1);
9887 printf(" Creating ");
9888 printtriangle(m, b, &tri2);
9889 printf(" Creating ");
9890 printtriangle(m, b, &tri3);
9891 }
9892 return;
9893 } else {
9894 /* Split the vertices in half. */
9895 divider = vertices >> 1;
9896 /* Recursively triangulate each half. */
9900 if (b->verbose > 1) {
9901 printf(" Joining triangulations with %d and %d vertices.\n", divider,
9902 vertices - divider);
9903 }
9904 /* Merge the two triangulations into one. */
9906 }
9907}
9908
9909#ifdef ANSI_DECLARATORS
9910long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
9911#else /* not ANSI_DECLARATORS */
9912long removeghosts(m, b, startghost)
9913struct mesh *m;
9914struct behavior *b;
9916#endif /* not ANSI_DECLARATORS */
9917
9918{
9919 struct otri searchedge;
9924 triangle ptr; /* Temporary variable used by sym(). */
9925
9926 if (b->verbose) {
9927 printf(" Removing ghost triangles.\n");
9928 }
9929 /* Find an edge on the convex hull to start point location from. */
9932 m->dummytri[0] = encode(searchedge);
9933 /* Remove the bounding box and count the convex hull edges. */
9935 hullsize = 0;
9936 do {
9937 hullsize++;
9941 /* If no PSLG is involved, set the boundary markers of all the vertices */
9942 /* on the convex hull. If a PSLG is used, this step is done later. */
9943 if (!b->poly) {
9944 /* Watch out for the case where all the input vertices are collinear. */
9945 if (dissolveedge.tri != m->dummytri) {
9947 if (vertexmark(markorg) == 0) {
9949 }
9950 }
9951 }
9952 /* Remove a bounding triangle from a convex hull triangle. */
9954 /* Find the next bounding triangle. */
9956 /* Delete the bounding triangle. */
9958 } while (!otriequal(dissolveedge, *startghost));
9959 return hullsize;
9960}
9961
9962/*****************************************************************************/
9963/* */
9964/* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */
9965/* conquer method. */
9966/* */
9967/* Sorts the vertices, calls a recursive procedure to triangulate them, and */
9968/* removes the bounding box, setting boundary markers as appropriate. */
9969/* */
9970/*****************************************************************************/
9971
9972#ifdef ANSI_DECLARATORS
9973long divconqdelaunay(struct mesh *m, struct behavior *b)
9974#else /* not ANSI_DECLARATORS */
9975long divconqdelaunay(m, b)
9976struct mesh *m;
9977struct behavior *b;
9978#endif /* not ANSI_DECLARATORS */
9979
9980{
9982 struct otri hullleft, hullright;
9983 int divider;
9984 int i, j;
9985
9986 if (b->verbose) {
9987 printf(" Sorting vertices.\n");
9988 }
9989
9990 /* Allocate an array of pointers to vertices for sorting. */
9991 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
9992 traversalinit(&m->vertices);
9993 for (i = 0; i < m->invertices; i++) {
9995 }
9996 /* Sort the vertices. */
9997 vertexsort(sortarray, m->invertices);
9998 /* Discard duplicate vertices, which can really mess up the algorithm. */
9999 i = 0;
10000 for (j = 1; j < m->invertices; j++) {
10001 if ((sortarray[i][0] == sortarray[j][0])
10002 && (sortarray[i][1] == sortarray[j][1])) {
10003 if (!b->quiet) {
10004 printf(
10005"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10006 sortarray[j][0], sortarray[j][1]);
10007 }
10008 setvertextype(sortarray[j], UNDEADVERTEX);
10009 m->undeads++;
10010 } else {
10011 i++;
10012 sortarray[i] = sortarray[j];
10013 }
10014 }
10015 i++;
10016 if (b->dwyer) {
10017 /* Re-sort the array of vertices to accommodate alternating cuts. */
10018 divider = i >> 1;
10019 if (i - divider >= 2) {
10020 if (divider >= 2) {
10022 }
10024 }
10025 }
10026
10027 if (b->verbose) {
10028 printf(" Forming triangulation.\n");
10029 }
10030
10031 /* Form the Delaunay triangulation. */
10032 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10034
10035 return removeghosts(m, b, &hullleft);
10036}
10037
10040/********* Divide-and-conquer Delaunay triangulation ends here *********/
10041
10042/********* Incremental Delaunay triangulation begins here *********/
10045
10046/*****************************************************************************/
10047/* */
10048/* boundingbox() Form an "infinite" bounding triangle to insert vertices */
10049/* into. */
10050/* */
10051/* The vertices at "infinity" are assigned finite coordinates, which are */
10052/* used by the point location routines, but (mostly) ignored by the */
10053/* Delaunay edge flip routines. */
10054/* */
10055/*****************************************************************************/
10056
10057#ifndef REDUCED
10058
10059#ifdef ANSI_DECLARATORS
10060void boundingbox(struct mesh *m, struct behavior *b)
10061#else /* not ANSI_DECLARATORS */
10062void boundingbox(m, b)
10063struct mesh *m;
10064struct behavior *b;
10065#endif /* not ANSI_DECLARATORS */
10066
10067{
10068 struct otri inftri; /* Handle for the triangular bounding box. */
10069 REAL width;
10070
10071 if (b->verbose) {
10072 printf(" Creating triangular bounding box.\n");
10073 }
10074 /* Find the width (or height, whichever is larger) of the triangulation. */
10075 width = m->xmax - m->xmin;
10076 if (m->ymax - m->ymin > width) {
10077 width = m->ymax - m->ymin;
10078 }
10079 if (width == 0.0) {
10080 width = 1.0;
10081 }
10082 /* Create the vertices of the bounding box. */
10083 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10084 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10085 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10086 m->infvertex1[0] = m->xmin - 50.0 * width;
10087 m->infvertex1[1] = m->ymin - 40.0 * width;
10088 m->infvertex2[0] = m->xmax + 50.0 * width;
10089 m->infvertex2[1] = m->ymin - 40.0 * width;
10090 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10091 m->infvertex3[1] = m->ymax + 60.0 * width;
10092
10093 /* Create the bounding box. */
10094 maketriangle(m, b, &inftri);
10095 setorg(inftri, m->infvertex1);
10096 setdest(inftri, m->infvertex2);
10097 setapex(inftri, m->infvertex3);
10098 /* Link dummytri to the bounding box so we can always find an */
10099 /* edge to begin searching (point location) from. */
10100 m->dummytri[0] = (triangle) inftri.tri;
10101 if (b->verbose > 2) {
10102 printf(" Creating ");
10103 printtriangle(m, b, &inftri);
10104 }
10105}
10106
10107#endif /* not REDUCED */
10108
10109/*****************************************************************************/
10110/* */
10111/* removebox() Remove the "infinite" bounding triangle, setting boundary */
10112/* markers as appropriate. */
10113/* */
10114/* The triangular bounding box has three boundary triangles (one for each */
10115/* side of the bounding box), and a bunch of triangles fanning out from */
10116/* the three bounding box vertices (one triangle for each edge of the */
10117/* convex hull of the inner mesh). This routine removes these triangles. */
10118/* */
10119/* Returns the number of edges on the convex hull of the triangulation. */
10120/* */
10121/*****************************************************************************/
10122
10123#ifndef REDUCED
10124
10125#ifdef ANSI_DECLARATORS
10126long removebox(struct mesh *m, struct behavior *b)
10127#else /* not ANSI_DECLARATORS */
10128long removebox(m, b)
10129struct mesh *m;
10130struct behavior *b;
10131#endif /* not ANSI_DECLARATORS */
10132
10133{
10134 struct otri deadtriangle;
10136 struct otri checkedge;
10137 struct otri nextedge, finaledge, dissolveedge;
10139 long hullsize;
10140 triangle ptr; /* Temporary variable used by sym(). */
10141
10142 if (b->verbose) {
10143 printf(" Removing triangular bounding box.\n");
10144 }
10145 /* Find a boundary triangle. */
10146 nextedge.tri = m->dummytri;
10147 nextedge.orient = 0;
10149 /* Mark a place to stop. */
10150 lprev(nextedge, finaledge);
10153 /* Find a triangle (on the boundary of the vertex set) that isn't */
10154 /* a bounding box triangle. */
10157 /* Check whether nextedge is another boundary triangle */
10158 /* adjacent to the first one. */
10161 if (checkedge.tri == m->dummytri) {
10162 /* Go on to the next triangle. There are only three boundary */
10163 /* triangles, and this next triangle cannot be the third one, */
10164 /* so it's safe to stop here. */
10167 }
10168 /* Find a new boundary edge to search from, as the current search */
10169 /* edge lies on a bounding box triangle and will be deleted. */
10170 m->dummytri[0] = encode(searchedge);
10171 hullsize = -2l;
10172 while (!otriequal(nextedge, finaledge)) {
10173 hullsize++;
10176 /* If not using a PSLG, the vertices should be marked now. */
10177 /* (If using a PSLG, markhull() will do the job.) */
10178 if (!b->poly) {
10179 /* Be careful! One must check for the case where all the input */
10180 /* vertices are collinear, and thus all the triangles are part of */
10181 /* the bounding box. Otherwise, the setvertexmark() call below */
10182 /* will cause a bad pointer reference. */
10183 if (dissolveedge.tri != m->dummytri) {
10185 if (vertexmark(markorg) == 0) {
10187 }
10188 }
10189 }
10190 /* Disconnect the bounding box triangle from the mesh triangle. */
10194 /* Get rid of the bounding box triangle. */
10196 /* Do we need to turn the corner? */
10197 if (nextedge.tri == m->dummytri) {
10198 /* Turn the corner. */
10200 }
10201 }
10202 triangledealloc(m, finaledge.tri);
10203
10204 trifree((VOID *) m->infvertex1); /* Deallocate the bounding box vertices. */
10205 trifree((VOID *) m->infvertex2);
10206 trifree((VOID *) m->infvertex3);
10207
10208 return hullsize;
10209}
10210
10211#endif /* not REDUCED */
10212
10213/*****************************************************************************/
10214/* */
10215/* incrementaldelaunay() Form a Delaunay triangulation by incrementally */
10216/* inserting vertices. */
10217/* */
10218/* Returns the number of edges on the convex hull of the triangulation. */
10219/* */
10220/*****************************************************************************/
10221
10222#ifndef REDUCED
10223
10224#ifdef ANSI_DECLARATORS
10225long incrementaldelaunay(struct mesh *m, struct behavior *b)
10226#else /* not ANSI_DECLARATORS */
10227long incrementaldelaunay(m, b)
10228struct mesh *m;
10229struct behavior *b;
10230#endif /* not ANSI_DECLARATORS */
10231
10232{
10233 struct otri starttri;
10235
10236 /* Create a triangular bounding box. */
10238 if (b->verbose) {
10239 printf(" Incrementally inserting vertices.\n");
10240 }
10241 traversalinit(&m->vertices);
10243 while (vertexloop != (vertex) NULL) {
10244 starttri.tri = m->dummytri;
10245 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10246 == DUPLICATEVERTEX) {
10247 if (!b->quiet) {
10248 printf(
10249"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10250 vertexloop[0], vertexloop[1]);
10251 }
10252 setvertextype(vertexloop, UNDEADVERTEX);
10253 m->undeads++;
10254 }
10256 }
10257 /* Remove the bounding box. */
10258 return removebox(m, b);
10259}
10260
10261#endif /* not REDUCED */
10262
10265/********* Incremental Delaunay triangulation ends here *********/
10266
10267/********* Sweepline Delaunay triangulation begins here *********/
10270
10271#ifndef REDUCED
10272
10273#ifdef ANSI_DECLARATORS
10274void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10275#else /* not ANSI_DECLARATORS */
10277struct event **heap;
10278int heapsize;
10280#endif /* not ANSI_DECLARATORS */
10281
10282{
10283 REAL eventx, eventy;
10287
10291 notdone = eventnum > 0;
10292 while (notdone) {
10293 parent = (eventnum - 1) >> 1;
10294 if ((heap[parent]->ykey < eventy) ||
10295 ((heap[parent]->ykey == eventy)
10296 && (heap[parent]->xkey <= eventx))) {
10297 notdone = 0;
10298 } else {
10300 heap[eventnum]->heapposition = eventnum;
10301
10302 eventnum = parent;
10303 notdone = eventnum > 0;
10304 }
10305 }
10307 newevent->heapposition = eventnum;
10308}
10309
10310#endif /* not REDUCED */
10311
10312#ifndef REDUCED
10313
10314#ifdef ANSI_DECLARATORS
10315void eventheapify(struct event **heap, int heapsize, int eventnum)
10316#else /* not ANSI_DECLARATORS */
10318struct event **heap;
10319int heapsize;
10320int eventnum;
10321#endif /* not ANSI_DECLARATORS */
10322
10323{
10324 struct event *thisevent;
10325 REAL eventx, eventy;
10328 int notdone;
10329
10331 eventx = thisevent->xkey;
10332 eventy = thisevent->ykey;
10333 leftchild = 2 * eventnum + 1;
10335 while (notdone) {
10336 if ((heap[leftchild]->ykey < eventy) ||
10337 ((heap[leftchild]->ykey == eventy)
10338 && (heap[leftchild]->xkey < eventx))) {
10340 } else {
10342 }
10343 rightchild = leftchild + 1;
10344 if (rightchild < heapsize) {
10345 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10347 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10349 }
10350 }
10351 if (smallest == eventnum) {
10352 notdone = 0;
10353 } else {
10355 heap[eventnum]->heapposition = eventnum;
10357 thisevent->heapposition = smallest;
10358
10360 leftchild = 2 * eventnum + 1;
10362 }
10363 }
10364}
10365
10366#endif /* not REDUCED */
10367
10368#ifndef REDUCED
10369
10370#ifdef ANSI_DECLARATORS
10372#else /* not ANSI_DECLARATORS */
10374struct event **heap;
10375int heapsize;
10376int eventnum;
10377#endif /* not ANSI_DECLARATORS */
10378
10379{
10380 struct event *moveevent;
10381 REAL eventx, eventy;
10382 int parent;
10383 int notdone;
10384
10386 if (eventnum > 0) {
10387 eventx = moveevent->xkey;
10388 eventy = moveevent->ykey;
10389 do {
10390 parent = (eventnum - 1) >> 1;
10391 if ((heap[parent]->ykey < eventy) ||
10392 ((heap[parent]->ykey == eventy)
10393 && (heap[parent]->xkey <= eventx))) {
10394 notdone = 0;
10395 } else {
10397 heap[eventnum]->heapposition = eventnum;
10398
10399 eventnum = parent;
10400 notdone = eventnum > 0;
10401 }
10402 } while (notdone);
10403 }
10405 moveevent->heapposition = eventnum;
10407}
10408
10409#endif /* not REDUCED */
10410
10411#ifndef REDUCED
10412
10413#ifdef ANSI_DECLARATORS
10414void createeventheap(struct mesh *m, struct event ***eventheap,
10415 struct event **events, struct event **freeevents)
10416#else /* not ANSI_DECLARATORS */
10418struct mesh *m;
10419struct event ***eventheap;
10420struct event **events;
10422#endif /* not ANSI_DECLARATORS */
10423
10424{
10425 vertex thisvertex;
10427 int i;
10428
10429 maxevents = (3 * m->invertices) / 2;
10430 *eventheap = (struct event **) trimalloc(maxevents *
10431 (int) sizeof(struct event *));
10432 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10433 traversalinit(&m->vertices);
10434 for (i = 0; i < m->invertices; i++) {
10435 thisvertex = vertextraverse(m);
10436 (*events)[i].eventptr = (VOID *) thisvertex;
10437 (*events)[i].xkey = thisvertex[0];
10438 (*events)[i].ykey = thisvertex[1];
10440 }
10441 *freeevents = (struct event *) NULL;
10442 for (i = maxevents - 1; i >= m->invertices; i--) {
10443 (*events)[i].eventptr = (VOID *) *freeevents;
10444 *freeevents = *events + i;
10445 }
10446}
10447
10448#endif /* not REDUCED */
10449
10450#ifndef REDUCED
10451
10452#ifdef ANSI_DECLARATORS
10454#else /* not ANSI_DECLARATORS */
10456struct mesh *m;
10457struct otri *fronttri;
10459#endif /* not ANSI_DECLARATORS */
10460
10461{
10463 REAL dxa, dya, dxb, dyb;
10464
10465 m->hyperbolacount++;
10466
10469 if ((leftvertex[1] < rightvertex[1]) ||
10470 ((leftvertex[1] == rightvertex[1]) &&
10471 (leftvertex[0] < rightvertex[0]))) {
10472 if (newsite[0] >= rightvertex[0]) {
10473 return 1;
10474 }
10475 } else {
10476 if (newsite[0] <= leftvertex[0]) {
10477 return 0;
10478 }
10479 }
10480 dxa = leftvertex[0] - newsite[0];
10481 dya = leftvertex[1] - newsite[1];
10482 dxb = rightvertex[0] - newsite[0];
10483 dyb = rightvertex[1] - newsite[1];
10484 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10485}
10486
10487#endif /* not REDUCED */
10488
10489#ifndef REDUCED
10490
10491#ifdef ANSI_DECLARATORS
10493#else /* not ANSI_DECLARATORS */
10494REAL circletop(m, pa, pb, pc, ccwabc)
10495struct mesh *m;
10496vertex pa;
10497vertex pb;
10498vertex pc;
10500#endif /* not ANSI_DECLARATORS */
10501
10502{
10503 REAL xac, yac, xbc, ybc, xab, yab;
10505
10506 m->circletopcount++;
10507
10508 xac = pa[0] - pc[0];
10509 yac = pa[1] - pc[1];
10510 xbc = pb[0] - pc[0];
10511 ybc = pb[1] - pc[1];
10512 xab = pa[0] - pb[0];
10513 yab = pa[1] - pb[1];
10514 aclen2 = xac * xac + yac * yac;
10515 bclen2 = xbc * xbc + ybc * ybc;
10516 ablen2 = xab * xab + yab * yab;
10517 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10518 / (2.0 * ccwabc);
10519}
10520
10521#endif /* not REDUCED */
10522
10523#ifndef REDUCED
10524
10525#ifdef ANSI_DECLARATORS
10527 struct event **eventheap, int *heapsize)
10528#else /* not ANSI_DECLARATORS */
10531struct event **freeevents;
10532struct event **eventheap;
10533int *heapsize;
10534#endif /* not ANSI_DECLARATORS */
10535
10536{
10537 struct event *deadevent;
10539 int eventnum;
10540
10542 if (eventvertex != (vertex) NULL) {
10543 deadevent = (struct event *) eventvertex;
10544 eventnum = deadevent->heapposition;
10545 deadevent->eventptr = (VOID *) *freeevents;
10546 *freeevents = deadevent;
10548 (*heapsize)--;
10549 setorg(*checktri, NULL);
10550 }
10551}
10552
10553#endif /* not REDUCED */
10554
10555#ifndef REDUCED
10556
10557#ifdef ANSI_DECLARATORS
10558struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10560#else /* not ANSI_DECLARATORS */
10562struct mesh *m;
10563struct splaynode *splaytree;
10565struct otri *searchtri;
10566#endif /* not ANSI_DECLARATORS */
10567
10568{
10569 struct splaynode *child, *grandchild;
10574
10575 if (splaytree == (struct splaynode *) NULL) {
10576 return (struct splaynode *) NULL;
10577 }
10579 if (checkvertex == splaytree->keydest) {
10581 if (rightofroot) {
10582 otricopy(splaytree->keyedge, *searchtri);
10583 child = splaytree->rchild;
10584 } else {
10585 child = splaytree->lchild;
10586 }
10587 if (child == (struct splaynode *) NULL) {
10588 return splaytree;
10589 }
10590 destT(child->keyedge, checkvertex);
10591 if (checkvertex != child->keydest) {
10592 child = splay(m, child, searchpoint, searchtri);
10593 if (child == (struct splaynode *) NULL) {
10594 if (rightofroot) {
10595 splaytree->rchild = (struct splaynode *) NULL;
10596 } else {
10597 splaytree->lchild = (struct splaynode *) NULL;
10598 }
10599 return splaytree;
10600 }
10601 }
10603 if (rightofchild) {
10604 otricopy(child->keyedge, *searchtri);
10605 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10606 child->rchild = grandchild;
10607 } else {
10608 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10609 child->lchild = grandchild;
10610 }
10611 if (grandchild == (struct splaynode *) NULL) {
10612 if (rightofroot) {
10613 splaytree->rchild = child->lchild;
10614 child->lchild = splaytree;
10615 } else {
10616 splaytree->lchild = child->rchild;
10617 child->rchild = splaytree;
10618 }
10619 return child;
10620 }
10621 if (rightofchild) {
10622 if (rightofroot) {
10623 splaytree->rchild = child->lchild;
10624 child->lchild = splaytree;
10625 } else {
10626 splaytree->lchild = grandchild->rchild;
10627 grandchild->rchild = splaytree;
10628 }
10629 child->rchild = grandchild->lchild;
10630 grandchild->lchild = child;
10631 } else {
10632 if (rightofroot) {
10633 splaytree->rchild = grandchild->lchild;
10634 grandchild->lchild = splaytree;
10635 } else {
10636 splaytree->lchild = child->rchild;
10637 child->rchild = splaytree;
10638 }
10639 child->lchild = grandchild->rchild;
10640 grandchild->rchild = child;
10641 }
10642 return grandchild;
10643 } else {
10646
10647 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10648 if (lefttree == (struct splaynode *) NULL) {
10649 return righttree;
10650 } else if (righttree == (struct splaynode *) NULL) {
10651 return lefttree;
10652 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10653 lefttree->rchild = righttree->lchild;
10654 righttree->lchild = lefttree;
10655 return righttree;
10656 } else if (righttree->lchild == (struct splaynode *) NULL) {
10657 righttree->lchild = lefttree->rchild;
10658 lefttree->rchild = righttree;
10659 return lefttree;
10660 } else {
10661/* printf("Holy Toledo!!!\n"); */
10662 leftright = lefttree->rchild;
10663 while (leftright->rchild != (struct splaynode *) NULL) {
10664 leftright = leftright->rchild;
10665 }
10667 return lefttree;
10668 }
10669 }
10670}
10671
10672#endif /* not REDUCED */
10673
10674#ifndef REDUCED
10675
10676#ifdef ANSI_DECLARATORS
10678 struct otri *newkey, vertex searchpoint)
10679#else /* not ANSI_DECLARATORS */
10681struct mesh *m;
10682struct splaynode *splayroot;
10683struct otri *newkey;
10685#endif /* not ANSI_DECLARATORS */
10686
10687{
10688 struct splaynode *newsplaynode;
10689
10690 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10691 otricopy(*newkey, newsplaynode->keyedge);
10692 destT(*newkey, newsplaynode->keydest);
10693 if (splayroot == (struct splaynode *) NULL) {
10694 newsplaynode->lchild = (struct splaynode *) NULL;
10695 newsplaynode->rchild = (struct splaynode *) NULL;
10696 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10697 newsplaynode->lchild = splayroot;
10698 newsplaynode->rchild = splayroot->rchild;
10699 splayroot->rchild = (struct splaynode *) NULL;
10700 } else {
10701 newsplaynode->lchild = splayroot->lchild;
10702 newsplaynode->rchild = splayroot;
10703 splayroot->lchild = (struct splaynode *) NULL;
10704 }
10705 return newsplaynode;
10706}
10707
10708#endif /* not REDUCED */
10709
10710#ifndef REDUCED
10711
10712#ifdef ANSI_DECLARATORS
10713struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10714 struct splaynode *splayroot,
10715 struct otri *newkey,
10716 vertex pa, vertex pb, vertex pc, REAL topy)
10717#else /* not ANSI_DECLARATORS */
10719struct mesh *m;
10720struct behavior *b;
10721struct splaynode *splayroot;
10722struct otri *newkey;
10723vertex pa;
10724vertex pb;
10725vertex pc;
10726REAL topy;
10727#endif /* not ANSI_DECLARATORS */
10728
10729{
10730 REAL ccwabc;
10731 REAL xac, yac, xbc, ybc;
10732 REAL aclen2, bclen2;
10733 REAL searchpoint[2];
10734 struct otri dummytri;
10735
10736 ccwabc = counterclockwise(m, b, pa, pb, pc);
10737 xac = pa[0] - pc[0];
10738 yac = pa[1] - pc[1];
10739 xbc = pb[0] - pc[0];
10740 ybc = pb[1] - pc[1];
10741 aclen2 = xac * xac + yac * yac;
10742 bclen2 = xbc * xbc + ybc * ybc;
10743 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10744 searchpoint[1] = topy;
10747}
10748
10749#endif /* not REDUCED */
10750
10751#ifndef REDUCED
10752
10753#ifdef ANSI_DECLARATORS
10756 struct otri *searchtri, int *farright)
10757#else /* not ANSI_DECLARATORS */
10760struct mesh *m;
10761struct splaynode *splayroot;
10762struct otri *bottommost;
10764struct otri *searchtri;
10765int *farright;
10766#endif /* not ANSI_DECLARATORS */
10767
10768{
10769 int farrightflag;
10770 triangle ptr; /* Temporary variable used by onext(). */
10771
10774
10777 onextself(*searchtri);
10778 farrightflag = otriequal(*searchtri, *bottommost);
10779 }
10781 return splayroot;
10782}
10783
10784#endif /* not REDUCED */
10785
10786#ifndef REDUCED
10787
10788#ifdef ANSI_DECLARATORS
10789long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10790#else /* not ANSI_DECLARATORS */
10791long sweeplinedelaunay(m, b)
10792struct mesh *m;
10793struct behavior *b;
10794#endif /* not ANSI_DECLARATORS */
10795
10796{
10797 struct event **eventheap;
10798 struct event *events;
10799 struct event *freeevents;
10801 struct event *newevent;
10802 struct splaynode *splayroot;
10803 struct otri bottommost;
10804 struct otri searchtri;
10806 struct otri lefttri, righttri, farlefttri, farrighttri;
10813 int heapsize;
10815 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
10816
10817 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10818 SPLAYNODEPERBLOCK, 0);
10819 splayroot = (struct splaynode *) NULL;
10820
10821 if (b->verbose) {
10822 printf(" Placing vertices in event heap.\n");
10823 }
10825 heapsize = m->invertices;
10826
10827 if (b->verbose) {
10828 printf(" Forming triangulation.\n");
10829 }
10830 maketriangle(m, b, &lefttri);
10832 bond(lefttri, righttri);
10833 lnextself(lefttri);
10835 bond(lefttri, righttri);
10836 lnextself(lefttri);
10838 bond(lefttri, righttri);
10840 eventheap[0]->eventptr = (VOID *) freeevents;
10841 freeevents = eventheap[0];
10843 heapsize--;
10844 do {
10845 if (heapsize == 0) {
10846 printf("Error: Input vertices are all identical.\n");
10847 triexit(1);
10848 }
10850 eventheap[0]->eventptr = (VOID *) freeevents;
10851 freeevents = eventheap[0];
10853 heapsize--;
10854 if ((firstvertex[0] == secondvertex[0]) &&
10855 (firstvertex[1] == secondvertex[1])) {
10856 if (!b->quiet) {
10857 printf(
10858"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10859 secondvertex[0], secondvertex[1]);
10860 }
10861 setvertextype(secondvertex, UNDEADVERTEX);
10862 m->undeads++;
10863 }
10864 } while ((firstvertex[0] == secondvertex[0]) &&
10865 (firstvertex[1] == secondvertex[1]));
10872 while (heapsize > 0) {
10873 nextevent = eventheap[0];
10875 heapsize--;
10876 check4events = 1;
10877 if (nextevent->xkey < m->xmin) {
10878 decode(nextevent->eventptr, fliptri);
10879 oprev(fliptri, farlefttri);
10880 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10881 onext(fliptri, farrighttri);
10883
10884 if (otriequal(farlefttri, bottommost)) {
10886 }
10887 flip(m, b, &fliptri);
10888 setapex(fliptri, NULL);
10889 lprev(fliptri, lefttri);
10891 sym(lefttri, farlefttri);
10892
10893 if (randomnation(SAMPLERATE) == 0) {
10900 }
10901 } else {
10902 nextvertex = (vertex) nextevent->eventptr;
10903 if ((nextvertex[0] == lastvertex[0]) &&
10904 (nextvertex[1] == lastvertex[1])) {
10905 if (!b->quiet) {
10906 printf(
10907"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10908 nextvertex[0], nextvertex[1]);
10909 }
10910 setvertextype(nextvertex, UNDEADVERTEX);
10911 m->undeads++;
10912 check4events = 0;
10913 } else {
10915
10918/*
10919 otricopy(bottommost, searchtri);
10920 farrightflag = 0;
10921 while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) {
10922 onextself(searchtri);
10923 farrightflag = otriequal(searchtri, bottommost);
10924 }
10925*/
10926
10928
10930 sym(searchtri, farlefttri);
10931 maketriangle(m, b, &lefttri);
10934 setorg(lefttri, connectvertex);
10935 setdest(lefttri, nextvertex);
10938 bond(lefttri, righttri);
10939 lnextself(lefttri);
10941 bond(lefttri, righttri);
10942 lnextself(lefttri);
10944 bond(lefttri, farlefttri);
10946 if (!farrightflag && otriequal(farrighttri, bottommost)) {
10947 otricopy(lefttri, bottommost);
10948 }
10949
10950 if (randomnation(SAMPLERATE) == 0) {
10952 } else if (randomnation(SAMPLERATE) == 0) {
10955 }
10956 }
10957 }
10958 nextevent->eventptr = (VOID *) freeevents;
10960
10961 if (check4events) {
10962 apex(farlefttri, leftvertex);
10963 destT(lefttri, midvertex);
10964 apex(lefttri, rightvertex);
10966 if (lefttest > 0.0) {
10968 freeevents = (struct event *) freeevents->eventptr;
10969 newevent->xkey = m->xminextreme;
10971 lefttest);
10972 newevent->eventptr = (VOID *) encode(lefttri);
10974 heapsize++;
10975 setorg(lefttri, newevent);
10976 }
10981 if (righttest > 0.0) {
10983 freeevents = (struct event *) freeevents->eventptr;
10984 newevent->xkey = m->xminextreme;
10986 righttest);
10987 newevent->eventptr = (VOID *) encode(farrighttri);
10989 heapsize++;
10991 }
10992 }
10993 }
10994
10995 pooldeinit(&m->splaynodes);
10997 return removeghosts(m, b, &bottommost);
10998}
10999
11000#endif /* not REDUCED */
11001
11004/********* Sweepline Delaunay triangulation ends here *********/
11005
11006/********* General mesh construction routines begin here *********/
11009
11010/*****************************************************************************/
11011/* */
11012/* delaunay() Form a Delaunay triangulation. */
11013/* */
11014/*****************************************************************************/
11015
11016#ifdef ANSI_DECLARATORS
11017long delaunay(struct mesh *m, struct behavior *b)
11018#else /* not ANSI_DECLARATORS */
11019long delaunay(m, b)
11020struct mesh *m;
11021struct behavior *b;
11022#endif /* not ANSI_DECLARATORS */
11023
11024{
11025 long hulledges;
11026
11027 m->eextras = 0;
11029
11030#ifdef REDUCED
11031 if (!b->quiet) {
11032 printf(
11033 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11034 }
11036#else /* not REDUCED */
11037 if (!b->quiet) {
11038 printf("Constructing Delaunay triangulation ");
11039 if (b->incremental) {
11040 printf("by incremental method.\n");
11041 } else if (b->sweepline) {
11042 printf("by sweepline method.\n");
11043 } else {
11044 printf("by divide-and-conquer method.\n");
11045 }
11046 }
11047 if (b->incremental) {
11049 } else if (b->sweepline) {
11051 } else {
11053 }
11054#endif /* not REDUCED */
11055
11056 if (m->triangles.items == 0) {
11057 /* The input vertices were all collinear, so there are no triangles. */
11058 return 0l;
11059 } else {
11060 return hulledges;
11061 }
11062}
11063
11064/*****************************************************************************/
11065/* */
11066/* reconstruct() Reconstruct a triangulation from its .ele (and possibly */
11067/* .poly) file. Used when the -r switch is used. */
11068/* */
11069/* Reads an .ele file and reconstructs the original mesh. If the -p switch */
11070/* is used, this procedure will also read a .poly file and reconstruct the */
11071/* subsegments of the original mesh. If the -a switch is used, this */
11072/* procedure will also read an .area file and set a maximum area constraint */
11073/* on each triangle. */
11074/* */
11075/* Vertices that are not corners of triangles, such as nodes on edges of */
11076/* subparametric elements, are discarded. */
11077/* */
11078/* This routine finds the adjacencies between triangles (and subsegments) */
11079/* by forming one stack of triangles for each vertex. Each triangle is on */
11080/* three different stacks simultaneously. Each triangle's subsegment */
11081/* pointers are used to link the items in each stack. This memory-saving */
11082/* feature makes the code harder to read. The most important thing to keep */
11083/* in mind is that each triangle is removed from a stack precisely when */
11084/* the corresponding pointer is adjusted to refer to a subsegment rather */
11085/* than the next triangle of the stack. */
11086/* */
11087/*****************************************************************************/
11088
11089#ifndef CDT_ONLY
11090
11091#ifdef TRILIBRARY
11092
11093#ifdef ANSI_DECLARATORS
11094int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11096 int elements, int corners, int attribs,
11098#else /* not ANSI_DECLARATORS */
11102struct mesh *m;
11103struct behavior *b;
11104int *trianglelist;
11105REAL *triangleattriblist;
11106REAL *trianglearealist;
11107int elements;
11108int corners;
11109int attribs;
11110int *segmentlist;
11113#endif /* not ANSI_DECLARATORS */
11114
11115#else /* not TRILIBRARY */
11116
11117#ifdef ANSI_DECLARATORS
11118long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11119 char *areafilename, char *polyfilename, FILE *polyfile)
11120#else /* not ANSI_DECLARATORS */
11122struct mesh *m;
11123struct behavior *b;
11124char *elefilename;
11125char *areafilename;
11126char *polyfilename;
11128#endif /* not ANSI_DECLARATORS */
11129
11130#endif /* not TRILIBRARY */
11131
11132{
11133#ifdef TRILIBRARY
11134 int vertexindex;
11136#else /* not TRILIBRARY */
11137 FILE *elefile;
11139 char inputline[INPUTLINESIZE];
11142#endif /* not TRILIBRARY */
11145 struct otri checktri;
11157 REAL area;
11158 int corner[3];
11159 int end[2];
11165 long hullsize;
11168 int i, j;
11169 triangle ptr; /* Temporary variable used by sym(). */
11170
11171#ifdef TRILIBRARY
11172 m->inelements = elements;
11174 if (incorners < 3) {
11175 printf("Error: Triangles must have at least 3 vertices.\n");
11176 triexit(1);
11177 }
11178 m->eextras = attribs;
11179#else /* not TRILIBRARY */
11180 /* Read the triangles from an .ele file. */
11181 if (!b->quiet) {
11182 printf("Opening %s.\n", elefilename);
11183 }
11184 elefile = fopen(elefilename, "r");
11185 if (elefile == (FILE *) NULL) {
11186 printf(" Error: Cannot access file %s.\n", elefilename);
11187 triexit(1);
11188 }
11189 /* Read number of triangles, number of vertices per triangle, and */
11190 /* number of triangle attributes from .ele file. */
11192 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11194 if (*stringptr == '\0') {
11195 incorners = 3;
11196 } else {
11197 incorners = (int) strtol(stringptr, &stringptr, 0);
11198 if (incorners < 3) {
11199 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11200 elefilename);
11201 triexit(1);
11202 }
11203 }
11205 if (*stringptr == '\0') {
11206 m->eextras = 0;
11207 } else {
11208 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11209 }
11210#endif /* not TRILIBRARY */
11211
11213
11214 /* Create the triangles. */
11215 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11217 /* Mark the triangle as living. */
11218 triangleloop.tri[3] = (triangle) triangleloop.tri;
11219 }
11220
11221 segmentmarkers = 0;
11222 if (b->poly) {
11223#ifdef TRILIBRARY
11224 m->insegments = numberofsegments;
11225 segmentmarkers = segmentmarkerlist != (int *) NULL;
11226#else /* not TRILIBRARY */
11227 /* Read number of segments and number of segment */
11228 /* boundary markers from .poly file. */
11229 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11230 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11232 if (*stringptr != '\0') {
11233 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11234 }
11235#endif /* not TRILIBRARY */
11236
11237 /* Create the subsegments. */
11238 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11240 /* Mark the subsegment as living. */
11241 subsegloop.ss[2] = (subseg) subsegloop.ss;
11242 }
11243 }
11244
11245#ifdef TRILIBRARY
11247 attribindex = 0;
11248#else /* not TRILIBRARY */
11249 if (b->vararea) {
11250 /* Open an .area file, check for consistency with the .ele file. */
11251 if (!b->quiet) {
11252 printf("Opening %s.\n", areafilename);
11253 }
11254 areafile = fopen(areafilename, "r");
11255 if (areafile == (FILE *) NULL) {
11256 printf(" Error: Cannot access file %s.\n", areafilename);
11257 triexit(1);
11258 }
11260 areaelements = (int) strtol(stringptr, &stringptr, 0);
11261 if (areaelements != m->inelements) {
11262 printf("Error: %s and %s disagree on number of triangles.\n",
11264 triexit(1);
11265 }
11266 }
11267#endif /* not TRILIBRARY */
11268
11269 if (!b->quiet) {
11270 printf("Reconstructing mesh.\n");
11271 }
11272 /* Allocate a temporary array that maps each vertex to some adjacent */
11273 /* triangle. I took care to allocate all the permanent memory for */
11274 /* triangles and subsegments first. */
11275 vertexarray = (triangle *) trimalloc(m->vertices.items *
11276 (int) sizeof(triangle));
11277 /* Each vertex is initially unrepresented. */
11278 for (i = 0; i < m->vertices.items; i++) {
11279 vertexarray[i] = (triangle) m->dummytri;
11280 }
11281
11282 if (b->verbose) {
11283 printf(" Assembling triangles.\n");
11284 }
11285 /* Read the triangles from the .ele file, and link */
11286 /* together those that share an edge. */
11287 traversalinit(&m->triangles);
11289 elementnumber = b->firstnumber;
11290 while (triangleloop.tri != (triangle *) NULL) {
11291#ifdef TRILIBRARY
11292 /* Copy the triangle's three corners. */
11293 for (j = 0; j < 3; j++) {
11295 if ((corner[j] < b->firstnumber) ||
11296 (corner[j] >= b->firstnumber + m->invertices)) {
11297 printf("Error: Triangle %ld has an invalid vertex index.\n",
11299 triexit(1);
11300 }
11301 }
11302#else /* not TRILIBRARY */
11303 /* Read triangle number and the triangle's three corners. */
11305 for (j = 0; j < 3; j++) {
11307 if (*stringptr == '\0') {
11308 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11310 triexit(1);
11311 } else {
11312 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11313 if ((corner[j] < b->firstnumber) ||
11314 (corner[j] >= b->firstnumber + m->invertices)) {
11315 printf("Error: Triangle %ld has an invalid vertex index.\n",
11317 triexit(1);
11318 }
11319 }
11320 }
11321#endif /* not TRILIBRARY */
11322
11323 /* Find out about (and throw away) extra nodes. */
11324 for (j = 3; j < incorners; j++) {
11325#ifdef TRILIBRARY
11327#else /* not TRILIBRARY */
11329 if (*stringptr != '\0') {
11330 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11331#endif /* not TRILIBRARY */
11332 if ((killvertexindex >= b->firstnumber) &&
11333 (killvertexindex < b->firstnumber + m->invertices)) {
11334 /* Delete the non-corner vertex if it's not already deleted. */
11336 if (vertextype(killvertex) != DEADVERTEX) {
11338 }
11339 }
11340#ifndef TRILIBRARY
11341 }
11342#endif /* not TRILIBRARY */
11343 }
11344
11345 /* Read the triangle's attributes. */
11346 for (j = 0; j < m->eextras; j++) {
11347#ifdef TRILIBRARY
11348 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11349#else /* not TRILIBRARY */
11351 if (*stringptr == '\0') {
11352 setelemattribute(triangleloop, j, 0);
11353 } else {
11354 setelemattribute(triangleloop, j,
11355 (REAL) strtod(stringptr, &stringptr));
11356 }
11357#endif /* not TRILIBRARY */
11358 }
11359
11360 if (b->vararea) {
11361#ifdef TRILIBRARY
11362 area = trianglearealist[elementnumber - b->firstnumber];
11363#else /* not TRILIBRARY */
11364 /* Read an area constraint from the .area file. */
11367 if (*stringptr == '\0') {
11368 area = -1.0; /* No constraint on this triangle. */
11369 } else {
11370 area = (REAL) strtod(stringptr, &stringptr);
11371 }
11372#endif /* not TRILIBRARY */
11373 setareabound(triangleloop, area);
11374 }
11375
11376 /* Set the triangle's vertices. */
11377 triangleloop.orient = 0;
11381 /* Try linking the triangle to others that share these vertices. */
11382 for (triangleloop.orient = 0; triangleloop.orient < 3;
11383 triangleloop.orient++) {
11384 /* Take the number for the origin of triangleloop. */
11386 /* Look for other triangles having this vertex. */
11387 nexttri = vertexarray[aroundvertex - b->firstnumber];
11388 /* Link the current triangle to the next one in the stack. */
11389 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11390 /* Push the current triangle onto the stack. */
11391 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11393 if (checktri.tri != m->dummytri) {
11396 /* Look for other triangles that share an edge. */
11397 do {
11400 if (tapex == checkdest) {
11401 /* The two triangles share an edge; bond them together. */
11404 }
11405 if (tdest == checkapex) {
11406 /* The two triangles share an edge; bond them together. */
11409 }
11410 /* Find the next triangle in the stack. */
11411 nexttri = checktri.tri[6 + checktri.orient];
11413 } while (checktri.tri != m->dummytri);
11414 }
11415 }
11417 elementnumber++;
11418 }
11419
11420#ifdef TRILIBRARY
11421 vertexindex = 0;
11422#else /* not TRILIBRARY */
11424 if (b->vararea) {
11426 }
11427#endif /* not TRILIBRARY */
11428
11429 hullsize = 0; /* Prepare to count the boundary edges. */
11430 if (b->poly) {
11431 if (b->verbose) {
11432 printf(" Marking segments in triangulation.\n");
11433 }
11434 /* Read the segments from the .poly file, and link them */
11435 /* to their neighboring triangles. */
11436 boundmarker = 0;
11437 traversalinit(&m->subsegs);
11439 segmentnumber = b->firstnumber;
11440 while (subsegloop.ss != (subseg *) NULL) {
11441#ifdef TRILIBRARY
11442 end[0] = segmentlist[vertexindex++];
11443 end[1] = segmentlist[vertexindex++];
11444 if (segmentmarkers) {
11445 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11446 }
11447#else /* not TRILIBRARY */
11448 /* Read the endpoints of each segment, and possibly a boundary marker. */
11449 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11450 /* Skip the first (segment number) field. */
11452 if (*stringptr == '\0') {
11453 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11454 polyfilename);
11455 triexit(1);
11456 } else {
11457 end[0] = (int) strtol(stringptr, &stringptr, 0);
11458 }
11460 if (*stringptr == '\0') {
11461 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11463 triexit(1);
11464 } else {
11465 end[1] = (int) strtol(stringptr, &stringptr, 0);
11466 }
11467 if (segmentmarkers) {
11469 if (*stringptr == '\0') {
11470 boundmarker = 0;
11471 } else {
11472 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11473 }
11474 }
11475#endif /* not TRILIBRARY */
11476 for (j = 0; j < 2; j++) {
11477 if ((end[j] < b->firstnumber) ||
11478 (end[j] >= b->firstnumber + m->invertices)) {
11479 printf("Error: Segment %ld has an invalid vertex index.\n",
11481 triexit(1);
11482 }
11483 }
11484
11485 /* set the subsegment's vertices. */
11486 subsegloop.ssorient = 0;
11487 segmentorg = getvertex(m, b, end[0]);
11488 segmentdest = getvertex(m, b, end[1]);
11489 setsorg(subsegloop, segmentorg);
11490 setsdest(subsegloop, segmentdest);
11491 setsegorg(subsegloop, segmentorg);
11492 setsegdest(subsegloop, segmentdest);
11493 setmark(subsegloop, boundmarker);
11494 /* Try linking the subsegment to triangles that share these vertices. */
11495 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11496 subsegloop.ssorient++) {
11497 /* Take the number for the destination of subsegloop. */
11498 aroundvertex = end[1 - subsegloop.ssorient];
11499 /* Look for triangles having this vertex. */
11500 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11501 nexttri = vertexarray[aroundvertex - b->firstnumber];
11503 sorg(subsegloop, shorg);
11504 notfound = 1;
11505 /* Look for triangles having this edge. Note that I'm only */
11506 /* comparing each triangle's destination with the subsegment; */
11507 /* each triangle's apex is handled through a different vertex. */
11508 /* Because each triangle appears on three vertices' lists, each */
11509 /* occurrence of a triangle on a list can (and does) represent */
11510 /* an edge. In this way, most edges are represented twice, and */
11511 /* every triangle-subsegment bond is represented once. */
11512 while (notfound && (checktri.tri != m->dummytri)) {
11514 if (shorg == checkdest) {
11515 /* We have a match. Remove this triangle from the list. */
11516 *prevlink = checktri.tri[6 + checktri.orient];
11517 /* Bond the subsegment to the triangle. */
11518 tsbond(checktri, subsegloop);
11519 /* Check if this is a boundary edge. */
11521 if (checkneighbor.tri == m->dummytri) {
11522 /* The next line doesn't insert a subsegment (because there's */
11523 /* already one there), but it sets the boundary markers of */
11524 /* the existing subsegment and its vertices. */
11525 insertsubseg(m, b, &checktri, 1);
11526 hullsize++;
11527 }
11528 notfound = 0;
11529 }
11530 /* Find the next triangle in the stack. */
11531 prevlink = &checktri.tri[6 + checktri.orient];
11532 nexttri = checktri.tri[6 + checktri.orient];
11534 }
11535 }
11537 segmentnumber++;
11538 }
11539 }
11540
11541 /* Mark the remaining edges as not being attached to any subsegment. */
11542 /* Also, count the (yet uncounted) boundary edges. */
11543 for (i = 0; i < m->vertices.items; i++) {
11544 /* Search the stack of triangles adjacent to a vertex. */
11547 while (checktri.tri != m->dummytri) {
11548 /* Find the next triangle in the stack before this */
11549 /* information gets overwritten. */
11550 nexttri = checktri.tri[6 + checktri.orient];
11551 /* No adjacent subsegment. (This overwrites the stack info.) */
11552 tsdissolve(checktri);
11554 if (checkneighbor.tri == m->dummytri) {
11555 insertsubseg(m, b, &checktri, 1);
11556 hullsize++;
11557 }
11559 }
11560 }
11561
11562 trifree((VOID *) vertexarray);
11563 return hullsize;
11564}
11565
11566#endif /* not CDT_ONLY */
11567
11570/********* General mesh construction routines end here *********/
11571
11572/********* Segment insertion begins here *********/
11575
11576/*****************************************************************************/
11577/* */
11578/* finddirection() Find the first triangle on the path from one point */
11579/* to another. */
11580/* */
11581/* Finds the triangle that intersects a line segment drawn from the */
11582/* origin of `searchtri' to the point `searchpoint', and returns the result */
11583/* in `searchtri'. The origin of `searchtri' does not change, even though */
11584/* the triangle returned may differ from the one passed in. This routine */
11585/* is used to find the direction to move in to get from one point to */
11586/* another. */
11587/* */
11588/* The return value notes whether the destination or apex of the found */
11589/* triangle is collinear with the two points in question. */
11590/* */
11591/*****************************************************************************/
11592
11593#ifdef ANSI_DECLARATORS
11595 struct otri *searchtri,
11597#else /* not ANSI_DECLARATORS */
11599struct mesh *m;
11600struct behavior *b;
11601struct otri *searchtri;
11603#endif /* not ANSI_DECLARATORS */
11604
11605{
11606 struct otri checktri;
11611 triangle ptr; /* Temporary variable used by onext() and oprev(). */
11612
11616 /* Is `searchpoint' to the left? */
11618 leftflag = leftccw > 0.0;
11619 /* Is `searchpoint' to the right? */
11621 rightflag = rightccw > 0.0;
11623 /* `searchtri' faces directly away from `searchpoint'. We could go left */
11624 /* or right. Ask whether it's a triangle or a boundary on the left. */
11625 onext(*searchtri, checktri);
11626 if (checktri.tri == m->dummytri) {
11627 leftflag = 0;
11628 } else {
11629 rightflag = 0;
11630 }
11631 }
11632 while (leftflag) {
11633 /* Turn left until satisfied. */
11634 onextself(*searchtri);
11635 if (searchtri->tri == m->dummytri) {
11636 printf("Internal error in finddirection(): Unable to find a\n");
11637 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11638 startvertex[1]);
11639 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11640 internalerror();
11641 }
11643 rightccw = leftccw;
11645 leftflag = leftccw > 0.0;
11646 }
11647 while (rightflag) {
11648 /* Turn right until satisfied. */
11649 oprevself(*searchtri);
11650 if (searchtri->tri == m->dummytri) {
11651 printf("Internal error in finddirection(): Unable to find a\n");
11652 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11653 startvertex[1]);
11654 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11655 internalerror();
11656 }
11658 leftccw = rightccw;
11660 rightflag = rightccw > 0.0;
11661 }
11662 if (leftccw == 0.0) {
11663 return LEFTCOLLINEAR;
11664 } else if (rightccw == 0.0) {
11665 return RIGHTCOLLINEAR;
11666 } else {
11667 return WITHIN;
11668 }
11669}
11670
11671/*****************************************************************************/
11672/* */
11673/* segmentintersection() Find the intersection of an existing segment */
11674/* and a segment that is being inserted. Insert */
11675/* a vertex at the intersection, splitting an */
11676/* existing subsegment. */
11677/* */
11678/* The segment being inserted connects the apex of splittri to endpoint2. */
11679/* splitsubseg is the subsegment being split, and MUST adjoin splittri. */
11680/* Hence, endpoints of the subsegment being split are the origin and */
11681/* destination of splittri. */
11682/* */
11683/* On completion, splittri is a handle having the newly inserted */
11684/* intersection point as its origin, and endpoint1 as its destination. */
11685/* */
11686/*****************************************************************************/
11687
11688#ifdef ANSI_DECLARATORS
11689void segmentintersection(struct mesh *m, struct behavior *b,
11690 struct otri *splittri, struct osub *splitsubseg,
11692#else /* not ANSI_DECLARATORS */
11694struct mesh *m;
11695struct behavior *b;
11696struct otri *splittri;
11697struct osub *splitsubseg;
11699#endif /* not ANSI_DECLARATORS */
11700
11701{
11702 struct osub opposubseg;
11704 vertex torg, tdest;
11709 REAL ex, ey;
11710 REAL tx, ty;
11711 REAL etx, ety;
11713 int i;
11714 triangle ptr; /* Temporary variable used by onext(). */
11715 subseg sptr; /* Temporary variable used by snext(). */
11716
11717 /* Find the other three segment endpoints. */
11719 org(*splittri, torg);
11720 destT(*splittri, tdest);
11721 /* Segment intersection formulae; see the Antonio reference. */
11722 tx = tdest[0] - torg[0];
11723 ty = tdest[1] - torg[1];
11724 ex = endpoint2[0] - endpoint1[0];
11725 ey = endpoint2[1] - endpoint1[1];
11726 etx = torg[0] - endpoint2[0];
11727 ety = torg[1] - endpoint2[1];
11728 denom = ty * ex - tx * ey;
11729 if (denom == 0.0) {
11730 printf("Internal error in segmentintersection():");
11731 printf(" Attempt to find intersection of parallel segments.\n");
11732 internalerror();
11733 }
11734 split = (ey * etx - ex * ety) / denom;
11735 /* Create the new vertex. */
11736 newvertex = (vertex) poolalloc(&m->vertices);
11737 /* Interpolate its coordinate and attributes. */
11738 for (i = 0; i < 2 + m->nextras; i++) {
11739 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11740 }
11743 if (b->verbose > 1) {
11744 printf(
11745 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11746 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11747 }
11748 /* Insert the intersection vertex. This should always succeed. */
11751 printf("Internal error in segmentintersection():\n");
11752 printf(" Failure to split a segment.\n");
11753 internalerror();
11754 }
11755 /* Record a triangle whose origin is the new vertex. */
11757 if (m->steinerleft > 0) {
11758 m->steinerleft--;
11759 }
11760
11761 /* Divide the segment into two, and correct the segment endpoints. */
11762 ssymself(*splitsubseg);
11763 spivot(*splitsubseg, opposubseg);
11766 do {
11767 setsegorg(*splitsubseg, newvertex);
11769 } while (splitsubseg->ss != m->dummysub);
11770 do {
11771 setsegorg(opposubseg, newvertex);
11773 } while (opposubseg.ss != m->dummysub);
11774
11775 /* Inserting the vertex may have caused edge flips. We wish to rediscover */
11776 /* the edge connecting endpoint1 to the new intersection vertex. */
11780 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11781 onextself(*splittri);
11782 } else if ((rightvertex[0] != endpoint1[0]) ||
11783 (rightvertex[1] != endpoint1[1])) {
11784 printf("Internal error in segmentintersection():\n");
11785 printf(" Topological inconsistency after splitting a segment.\n");
11786 internalerror();
11787 }
11788 /* `splittri' should have destination endpoint1. */
11789}
11790
11791/*****************************************************************************/
11792/* */
11793/* scoutsegment() Scout the first triangle on the path from one endpoint */
11794/* to another, and check for completion (reaching the */
11795/* second endpoint), a collinear vertex, or the */
11796/* intersection of two segments. */
11797/* */
11798/* Returns one if the entire segment is successfully inserted, and zero if */
11799/* the job must be finished by conformingedge() or constrainededge(). */
11800/* */
11801/* If the first triangle on the path has the second endpoint as its */
11802/* destination or apex, a subsegment is inserted and the job is done. */
11803/* */
11804/* If the first triangle on the path has a destination or apex that lies on */
11805/* the segment, a subsegment is inserted connecting the first endpoint to */
11806/* the collinear vertex, and the search is continued from the collinear */
11807/* vertex. */
11808/* */
11809/* If the first triangle on the path has a subsegment opposite its origin, */
11810/* then there is a segment that intersects the segment being inserted. */
11811/* Their intersection vertex is inserted, splitting the subsegment. */
11812/* */
11813/*****************************************************************************/
11814
11815#ifdef ANSI_DECLARATORS
11816int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11818#else /* not ANSI_DECLARATORS */
11820struct mesh *m;
11821struct behavior *b;
11822struct otri *searchtri;
11825#endif /* not ANSI_DECLARATORS */
11826
11827{
11828 struct otri crosstri;
11832 subseg sptr; /* Temporary variable used by tspivot(). */
11833
11837 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11838 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11839 /* The segment is already an edge in the mesh. */
11840 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11842 }
11843 /* Insert a subsegment, if there isn't already one there. */
11845 return 1;
11846 } else if (collinear == LEFTCOLLINEAR) {
11847 /* We've collided with a vertex between the segment's endpoints. */
11848 /* Make the collinear vertex be the triangle's origin. */
11851 /* Insert the remainder of the segment. */
11853 } else if (collinear == RIGHTCOLLINEAR) {
11854 /* We've collided with a vertex between the segment's endpoints. */
11856 /* Make the collinear vertex be the triangle's origin. */
11858 /* Insert the remainder of the segment. */
11860 } else {
11861 lnext(*searchtri, crosstri);
11863 /* Check for a crossing segment. */
11864 if (crosssubseg.ss == m->dummysub) {
11865 return 0;
11866 } else {
11867 /* Insert a vertex at the intersection. */
11869 otricopy(crosstri, *searchtri);
11871 /* Insert the remainder of the segment. */
11873 }
11874 }
11875}
11876
11877/*****************************************************************************/
11878/* */
11879/* conformingedge() Force a segment into a conforming Delaunay */
11880/* triangulation by inserting a vertex at its midpoint, */
11881/* and recursively forcing in the two half-segments if */
11882/* necessary. */
11883/* */
11884/* Generates a sequence of subsegments connecting `endpoint1' to */
11885/* `endpoint2'. `newmark' is the boundary marker of the segment, assigned */
11886/* to each new splitting vertex and subsegment. */
11887/* */
11888/* Note that conformingedge() does not always maintain the conforming */
11889/* Delaunay property. Once inserted, segments are locked into place; */
11890/* vertices inserted later (to force other segments in) may render these */
11891/* fixed segments non-Delaunay. The conforming Delaunay property will be */
11892/* restored by enforcequality() by splitting encroached subsegments. */
11893/* */
11894/*****************************************************************************/
11895
11896#ifndef REDUCED
11897#ifndef CDT_ONLY
11898
11899#ifdef ANSI_DECLARATORS
11900void conformingedge(struct mesh *m, struct behavior *b,
11902#else /* not ANSI_DECLARATORS */
11904struct mesh *m;
11905struct behavior *b;
11908int newmark;
11909#endif /* not ANSI_DECLARATORS */
11910
11911{
11912 struct otri searchtri1, searchtri2;
11913 struct osub brokensubseg;
11917 int i;
11918 subseg sptr; /* Temporary variable used by tspivot(). */
11919
11920 if (b->verbose > 2) {
11921 printf("Forcing segment into triangulation by recursive splitting:\n");
11922 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11923 endpoint2[0], endpoint2[1]);
11924 }
11925 /* Create a new vertex to insert in the middle of the segment. */
11926 newvertex = (vertex) poolalloc(&m->vertices);
11927 /* Interpolate coordinates and attributes. */
11928 for (i = 0; i < 2 + m->nextras; i++) {
11929 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11930 }
11932 setvertextype(newvertex, SEGMENTVERTEX);
11933 /* No known triangle to search from. */
11934 searchtri1.tri = m->dummytri;
11935 /* Attempt to insert the new vertex. */
11936 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11937 0, 0);
11939 if (b->verbose > 2) {
11940 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
11941 newvertex[0], newvertex[1]);
11942 }
11943 /* Use the vertex that's already there. */
11945 org(searchtri1, newvertex);
11946 } else {
11947 if (success == VIOLATINGVERTEX) {
11948 if (b->verbose > 2) {
11949 printf(" Two segments intersect at (%.12g, %.12g).\n",
11950 newvertex[0], newvertex[1]);
11951 }
11952 /* By fluke, we've landed right on another segment. Split it. */
11953 tspivot(searchtri1, brokensubseg);
11954 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11955 0, 0);
11956 if (success != SUCCESSFULVERTEX) {
11957 printf("Internal error in conformingedge():\n");
11958 printf(" Failure to split a segment.\n");
11959 internalerror();
11960 }
11961 }
11962 /* The vertex has been inserted successfully. */
11963 if (m->steinerleft > 0) {
11964 m->steinerleft--;
11965 }
11966 }
11967 otricopy(searchtri1, searchtri2);
11968 /* `searchtri1' and `searchtri2' are fastened at their origins to */
11969 /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */
11970 /* respectively. First, we must get `searchtri2' out of the way so it */
11971 /* won't be invalidated during the insertion of the first half of the */
11972 /* segment. */
11973 finddirection(m, b, &searchtri2, endpoint2);
11974 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11975 /* The origin of searchtri1 may have changed if a collision with an */
11976 /* intervening vertex on the segment occurred. */
11977 org(searchtri1, midvertex1);
11979 }
11980 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11981 /* The origin of searchtri2 may have changed if a collision with an */
11982 /* intervening vertex on the segment occurred. */
11983 org(searchtri2, midvertex2);
11985 }
11986}
11987
11988#endif /* not CDT_ONLY */
11989#endif /* not REDUCED */
11990
11991/*****************************************************************************/
11992/* */
11993/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */
11994/* recursively from an existing vertex. Pay special */
11995/* attention to stacking inverted triangles. */
11996/* */
11997/* This is a support routine for inserting segments into a constrained */
11998/* Delaunay triangulation. */
11999/* */
12000/* The origin of fixuptri is treated as if it has just been inserted, and */
12001/* the local Delaunay condition needs to be enforced. It is only enforced */
12002/* in one sector, however, that being the angular range defined by */
12003/* fixuptri. */
12004/* */
12005/* This routine also needs to make decisions regarding the "stacking" of */
12006/* triangles. (Read the description of constrainededge() below before */
12007/* reading on here, so you understand the algorithm.) If the position of */
12008/* the new vertex (the origin of fixuptri) indicates that the vertex before */
12009/* it on the polygon is a reflex vertex, then "stack" the triangle by */
12010/* doing nothing. (fixuptri is an inverted triangle, which is how stacked */
12011/* triangles are identified.) */
12012/* */
12013/* Otherwise, check whether the vertex before that was a reflex vertex. */
12014/* If so, perform an edge flip, thereby eliminating an inverted triangle */
12015/* (popping it off the stack). The edge flip may result in the creation */
12016/* of a new inverted triangle, depending on whether or not the new vertex */
12017/* is visible to the vertex three edges behind on the polygon. */
12018/* */
12019/* If neither of the two vertices behind the new vertex are reflex */
12020/* vertices, fixuptri and fartri, the triangle opposite it, are not */
12021/* inverted; hence, ensure that the edge between them is locally Delaunay. */
12022/* */
12023/* `leftside' indicates whether or not fixuptri is to the left of the */
12024/* segment being inserted. (Imagine that the segment is pointing up from */
12025/* endpoint1 to endpoint2.) */
12026/* */
12027/*****************************************************************************/
12028
12029#ifdef ANSI_DECLARATORS
12030void delaunayfixup(struct mesh *m, struct behavior *b,
12031 struct otri *fixuptri, int leftside)
12032#else /* not ANSI_DECLARATORS */
12034struct mesh *m;
12035struct behavior *b;
12036struct otri *fixuptri;
12038#endif /* not ANSI_DECLARATORS */
12039
12040{
12041 struct otri neartri;
12042 struct otri fartri;
12045 triangle ptr; /* Temporary variable used by sym(). */
12046 subseg sptr; /* Temporary variable used by tspivot(). */
12047
12048 lnext(*fixuptri, neartri);
12049 sym(neartri, fartri);
12050 /* Check if the edge opposite the origin of fixuptri can be flipped. */
12051 if (fartri.tri == m->dummytri) {
12052 return;
12053 }
12054 tspivot(neartri, faredge);
12055 if (faredge.ss != m->dummysub) {
12056 return;
12057 }
12058 /* Find all the relevant vertices. */
12059 apex(neartri, nearvertex);
12060 org(neartri, leftvertex);
12063 /* Check whether the previous polygon vertex is a reflex vertex. */
12066 /* leftvertex is a reflex vertex too. Nothing can */
12067 /* be done until a convex section is found. */
12068 return;
12069 }
12070 } else {
12072 /* rightvertex is a reflex vertex too. Nothing can */
12073 /* be done until a convex section is found. */
12074 return;
12075 }
12076 }
12078 /* fartri is not an inverted triangle, and farvertex is not a reflex */
12079 /* vertex. As there are no reflex vertices, fixuptri isn't an */
12080 /* inverted triangle, either. Hence, test the edge between the */
12081 /* triangles to ensure it is locally Delaunay. */
12083 0.0) {
12084 return;
12085 }
12086 /* Not locally Delaunay; go on to an edge flip. */
12087 } /* else fartri is inverted; remove it from the stack by flipping. */
12088 flip(m, b, &neartri);
12089 lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */
12090 /* Recursively process the two triangles that result from the flip. */
12093}
12094
12095/*****************************************************************************/
12096/* */
12097/* constrainededge() Force a segment into a constrained Delaunay */
12098/* triangulation by deleting the triangles it */
12099/* intersects, and triangulating the polygons that */
12100/* form on each side of it. */
12101/* */
12102/* Generates a single subsegment connecting `endpoint1' to `endpoint2'. */
12103/* The triangle `starttri' has `endpoint1' as its origin. `newmark' is the */
12104/* boundary marker of the segment. */
12105/* */
12106/* To insert a segment, every triangle whose interior intersects the */
12107/* segment is deleted. The union of these deleted triangles is a polygon */
12108/* (which is not necessarily monotone, but is close enough), which is */
12109/* divided into two polygons by the new segment. This routine's task is */
12110/* to generate the Delaunay triangulation of these two polygons. */
12111/* */
12112/* You might think of this routine's behavior as a two-step process. The */
12113/* first step is to walk from endpoint1 to endpoint2, flipping each edge */
12114/* encountered. This step creates a fan of edges connected to endpoint1, */
12115/* including the desired edge to endpoint2. The second step enforces the */
12116/* Delaunay condition on each side of the segment in an incremental manner: */
12117/* proceeding along the polygon from endpoint1 to endpoint2 (this is done */
12118/* independently on each side of the segment), each vertex is "enforced" */
12119/* as if it had just been inserted, but affecting only the previous */
12120/* vertices. The result is the same as if the vertices had been inserted */
12121/* in the order they appear on the polygon, so the result is Delaunay. */
12122/* */
12123/* In truth, constrainededge() interleaves these two steps. The procedure */
12124/* walks from endpoint1 to endpoint2, and each time an edge is encountered */
12125/* and flipped, the newly exposed vertex (at the far end of the flipped */
12126/* edge) is "enforced" upon the previously flipped edges, usually affecting */
12127/* only one side of the polygon (depending upon which side of the segment */
12128/* the vertex falls on). */
12129/* */
12130/* The algorithm is complicated by the need to handle polygons that are not */
12131/* convex. Although the polygon is not necessarily monotone, it can be */
12132/* triangulated in a manner similar to the stack-based algorithms for */
12133/* monotone polygons. For each reflex vertex (local concavity) of the */
12134/* polygon, there will be an inverted triangle formed by one of the edge */
12135/* flips. (An inverted triangle is one with negative area - that is, its */
12136/* vertices are arranged in clockwise order - and is best thought of as a */
12137/* wrinkle in the fabric of the mesh.) Each inverted triangle can be */
12138/* thought of as a reflex vertex pushed on the stack, waiting to be fixed */
12139/* later. */
12140/* */
12141/* A reflex vertex is popped from the stack when a vertex is inserted that */
12142/* is visible to the reflex vertex. (However, if the vertex behind the */
12143/* reflex vertex is not visible to the reflex vertex, a new inverted */
12144/* triangle will take its place on the stack.) These details are handled */
12145/* by the delaunayfixup() routine above. */
12146/* */
12147/*****************************************************************************/
12148
12149#ifdef ANSI_DECLARATORS
12150void constrainededge(struct mesh *m, struct behavior *b,
12151 struct otri *starttri, vertex endpoint2, int newmark)
12152#else /* not ANSI_DECLARATORS */
12154struct mesh *m;
12155struct behavior *b;
12156struct otri *starttri;
12158int newmark;
12159#endif /* not ANSI_DECLARATORS */
12160
12161{
12162 struct otri fixuptri, fixuptri2;
12163 struct osub crosssubseg;
12166 REAL area;
12168 int done;
12169 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12170 subseg sptr; /* Temporary variable used by tspivot(). */
12171
12175 /* `collision' indicates whether we have found a vertex directly */
12176 /* between endpoint1 and endpoint2. */
12177 collision = 0;
12178 done = 0;
12179 do {
12181 /* `farvertex' is the extreme point of the polygon we are "digging" */
12182 /* to get from endpoint1 to endpoint2. */
12183 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12184 oprev(fixuptri, fixuptri2);
12185 /* Enforce the Delaunay condition around endpoint2. */
12186 delaunayfixup(m, b, &fixuptri, 0);
12187 delaunayfixup(m, b, &fixuptri2, 1);
12188 done = 1;
12189 } else {
12190 /* Check whether farvertex is to the left or right of the segment */
12191 /* being inserted, to decide which edge of fixuptri to dig */
12192 /* through next. */
12194 if (area == 0.0) {
12195 /* We've collided with a vertex between endpoint1 and endpoint2. */
12196 collision = 1;
12197 oprev(fixuptri, fixuptri2);
12198 /* Enforce the Delaunay condition around farvertex. */
12199 delaunayfixup(m, b, &fixuptri, 0);
12200 delaunayfixup(m, b, &fixuptri2, 1);
12201 done = 1;
12202 } else {
12203 if (area > 0.0) { /* farvertex is to the left of the segment. */
12204 oprev(fixuptri, fixuptri2);
12205 /* Enforce the Delaunay condition around farvertex, on the */
12206 /* left side of the segment only. */
12207 delaunayfixup(m, b, &fixuptri2, 1);
12208 /* Flip the edge that crosses the segment. After the edge is */
12209 /* flipped, one of its endpoints is the fan vertex, and the */
12210 /* destination of fixuptri is the fan vertex. */
12212 } else { /* farvertex is to the right of the segment. */
12213 delaunayfixup(m, b, &fixuptri, 0);
12214 /* Flip the edge that crosses the segment. After the edge is */
12215 /* flipped, one of its endpoints is the fan vertex, and the */
12216 /* destination of fixuptri is the fan vertex. */
12217 oprevself(fixuptri);
12218 }
12219 /* Check for two intersecting segments. */
12221 if (crosssubseg.ss == m->dummysub) {
12222 flip(m, b, &fixuptri); /* May create inverted triangle at left. */
12223 } else {
12224 /* We've collided with a segment between endpoint1 and endpoint2. */
12225 collision = 1;
12226 /* Insert a vertex at the intersection. */
12228 done = 1;
12229 }
12230 }
12231 }
12232 } while (!done);
12233 /* Insert a subsegment to make the segment permanent. */
12235 /* If there was a collision with an interceding vertex, install another */
12236 /* segment connecting that vertex with endpoint2. */
12238 /* Insert the remainder of the segment. */
12241 }
12242 }
12243}
12244
12245/*****************************************************************************/
12246/* */
12247/* insertsegment() Insert a PSLG segment into a triangulation. */
12248/* */
12249/*****************************************************************************/
12250
12251#ifdef ANSI_DECLARATORS
12252void insertsegment(struct mesh *m, struct behavior *b,
12254#else /* not ANSI_DECLARATORS */
12256struct mesh *m;
12257struct behavior *b;
12260int newmark;
12261#endif /* not ANSI_DECLARATORS */
12262
12263{
12264 struct otri searchtri1, searchtri2;
12267 triangle ptr; /* Temporary variable used by sym(). */
12268
12269 if (b->verbose > 1) {
12270 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12271 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12272 }
12273
12274 /* Find a triangle whose origin is the segment's first endpoint. */
12275 checkvertex = (vertex) NULL;
12276 encodedtri = vertex2tri(endpoint1);
12277 if (encodedtri != (triangle) NULL) {
12278 decode(encodedtri, searchtri1);
12279 org(searchtri1, checkvertex);
12280 }
12282 /* Find a boundary triangle to search from. */
12283 searchtri1.tri = m->dummytri;
12284 searchtri1.orient = 0;
12285 symself(searchtri1);
12286 /* Search for the segment's first endpoint by point location. */
12287 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12288 printf(
12289 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12290 printf(" (%.12g, %.12g) in triangulation.\n",
12291 endpoint1[0], endpoint1[1]);
12292 internalerror();
12293 }
12294 }
12295 /* Remember this triangle to improve subsequent point location. */
12296 otricopy(searchtri1, m->recenttri);
12297 /* Scout the beginnings of a path from the first endpoint */
12298 /* toward the second. */
12299 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12300 /* The segment was easily inserted. */
12301 return;
12302 }
12303 /* The first endpoint may have changed if a collision with an intervening */
12304 /* vertex on the segment occurred. */
12305 org(searchtri1, endpoint1);
12306
12307 /* Find a triangle whose origin is the segment's second endpoint. */
12308 checkvertex = (vertex) NULL;
12309 encodedtri = vertex2tri(endpoint2);
12310 if (encodedtri != (triangle) NULL) {
12311 decode(encodedtri, searchtri2);
12312 org(searchtri2, checkvertex);
12313 }
12314 if (checkvertex != endpoint2) {
12315 /* Find a boundary triangle to search from. */
12316 searchtri2.tri = m->dummytri;
12317 searchtri2.orient = 0;
12318 symself(searchtri2);
12319 /* Search for the segment's second endpoint by point location. */
12320 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12321 printf(
12322 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12323 printf(" (%.12g, %.12g) in triangulation.\n",
12324 endpoint2[0], endpoint2[1]);
12325 internalerror();
12326 }
12327 }
12328 /* Remember this triangle to improve subsequent point location. */
12329 otricopy(searchtri2, m->recenttri);
12330 /* Scout the beginnings of a path from the second endpoint */
12331 /* toward the first. */
12332 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12333 /* The segment was easily inserted. */
12334 return;
12335 }
12336 /* The second endpoint may have changed if a collision with an intervening */
12337 /* vertex on the segment occurred. */
12338 org(searchtri2, endpoint2);
12339
12340#ifndef REDUCED
12341#ifndef CDT_ONLY
12342 if (b->splitseg) {
12343 /* Insert vertices to force the segment into the triangulation. */
12345 } else {
12346#endif /* not CDT_ONLY */
12347#endif /* not REDUCED */
12348 /* Insert the segment directly into the triangulation. */
12349 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12350#ifndef REDUCED
12351#ifndef CDT_ONLY
12352 }
12353#endif /* not CDT_ONLY */
12354#endif /* not REDUCED */
12355}
12356
12357/*****************************************************************************/
12358/* */
12359/* markhull() Cover the convex hull of a triangulation with subsegments. */
12360/* */
12361/*****************************************************************************/
12362
12363#ifdef ANSI_DECLARATORS
12364void markhull(struct mesh *m, struct behavior *b)
12365#else /* not ANSI_DECLARATORS */
12366void markhull(m, b)
12367struct mesh *m;
12368struct behavior *b;
12369#endif /* not ANSI_DECLARATORS */
12370
12371{
12372 struct otri hulltri;
12373 struct otri nexttri;
12374 struct otri starttri;
12375 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12376
12377 /* Find a triangle handle on the hull. */
12378 hulltri.tri = m->dummytri;
12379 hulltri.orient = 0;
12380 symself(hulltri);
12381 /* Remember where we started so we know when to stop. */
12383 /* Go once counterclockwise around the convex hull. */
12384 do {
12385 /* Create a subsegment if there isn't already one here. */
12386 insertsubseg(m, b, &hulltri, 1);
12387 /* To find the next hull edge, go clockwise around the next vertex. */
12388 lnextself(hulltri);
12389 oprev(hulltri, nexttri);
12390 while (nexttri.tri != m->dummytri) {
12391 otricopy(nexttri, hulltri);
12392 oprev(hulltri, nexttri);
12393 }
12394 } while (!otriequal(hulltri, starttri));
12395}
12396
12397/*****************************************************************************/
12398/* */
12399/* formskeleton() Create the segments of a triangulation, including PSLG */
12400/* segments and edges on the convex hull. */
12401/* */
12402/* The PSLG segments are read from a .poly file. The return value is the */
12403/* number of segments in the file. */
12404/* */
12405/*****************************************************************************/
12406
12407#ifdef TRILIBRARY
12408
12409#ifdef ANSI_DECLARATORS
12410void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12412#else /* not ANSI_DECLARATORS */
12414struct mesh *m;
12415struct behavior *b;
12416int *segmentlist;
12419#endif /* not ANSI_DECLARATORS */
12420
12421#else /* not TRILIBRARY */
12422
12423#ifdef ANSI_DECLARATORS
12424void formskeleton(struct mesh *m, struct behavior *b,
12425 FILE *polyfile, char *polyfilename)
12426#else /* not ANSI_DECLARATORS */
12428struct mesh *m;
12429struct behavior *b;
12430FILE *polyfile;
12431char *polyfilename;
12432#endif /* not ANSI_DECLARATORS */
12433
12434#endif /* not TRILIBRARY */
12435
12436{
12437#ifdef TRILIBRARY
12438 char polyfilename[6];
12440#else /* not TRILIBRARY */
12441 char inputline[INPUTLINESIZE];
12442 char *stringptr;
12443#endif /* not TRILIBRARY */
12445 int segmentmarkers;
12447 int boundmarker;
12448 int i;
12449
12450 if (b->poly) {
12451 if (!b->quiet) {
12452 printf("Recovering segments in Delaunay triangulation.\n");
12453 }
12454#ifdef TRILIBRARY
12455 strcpy(polyfilename, "input");
12456 m->insegments = numberofsegments;
12457 segmentmarkers = segmentmarkerlist != (int *) NULL;
12458 index = 0;
12459#else /* not TRILIBRARY */
12460 /* Read the segments from a .poly file. */
12461 /* Read number of segments and number of boundary markers. */
12463 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12465 if (*stringptr == '\0') {
12466 segmentmarkers = 0;
12467 } else {
12468 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12469 }
12470#endif /* not TRILIBRARY */
12471 /* If the input vertices are collinear, there is no triangulation, */
12472 /* so don't try to insert segments. */
12473 if (m->triangles.items == 0) {
12474 return;
12475 }
12476
12477 /* If segments are to be inserted, compute a mapping */
12478 /* from vertices to triangles. */
12479 if (m->insegments > 0) {
12480 makevertexmap(m, b);
12481 if (b->verbose) {
12482 printf(" Recovering PSLG segments.\n");
12483 }
12484 }
12485
12486 boundmarker = 0;
12487 /* Read and insert the segments. */
12488 for (i = 0; i < m->insegments; i++) {
12489#ifdef TRILIBRARY
12490 end1 = segmentlist[index++];
12491 end2 = segmentlist[index++];
12492 if (segmentmarkers) {
12494 }
12495#else /* not TRILIBRARY */
12496 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12498 if (*stringptr == '\0') {
12499 printf("Error: Segment %d has no endpoints in %s.\n",
12500 b->firstnumber + i, polyfilename);
12501 triexit(1);
12502 } else {
12503 end1 = (int) strtol(stringptr, &stringptr, 0);
12504 }
12506 if (*stringptr == '\0') {
12507 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12508 b->firstnumber + i, polyfilename);
12509 triexit(1);
12510 } else {
12511 end2 = (int) strtol(stringptr, &stringptr, 0);
12512 }
12513 if (segmentmarkers) {
12515 if (*stringptr == '\0') {
12516 boundmarker = 0;
12517 } else {
12518 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12519 }
12520 }
12521#endif /* not TRILIBRARY */
12522 if ((end1 < b->firstnumber) ||
12523 (end1 >= b->firstnumber + m->invertices)) {
12524 if (!b->quiet) {
12525 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12526 b->firstnumber + i, polyfilename);
12527 }
12528 } else if ((end2 < b->firstnumber) ||
12529 (end2 >= b->firstnumber + m->invertices)) {
12530 if (!b->quiet) {
12531 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12532 b->firstnumber + i, polyfilename);
12533 }
12534 } else {
12535 /* Find the vertices numbered `end1' and `end2'. */
12536 endpoint1 = getvertex(m, b, end1);
12537 endpoint2 = getvertex(m, b, end2);
12538 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12539 if (!b->quiet) {
12540 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12541 b->firstnumber + i, polyfilename);
12542 }
12543 } else {
12545 }
12546 }
12547 }
12548 } else {
12549 m->insegments = 0;
12550 }
12551 if (b->convex || !b->poly) {
12552 /* Enclose the convex hull with subsegments. */
12553 if (b->verbose) {
12554 printf(" Enclosing convex hull with segments.\n");
12555 }
12556 markhull(m, b);
12557 }
12558}
12559
12562/********* Segment insertion ends here *********/
12563
12564/********* Carving out holes and concavities begins here *********/
12567
12568/*****************************************************************************/
12569/* */
12570/* infecthull() Virally infect all of the triangles of the convex hull */
12571/* that are not protected by subsegments. Where there are */
12572/* subsegments, set boundary markers as appropriate. */
12573/* */
12574/*****************************************************************************/
12575
12576#ifdef ANSI_DECLARATORS
12577void infecthull(struct mesh *m, struct behavior *b)
12578#else /* not ANSI_DECLARATORS */
12579void infecthull(m, b)
12580struct mesh *m;
12581struct behavior *b;
12582#endif /* not ANSI_DECLARATORS */
12583
12584{
12585 struct otri hulltri;
12586 struct otri nexttri;
12587 struct otri starttri;
12591 triangle ptr; /* Temporary variable used by sym(). */
12592 subseg sptr; /* Temporary variable used by tspivot(). */
12593
12594 if (b->verbose) {
12595 printf(" Marking concavities (external triangles) for elimination.\n");
12596 }
12597 /* Find a triangle handle on the hull. */
12598 hulltri.tri = m->dummytri;
12599 hulltri.orient = 0;
12600 symself(hulltri);
12601 /* Remember where we started so we know when to stop. */
12602 otricopy(hulltri, starttri);
12603 /* Go once counterclockwise around the convex hull. */
12604 do {
12605 /* Ignore triangles that are already infected. */
12606 if (!infected(hulltri)) {
12607 /* Is the triangle protected by a subsegment? */
12608 tspivot(hulltri, hullsubseg);
12609 if (hullsubseg.ss == m->dummysub) {
12610 /* The triangle is not protected; infect it. */
12611 if (!infected(hulltri)) {
12612 infect(hulltri);
12613 deadtriangle = (triangle **) poolalloc(&m->viri);
12614 *deadtriangle = hulltri.tri;
12615 }
12616 } else {
12617 /* The triangle is protected; set boundary markers if appropriate. */
12618 if (markT(hullsubseg) == 0) {
12619 setmark(hullsubseg, 1);
12620 org(hulltri, horg);
12621 destT(hulltri, hdest);
12622 if (vertexmark(horg) == 0) {
12623 setvertexmark(horg, 1);
12624 }
12625 if (vertexmark(hdest) == 0) {
12626 setvertexmark(hdest, 1);
12627 }
12628 }
12629 }
12630 }
12631 /* To find the next hull edge, go clockwise around the next vertex. */
12632 lnextself(hulltri);
12633 oprev(hulltri, nexttri);
12634 while (nexttri.tri != m->dummytri) {
12635 otricopy(nexttri, hulltri);
12636 oprev(hulltri, nexttri);
12637 }
12638 } while (!otriequal(hulltri, starttri));
12639}
12640
12641/*****************************************************************************/
12642/* */
12643/* plague() Spread the virus from all infected triangles to any neighbors */
12644/* not protected by subsegments. Delete all infected triangles. */
12645/* */
12646/* This is the procedure that actually creates holes and concavities. */
12647/* */
12648/* This procedure operates in two phases. The first phase identifies all */
12649/* the triangles that will die, and marks them as infected. They are */
12650/* marked to ensure that each triangle is added to the virus pool only */
12651/* once, so the procedure will terminate. */
12652/* */
12653/* The second phase actually eliminates the infected triangles. It also */
12654/* eliminates orphaned vertices. */
12655/* */
12656/*****************************************************************************/
12657
12658#ifdef ANSI_DECLARATORS
12659void plague(struct mesh *m, struct behavior *b)
12660#else /* not ANSI_DECLARATORS */
12661void plague(m, b)
12662struct mesh *m;
12663struct behavior *b;
12664#endif /* not ANSI_DECLARATORS */
12665
12666{
12667 struct otri testtri;
12676 triangle ptr; /* Temporary variable used by sym() and onext(). */
12677 subseg sptr; /* Temporary variable used by tspivot(). */
12678
12679 if (b->verbose) {
12680 printf(" Marking neighbors of marked triangles.\n");
12681 }
12682 /* Loop through all the infected triangles, spreading the virus to */
12683 /* their neighbors, then to their neighbors' neighbors. */
12684 traversalinit(&m->viri);
12685 virusloop = (triangle **) traverse(&m->viri);
12686 while (virusloop != (triangle **) NULL) {
12687 testtri.tri = *virusloop;
12688 /* A triangle is marked as infected by messing with one of its pointers */
12689 /* to subsegments, setting it to an illegal value. Hence, we have to */
12690 /* temporarily uninfect this triangle so that we can examine its */
12691 /* adjacent subsegments. */
12692 uninfect(testtri);
12693 if (b->verbose > 2) {
12694 /* Assign the triangle an orientation for convenience in */
12695 /* checking its vertices. */
12696 testtri.orient = 0;
12700 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12701 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12702 deadapex[0], deadapex[1]);
12703 }
12704 /* Check each of the triangle's three neighbors. */
12705 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12706 /* Find the neighbor. */
12708 /* Check for a subsegment between the triangle and its neighbor. */
12710 /* Check if the neighbor is nonexistent or already infected. */
12711 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12712 if (neighborsubseg.ss != m->dummysub) {
12713 /* There is a subsegment separating the triangle from its */
12714 /* neighbor, but both triangles are dying, so the subsegment */
12715 /* dies too. */
12717 if (neighbor.tri != m->dummytri) {
12718 /* Make sure the subsegment doesn't get deallocated again */
12719 /* later when the infected neighbor is visited. */
12720 uninfect(neighbor);
12721 tsdissolve(neighbor);
12722 infect(neighbor);
12723 }
12724 }
12725 } else { /* The neighbor exists and is not infected. */
12726 if (neighborsubseg.ss == m->dummysub) {
12727 /* There is no subsegment protecting the neighbor, so */
12728 /* the neighbor becomes infected. */
12729 if (b->verbose > 2) {
12733 printf(
12734 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12735 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12736 deadapex[0], deadapex[1]);
12737 }
12738 infect(neighbor);
12739 /* Ensure that the neighbor's neighbors will be infected. */
12740 deadtriangle = (triangle **) poolalloc(&m->viri);
12741 *deadtriangle = neighbor.tri;
12742 } else { /* The neighbor is protected by a subsegment. */
12743 /* Remove this triangle from the subsegment. */
12744 stdissolve(neighborsubseg);
12745 /* The subsegment becomes a boundary. Set markers accordingly. */
12746 if (markT(neighborsubseg) == 0) {
12747 setmark(neighborsubseg, 1);
12748 }
12749 org(neighbor, norg);
12751 if (vertexmark(norg) == 0) {
12752 setvertexmark(norg, 1);
12753 }
12754 if (vertexmark(ndest) == 0) {
12755 setvertexmark(ndest, 1);
12756 }
12757 }
12758 }
12759 }
12760 /* Remark the triangle as infected, so it doesn't get added to the */
12761 /* virus pool again. */
12762 infect(testtri);
12763 virusloop = (triangle **) traverse(&m->viri);
12764 }
12765
12766 if (b->verbose) {
12767 printf(" Deleting marked triangles.\n");
12768 }
12769
12770 traversalinit(&m->viri);
12771 virusloop = (triangle **) traverse(&m->viri);
12772 while (virusloop != (triangle **) NULL) {
12773 testtri.tri = *virusloop;
12774
12775 /* Check each of the three corners of the triangle for elimination. */
12776 /* This is done by walking around each vertex, checking if it is */
12777 /* still connected to at least one live triangle. */
12778 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12780 /* Check if the vertex has already been tested. */
12781 if (testvertex != (vertex) NULL) {
12782 killorg = 1;
12783 /* Mark the corner of the triangle as having been tested. */
12784 setorg(testtri, NULL);
12785 /* Walk counterclockwise about the vertex. */
12786 onext(testtri, neighbor);
12787 /* Stop upon reaching a boundary or the starting triangle. */
12788 while ((neighbor.tri != m->dummytri) &&
12789 (!otriequal(neighbor, testtri))) {
12790 if (infected(neighbor)) {
12791 /* Mark the corner of this triangle as having been tested. */
12792 setorg(neighbor, NULL);
12793 } else {
12794 /* A live triangle. The vertex survives. */
12795 killorg = 0;
12796 }
12797 /* Walk counterclockwise about the vertex. */
12798 onextself(neighbor);
12799 }
12800 /* If we reached a boundary, we must walk clockwise as well. */
12801 if (neighbor.tri == m->dummytri) {
12802 /* Walk clockwise about the vertex. */
12804 /* Stop upon reaching a boundary. */
12805 while (neighbor.tri != m->dummytri) {
12806 if (infected(neighbor)) {
12807 /* Mark the corner of this triangle as having been tested. */
12808 setorg(neighbor, NULL);
12809 } else {
12810 /* A live triangle. The vertex survives. */
12811 killorg = 0;
12812 }
12813 /* Walk clockwise about the vertex. */
12814 oprevself(neighbor);
12815 }
12816 }
12817 if (killorg) {
12818 if (b->verbose > 1) {
12819 printf(" Deleting vertex (%.12g, %.12g)\n",
12820 testvertex[0], testvertex[1]);
12821 }
12822 setvertextype(testvertex, UNDEADVERTEX);
12823 m->undeads++;
12824 }
12825 }
12826 }
12827
12828 /* Record changes in the number of boundary edges, and disconnect */
12829 /* dead triangles from their neighbors. */
12830 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12832 if (neighbor.tri == m->dummytri) {
12833 /* There is no neighboring triangle on this edge, so this edge */
12834 /* is a boundary edge. This triangle is being deleted, so this */
12835 /* boundary edge is deleted. */
12836 m->hullsize--;
12837 } else {
12838 /* Disconnect the triangle from its neighbor. */
12840 /* There is a neighboring triangle on this edge, so this edge */
12841 /* becomes a boundary edge when this triangle is deleted. */
12842 m->hullsize++;
12843 }
12844 }
12845 /* Return the dead triangle to the pool of triangles. */
12847 virusloop = (triangle **) traverse(&m->viri);
12848 }
12849 /* Empty the virus pool. */
12850 poolrestart(&m->viri);
12851}
12852
12853/*****************************************************************************/
12854/* */
12855/* regionplague() Spread regional attributes and/or area constraints */
12856/* (from a .poly file) throughout the mesh. */
12857/* */
12858/* This procedure operates in two phases. The first phase spreads an */
12859/* attribute and/or an area constraint through a (segment-bounded) region. */
12860/* The triangles are marked to ensure that each triangle is added to the */
12861/* virus pool only once, so the procedure will terminate. */
12862/* */
12863/* The second phase uninfects all infected triangles, returning them to */
12864/* normal. */
12865/* */
12866/*****************************************************************************/
12867
12868#ifdef ANSI_DECLARATORS
12869void regionplague(struct mesh *m, struct behavior *b,
12870 REAL attribute, REAL area)
12871#else /* not ANSI_DECLARATORS */
12873struct mesh *m;
12874struct behavior *b;
12875REAL attribute;
12876REAL area;
12877#endif /* not ANSI_DECLARATORS */
12878
12879{
12880 struct otri testtri;
12881 struct otri neighbor;
12884 struct osub neighborsubseg;
12886 triangle ptr; /* Temporary variable used by sym() and onext(). */
12887 subseg sptr; /* Temporary variable used by tspivot(). */
12888
12889 if (b->verbose > 1) {
12890 printf(" Marking neighbors of marked triangles.\n");
12891 }
12892 /* Loop through all the infected triangles, spreading the attribute */
12893 /* and/or area constraint to their neighbors, then to their neighbors' */
12894 /* neighbors. */
12895 traversalinit(&m->viri);
12896 virusloop = (triangle **) traverse(&m->viri);
12897 while (virusloop != (triangle **) NULL) {
12898 testtri.tri = *virusloop;
12899 /* A triangle is marked as infected by messing with one of its pointers */
12900 /* to subsegments, setting it to an illegal value. Hence, we have to */
12901 /* temporarily uninfect this triangle so that we can examine its */
12902 /* adjacent subsegments. */
12903 uninfect(testtri);
12904 if (b->regionattrib) {
12905 /* Set an attribute. */
12906 setelemattribute(testtri, m->eextras, attribute);
12907 }
12908 if (b->vararea) {
12909 /* Set an area constraint. */
12910 setareabound(testtri, area);
12911 }
12912 if (b->verbose > 2) {
12913 /* Assign the triangle an orientation for convenience in */
12914 /* checking its vertices. */
12915 testtri.orient = 0;
12919 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12921 regionapex[0], regionapex[1]);
12922 }
12923 /* Check each of the triangle's three neighbors. */
12924 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12925 /* Find the neighbor. */
12927 /* Check for a subsegment between the triangle and its neighbor. */
12929 /* Make sure the neighbor exists, is not already infected, and */
12930 /* isn't protected by a subsegment. */
12931 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12932 && (neighborsubseg.ss == m->dummysub)) {
12933 if (b->verbose > 2) {
12937 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12939 regionapex[0], regionapex[1]);
12940 }
12941 /* Infect the neighbor. */
12942 infect(neighbor);
12943 /* Ensure that the neighbor's neighbors will be infected. */
12944 regiontri = (triangle **) poolalloc(&m->viri);
12945 *regiontri = neighbor.tri;
12946 }
12947 }
12948 /* Remark the triangle as infected, so it doesn't get added to the */
12949 /* virus pool again. */
12950 infect(testtri);
12951 virusloop = (triangle **) traverse(&m->viri);
12952 }
12953
12954 /* Uninfect all triangles. */
12955 if (b->verbose > 1) {
12956 printf(" Unmarking marked triangles.\n");
12957 }
12958 traversalinit(&m->viri);
12959 virusloop = (triangle **) traverse(&m->viri);
12960 while (virusloop != (triangle **) NULL) {
12961 testtri.tri = *virusloop;
12962 uninfect(testtri);
12963 virusloop = (triangle **) traverse(&m->viri);
12964 }
12965 /* Empty the virus pool. */
12966 poolrestart(&m->viri);
12967}
12968
12969/*****************************************************************************/
12970/* */
12971/* carveholes() Find the holes and infect them. Find the area */
12972/* constraints and infect them. Infect the convex hull. */
12973/* Spread the infection and kill triangles. Spread the */
12974/* area constraints. */
12975/* */
12976/* This routine mainly calls other routines to carry out all these */
12977/* functions. */
12978/* */
12979/*****************************************************************************/
12980
12981#ifdef ANSI_DECLARATORS
12982void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12983 REAL *regionlist, int regions)
12984#else /* not ANSI_DECLARATORS */
12986struct mesh *m;
12987struct behavior *b;
12988REAL *holelist;
12989int holes;
12990REAL *regionlist;
12992#endif /* not ANSI_DECLARATORS */
12993
12994{
12995 struct otri searchtri;
12996 struct otri triangleloop;
13002 int i;
13003 triangle ptr; /* Temporary variable used by sym(). */
13004
13005 if (!(b->quiet || (b->noholes && b->convex))) {
13006 printf("Removing unwanted triangles.\n");
13007 if (b->verbose && (holes > 0)) {
13008 printf(" Marking holes for elimination.\n");
13009 }
13010 }
13011
13012 if (regions > 0) {
13013 /* Allocate storage for the triangles in which region points fall. */
13014 regiontris = (struct otri *) trimalloc(regions *
13015 (int) sizeof(struct otri));
13016 } else {
13017 regiontris = (struct otri *) NULL;
13018 }
13019
13020 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13021 /* Initialize a pool of viri to be used for holes, concavities, */
13022 /* regional attributes, and/or regional area constraints. */
13023 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13024 }
13025
13026 if (!b->convex) {
13027 /* Mark as infected any unprotected triangles on the boundary. */
13028 /* This is one way by which concavities are created. */
13029 infecthull(m, b);
13030 }
13031
13032 if ((holes > 0) && !b->noholes) {
13033 /* Infect each triangle in which a hole lies. */
13034 for (i = 0; i < 2 * holes; i += 2) {
13035 /* Ignore holes that aren't within the bounds of the mesh. */
13036 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13037 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13038 /* Start searching from some triangle on the outer boundary. */
13039 searchtri.tri = m->dummytri;
13040 searchtri.orient = 0;
13042 /* Ensure that the hole is to the left of this boundary edge; */
13043 /* otherwise, locate() will falsely report that the hole */
13044 /* falls within the starting triangle. */
13048 0.0) {
13049 /* Find a triangle that contains the hole. */
13051 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13052 /* Infect the triangle. This is done by marking the triangle */
13053 /* as infected and including the triangle in the virus pool. */
13054 infect(searchtri);
13055 holetri = (triangle **) poolalloc(&m->viri);
13056 *holetri = searchtri.tri;
13057 }
13058 }
13059 }
13060 }
13061 }
13062
13063 /* Now, we have to find all the regions BEFORE we carve the holes, because */
13064 /* locate() won't work when the triangulation is no longer convex. */
13065 /* (Incidentally, this is the reason why regional attributes and area */
13066 /* constraints can't be used when refining a preexisting mesh, which */
13067 /* might not be convex; they can only be used with a freshly */
13068 /* triangulated PSLG.) */
13069 if (regions > 0) {
13070 /* Find the starting triangle for each region. */
13071 for (i = 0; i < regions; i++) {
13072 regiontris[i].tri = m->dummytri;
13073 /* Ignore region points that aren't within the bounds of the mesh. */
13074 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13075 (regionlist[4 * i + 1] >= m->ymin) &&
13076 (regionlist[4 * i + 1] <= m->ymax)) {
13077 /* Start searching from some triangle on the outer boundary. */
13078 searchtri.tri = m->dummytri;
13079 searchtri.orient = 0;
13081 /* Ensure that the region point is to the left of this boundary */
13082 /* edge; otherwise, locate() will falsely report that the */
13083 /* region point falls within the starting triangle. */
13087 0.0) {
13088 /* Find a triangle that contains the region point. */
13089 intersect = locate(m, b, &regionlist[4 * i], &searchtri);
13090 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13091 /* Record the triangle for processing after the */
13092 /* holes have been carved. */
13094 }
13095 }
13096 }
13097 }
13098 }
13099
13100 if (m->viri.items > 0) {
13101 /* Carve the holes and concavities. */
13102 plague(m, b);
13103 }
13104 /* The virus pool should be empty now. */
13105
13106 if (regions > 0) {
13107 if (!b->quiet) {
13108 if (b->regionattrib) {
13109 if (b->vararea) {
13110 printf("Spreading regional attributes and area constraints.\n");
13111 } else {
13112 printf("Spreading regional attributes.\n");
13113 }
13114 } else {
13115 printf("Spreading regional area constraints.\n");
13116 }
13117 }
13118 if (b->regionattrib && !b->refine) {
13119 /* Assign every triangle a regional attribute of zero. */
13120 traversalinit(&m->triangles);
13121 triangleloop.orient = 0;
13123 while (triangleloop.tri != (triangle *) NULL) {
13124 setelemattribute(triangleloop, m->eextras, 0.0);
13126 }
13127 }
13128 for (i = 0; i < regions; i++) {
13129 if (regiontris[i].tri != m->dummytri) {
13130 /* Make sure the triangle under consideration still exists. */
13131 /* It may have been eaten by the virus. */
13132 if (!deadtri(regiontris[i].tri)) {
13133 /* Put one triangle in the virus pool. */
13134 infect(regiontris[i]);
13135 regiontri = (triangle **) poolalloc(&m->viri);
13136 *regiontri = regiontris[i].tri;
13137 /* Apply one region's attribute and/or area constraint. */
13138 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13139 /* The virus pool should be empty now. */
13140 }
13141 }
13142 }
13143 if (b->regionattrib && !b->refine) {
13144 /* Note the fact that each triangle has an additional attribute. */
13145 m->eextras++;
13146 }
13147 }
13148
13149 /* Free up memory. */
13150 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13151 pooldeinit(&m->viri);
13152 }
13153 if (regions > 0) {
13154 trifree((VOID *) regiontris);
13155 }
13156}
13157
13160/********* Carving out holes and concavities ends here *********/
13161
13162/********* Mesh quality maintenance begins here *********/
13165
13166/*****************************************************************************/
13167/* */
13168/* tallyencs() Traverse the entire list of subsegments, and check each */
13169/* to see if it is encroached. If so, add it to the list. */
13170/* */
13171/*****************************************************************************/
13172
13173#ifndef CDT_ONLY
13174
13175#ifdef ANSI_DECLARATORS
13176void tallyencs(struct mesh *m, struct behavior *b)
13177#else /* not ANSI_DECLARATORS */
13178void tallyencs(m, b)
13179struct mesh *m;
13180struct behavior *b;
13181#endif /* not ANSI_DECLARATORS */
13182
13183{
13184 struct osub subsegloop;
13186
13187 traversalinit(&m->subsegs);
13188 subsegloop.ssorient = 0;
13190 while (subsegloop.ss != (subseg *) NULL) {
13191 /* If the segment is encroached, add it to the list. */
13194 }
13195}
13196
13197#endif /* not CDT_ONLY */
13198
13199/*****************************************************************************/
13200/* */
13201/* precisionerror() Print an error message for precision problems. */
13202/* */
13203/*****************************************************************************/
13204
13205#ifndef CDT_ONLY
13206
13208{
13209 printf("Try increasing the area criterion and/or reducing the minimum\n");
13210 printf(" allowable angle so that tiny triangles are not created.\n");
13211#ifdef SINGLE
13212 printf("Alternatively, try recompiling me with double precision\n");
13213 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13214 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13215#endif /* SINGLE */
13216}
13217
13218#endif /* not CDT_ONLY */
13219
13220/*****************************************************************************/
13221/* */
13222/* splitencsegs() Split all the encroached subsegments. */
13223/* */
13224/* Each encroached subsegment is repaired by splitting it - inserting a */
13225/* vertex at or near its midpoint. Newly inserted vertices may encroach */
13226/* upon other subsegments; these are also repaired. */
13227/* */
13228/* `triflaws' is a flag that specifies whether one should take note of new */
13229/* bad triangles that result from inserting vertices to repair encroached */
13230/* subsegments. */
13231/* */
13232/*****************************************************************************/
13233
13234#ifndef CDT_ONLY
13235
13236#ifdef ANSI_DECLARATORS
13237void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13238#else /* not ANSI_DECLARATORS */
13239void splitencsegs(m, b, triflaws)
13240struct mesh *m;
13241struct behavior *b;
13242int triflaws;
13243#endif /* not ANSI_DECLARATORS */
13244
13245{
13246 struct otri enctri;
13247 struct otri testtri;
13248 struct osub testsh;
13255 REAL split;
13258 int dummy;
13259 int i;
13260 triangle ptr; /* Temporary variable used by stpivot(). */
13261 subseg sptr; /* Temporary variable used by snext(). */
13262
13263 /* Note that steinerleft == -1 if an unlimited number */
13264 /* of Steiner points is allowed. */
13265 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13266 traversalinit(&m->badsubsegs);
13268 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13269 sdecode(encloop->encsubseg, currentenc);
13270 sorg(currentenc, eorg);
13271 sdest(currentenc, edest);
13272 /* Make sure that this segment is still the same segment it was */
13273 /* when it was determined to be encroached. If the segment was */
13274 /* enqueued multiple times (because several newly inserted */
13275 /* vertices encroached it), it may have already been split. */
13276 if (!deadsubseg(currentenc.ss) &&
13277 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13278 /* To decide where to split a segment, we need to know if the */
13279 /* segment shares an endpoint with an adjacent segment. */
13280 /* The concern is that, if we simply split every encroached */
13281 /* segment in its center, two adjacent segments with a small */
13282 /* angle between them might lead to an infinite loop; each */
13283 /* vertex added to split one segment will encroach upon the */
13284 /* other segment, which must then be split with a vertex that */
13285 /* will encroach upon the first segment, and so on forever. */
13286 /* To avoid this, imagine a set of concentric circles, whose */
13287 /* radii are powers of two, about each segment endpoint. */
13288 /* These concentric circles determine where the segment is */
13289 /* split. (If both endpoints are shared with adjacent */
13290 /* segments, split the segment in the middle, and apply the */
13291 /* concentric circles for later splittings.) */
13292
13293 /* Is the origin shared with another segment? */
13294 stpivot(currentenc, enctri);
13295 lnext(enctri, testtri);
13297 acuteorg = testsh.ss != m->dummysub;
13298 /* Is the destination shared with another segment? */
13301 acutedest = testsh.ss != m->dummysub;
13302
13303 /* If we're using Chew's algorithm (rather than Ruppert's) */
13304 /* to define encroachment, delete free vertices from the */
13305 /* subsegment's diametral circle. */
13306 if (!b->conformdel && !acuteorg && !acutedest) {
13307 apex(enctri, eapex);
13308 while ((vertextype(eapex) == FREEVERTEX) &&
13309 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13310 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13311 deletevertex(m, b, &testtri);
13312 stpivot(currentenc, enctri);
13313 apex(enctri, eapex);
13314 lprev(enctri, testtri);
13315 }
13316 }
13317
13318 /* Now, check the other side of the segment, if there's a triangle */
13319 /* there. */
13320 sym(enctri, testtri);
13321 if (testtri.tri != m->dummytri) {
13322 /* Is the destination shared with another segment? */
13325 acutedest2 = testsh.ss != m->dummysub;
13327 /* Is the origin shared with another segment? */
13330 acuteorg2 = testsh.ss != m->dummysub;
13332
13333 /* Delete free vertices from the subsegment's diametral circle. */
13334 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13335 org(testtri, eapex);
13336 while ((vertextype(eapex) == FREEVERTEX) &&
13337 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13338 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13339 deletevertex(m, b, &testtri);
13340 sym(enctri, testtri);
13341 apex(testtri, eapex);
13343 }
13344 }
13345 }
13346
13347 /* Use the concentric circles if exactly one endpoint is shared */
13348 /* with another adjacent segment. */
13349 if (acuteorg || acutedest) {
13350 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13351 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13352 /* Find the power of two that most evenly splits the segment. */
13353 /* The worst case is a 2:1 ratio between subsegment lengths. */
13354 nearestpoweroftwo = 1.0;
13355 while (segmentlength > 3.0 * nearestpoweroftwo) {
13356 nearestpoweroftwo *= 2.0;
13357 }
13358 while (segmentlength < 1.5 * nearestpoweroftwo) {
13359 nearestpoweroftwo *= 0.5;
13360 }
13361 /* Where do we split the segment? */
13363 if (acutedest) {
13364 split = 1.0 - split;
13365 }
13366 } else {
13367 /* If we're not worried about adjacent segments, split */
13368 /* this segment in the middle. */
13369 split = 0.5;
13370 }
13371
13372 /* Create the new vertex. */
13373 newvertex = (vertex) poolalloc(&m->vertices);
13374 /* Interpolate its coordinate and attributes. */
13375 for (i = 0; i < 2 + m->nextras; i++) {
13376 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13377 }
13378
13379 if (!b->noexact) {
13380 /* Roundoff in the above calculation may yield a `newvertex' */
13381 /* that is not precisely collinear with `eorg' and `edest'. */
13382 /* Improve collinearity by one step of iterative refinement. */
13384 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13385 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13386 if ((multiplier != 0.0) && (divisor != 0.0)) {
13388 /* Watch out for NANs. */
13389 if (multiplier == multiplier) {
13390 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13391 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13392 }
13393 }
13394 }
13395
13397 setvertextype(newvertex, SEGMENTVERTEX);
13398 if (b->verbose > 1) {
13399 printf(
13400 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13401 eorg[0], eorg[1], edest[0], edest[1],
13402 newvertex[0], newvertex[1]);
13403 }
13404 /* Check whether the new vertex lies on an endpoint. */
13405 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13406 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13407 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13408 newvertex[0], newvertex[1]);
13409 printf("I attempted to split a segment to a smaller size than\n");
13410 printf(" can be accommodated by the finite precision of\n");
13411 printf(" floating point arithmetic.\n");
13413 triexit(1);
13414 }
13415 /* Insert the splitting vertex. This should always succeed. */
13416 success = insertvertex(m, b, newvertex, &enctri, &currentenc,
13417 1, triflaws);
13419 printf("Internal error in splitencsegs():\n");
13420 printf(" Failure to split a segment.\n");
13421 internalerror();
13422 }
13423 if (m->steinerleft > 0) {
13424 m->steinerleft--;
13425 }
13426 /* Check the two new subsegments to see if they're encroached. */
13430 }
13431
13434 }
13435 }
13436}
13437
13438#endif /* not CDT_ONLY */
13439
13440/*****************************************************************************/
13441/* */
13442/* tallyfaces() Test every triangle in the mesh for quality measures. */
13443/* */
13444/*****************************************************************************/
13445
13446#ifndef CDT_ONLY
13447
13448#ifdef ANSI_DECLARATORS
13449void tallyfaces(struct mesh *m, struct behavior *b)
13450#else /* not ANSI_DECLARATORS */
13451void tallyfaces(m, b)
13452struct mesh *m;
13453struct behavior *b;
13454#endif /* not ANSI_DECLARATORS */
13455
13456{
13457 struct otri triangleloop;
13458
13459 if (b->verbose) {
13460 printf(" Making a list of bad triangles.\n");
13461 }
13462 traversalinit(&m->triangles);
13463 triangleloop.orient = 0;
13465 while (triangleloop.tri != (triangle *) NULL) {
13466 /* If the triangle is bad, enqueue it. */
13469 }
13470}
13471
13472#endif /* not CDT_ONLY */
13473
13474/*****************************************************************************/
13475/* */
13476/* splittriangle() Inserts a vertex at the circumcenter of a triangle. */
13477/* Deletes the newly inserted vertex if it encroaches */
13478/* upon a segment. */
13479/* */
13480/*****************************************************************************/
13481
13482#ifndef CDT_ONLY
13483
13484#ifdef ANSI_DECLARATORS
13485void splittriangle(struct mesh *m, struct behavior *b,
13486 struct badtriang *badtri)
13487#else /* not ANSI_DECLARATORS */
13488void splittriangle(m, b, badtri)
13489struct mesh *m;
13490struct behavior *b;
13491struct badtriang *badtri;
13492#endif /* not ANSI_DECLARATORS */
13493
13494{
13495 struct otri badotri;
13498 REAL xi, eta;
13501 int i;
13502
13503 decode(badtri->poortri, badotri);
13504 org(badotri, borg);
13505 destT(badotri, bdest);
13506 apex(badotri, bapex);
13507 /* Make sure that this triangle is still the same triangle it was */
13508 /* when it was tested and determined to be of bad quality. */
13509 /* Subsequent transformations may have made it a different triangle. */
13510 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13511 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13512 if (b->verbose > 1) {
13513 printf(" Splitting this triangle at its circumcenter:\n");
13514 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13515 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13516 }
13517
13518 errorflag = 0;
13519 /* Create a new vertex at the triangle's circumcenter. */
13520 newvertex = (vertex) poolalloc(&m->vertices);
13521 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13522
13523 /* Check whether the new vertex lies on a triangle vertex. */
13524 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13525 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13526 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13527 if (!b->quiet) {
13528 printf(
13529 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13530 newvertex[0], newvertex[1]);
13531 errorflag = 1;
13532 }
13534 } else {
13535 for (i = 2; i < 2 + m->nextras; i++) {
13536 /* Interpolate the vertex attributes at the circumcenter. */
13537 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13538 + eta * (bapex[i] - borg[i]);
13539 }
13540 /* The new vertex must be in the interior, and therefore is a */
13541 /* free vertex with a marker of zero. */
13543 setvertextype(newvertex, FREEVERTEX);
13544
13545 /* Ensure that the handle `badotri' does not represent the longest */
13546 /* edge of the triangle. This ensures that the circumcenter must */
13547 /* fall to the left of this edge, so point location will work. */
13548 /* (If the angle org-apex-dest exceeds 90 degrees, then the */
13549 /* circumcenter lies outside the org-dest edge, and eta is */
13550 /* negative. Roundoff error might prevent eta from being */
13551 /* negative when it should be, so I test eta against xi.) */
13552 if (eta < xi) {
13553 lprevself(badotri);
13554 }
13555
13556 /* Insert the circumcenter, searching from the edge of the triangle, */
13557 /* and maintain the Delaunay property of the triangulation. */
13558 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13559 1, 1);
13560 if (success == SUCCESSFULVERTEX) {
13561 if (m->steinerleft > 0) {
13562 m->steinerleft--;
13563 }
13564 } else if (success == ENCROACHINGVERTEX) {
13565 /* If the newly inserted vertex encroaches upon a subsegment, */
13566 /* delete the new vertex. */
13567 undovertex(m, b);
13568 if (b->verbose > 1) {
13569 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13570 }
13572 } else if (success == VIOLATINGVERTEX) {
13573 /* Failed to insert the new vertex, but some subsegment was */
13574 /* marked as being encroached. */
13576 } else { /* success == DUPLICATEVERTEX */
13577 /* Couldn't insert the new vertex because a vertex is already there. */
13578 if (!b->quiet) {
13579 printf(
13580 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13581 newvertex[0], newvertex[1]);
13582 errorflag = 1;
13583 }
13585 }
13586 }
13587 if (errorflag) {
13588 if (b->verbose) {
13589 printf(" The new vertex is at the circumcenter of triangle\n");
13590 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13591 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13592 }
13593 printf("This probably means that I am trying to refine triangles\n");
13594 printf(" to a smaller size than can be accommodated by the finite\n");
13595 printf(" precision of floating point arithmetic. (You can be\n");
13596 printf(" sure of this if I fail to terminate.)\n");
13598 }
13599 }
13600}
13601
13602#endif /* not CDT_ONLY */
13603
13604/*****************************************************************************/
13605/* */
13606/* enforcequality() Remove all the encroached subsegments and bad */
13607/* triangles from the triangulation. */
13608/* */
13609/*****************************************************************************/
13610
13611#ifndef CDT_ONLY
13612
13613#ifdef ANSI_DECLARATORS
13614void enforcequality(struct mesh *m, struct behavior *b)
13615#else /* not ANSI_DECLARATORS */
13616void enforcequality(m, b)
13617struct mesh *m;
13618struct behavior *b;
13619#endif /* not ANSI_DECLARATORS */
13620
13621{
13622 struct badtriang *badtri;
13623 int i;
13624
13625 if (!b->quiet) {
13626 printf("Adding Steiner points to enforce quality.\n");
13627 }
13628 /* Initialize the pool of encroached subsegments. */
13629 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13630 BADSUBSEGPERBLOCK, 0);
13631 if (b->verbose) {
13632 printf(" Looking for encroached subsegments.\n");
13633 }
13634 /* Test all segments to see if they're encroached. */
13636 if (b->verbose && (m->badsubsegs.items > 0)) {
13637 printf(" Splitting encroached subsegments.\n");
13638 }
13639 /* Fix encroached subsegments without noting bad triangles. */
13641 /* At this point, if we haven't run out of Steiner points, the */
13642 /* triangulation should be (conforming) Delaunay. */
13643
13644 /* Next, we worry about enforcing triangle quality. */
13645 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13646 /* Initialize the pool of bad triangles. */
13647 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13648 BADTRIPERBLOCK, 0);
13649 /* Initialize the queues of bad triangles. */
13650 for (i = 0; i < 4096; i++) {
13651 m->queuefront[i] = (struct badtriang *) NULL;
13652 }
13653 m->firstnonemptyq = -1;
13654 /* Test all triangles to see if they're bad. */
13655 tallyfaces(m, b);
13656 /* Initialize the pool of recently flipped triangles. */
13657 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13658 FLIPSTACKERPERBLOCK, 0);
13659 m->checkquality = 1;
13660 if (b->verbose) {
13661 printf(" Splitting bad triangles.\n");
13662 }
13663 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13664 /* Fix one bad triangle by inserting a vertex at its circumcenter. */
13667 if (m->badsubsegs.items > 0) {
13668 /* Put bad triangle back in queue for another try later. */
13670 /* Fix any encroached subsegments that resulted. */
13671 /* Record any new bad triangles that result. */
13672 splitencsegs(m, b, 1);
13673 } else {
13674 /* Return the bad triangle to the pool. */
13675 pooldealloc(&m->badtriangles, (VOID *) badtri);
13676 }
13677 }
13678 }
13679 /* At this point, if the "-D" switch was selected and we haven't run out */
13680 /* of Steiner points, the triangulation should be (conforming) Delaunay */
13681 /* and have no low-quality triangles. */
13682
13683 /* Might we have run out of Steiner points too soon? */
13684 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13685 (m->steinerleft == 0)) {
13686 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13687 if (m->badsubsegs.items == 1) {
13688 printf(" one encroached subsegment, and therefore might not be truly\n"
13689 );
13690 } else {
13691 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13692 , m->badsubsegs.items);
13693 }
13694 printf(" Delaunay. If the Delaunay property is important to you,\n");
13695 printf(" try increasing the number of Steiner points (controlled by\n");
13696 printf(" the -S switch) slightly and try again.\n\n");
13697 }
13698}
13699
13700#endif /* not CDT_ONLY */
13701
13704/********* Mesh quality maintenance ends here *********/
13705
13706/*****************************************************************************/
13707/* */
13708/* highorder() Create extra nodes for quadratic subparametric elements. */
13709/* */
13710/*****************************************************************************/
13711
13712#ifdef ANSI_DECLARATORS
13713void highorder(struct mesh *m, struct behavior *b)
13714#else /* not ANSI_DECLARATORS */
13715void highorder(m, b)
13716struct mesh *m;
13717struct behavior *b;
13718#endif /* not ANSI_DECLARATORS */
13719
13720{
13721 struct otri triangleloop, trisym;
13724 vertex torg, tdest;
13725 int i;
13726 triangle ptr; /* Temporary variable used by sym(). */
13727 subseg sptr; /* Temporary variable used by tspivot(). */
13728
13729 if (!b->quiet) {
13730 printf("Adding vertices for second-order triangles.\n");
13731 }
13732 /* The following line ensures that dead items in the pool of nodes */
13733 /* cannot be allocated for the extra nodes associated with high */
13734 /* order elements. This ensures that the primary nodes (at the */
13735 /* corners of elements) will occur earlier in the output files, and */
13736 /* have lower indices, than the extra nodes. */
13737 m->vertices.deaditemstack = (VOID *) NULL;
13738
13739 traversalinit(&m->triangles);
13741 /* To loop over the set of edges, loop over all triangles, and look at */
13742 /* the three edges of each triangle. If there isn't another triangle */
13743 /* adjacent to the edge, operate on the edge. If there is another */
13744 /* adjacent triangle, operate on the edge only if the current triangle */
13745 /* has a smaller pointer than its neighbor. This way, each edge is */
13746 /* considered only once. */
13747 while (triangleloop.tri != (triangle *) NULL) {
13748 for (triangleloop.orient = 0; triangleloop.orient < 3;
13749 triangleloop.orient++) {
13751 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13754 /* Create a new node in the middle of the edge. Interpolate */
13755 /* its attributes. */
13756 newvertex = (vertex) poolalloc(&m->vertices);
13757 for (i = 0; i < 2 + m->nextras; i++) {
13758 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13759 }
13760 /* Set the new node's marker to zero or one, depending on */
13761 /* whether it lies on a boundary. */
13762 setvertexmark(newvertex, trisym.tri == m->dummytri);
13764 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13765 if (b->usesegments) {
13767 /* If this edge is a segment, transfer the marker to the new node. */
13768 if (checkmark.ss != m->dummysub) {
13770 setvertextype(newvertex, SEGMENTVERTEX);
13771 }
13772 }
13773 if (b->verbose > 1) {
13774 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13775 }
13776 /* Record the new node in the (one or two) adjacent elements. */
13777 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13779 if (trisym.tri != m->dummytri) {
13780 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13781 }
13782 }
13783 }
13785 }
13786}
13787
13788/********* File I/O routines begin here *********/
13791
13792/*****************************************************************************/
13793/* */
13794/* readline() Read a nonempty line from a file. */
13795/* */
13796/* A line is considered "nonempty" if it contains something that looks like */
13797/* a number. Comments (prefaced by `#') are ignored. */
13798/* */
13799/*****************************************************************************/
13800
13801#ifndef TRILIBRARY
13802
13803#ifdef ANSI_DECLARATORS
13804char *readline(char *string, FILE *infile, char *infilename)
13805#else /* not ANSI_DECLARATORS */
13807char *string;
13808FILE *infile;
13810#endif /* not ANSI_DECLARATORS */
13811
13812{
13813 char *result;
13814
13815 /* Search for something that looks like a number. */
13816 do {
13817 result = fgets(string, INPUTLINESIZE, infile);
13818 if (result == (char *) NULL) {
13819 printf(" Error: Unexpected end of file in %s.\n", infilename);
13820 triexit(1);
13821 }
13822 /* Skip anything that doesn't look like a number, a comment, */
13823 /* or the end of a line. */
13824 while ((*result != '\0') && (*result != '#')
13825 && (*result != '.') && (*result != '+') && (*result != '-')
13826 && ((*result < '0') || (*result > '9'))) {
13827 result++;
13828 }
13829 /* If it's a comment or end of line, read another line and try again. */
13830 } while ((*result == '#') || (*result == '\0'));
13831 return result;
13832}
13833
13834#endif /* not TRILIBRARY */
13835
13836/*****************************************************************************/
13837/* */
13838/* findfield() Find the next field of a string. */
13839/* */
13840/* Jumps past the current field by searching for whitespace, then jumps */
13841/* past the whitespace to find the next field. */
13842/* */
13843/*****************************************************************************/
13844
13845#ifndef TRILIBRARY
13846
13847#ifdef ANSI_DECLARATORS
13848char *findfield(char *string)
13849#else /* not ANSI_DECLARATORS */
13850char *findfield(string)
13851char *string;
13852#endif /* not ANSI_DECLARATORS */
13853
13854{
13855 char *result;
13856
13857 result = string;
13858 /* Skip the current field. Stop upon reaching whitespace. */
13859 while ((*result != '\0') && (*result != '#')
13860 && (*result != ' ') && (*result != '\t')) {
13861 result++;
13862 }
13863 /* Now skip the whitespace and anything else that doesn't look like a */
13864 /* number, a comment, or the end of a line. */
13865 while ((*result != '\0') && (*result != '#')
13866 && (*result != '.') && (*result != '+') && (*result != '-')
13867 && ((*result < '0') || (*result > '9'))) {
13868 result++;
13869 }
13870 /* Check for a comment (prefixed with `#'). */
13871 if (*result == '#') {
13872 *result = '\0';
13873 }
13874 return result;
13875}
13876
13877#endif /* not TRILIBRARY */
13878
13879/*****************************************************************************/
13880/* */
13881/* readnodes() Read the vertices from a file, which may be a .node or */
13882/* .poly file. */
13883/* */
13884/*****************************************************************************/
13885
13886#ifndef TRILIBRARY
13887
13888#ifdef ANSI_DECLARATORS
13889void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13890 char *polyfilename, FILE **polyfile)
13891#else /* not ANSI_DECLARATORS */
13893struct mesh *m;
13894struct behavior *b;
13895char *nodefilename;
13896char *polyfilename;
13897FILE **polyfile;
13898#endif /* not ANSI_DECLARATORS */
13899
13900{
13901 FILE *infile;
13903 char inputline[INPUTLINESIZE];
13904 char *stringptr;
13905 char *infilename;
13906 REAL x, y;
13910 int i, j;
13911
13912 if (b->poly) {
13913 /* Read the vertices from a .poly file. */
13914 if (!b->quiet) {
13915 printf("Opening %s.\n", polyfilename);
13916 }
13917 *polyfile = fopen(polyfilename, "r");
13918 if (*polyfile == (FILE *) NULL) {
13919 printf(" Error: Cannot access file %s.\n", polyfilename);
13920 triexit(1);
13921 }
13922 /* Read number of vertices, number of dimensions, number of vertex */
13923 /* attributes, and number of boundary markers. */
13925 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13927 if (*stringptr == '\0') {
13928 m->mesh_dim = 2;
13929 } else {
13930 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13931 }
13933 if (*stringptr == '\0') {
13934 m->nextras = 0;
13935 } else {
13936 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13937 }
13939 if (*stringptr == '\0') {
13940 nodemarkers = 0;
13941 } else {
13942 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13943 }
13944 if (m->invertices > 0) {
13945 infile = *polyfile;
13947 m->readnodefile = 0;
13948 } else {
13949 /* If the .poly file claims there are zero vertices, that means that */
13950 /* the vertices should be read from a separate .node file. */
13951 m->readnodefile = 1;
13953 }
13954 } else {
13955 m->readnodefile = 1;
13957 *polyfile = (FILE *) NULL;
13958 }
13959
13960 if (m->readnodefile) {
13961 /* Read the vertices from a .node file. */
13962 if (!b->quiet) {
13963 printf("Opening %s.\n", nodefilename);
13964 }
13965 infile = fopen(nodefilename, "r");
13966 if (infile == (FILE *) NULL) {
13967 printf(" Error: Cannot access file %s.\n", nodefilename);
13968 triexit(1);
13969 }
13970 /* Read number of vertices, number of dimensions, number of vertex */
13971 /* attributes, and number of boundary markers. */
13973 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13975 if (*stringptr == '\0') {
13976 m->mesh_dim = 2;
13977 } else {
13978 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13979 }
13981 if (*stringptr == '\0') {
13982 m->nextras = 0;
13983 } else {
13984 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13985 }
13987 if (*stringptr == '\0') {
13988 nodemarkers = 0;
13989 } else {
13990 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13991 }
13992 }
13993
13994 if (m->invertices < 3) {
13995 printf("Error: Input must have at least three input vertices.\n");
13996 triexit(1);
13997 }
13998 if (m->mesh_dim != 2) {
13999 printf("Error: Triangle only works with two-dimensional meshes.\n");
14000 triexit(1);
14001 }
14002 if (m->nextras == 0) {
14003 b->weighted = 0;
14004 }
14005
14007
14008 /* Read the vertices. */
14009 for (i = 0; i < m->invertices; i++) {
14010 vertexloop = (vertex) poolalloc(&m->vertices);
14012 if (i == 0) {
14013 firstnode = (int) strtol(stringptr, &stringptr, 0);
14014 if ((firstnode == 0) || (firstnode == 1)) {
14015 b->firstnumber = firstnode;
14016 }
14017 }
14019 if (*stringptr == '\0') {
14020 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14021 triexit(1);
14022 }
14023 x = (REAL) strtod(stringptr, &stringptr);
14025 if (*stringptr == '\0') {
14026 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14027 triexit(1);
14028 }
14029 y = (REAL) strtod(stringptr, &stringptr);
14030 vertexloop[0] = x;
14031 vertexloop[1] = y;
14032 /* Read the vertex attributes. */
14033 for (j = 2; j < 2 + m->nextras; j++) {
14035 if (*stringptr == '\0') {
14036 vertexloop[j] = 0.0;
14037 } else {
14038 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14039 }
14040 }
14041 if (nodemarkers) {
14042 /* Read a vertex marker. */
14044 if (*stringptr == '\0') {
14046 } else {
14047 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14049 }
14050 } else {
14051 /* If no markers are specified in the file, they default to zero. */
14053 }
14054 setvertextype(vertexloop, INPUTVERTEX);
14055 /* Determine the smallest and largest x and y coordinates. */
14056 if (i == 0) {
14057 m->xmin = m->xmax = x;
14058 m->ymin = m->ymax = y;
14059 } else {
14060 m->xmin = (x < m->xmin) ? x : m->xmin;
14061 m->xmax = (x > m->xmax) ? x : m->xmax;
14062 m->ymin = (y < m->ymin) ? y : m->ymin;
14063 m->ymax = (y > m->ymax) ? y : m->ymax;
14064 }
14065 }
14066 if (m->readnodefile) {
14067 fclose(infile);
14068 }
14069
14070 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14071 /* Delaunay algorithm. */
14072 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14073}
14074
14075#endif /* not TRILIBRARY */
14076
14077/*****************************************************************************/
14078/* */
14079/* transfernodes() Read the vertices from memory. */
14080/* */
14081/*****************************************************************************/
14082
14083#ifdef TRILIBRARY
14084
14085#ifdef ANSI_DECLARATORS
14086void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14087 REAL *pointattriblist, int *pointmarkerlist,
14089#else /* not ANSI_DECLARATORS */
14092struct mesh *m;
14093struct behavior *b;
14094REAL *pointlist;
14095REAL *pointattriblist;
14096int *pointmarkerlist;
14097int numberofpoints;
14099#endif /* not ANSI_DECLARATORS */
14100
14101{
14103 REAL x, y;
14104 int i, j;
14106 int attribindex;
14107
14108 m->invertices = numberofpoints;
14109 m->mesh_dim = 2;
14111 m->readnodefile = 0;
14112 if (m->invertices < 3) {
14113 printf("Error: Input must have at least three input vertices.\n");
14114 triexit(1);
14115 }
14116 if (m->nextras == 0) {
14117 b->weighted = 0;
14118 }
14119
14121
14122 /* Read the vertices. */
14123 coordindex = 0;
14124 attribindex = 0;
14125 for (i = 0; i < m->invertices; i++) {
14126 vertexloop = (vertex) poolalloc(&m->vertices);
14127 /* Read the vertex coordinates. */
14128 x = vertexloop[0] = pointlist[coordindex++];
14129 y = vertexloop[1] = pointlist[coordindex++];
14130 /* Read the vertex attributes. */
14131 for (j = 0; j < numberofpointattribs; j++) {
14133 }
14134 if (pointmarkerlist != (int *) NULL) {
14135 /* Read a vertex marker. */
14137 } else {
14138 /* If no markers are specified, they default to zero. */
14140 }
14141 setvertextype(vertexloop, INPUTVERTEX);
14142 /* Determine the smallest and largest x and y coordinates. */
14143 if (i == 0) {
14144 m->xmin = m->xmax = x;
14145 m->ymin = m->ymax = y;
14146 } else {
14147 m->xmin = (x < m->xmin) ? x : m->xmin;
14148 m->xmax = (x > m->xmax) ? x : m->xmax;
14149 m->ymin = (y < m->ymin) ? y : m->ymin;
14150 m->ymax = (y > m->ymax) ? y : m->ymax;
14151 }
14152 }
14153
14154 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14155 /* Delaunay algorithm. */
14156 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14157}
14158
14159#endif /* TRILIBRARY */
14160
14161/*****************************************************************************/
14162/* */
14163/* readholes() Read the holes, and possibly regional attributes and area */
14164/* constraints, from a .poly file. */
14165/* */
14166/*****************************************************************************/
14167
14168#ifndef TRILIBRARY
14169
14170#ifdef ANSI_DECLARATORS
14171void readholes(struct mesh *m, struct behavior *b,
14172 FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14173 REAL **rlist, int *regions)
14174#else /* not ANSI_DECLARATORS */
14176struct mesh *m;
14177struct behavior *b;
14178FILE *polyfile;
14179char *polyfilename;
14180REAL **hlist;
14181int *holes;
14182REAL **rlist;
14183int *regions;
14184#endif /* not ANSI_DECLARATORS */
14185
14186{
14187 REAL *holelist;
14188 REAL *regionlist;
14189 char inputline[INPUTLINESIZE];
14190 char *stringptr;
14191 int index;
14192 int i;
14193
14194 /* Read the holes. */
14196 *holes = (int) strtol(stringptr, &stringptr, 0);
14197 if (*holes > 0) {
14198 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14199 *hlist = holelist;
14200 for (i = 0; i < 2 * *holes; i += 2) {
14203 if (*stringptr == '\0') {
14204 printf("Error: Hole %d has no x coordinate.\n",
14205 b->firstnumber + (i >> 1));
14206 triexit(1);
14207 } else {
14208 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14209 }
14211 if (*stringptr == '\0') {
14212 printf("Error: Hole %d has no y coordinate.\n",
14213 b->firstnumber + (i >> 1));
14214 triexit(1);
14215 } else {
14216 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14217 }
14218 }
14219 } else {
14220 *hlist = (REAL *) NULL;
14221 }
14222
14223#ifndef CDT_ONLY
14224 if ((b->regionattrib || b->vararea) && !b->refine) {
14225 /* Read the area constraints. */
14227 *regions = (int) strtol(stringptr, &stringptr, 0);
14228 if (*regions > 0) {
14229 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14230 *rlist = regionlist;
14231 index = 0;
14232 for (i = 0; i < *regions; i++) {
14235 if (*stringptr == '\0') {
14236 printf("Error: Region %d has no x coordinate.\n",
14237 b->firstnumber + i);
14238 triexit(1);
14239 } else {
14240 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14241 }
14243 if (*stringptr == '\0') {
14244 printf("Error: Region %d has no y coordinate.\n",
14245 b->firstnumber + i);
14246 triexit(1);
14247 } else {
14248 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14249 }
14251 if (*stringptr == '\0') {
14252 printf(
14253 "Error: Region %d has no region attribute or area constraint.\n",
14254 b->firstnumber + i);
14255 triexit(1);
14256 } else {
14257 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14258 }
14260 if (*stringptr == '\0') {
14262 } else {
14263 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14264 }
14265 index++;
14266 }
14267 }
14268 } else {
14269 /* Set `*regions' to zero to avoid an accidental free() later. */
14270 *regions = 0;
14271 *rlist = (REAL *) NULL;
14272 }
14273#endif /* not CDT_ONLY */
14274
14276}
14277
14278#endif /* not TRILIBRARY */
14279
14280/*****************************************************************************/
14281/* */
14282/* finishfile() Write the command line to the output file so the user */
14283/* can remember how the file was generated. Close the file. */
14284/* */
14285/*****************************************************************************/
14286
14287#ifndef TRILIBRARY
14288
14289#ifdef ANSI_DECLARATORS
14290void finishfile(FILE *outfile, int argc, char **argv)
14291#else /* not ANSI_DECLARATORS */
14294int argc;
14295char **argv;
14296#endif /* not ANSI_DECLARATORS */
14297
14298{
14299 int i;
14300
14301 fprintf(outfile, "# Generated by");
14302 for (i = 0; i < argc; i++) {
14303 fprintf(outfile, " ");
14304 fputs(argv[i], outfile);
14305 }
14308}
14309
14310#endif /* not TRILIBRARY */
14311
14312/*****************************************************************************/
14313/* */
14314/* writenodes() Number the vertices and write them to a .node file. */
14315/* */
14316/* To save memory, the vertex numbers are written over the boundary markers */
14317/* after the vertices are written to a file. */
14318/* */
14319/*****************************************************************************/
14320
14321#ifdef TRILIBRARY
14322
14323#ifdef ANSI_DECLARATORS
14324void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14325 REAL **pointattriblist, int **pointmarkerlist)
14326#else /* not ANSI_DECLARATORS */
14328struct mesh *m;
14329struct behavior *b;
14330REAL **pointlist;
14331REAL **pointattriblist;
14332int **pointmarkerlist;
14333#endif /* not ANSI_DECLARATORS */
14334
14335#else /* not TRILIBRARY */
14336
14337#ifdef ANSI_DECLARATORS
14338void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14339 int argc, char **argv)
14340#else /* not ANSI_DECLARATORS */
14342struct mesh *m;
14343struct behavior *b;
14344char *nodefilename;
14345int argc;
14346char **argv;
14347#endif /* not ANSI_DECLARATORS */
14348
14349#endif /* not TRILIBRARY */
14350
14351{
14352#ifdef TRILIBRARY
14353 REAL *plist;
14354 REAL *palist;
14356 int coordindex;
14357 int attribindex;
14358#else /* not TRILIBRARY */
14359 FILE *outfile;
14360#endif /* not TRILIBRARY */
14364 int i;
14365
14366 if (b->jettison) {
14367 outvertices = m->vertices.items - m->undeads;
14368 } else {
14369 outvertices = m->vertices.items;
14370 }
14371
14372#ifdef TRILIBRARY
14373 if (!b->quiet) {
14374 printf("Writing vertices.\n");
14375 }
14376 /* Allocate memory for output vertices if necessary. */
14377 if (*pointlist == (REAL *) NULL) {
14378 *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14379 }
14380 /* Allocate memory for output vertex attributes if necessary. */
14381 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14382 *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14383 sizeof(REAL)));
14384 }
14385 /* Allocate memory for output vertex markers if necessary. */
14386 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14387 *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14388 }
14392 coordindex = 0;
14393 attribindex = 0;
14394#else /* not TRILIBRARY */
14395 if (!b->quiet) {
14396 printf("Writing %s.\n", nodefilename);
14397 }
14398 outfile = fopen(nodefilename, "w");
14399 if (outfile == (FILE *) NULL) {
14400 printf(" Error: Cannot create file %s.\n", nodefilename);
14401 triexit(1);
14402 }
14403 /* Number of vertices, number of dimensions, number of vertex attributes, */
14404 /* and number of boundary markers (zero or one). */
14405 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14406 m->nextras, 1 - b->nobound);
14407#endif /* not TRILIBRARY */
14408
14409 traversalinit(&m->vertices);
14410 vertexnumber = b->firstnumber;
14412 while (vertexloop != (vertex) NULL) {
14413 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14414#ifdef TRILIBRARY
14415 /* X and y coordinates. */
14416 plist[coordindex++] = vertexloop[0];
14417 plist[coordindex++] = vertexloop[1];
14418 /* Vertex attributes. */
14419 for (i = 0; i < m->nextras; i++) {
14420 palist[attribindex++] = vertexloop[2 + i];
14421 }
14422 if (!b->nobound) {
14423 /* Copy the boundary marker. */
14424 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14425 }
14426#else /* not TRILIBRARY */
14427 /* Vertex number, x and y coordinates. */
14428 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14429 vertexloop[1]);
14430 for (i = 0; i < m->nextras; i++) {
14431 /* Write an attribute. */
14432 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14433 }
14434 if (b->nobound) {
14435 fprintf(outfile, "\n");
14436 } else {
14437 /* Write the boundary marker. */
14438 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14439 }
14440#endif /* not TRILIBRARY */
14441
14443 vertexnumber++;
14444 }
14446 }
14447
14448#ifndef TRILIBRARY
14450#endif /* not TRILIBRARY */
14451}
14452
14453/*****************************************************************************/
14454/* */
14455/* numbernodes() Number the vertices. */
14456/* */
14457/* Each vertex is assigned a marker equal to its number. */
14458/* */
14459/* Used when writenodes() is not called because no .node file is written. */
14460/* */
14461/*****************************************************************************/
14462
14463#ifdef ANSI_DECLARATORS
14464void numbernodes(struct mesh *m, struct behavior *b)
14465#else /* not ANSI_DECLARATORS */
14466void numbernodes(m, b)
14467struct mesh *m;
14468struct behavior *b;
14469#endif /* not ANSI_DECLARATORS */
14470
14471{
14473 int vertexnumber;
14474
14475 traversalinit(&m->vertices);
14476 vertexnumber = b->firstnumber;
14478 while (vertexloop != (vertex) NULL) {
14480 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14481 vertexnumber++;
14482 }
14484 }
14485}
14486
14487/*****************************************************************************/
14488/* */
14489/* writeelements() Write the triangles to an .ele file. */
14490/* */
14491/*****************************************************************************/
14492
14493#ifdef TRILIBRARY
14494
14495#ifdef ANSI_DECLARATORS
14496void writeelements(struct mesh *m, struct behavior *b,
14497 int **trianglelist, REAL **triangleattriblist)
14498#else /* not ANSI_DECLARATORS */
14500struct mesh *m;
14501struct behavior *b;
14502int **trianglelist;
14503REAL **triangleattriblist;
14504#endif /* not ANSI_DECLARATORS */
14505
14506#else /* not TRILIBRARY */
14507
14508#ifdef ANSI_DECLARATORS
14509void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14510 int argc, char **argv)
14511#else /* not ANSI_DECLARATORS */
14513struct mesh *m;
14514struct behavior *b;
14515char *elefilename;
14516int argc;
14517char **argv;
14518#endif /* not ANSI_DECLARATORS */
14519
14520#endif /* not TRILIBRARY */
14521
14522{
14523#ifdef TRILIBRARY
14524 int *tlist;
14525 REAL *talist;
14526 int vertexindex;
14527 int attribindex;
14528#else /* not TRILIBRARY */
14529 FILE *outfile;
14530#endif /* not TRILIBRARY */
14531 struct otri triangleloop;
14534 long elementnumber;
14535 int i;
14536
14537#ifdef TRILIBRARY
14538 if (!b->quiet) {
14539 printf("Writing triangles.\n");
14540 }
14541 /* Allocate memory for output triangles if necessary. */
14542 if (*trianglelist == (int *) NULL) {
14543 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14544 ((b->order + 1) * (b->order + 2) /
14545 2) * sizeof(int)));
14546 }
14547 /* Allocate memory for output triangle attributes if necessary. */
14548 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14549 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14550 m->eextras *
14551 sizeof(REAL)));
14552 }
14555 vertexindex = 0;
14556 attribindex = 0;
14557#else /* not TRILIBRARY */
14558 if (!b->quiet) {
14559 printf("Writing %s.\n", elefilename);
14560 }
14561 outfile = fopen(elefilename, "w");
14562 if (outfile == (FILE *) NULL) {
14563 printf(" Error: Cannot create file %s.\n", elefilename);
14564 triexit(1);
14565 }
14566 /* Number of triangles, vertices per triangle, attributes per triangle. */
14567 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14568 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14569#endif /* not TRILIBRARY */
14570
14571 traversalinit(&m->triangles);
14573 triangleloop.orient = 0;
14574 elementnumber = b->firstnumber;
14575 while (triangleloop.tri != (triangle *) NULL) {
14579 if (b->order == 1) {
14580#ifdef TRILIBRARY
14581 tlist[vertexindex++] = vertexmark(p1);
14582 tlist[vertexindex++] = vertexmark(p2);
14583 tlist[vertexindex++] = vertexmark(p3);
14584#else /* not TRILIBRARY */
14585 /* Triangle number, indices for three vertices. */
14586 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14587 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14588#endif /* not TRILIBRARY */
14589 } else {
14590 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14591 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14592 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14593#ifdef TRILIBRARY
14594 tlist[vertexindex++] = vertexmark(p1);
14595 tlist[vertexindex++] = vertexmark(p2);
14596 tlist[vertexindex++] = vertexmark(p3);
14597 tlist[vertexindex++] = vertexmark(mid1);
14598 tlist[vertexindex++] = vertexmark(mid2);
14599 tlist[vertexindex++] = vertexmark(mid3);
14600#else /* not TRILIBRARY */
14601 /* Triangle number, indices for six vertices. */
14602 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14603 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14604 vertexmark(mid2), vertexmark(mid3));
14605#endif /* not TRILIBRARY */
14606 }
14607
14608#ifdef TRILIBRARY
14609 for (i = 0; i < m->eextras; i++) {
14610 talist[attribindex++] = elemattribute(triangleloop, i);
14611 }
14612#else /* not TRILIBRARY */
14613 for (i = 0; i < m->eextras; i++) {
14614 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14615 }
14616 fprintf(outfile, "\n");
14617#endif /* not TRILIBRARY */
14618
14620 elementnumber++;
14621 }
14622
14623#ifndef TRILIBRARY
14625#endif /* not TRILIBRARY */
14626}
14627
14628/*****************************************************************************/
14629/* */
14630/* writepoly() Write the segments and holes to a .poly file. */
14631/* */
14632/*****************************************************************************/
14633
14634#ifdef TRILIBRARY
14635
14636#ifdef ANSI_DECLARATORS
14637void writepoly(struct mesh *m, struct behavior *b,
14638 int **segmentlist, int **segmentmarkerlist)
14639#else /* not ANSI_DECLARATORS */
14641struct mesh *m;
14642struct behavior *b;
14643int **segmentlist;
14644int **segmentmarkerlist;
14645#endif /* not ANSI_DECLARATORS */
14646
14647#else /* not TRILIBRARY */
14648
14649#ifdef ANSI_DECLARATORS
14650void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14651 REAL *holelist, int holes, REAL *regionlist, int regions,
14652 int argc, char **argv)
14653#else /* not ANSI_DECLARATORS */
14655 argc, argv)
14656struct mesh *m;
14657struct behavior *b;
14658char *polyfilename;
14659REAL *holelist;
14660int holes;
14661REAL *regionlist;
14662int regions;
14663int argc;
14664char **argv;
14665#endif /* not ANSI_DECLARATORS */
14666
14667#endif /* not TRILIBRARY */
14668
14669{
14670#ifdef TRILIBRARY
14671 int *slist;
14673 int index;
14674#else /* not TRILIBRARY */
14675 FILE *outfile;
14677#endif /* not TRILIBRARY */
14678 struct osub subsegloop;
14681
14682#ifdef TRILIBRARY
14683 if (!b->quiet) {
14684 printf("Writing segments.\n");
14685 }
14686 /* Allocate memory for output segments if necessary. */
14687 if (*segmentlist == (int *) NULL) {
14688 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14689 sizeof(int)));
14690 }
14691 /* Allocate memory for output segment markers if necessary. */
14692 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14693 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14694 sizeof(int)));
14695 }
14698 index = 0;
14699#else /* not TRILIBRARY */
14700 if (!b->quiet) {
14701 printf("Writing %s.\n", polyfilename);
14702 }
14703 outfile = fopen(polyfilename, "w");
14704 if (outfile == (FILE *) NULL) {
14705 printf(" Error: Cannot create file %s.\n", polyfilename);
14706 triexit(1);
14707 }
14708 /* The zero indicates that the vertices are in a separate .node file. */
14709 /* Followed by number of dimensions, number of vertex attributes, */
14710 /* and number of boundary markers (zero or one). */
14711 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14712 1 - b->nobound);
14713 /* Number of segments, number of boundary markers (zero or one). */
14714 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14715#endif /* not TRILIBRARY */
14716
14717 traversalinit(&m->subsegs);
14719 subsegloop.ssorient = 0;
14720 subsegnumber = b->firstnumber;
14721 while (subsegloop.ss != (subseg *) NULL) {
14722 sorg(subsegloop, endpoint1);
14723 sdest(subsegloop, endpoint2);
14724#ifdef TRILIBRARY
14725 /* Copy indices of the segment's two endpoints. */
14726 slist[index++] = vertexmark(endpoint1);
14727 slist[index++] = vertexmark(endpoint2);
14728 if (!b->nobound) {
14729 /* Copy the boundary marker. */
14730 smlist[subsegnumber - b->firstnumber] = markT(subsegloop);
14731 }
14732#else /* not TRILIBRARY */
14733 /* Segment number, indices of its two endpoints, and possibly a marker. */
14734 if (b->nobound) {
14735 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14736 vertexmark(endpoint1), vertexmark(endpoint2));
14737 } else {
14738 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14739 vertexmark(endpoint1), vertexmark(endpoint2), markT(subsegloop));
14740 }
14741#endif /* not TRILIBRARY */
14742
14744 subsegnumber++;
14745 }
14746
14747#ifndef TRILIBRARY
14748#ifndef CDT_ONLY
14750 if (holes > 0) {
14751 for (holenumber = 0; holenumber < holes; holenumber++) {
14752 /* Hole number, x and y coordinates. */
14753 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14754 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14755 }
14756 }
14757 if (regions > 0) {
14758 fprintf(outfile, "%d\n", regions);
14760 /* Region number, x and y coordinates, attribute, maximum area. */
14761 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14762 b->firstnumber + regionnumber,
14764 regionlist[4 * regionnumber + 2],
14765 regionlist[4 * regionnumber + 3]);
14766 }
14767 }
14768#endif /* not CDT_ONLY */
14769
14771#endif /* not TRILIBRARY */
14772}
14773
14774/*****************************************************************************/
14775/* */
14776/* writeedges() Write the edges to an .edge file. */
14777/* */
14778/*****************************************************************************/
14779
14780#ifdef TRILIBRARY
14781
14782#ifdef ANSI_DECLARATORS
14783void writeedges(struct mesh *m, struct behavior *b,
14784 int **edgelist, int **edgemarkerlist)
14785#else /* not ANSI_DECLARATORS */
14787struct mesh *m;
14788struct behavior *b;
14789int **edgelist;
14791#endif /* not ANSI_DECLARATORS */
14792
14793#else /* not TRILIBRARY */
14794
14795#ifdef ANSI_DECLARATORS
14796void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14797 int argc, char **argv)
14798#else /* not ANSI_DECLARATORS */
14800struct mesh *m;
14801struct behavior *b;
14802char *edgefilename;
14803int argc;
14804char **argv;
14805#endif /* not ANSI_DECLARATORS */
14806
14807#endif /* not TRILIBRARY */
14808
14809{
14810#ifdef TRILIBRARY
14811 int *elist;
14813 int index;
14814#else /* not TRILIBRARY */
14815 FILE *outfile;
14816#endif /* not TRILIBRARY */
14818 struct osub checkmark;
14819 vertex p1, p2;
14821 triangle ptr; /* Temporary variable used by sym(). */
14822 subseg sptr; /* Temporary variable used by tspivot(). */
14823
14824#ifdef TRILIBRARY
14825 if (!b->quiet) {
14826 printf("Writing edges.\n");
14827 }
14828 /* Allocate memory for edges if necessary. */
14829 if (*edgelist == (int *) NULL) {
14830 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14831 }
14832 /* Allocate memory for edge markers if necessary. */
14833 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14834 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14835 }
14838 index = 0;
14839#else /* not TRILIBRARY */
14840 if (!b->quiet) {
14841 printf("Writing %s.\n", edgefilename);
14842 }
14843 outfile = fopen(edgefilename, "w");
14844 if (outfile == (FILE *) NULL) {
14845 printf(" Error: Cannot create file %s.\n", edgefilename);
14846 triexit(1);
14847 }
14848 /* Number of edges, number of boundary markers (zero or one). */
14849 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14850#endif /* not TRILIBRARY */
14851
14852 traversalinit(&m->triangles);
14854 edgenumber = b->firstnumber;
14855 /* To loop over the set of edges, loop over all triangles, and look at */
14856 /* the three edges of each triangle. If there isn't another triangle */
14857 /* adjacent to the edge, operate on the edge. If there is another */
14858 /* adjacent triangle, operate on the edge only if the current triangle */
14859 /* has a smaller pointer than its neighbor. This way, each edge is */
14860 /* considered only once. */
14861 while (triangleloop.tri != (triangle *) NULL) {
14862 for (triangleloop.orient = 0; triangleloop.orient < 3;
14863 triangleloop.orient++) {
14865 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14868#ifdef TRILIBRARY
14869 elist[index++] = vertexmark(p1);
14870 elist[index++] = vertexmark(p2);
14871#endif /* TRILIBRARY */
14872 if (b->nobound) {
14873#ifndef TRILIBRARY
14874 /* Edge number, indices of two endpoints. */
14875 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14876 vertexmark(p1), vertexmark(p2));
14877#endif /* not TRILIBRARY */
14878 } else {
14879 /* Edge number, indices of two endpoints, and a boundary marker. */
14880 /* If there's no subsegment, the boundary marker is zero. */
14881 if (b->usesegments) {
14883 if (checkmark.ss == m->dummysub) {
14884#ifdef TRILIBRARY
14885 emlist[edgenumber - b->firstnumber] = 0;
14886#else /* not TRILIBRARY */
14887 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14888 vertexmark(p1), vertexmark(p2), 0);
14889#endif /* not TRILIBRARY */
14890 } else {
14891#ifdef TRILIBRARY
14892 emlist[edgenumber - b->firstnumber] = markT(checkmark);
14893#else /* not TRILIBRARY */
14894 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14895 vertexmark(p1), vertexmark(p2), markT(checkmark));
14896#endif /* not TRILIBRARY */
14897 }
14898 } else {
14899#ifdef TRILIBRARY
14900 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14901#else /* not TRILIBRARY */
14902 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14903 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14904#endif /* not TRILIBRARY */
14905 }
14906 }
14907 edgenumber++;
14908 }
14909 }
14911 }
14912
14913#ifndef TRILIBRARY
14915#endif /* not TRILIBRARY */
14916}
14917
14918/*****************************************************************************/
14919/* */
14920/* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */
14921/* file. */
14922/* */
14923/* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
14924/* Hence, the Voronoi vertices are listed by traversing the Delaunay */
14925/* triangles, and the Voronoi edges are listed by traversing the Delaunay */
14926/* edges. */
14927/* */
14928/* WARNING: In order to assign numbers to the Voronoi vertices, this */
14929/* procedure messes up the subsegments or the extra nodes of every */
14930/* element. Hence, you should call this procedure last. */
14931/* */
14932/*****************************************************************************/
14933
14934#ifdef TRILIBRARY
14935
14936#ifdef ANSI_DECLARATORS
14937void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14938 REAL **vpointattriblist, int **vpointmarkerlist,
14939 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14940#else /* not ANSI_DECLARATORS */
14943struct mesh *m;
14944struct behavior *b;
14945REAL **vpointlist;
14946REAL **vpointattriblist;
14947int **vpointmarkerlist;
14948int **vedgelist;
14949int **vedgemarkerlist;
14951#endif /* not ANSI_DECLARATORS */
14952
14953#else /* not TRILIBRARY */
14954
14955#ifdef ANSI_DECLARATORS
14956void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14957 char *vedgefilename, int argc, char **argv)
14958#else /* not ANSI_DECLARATORS */
14960struct mesh *m;
14961struct behavior *b;
14962char *vnodefilename;
14963char *vedgefilename;
14964int argc;
14965char **argv;
14966#endif /* not ANSI_DECLARATORS */
14967
14968#endif /* not TRILIBRARY */
14969
14970{
14971#ifdef TRILIBRARY
14972 REAL *plist;
14973 REAL *palist;
14974 int *elist;
14976 int coordindex;
14977 int attribindex;
14978#else /* not TRILIBRARY */
14979 FILE *outfile;
14980#endif /* not TRILIBRARY */
14981 struct otri triangleloop, trisym;
14983 REAL circumcenter[2];
14984 REAL xi, eta;
14986 int p1, p2;
14987 int i;
14988 triangle ptr; /* Temporary variable used by sym(). */
14989
14990#ifdef TRILIBRARY
14991 if (!b->quiet) {
14992 printf("Writing Voronoi vertices.\n");
14993 }
14994 /* Allocate memory for Voronoi vertices if necessary. */
14995 if (*vpointlist == (REAL *) NULL) {
14996 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
14997 sizeof(REAL)));
14998 }
14999 /* Allocate memory for Voronoi vertex attributes if necessary. */
15000 if (*vpointattriblist == (REAL *) NULL) {
15001 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15002 m->nextras * sizeof(REAL)));
15003 }
15004 *vpointmarkerlist = (int *) NULL;
15005 plist = *vpointlist;
15007 coordindex = 0;
15008 attribindex = 0;
15009#else /* not TRILIBRARY */
15010 if (!b->quiet) {
15011 printf("Writing %s.\n", vnodefilename);
15012 }
15013 outfile = fopen(vnodefilename, "w");
15014 if (outfile == (FILE *) NULL) {
15015 printf(" Error: Cannot create file %s.\n", vnodefilename);
15016 triexit(1);
15017 }
15018 /* Number of triangles, two dimensions, number of vertex attributes, */
15019 /* no markers. */
15020 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15021#endif /* not TRILIBRARY */
15022
15023 traversalinit(&m->triangles);
15025 triangleloop.orient = 0;
15026 vnodenumber = b->firstnumber;
15027 while (triangleloop.tri != (triangle *) NULL) {
15031 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15032#ifdef TRILIBRARY
15033 /* X and y coordinates. */
15036 for (i = 2; i < 2 + m->nextras; i++) {
15037 /* Interpolate the vertex attributes at the circumcenter. */
15038 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15039 + eta * (tapex[i] - torg[i]);
15040 }
15041#else /* not TRILIBRARY */
15042 /* Voronoi vertex number, x and y coordinates. */
15043 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15044 circumcenter[1]);
15045 for (i = 2; i < 2 + m->nextras; i++) {
15046 /* Interpolate the vertex attributes at the circumcenter. */
15047 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15048 + eta * (tapex[i] - torg[i]));
15049 }
15050 fprintf(outfile, "\n");
15051#endif /* not TRILIBRARY */
15052
15053 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15055 vnodenumber++;
15056 }
15057
15058#ifndef TRILIBRARY
15060#endif /* not TRILIBRARY */
15061
15062#ifdef TRILIBRARY
15063 if (!b->quiet) {
15064 printf("Writing Voronoi edges.\n");
15065 }
15066 /* Allocate memory for output Voronoi edges if necessary. */
15067 if (*vedgelist == (int *) NULL) {
15068 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15069 }
15070 *vedgemarkerlist = (int *) NULL;
15071 /* Allocate memory for output Voronoi norms if necessary. */
15072 if (*vnormlist == (REAL *) NULL) {
15073 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15074 }
15075 elist = *vedgelist;
15077 coordindex = 0;
15078#else /* not TRILIBRARY */
15079 if (!b->quiet) {
15080 printf("Writing %s.\n", vedgefilename);
15081 }
15082 outfile = fopen(vedgefilename, "w");
15083 if (outfile == (FILE *) NULL) {
15084 printf(" Error: Cannot create file %s.\n", vedgefilename);
15085 triexit(1);
15086 }
15087 /* Number of edges, zero boundary markers. */
15088 fprintf(outfile, "%ld %d\n", m->edges, 0);
15089#endif /* not TRILIBRARY */
15090
15091 traversalinit(&m->triangles);
15093 vedgenumber = b->firstnumber;
15094 /* To loop over the set of edges, loop over all triangles, and look at */
15095 /* the three edges of each triangle. If there isn't another triangle */
15096 /* adjacent to the edge, operate on the edge. If there is another */
15097 /* adjacent triangle, operate on the edge only if the current triangle */
15098 /* has a smaller pointer than its neighbor. This way, each edge is */
15099 /* considered only once. */
15100 while (triangleloop.tri != (triangle *) NULL) {
15101 for (triangleloop.orient = 0; triangleloop.orient < 3;
15102 triangleloop.orient++) {
15104 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15105 /* Find the number of this triangle (and Voronoi vertex). */
15106 p1 = * (int *) (triangleloop.tri + 6);
15107 if (trisym.tri == m->dummytri) {
15110#ifdef TRILIBRARY
15111 /* Copy an infinite ray. Index of one endpoint, and -1. */
15112 elist[coordindex] = p1;
15113 normlist[coordindex++] = tdest[1] - torg[1];
15114 elist[coordindex] = -1;
15115 normlist[coordindex++] = torg[0] - tdest[0];
15116#else /* not TRILIBRARY */
15117 /* Write an infinite ray. Edge number, index of one endpoint, -1, */
15118 /* and x and y coordinates of a vector representing the */
15119 /* direction of the ray. */
15120 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15121 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15122#endif /* not TRILIBRARY */
15123 } else {
15124 /* Find the number of the adjacent triangle (and Voronoi vertex). */
15125 p2 = * (int *) (trisym.tri + 6);
15126 /* Finite edge. Write indices of two endpoints. */
15127#ifdef TRILIBRARY
15128 elist[coordindex] = p1;
15129 normlist[coordindex++] = 0.0;
15130 elist[coordindex] = p2;
15131 normlist[coordindex++] = 0.0;
15132#else /* not TRILIBRARY */
15133 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15134#endif /* not TRILIBRARY */
15135 }
15136 vedgenumber++;
15137 }
15138 }
15140 }
15141
15142#ifndef TRILIBRARY
15144#endif /* not TRILIBRARY */
15145}
15146
15147#ifdef TRILIBRARY
15148
15149#ifdef ANSI_DECLARATORS
15150void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15151#else /* not ANSI_DECLARATORS */
15153struct mesh *m;
15154struct behavior *b;
15156#endif /* not ANSI_DECLARATORS */
15157
15158#else /* not TRILIBRARY */
15159
15160#ifdef ANSI_DECLARATORS
15161void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15162 int argc, char **argv)
15163#else /* not ANSI_DECLARATORS */
15165struct mesh *m;
15166struct behavior *b;
15167char *neighborfilename;
15168int argc;
15169char **argv;
15170#endif /* not ANSI_DECLARATORS */
15171
15172#endif /* not TRILIBRARY */
15173
15174{
15175#ifdef TRILIBRARY
15176 int *nlist;
15177 int index;
15178#else /* not TRILIBRARY */
15179 FILE *outfile;
15180#endif /* not TRILIBRARY */
15181 struct otri triangleloop, trisym;
15182 long elementnumber;
15184 triangle ptr; /* Temporary variable used by sym(). */
15185
15186#ifdef TRILIBRARY
15187 if (!b->quiet) {
15188 printf("Writing neighbors.\n");
15189 }
15190 /* Allocate memory for neighbors if necessary. */
15191 if (*neighborlist == (int *) NULL) {
15192 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15193 sizeof(int)));
15194 }
15196 index = 0;
15197#else /* not TRILIBRARY */
15198 if (!b->quiet) {
15199 printf("Writing %s.\n", neighborfilename);
15200 }
15201 outfile = fopen(neighborfilename, "w");
15202 if (outfile == (FILE *) NULL) {
15203 printf(" Error: Cannot create file %s.\n", neighborfilename);
15204 triexit(1);
15205 }
15206 /* Number of triangles, three neighbors per triangle. */
15207 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15208#endif /* not TRILIBRARY */
15209
15210 traversalinit(&m->triangles);
15212 triangleloop.orient = 0;
15213 elementnumber = b->firstnumber;
15214 while (triangleloop.tri != (triangle *) NULL) {
15215 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15217 elementnumber++;
15218 }
15219 * (int *) (m->dummytri + 6) = -1;
15220
15221 traversalinit(&m->triangles);
15223 elementnumber = b->firstnumber;
15224 while (triangleloop.tri != (triangle *) NULL) {
15225 triangleloop.orient = 1;
15227 neighbor1 = * (int *) (trisym.tri + 6);
15228 triangleloop.orient = 2;
15230 neighbor2 = * (int *) (trisym.tri + 6);
15231 triangleloop.orient = 0;
15233 neighbor3 = * (int *) (trisym.tri + 6);
15234#ifdef TRILIBRARY
15235 nlist[index++] = neighbor1;
15236 nlist[index++] = neighbor2;
15237 nlist[index++] = neighbor3;
15238#else /* not TRILIBRARY */
15239 /* Triangle number, neighboring triangle numbers. */
15240 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15242#endif /* not TRILIBRARY */
15243
15245 elementnumber++;
15246 }
15247
15248#ifndef TRILIBRARY
15250#endif /* not TRILIBRARY */
15251}
15252
15253/*****************************************************************************/
15254/* */
15255/* writeoff() Write the triangulation to an .off file. */
15256/* */
15257/* OFF stands for the Object File Format, a format used by the Geometry */
15258/* Center's Geomview package. */
15259/* */
15260/*****************************************************************************/
15261
15262#ifndef TRILIBRARY
15263
15264#ifdef ANSI_DECLARATORS
15265void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15266 int argc, char **argv)
15267#else /* not ANSI_DECLARATORS */
15269struct mesh *m;
15270struct behavior *b;
15271char *offfilename;
15272int argc;
15273char **argv;
15274#endif /* not ANSI_DECLARATORS */
15275
15276{
15277 FILE *outfile;
15278 struct otri triangleloop;
15280 vertex p1, p2, p3;
15281 long outvertices;
15282
15283 if (!b->quiet) {
15284 printf("Writing %s.\n", offfilename);
15285 }
15286
15287 if (b->jettison) {
15288 outvertices = m->vertices.items - m->undeads;
15289 } else {
15290 outvertices = m->vertices.items;
15291 }
15292
15293 outfile = fopen(offfilename, "w");
15294 if (outfile == (FILE *) NULL) {
15295 printf(" Error: Cannot create file %s.\n", offfilename);
15296 triexit(1);
15297 }
15298 /* Number of vertices, triangles, and edges. */
15299 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15300 m->edges);
15301
15302 /* Write the vertices. */
15303 traversalinit(&m->vertices);
15305 while (vertexloop != (vertex) NULL) {
15306 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15307 /* The "0.0" is here because the OFF format uses 3D coordinates. */
15308 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15309 0.0);
15310 }
15312 }
15313
15314 /* Write the triangles. */
15315 traversalinit(&m->triangles);
15317 triangleloop.orient = 0;
15318 while (triangleloop.tri != (triangle *) NULL) {
15322 /* The "3" means a three-vertex polygon. */
15323 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15324 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15326 }
15328}
15329
15330#endif /* not TRILIBRARY */
15331
15334/********* File I/O routines end here *********/
15335
15336/*****************************************************************************/
15337/* */
15338/* quality_statistics() Print statistics about the quality of the mesh. */
15339/* */
15340/*****************************************************************************/
15341
15342#ifdef ANSI_DECLARATORS
15343void quality_statistics(struct mesh *m, struct behavior *b)
15344#else /* not ANSI_DECLARATORS */
15345void quality_statistics(m, b)
15346struct mesh *m;
15347struct behavior *b;
15348#endif /* not ANSI_DECLARATORS */
15349
15350{
15351 struct otri triangleloop;
15354 REAL ratiotable[16];
15355 REAL dx[3], dy[3];
15356 REAL edgelength[3];
15357 REAL dotproduct;
15369 int angletable[18];
15374 int i, ii, j, k;
15375
15376 printf("Mesh quality statistics:\n\n");
15377 radconst = PI / 18.0;
15378 degconst = 180.0 / PI;
15379 for (i = 0; i < 8; i++) {
15380 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15382 }
15383 for (i = 0; i < 18; i++) {
15384 angletable[i] = 0;
15385 }
15386
15387 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15388 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15389 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15390 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15391 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15392 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15393 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15394 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15395 for (i = 0; i < 16; i++) {
15396 aspecttable[i] = 0;
15397 }
15398
15399 worstaspect = 0.0;
15400 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15403 longest = 0.0;
15405 biggestarea = 0.0;
15406 worstaspect = 0.0;
15407 smallestangle = 0.0;
15408 biggestangle = 2.0;
15409 acutebiggest = 1;
15410
15411 traversalinit(&m->triangles);
15413 triangleloop.orient = 0;
15414 while (triangleloop.tri != (triangle *) NULL) {
15415 org(triangleloop, p[0]);
15416 destT(triangleloop, p[1]);
15417 apex(triangleloop, p[2]);
15418 trilongest2 = 0.0;
15419
15420 for (i = 0; i < 3; i++) {
15421 j = plus1mod3[i];
15422 k = minus1mod3[i];
15423 dx[i] = p[j][0] - p[k][0];
15424 dy[i] = p[j][1] - p[k][1];
15425 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15426 if (edgelength[i] > trilongest2) {
15428 }
15429 if (edgelength[i] > longest) {
15430 longest = edgelength[i];
15431 }
15432 if (edgelength[i] < shortest) {
15434 }
15435 }
15436
15437 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15438 if (triarea < smallestarea) {
15440 }
15441 if (triarea > biggestarea) {
15443 }
15447 }
15449 if (triaspect2 > worstaspect) {
15451 }
15452 aspectindex = 0;
15454 && (aspectindex < 15)) {
15455 aspectindex++;
15456 }
15458
15459 for (i = 0; i < 3; i++) {
15460 j = plus1mod3[i];
15461 k = minus1mod3[i];
15462 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15464 tendegree = 8;
15465 for (ii = 7; ii >= 0; ii--) {
15466 if (cossquare > cossquaretable[ii]) {
15467 tendegree = ii;
15468 }
15469 }
15470 if (dotproduct <= 0.0) {
15472 if (cossquare > smallestangle) {
15474 }
15475 if (acutebiggest && (cossquare < biggestangle)) {
15477 }
15478 } else {
15479 angletable[17 - tendegree]++;
15480 if (acutebiggest || (cossquare > biggestangle)) {
15482 acutebiggest = 0;
15483 }
15484 }
15485 }
15487 }
15488
15489 shortest = sqrt(shortest);
15490 longest = sqrt(longest);
15491 minaltitude = sqrt(minaltitude);
15492 worstaspect = sqrt(worstaspect);
15493 smallestarea *= 0.5;
15494 biggestarea *= 0.5;
15495 if (smallestangle >= 1.0) {
15496 smallestangle = 0.0;
15497 } else {
15498 smallestangle = degconst * acos(sqrt(smallestangle));
15499 }
15500 if (biggestangle >= 1.0) {
15501 biggestangle = 180.0;
15502 } else {
15503 if (acutebiggest) {
15504 biggestangle = degconst * acos(sqrt(biggestangle));
15505 } else {
15506 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15507 }
15508 }
15509
15510 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15512 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15513 shortest, longest);
15514 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15516
15517 printf(" Triangle aspect ratio histogram:\n");
15518 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15520 aspecttable[8]);
15521 for (i = 1; i < 7; i++) {
15522 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15524 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15525 }
15526 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15528 aspecttable[15]);
15529 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15530
15531 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15533
15534 printf(" Angle histogram:\n");
15535 for (i = 0; i < 9; i++) {
15536 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15537 i * 10, i * 10 + 10, angletable[i],
15538 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15539 }
15540 printf("\n");
15541}
15542
15543/*****************************************************************************/
15544/* */
15545/* statistics() Print all sorts of cool facts. */
15546/* */
15547/*****************************************************************************/
15548
15549#ifdef ANSI_DECLARATORS
15550void statistics(struct mesh *m, struct behavior *b)
15551#else /* not ANSI_DECLARATORS */
15552void statistics(m, b)
15553struct mesh *m;
15554struct behavior *b;
15555#endif /* not ANSI_DECLARATORS */
15556
15557{
15558 printf("\nStatistics:\n\n");
15559 printf(" Input vertices: %d\n", m->invertices);
15560 if (b->refine) {
15561 printf(" Input triangles: %d\n", m->inelements);
15562 }
15563 if (b->poly) {
15564 printf(" Input segments: %d\n", m->insegments);
15565 if (!b->refine) {
15566 printf(" Input holes: %d\n", m->holes);
15567 }
15568 }
15569
15570 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15571 printf(" Mesh triangles: %ld\n", m->triangles.items);
15572 printf(" Mesh edges: %ld\n", m->edges);
15573 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15574 if (b->poly || b->refine) {
15575 printf(" Mesh interior boundary edges: %ld\n",
15576 m->subsegs.items - m->hullsize);
15577 printf(" Mesh subsegments (constrained edges): %ld\n",
15578 m->subsegs.items);
15579 }
15580 printf("\n");
15581
15582 if (b->verbose) {
15584 printf("Memory allocation statistics:\n\n");
15585 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15586 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15587 if (m->subsegs.maxitems > 0) {
15588 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15589 }
15590 if (m->viri.maxitems > 0) {
15591 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15592 }
15593 if (m->badsubsegs.maxitems > 0) {
15594 printf(" Maximum number of encroached subsegments: %ld\n",
15595 m->badsubsegs.maxitems);
15596 }
15597 if (m->badtriangles.maxitems > 0) {
15598 printf(" Maximum number of bad triangles: %ld\n",
15599 m->badtriangles.maxitems);
15600 }
15601 if (m->flipstackers.maxitems > 0) {
15602 printf(" Maximum number of stacked triangle flips: %ld\n",
15603 m->flipstackers.maxitems);
15604 }
15605 if (m->splaynodes.maxitems > 0) {
15606 printf(" Maximum number of splay tree nodes: %ld\n",
15607 m->splaynodes.maxitems);
15608 }
15609 printf(" Approximate heap memory use (bytes): %ld\n\n",
15610 m->vertices.maxitems * m->vertices.itembytes +
15611 m->triangles.maxitems * m->triangles.itembytes +
15612 m->subsegs.maxitems * m->subsegs.itembytes +
15613 m->viri.maxitems * m->viri.itembytes +
15614 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15615 m->badtriangles.maxitems * m->badtriangles.itembytes +
15616 m->flipstackers.maxitems * m->flipstackers.itembytes +
15617 m->splaynodes.maxitems * m->splaynodes.itembytes);
15618
15619 printf("Algorithmic statistics:\n\n");
15620 if (!b->weighted) {
15621 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15622 } else {
15623 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15624 }
15625 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15626 if (m->hyperbolacount > 0) {
15627 printf(" Number of right-of-hyperbola tests: %ld\n",
15628 m->hyperbolacount);
15629 }
15630 if (m->circletopcount > 0) {
15631 printf(" Number of circle top computations: %ld\n",
15632 m->circletopcount);
15633 }
15634 if (m->circumcentercount > 0) {
15635 printf(" Number of triangle circumcenter computations: %ld\n",
15636 m->circumcentercount);
15637 }
15638 printf("\n");
15639 }
15640}
15641
15642/*****************************************************************************/
15643/* */
15644/* main() or triangulate() Gosh, do everything. */
15645/* */
15646/* The sequence is roughly as follows. Many of these steps can be skipped, */
15647/* depending on the command line switches. */
15648/* */
15649/* - Initialize constants and parse the command line. */
15650/* - Read the vertices from a file and either */
15651/* - triangulate them (no -r), or */
15652/* - read an old mesh from files and reconstruct it (-r). */
15653/* - Insert the PSLG segments (-p), and possibly segments on the convex */
15654/* hull (-c). */
15655/* - Read the holes (-p), regional attributes (-pA), and regional area */
15656/* constraints (-pa). Carve the holes and concavities, and spread the */
15657/* regional attributes and area constraints. */
15658/* - Enforce the constraints on minimum angle (-q) and maximum area (-a). */
15659/* Also enforce the conforming Delaunay property (-q and -a). */
15660/* - Compute the number of edges in the resulting mesh. */
15661/* - Promote the mesh's linear triangles to higher order elements (-o). */
15662/* - Write the output files and print the statistics. */
15663/* - Check the consistency and Delaunay property of the mesh (-C). */
15664/* */
15665/*****************************************************************************/
15666
15667#ifdef TRILIBRARY
15668
15669#ifdef ANSI_DECLARATORS
15670void triangulate(const char *triswitches, struct triangulateio *in,
15671 struct triangulateio *out, struct triangulateio *vorout)
15672#else /* not ANSI_DECLARATORS */
15675struct triangulateio *in;
15676struct triangulateio *out;
15678#endif /* not ANSI_DECLARATORS */
15679
15680#else /* not TRILIBRARY */
15681
15682#ifdef ANSI_DECLARATORS
15683int main(int argc, char **argv)
15684#else /* not ANSI_DECLARATORS */
15685int main(argc, argv)
15686int argc;
15687char **argv;
15688#endif /* not ANSI_DECLARATORS */
15689
15690#endif /* not TRILIBRARY */
15691
15692{
15693 struct mesh m;
15694 struct behavior b;
15695 REAL *holearray; /* Array of holes. */
15696 REAL *regionarray; /* Array of regional attributes and area constraints. */
15697#ifndef TRILIBRARY
15698 FILE *polyfile;
15699#endif /* not TRILIBRARY */
15700#ifndef NO_TIMER
15701 /* Variables for timing the performance of Triangle. The types are */
15702 /* defined in sys/time.h. */
15703 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15704 struct timezone tz;
15705#endif /* not NO_TIMER */
15706
15707#ifndef NO_TIMER
15708 gettimeofday(&tv0, &tz);
15709#endif /* not NO_TIMER */
15710
15711 triangleinit(&m);
15712#ifdef TRILIBRARY
15714#else /* not TRILIBRARY */
15716#endif /* not TRILIBRARY */
15717 m.steinerleft = b.steiner;
15718
15719#ifdef TRILIBRARY
15720 transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15721 in->pointmarkerlist, in->numberofpoints,
15722 in->numberofpointattributes);
15723#else /* not TRILIBRARY */
15724 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15725#endif /* not TRILIBRARY */
15726
15727#ifndef NO_TIMER
15728 if (!b.quiet) {
15729 gettimeofday(&tv1, &tz);
15730 }
15731#endif /* not NO_TIMER */
15732
15733#ifdef CDT_ONLY
15734 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15735#else /* not CDT_ONLY */
15736 if (b.refine) {
15737 /* Read and reconstruct a mesh. */
15738#ifdef TRILIBRARY
15739 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15740 in->triangleattributelist, in->trianglearealist,
15741 in->numberoftriangles, in->numberofcorners,
15742 in->numberoftriangleattributes,
15743 in->segmentlist, in->segmentmarkerlist,
15744 in->numberofsegments);
15745#else /* not TRILIBRARY */
15746 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15747 b.inpolyfilename, polyfile);
15748#endif /* not TRILIBRARY */
15749 } else {
15750 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15751 }
15752#endif /* not CDT_ONLY */
15753
15754#ifndef NO_TIMER
15755 if (!b.quiet) {
15756 gettimeofday(&tv2, &tz);
15757 if (b.refine) {
15758 printf("Mesh reconstruction");
15759 } else {
15760 printf("Delaunay");
15761 }
15762 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15763 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15764 }
15765#endif /* not NO_TIMER */
15766
15767 /* Ensure that no vertex can be mistaken for a triangular bounding */
15768 /* box vertex in insertvertex(). */
15769 m.infvertex1 = (vertex) NULL;
15770 m.infvertex2 = (vertex) NULL;
15771 m.infvertex3 = (vertex) NULL;
15772
15773 if (b.usesegments) {
15774 m.checksegments = 1; /* Segments will be introduced next. */
15775 if (!b.refine) {
15776 /* Insert PSLG segments and/or convex hull segments. */
15777#ifdef TRILIBRARY
15778 formskeleton(&m, &b, in->segmentlist,
15779 in->segmentmarkerlist, in->numberofsegments);
15780#else /* not TRILIBRARY */
15781 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15782#endif /* not TRILIBRARY */
15783 }
15784 }
15785
15786#ifndef NO_TIMER
15787 if (!b.quiet) {
15788 gettimeofday(&tv3, &tz);
15789 if (b.usesegments && !b.refine) {
15790 printf("Segment milliseconds: %ld\n",
15791 1000l * (tv3.tv_sec - tv2.tv_sec) +
15792 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15793 }
15794 }
15795#endif /* not NO_TIMER */
15796
15797 if (b.poly && (m.triangles.items > 0)) {
15798#ifdef TRILIBRARY
15799 holearray = in->holelist;
15800 m.holes = in->numberofholes;
15801 regionarray = in->regionlist;
15802 m.regions = in->numberofregions;
15803#else /* not TRILIBRARY */
15804 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15805 &regionarray, &m.regions);
15806#endif /* not TRILIBRARY */
15807 if (!b.refine) {
15808 /* Carve out holes and concavities. */
15809 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15810 }
15811 } else {
15812 /* Without a PSLG, there can be no holes or regional attributes */
15813 /* or area constraints. The following are set to zero to avoid */
15814 /* an accidental free() later. */
15815 m.holes = 0;
15816 m.regions = 0;
15817 }
15818
15819#ifndef NO_TIMER
15820 if (!b.quiet) {
15821 gettimeofday(&tv4, &tz);
15822 if (b.poly && !b.refine) {
15823 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15824 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15825 }
15826 }
15827#endif /* not NO_TIMER */
15828
15829#ifndef CDT_ONLY
15830 if (b.quality && (m.triangles.items > 0)) {
15831 enforcequality(&m, &b); /* Enforce angle and area constraints. */
15832 }
15833#endif /* not CDT_ONLY */
15834
15835#ifndef NO_TIMER
15836 if (!b.quiet) {
15837 gettimeofday(&tv5, &tz);
15838#ifndef CDT_ONLY
15839 if (b.quality) {
15840 printf("Quality milliseconds: %ld\n",
15841 1000l * (tv5.tv_sec - tv4.tv_sec) +
15842 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15843 }
15844#endif /* not CDT_ONLY */
15845 }
15846#endif /* not NO_TIMER */
15847
15848 /* Calculate the number of edges. */
15849 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15850
15851 if (b.order > 1) {
15852 highorder(&m, &b); /* Promote elements to higher polynomial order. */
15853 }
15854 if (!b.quiet) {
15855 printf("\n");
15856 }
15857
15858#ifdef TRILIBRARY
15859 if (b.jettison) {
15860 out->numberofpoints = m.vertices.items - m.undeads;
15861 } else {
15862 out->numberofpoints = m.vertices.items;
15863 }
15864 out->numberofpointattributes = m.nextras;
15865 out->numberoftriangles = m.triangles.items;
15866 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15867 out->numberoftriangleattributes = m.eextras;
15868 out->numberofedges = m.edges;
15869 if (b.usesegments) {
15870 out->numberofsegments = m.subsegs.items;
15871 } else {
15872 out->numberofsegments = m.hullsize;
15873 }
15874 if (vorout != (struct triangulateio *) NULL) {
15875 vorout->numberofpoints = m.triangles.items;
15876 vorout->numberofpointattributes = m.nextras;
15877 vorout->numberofedges = m.edges;
15878 }
15879#endif /* TRILIBRARY */
15880 /* If not using iteration numbers, don't write a .node file if one was */
15881 /* read, because the original one would be overwritten! */
15882 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15883 if (!b.quiet) {
15884#ifdef TRILIBRARY
15885 printf("NOT writing vertices.\n");
15886#else /* not TRILIBRARY */
15887 printf("NOT writing a .node file.\n");
15888#endif /* not TRILIBRARY */
15889 }
15890 numbernodes(&m, &b); /* We must remember to number the vertices. */
15891 } else {
15892 /* writenodes() numbers the vertices too. */
15893#ifdef TRILIBRARY
15894 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15895 &out->pointmarkerlist);
15896#else /* not TRILIBRARY */
15897 writenodes(&m, &b, b.outnodefilename, argc, argv);
15898#endif /* TRILIBRARY */
15899 }
15900 if (b.noelewritten) {
15901 if (!b.quiet) {
15902#ifdef TRILIBRARY
15903 printf("NOT writing triangles.\n");
15904#else /* not TRILIBRARY */
15905 printf("NOT writing an .ele file.\n");
15906#endif /* not TRILIBRARY */
15907 }
15908 } else {
15909#ifdef TRILIBRARY
15910 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15911#else /* not TRILIBRARY */
15912 writeelements(&m, &b, b.outelefilename, argc, argv);
15913#endif /* not TRILIBRARY */
15914 }
15915 /* The -c switch (convex switch) causes a PSLG to be written */
15916 /* even if none was read. */
15917 if (b.poly || b.convex) {
15918 /* If not using iteration numbers, don't overwrite the .poly file. */
15919 if (b.nopolywritten || b.noiterationnum) {
15920 if (!b.quiet) {
15921#ifdef TRILIBRARY
15922 printf("NOT writing segments.\n");
15923#else /* not TRILIBRARY */
15924 printf("NOT writing a .poly file.\n");
15925#endif /* not TRILIBRARY */
15926 }
15927 } else {
15928#ifdef TRILIBRARY
15929 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15930 out->numberofholes = m.holes;
15931 out->numberofregions = m.regions;
15932 if (b.poly) {
15933 out->holelist = in->holelist;
15934 out->regionlist = in->regionlist;
15935 } else {
15936 out->holelist = (REAL *) NULL;
15937 out->regionlist = (REAL *) NULL;
15938 }
15939#else /* not TRILIBRARY */
15940 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15941 m.regions, argc, argv);
15942#endif /* not TRILIBRARY */
15943 }
15944 }
15945#ifndef TRILIBRARY
15946#ifndef CDT_ONLY
15947 if (m.regions > 0) {
15948 trifree((VOID *) regionarray);
15949 }
15950#endif /* not CDT_ONLY */
15951 if (m.holes > 0) {
15952 trifree((VOID *) holearray);
15953 }
15954 if (b.geomview) {
15955 writeoff(&m, &b, b.offfilename, argc, argv);
15956 }
15957#endif /* not TRILIBRARY */
15958 if (b.edgesout) {
15959#ifdef TRILIBRARY
15960 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15961#else /* not TRILIBRARY */
15962 writeedges(&m, &b, b.edgefilename, argc, argv);
15963#endif /* not TRILIBRARY */
15964 }
15965 if (b.voronoi) {
15966#ifdef TRILIBRARY
15967 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15968 &vorout->pointmarkerlist, &vorout->edgelist,
15969 &vorout->edgemarkerlist, &vorout->normlist);
15970#else /* not TRILIBRARY */
15971 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15972#endif /* not TRILIBRARY */
15973 }
15974 if (b.neighbors) {
15975#ifdef TRILIBRARY
15976 writeneighbors(&m, &b, &out->neighborlist);
15977#else /* not TRILIBRARY */
15978 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15979#endif /* not TRILIBRARY */
15980 }
15981
15982 if (!b.quiet) {
15983#ifndef NO_TIMER
15984 gettimeofday(&tv6, &tz);
15985 printf("\nOutput milliseconds: %ld\n",
15986 1000l * (tv6.tv_sec - tv5.tv_sec) +
15987 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15988 printf("Total running milliseconds: %ld\n",
15989 1000l * (tv6.tv_sec - tv0.tv_sec) +
15990 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15991#endif /* not NO_TIMER */
15992
15993 statistics(&m, &b);
15994 }
15995
15996#ifndef REDUCED
15997 if (b.docheck) {
15998 checkmesh(&m, &b);
15999 checkdelaunay(&m, &b);
16000 }
16001#endif /* not REDUCED */
16002
16003 triangledeinit(&m, &b);
16004#ifndef TRILIBRARY
16005 return 0;
16006#endif /* not TRILIBRARY */
16007}
initial point of the source segment B
final point of the source segment t
c
Definition int_R.m:15
function int_R syms a b c u real f
Definition int_R.m:4
b
Definition int_R.m:16
x
Definition int_R.m:12
vertex subsegdest
Definition triangle.cpp:549
vertex subsegorg
Definition triangle.cpp:549
subseg encsubseg
Definition triangle.cpp:548
triangle poortri
Definition triangle.cpp:557
vertex triangapex
Definition triangle.cpp:559
vertex triangorg
Definition triangle.cpp:559
vertex triangdest
Definition triangle.cpp:559
struct badtriang * nexttriang
Definition triangle.cpp:560
int noexact
Definition triangle.cpp:788
char edgefilename[FILENAMESIZE]
Definition triangle.cpp:810
int nopolywritten
Definition triangle.cpp:787
char areafilename[FILENAMESIZE]
Definition triangle.cpp:806
REAL maxarea
Definition triangle.cpp:798
int steiner
Definition triangle.cpp:796
int conformdel
Definition triangle.cpp:788
char vedgefilename[FILENAMESIZE]
Definition triangle.cpp:812
int weighted
Definition triangle.cpp:784
REAL goodangle
Definition triangle.cpp:797
char inelefilename[FILENAMESIZE]
Definition triangle.cpp:804
int neighbors
Definition triangle.cpp:786
int noelewritten
Definition triangle.cpp:787
char neighborfilename[FILENAMESIZE]
Definition triangle.cpp:813
char vnodefilename[FILENAMESIZE]
Definition triangle.cpp:811
int fixedarea
Definition triangle.cpp:783
int usesegments
Definition triangle.cpp:793
int sweepline
Definition triangle.cpp:789
char outpolyfilename[FILENAMESIZE]
Definition triangle.cpp:809
int firstnumber
Definition triangle.cpp:785
char outnodefilename[FILENAMESIZE]
Definition triangle.cpp:807
int edgesout
Definition triangle.cpp:786
int noholes
Definition triangle.cpp:788
int geomview
Definition triangle.cpp:786
char outelefilename[FILENAMESIZE]
Definition triangle.cpp:808
int incremental
Definition triangle.cpp:789
int regionattrib
Definition triangle.cpp:784
int noiterationnum
Definition triangle.cpp:787
char inpolyfilename[FILENAMESIZE]
Definition triangle.cpp:805
int nobisect
Definition triangle.cpp:795
char innodefilename[FILENAMESIZE]
Definition triangle.cpp:803
int verbose
Definition triangle.cpp:792
int nobound
Definition triangle.cpp:787
int splitseg
Definition triangle.cpp:790
int vararea
Definition triangle.cpp:783
REAL offconstant
Definition triangle.cpp:797
int nonodewritten
Definition triangle.cpp:787
int voronoi
Definition triangle.cpp:786
char offfilename[FILENAMESIZE]
Definition triangle.cpp:814
int docheck
Definition triangle.cpp:791
int jettison
Definition triangle.cpp:784
int usertest
Definition triangle.cpp:783
int quality
Definition triangle.cpp:783
REAL minangle
Definition triangle.cpp:797
REAL ykey
Definition triangle.cpp:583
REAL xkey
Definition triangle.cpp:583
int heapposition
Definition triangle.cpp:585
VOID * eventptr
Definition triangle.cpp:584
struct flipstacker * prevflip
Definition triangle.cpp:569
triangle flippedtri
Definition triangle.cpp:568
int pathitemsleft
Definition triangle.cpp:640
VOID * pathitem
Definition triangle.cpp:633
int itemsperblock
Definition triangle.cpp:636
VOID ** pathblock
Definition triangle.cpp:632
long maxitems
Definition triangle.cpp:638
VOID * deaditemstack
Definition triangle.cpp:631
VOID * nextitem
Definition triangle.cpp:630
VOID ** nowblock
Definition triangle.cpp:629
int unallocateditems
Definition triangle.cpp:639
int itemsfirstblock
Definition triangle.cpp:637
VOID ** firstblock
Definition triangle.cpp:629
int mesh_dim
Definition triangle.cpp:699
struct memorypool badtriangles
Definition triangle.cpp:672
long orient3dcount
Definition triangle.cpp:716
long edges
Definition triangle.cpp:698
int eextras
Definition triangle.cpp:701
struct badtriang * queuetail[4096]
Definition triangle.cpp:680
long circumcentercount
Definition triangle.cpp:718
struct memorypool flipstackers
Definition triangle.cpp:673
int inelements
Definition triangle.cpp:693
long samples
Definition triangle.cpp:712
int regions
Definition triangle.cpp:696
int invertices
Definition triangle.cpp:692
REAL ymin
Definition triangle.cpp:690
struct memorypool subsegs
Definition triangle.cpp:668
struct memorypool viri
Definition triangle.cpp:670
struct otri recenttri
Definition triangle.cpp:740
int firstnonemptyq
Definition triangle.cpp:682
long hullsize
Definition triangle.cpp:702
long incirclecount
Definition triangle.cpp:714
vertex infvertex3
Definition triangle.cpp:723
int vertex2triindex
Definition triangle.cpp:705
REAL ymax
Definition triangle.cpp:690
subseg * dummysubbase
Definition triangle.cpp:735
int nextnonemptyq[4096]
Definition triangle.cpp:681
REAL xmax
Definition triangle.cpp:690
struct memorypool triangles
Definition triangle.cpp:667
int steinerleft
Definition triangle.cpp:703
int insegments
Definition triangle.cpp:694
int holes
Definition triangle.cpp:695
REAL xmin
Definition triangle.cpp:690
struct memorypool splaynodes
Definition triangle.cpp:674
struct flipstacker * lastflip
Definition triangle.cpp:686
int checksegments
Definition triangle.cpp:709
long counterclockcount
Definition triangle.cpp:715
triangle * dummytribase
Definition triangle.cpp:728
struct memorypool vertices
Definition triangle.cpp:669
long circletopcount
Definition triangle.cpp:719
int nextras
Definition triangle.cpp:700
struct badtriang * queuefront[4096]
Definition triangle.cpp:679
int highorderindex
Definition triangle.cpp:706
int readnodefile
Definition triangle.cpp:711
int undeads
Definition triangle.cpp:697
vertex infvertex1
Definition triangle.cpp:723
subseg * dummysub
Definition triangle.cpp:734
int checkquality
Definition triangle.cpp:710
int vertexmarkindex
Definition triangle.cpp:704
long hyperbolacount
Definition triangle.cpp:717
REAL xminextreme
Definition triangle.cpp:691
int elemattribindex
Definition triangle.cpp:707
int areaboundindex
Definition triangle.cpp:708
triangle * dummytri
Definition triangle.cpp:727
struct memorypool badsubsegs
Definition triangle.cpp:671
vertex infvertex2
Definition triangle.cpp:723
int ssorient
Definition triangle.cpp:534
subseg * ss
Definition triangle.cpp:533
triangle * tri
Definition triangle.cpp:516
int orient
Definition triangle.cpp:517
vertex keydest
Definition triangle.cpp:601
struct splaynode * lchild
Definition triangle.cpp:602
struct otri keyedge
Definition triangle.cpp:600
struct splaynode * rchild
Definition triangle.cpp:602
void check(bool ok, const char *message)
void printtriangle(struct mesh *m, struct behavior *b, struct otri *t) void printtriangle(m
INEXACT REAL tj1
REAL pivoty
int at_clen
int bycalen
REAL * finnow
REAL ct_a[4]
void triexit(int status) void triexit(status) int status
struct badsubseg * dyingseg
vertex joinvertex
char * stringptr
REAL dxao2
int vlength
unsigned long randomnation(unsigned int choices) unsigned long randomnation(choices) unsigned int choices
REAL denominator
int aytbctlen
struct triangulateio * vorout
void splitencsegs(struct mesh *m, struct behavior *b, int triflaws) void splitencsegs(m
int bytcattlen
int killvertexindex
FILE * elefile
struct splaynode * frontlocate(struct mesh *m, struct splaynode *splayroot, struct otri *bottommost, vertex searchvertex, struct otri *searchtri, int *farright) struct splaynode *frontlocate(m
INEXACT REAL cdxady1
int cxtabtlen
REAL at_c[4]
REAL tx
REAL dadist
REAL splitter
Definition triangle.cpp:646
int bt_clen
int bxtcalen
vertex innerrightorg
thisevent
void vedgefilename
REAL * holearray
int acutedest
int leftchild
INEXACT REAL Qnew
return newvertex
REAL ccwabc
int temp32alen
REAL cxtabtt[8]
int temp32blen
ydo
int temp16blen
struct otri * newotri
INEXACT REAL ab3
dxda
int ayybclen
struct otri hullleft hullright
vertex farrightapex
int bt_alen
int bxcalen
int * emlist
REAL cossquaretable[8]
int cytabttlen
struct otri fliptri
vertex segmentorg
int * smlist
int boundmarker
vertex p2
alignptr
REAL acytail
REAL bclen2
int bxtcattlen
REAL destorient
hulledges
void writepoly(struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist) void writepoly(m
int newmark
triangle ** virusloop
enum locateresult preciselocate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment) enum locateresult preciselocate(m
void firstedge
REAL bxtcc[8]
finddirectionresult
Definition triangle.cpp:389
@ LEFTCOLLINEAR
Definition triangle.cpp:389
@ RIGHTCOLLINEAR
Definition triangle.cpp:389
@ WITHIN
Definition triangle.cpp:389
vertex printvertex
REAL enow
REAL bheight
REAL bdxcdy
struct otri checkleft
elist
int end[2]
REAL detrighttail
int areaelements
int axbclen
REAL triaspect2
int badedge
vertex regionorg
int aybclen
newotri tri
REAL ct_b[4]
REAL adxcdy0
enum finddirectionresult collinear
struct otri lefttri righttri
setorg(top, botvertex)
void enqueuebadtriang(struct mesh *m, struct behavior *b, struct badtriang *badtri) void enqueuebadtriang(m
int end1
REAL * palist
vertex mid3
lnextself(newbotleft)
adx
REAL cdycdy0
int currentmarker
INEXACT REAL cdxt_bdyt1
long elementnumber
vertex leftbasevertex
REAL incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd) REAL incircle(m
void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, struct otri *innerleft, struct otri *innerright, struct otri *farright, int axis) void mergehulls(m
vertex midvertex
vertex upperleft
REAL ab[4]
vertex dyingvertex
INEXACT REAL cdxt_ady1
int axxbclen
void tallyfaces(struct mesh *m, struct behavior *b) void tallyfaces(m
vertex base1
Q
int cxtbblen
vertex fdest
int cytabtlen
REAL cc[4]
INEXACT REAL _j
REAL smallestangle
REAL orglen
vertex eorg
REAL D[16]
vertex org2
void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, REAL **vpointattriblist, int **vpointmarkerlist, int **vedgelist, int **vedgemarkerlist, REAL **vnormlist) void writevoronoi(m
int corner[3]
REAL dxb
eventheap[0] eventptr
void writeoff(struct mesh *m, struct behavior *b, char *offfilename, int argc, char **argv) void writeoff(m
REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight, REAL permanent) REAL orient3dadapt(pa
int segmentmarkers
REAL adxbdy
setdest(top, farvertex)
char infile
cdheight
right
void vertexdealloc(struct mesh *m, vertex dyingvertex) void vertexdealloc(m
void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg) void badsubsegdealloc(m
vertex bestvertex
int rightchild
REAL axtbb[8]
void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge) void unflip(m
REAL negate
REAL cxtab[8]
Split(b, bhi, blo)
int shouldbedelaunay
struct splaynode splayroot
vertex botvertex
int killorg
INEXACT REAL abig
vertex bdest
int bxtaalen
struct event * newevent
ybc
REAL ahi
REAL adyady0
void heapsize struct otri * checktri
void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri) void deletevertex(m
struct osub botlsubseg botrsubseg
void initializevertexpool(struct mesh *m, struct behavior *b) void initializevertexpool(m
void vedgelist
REAL bdxady0
subseg * dyingsubseg
REAL bdxtail
void starttri
int ablen
REAL fin1[1152]
int subsegmark
REAL dxao
struct badtriang * badtri
REAL aa[4]
INEXACT REAL adyt_bdx1
subseg sptr
REAL byyca[16]
int axtbcttlen
REAL minaltitude
void triangledeinit(struct mesh *m, struct behavior *b) void triangledeinit(m
REAL temp32b[32]
void undovertex(struct mesh *m, struct behavior *b) void undovertex(m
int sides
REAL errbound
void newevent struct event ** heap
struct osub neighborsubseg
divider
INEXACT REAL cc3
flip(m, b, &fixuptri)
REAL aytbctt[8]
INEXACT REAL u3
void statistics(struct mesh *m, struct behavior *b) void statistics(m
int trianglearealist
int trianglelist
INEXACT REAL abtt3
struct otri nextedge
REAL righttest
REAL axtbct[16]
struct osub faredge
symself(searchedge)
REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc) REAL circletop(m
REAL around
void innerleft
void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist, REAL *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs) void transfernodes(m
int h int elen
void vpointmarkerlist
int catlen
struct otri sidecasing topcasing outercasing
setvertextype(newvertex, INPUTVERTEX)
REAL adxt_bdyt0
REAL bxca[8]
REAL dy
REAL cyyab[16]
REAL cytbb[8]
vertex lowerright
INEXACT REAL bdybdy1
struct osub currentenc
REAL ey
vertexsize
int j
tlist
fclose(elefile)
nlist
vertex mid2
bdx
FILE * polyfile
int hindex
INEXACT REAL adxcdy1
strcpy(b->inpolyfilename, b->innodefilename)
REAL cytaa[8]
REAL adyt_bdx0
int aytcclen
long subsegnumber
int elements
void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, REAL *regionlist, int regions) void carveholes(m
REAL aytbb[8]
void out
REAL attrib
sprintf(b->outnodefilename, workstring, meshnumber+1)
int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h) int fast_expansion_sum_zeroelim(elen
REAL bdxt_adyt0
INEXACT REAL cdyt_adx1
long samplesleft
printf("triangle x%lx with orientation %d:\n",(unsigned long) t->tri, t->orient)
called is pointed to *void trianglebytes
void vorout char * triswitches
REAL cdxady
struct otri neighbor
REAL aodist
sampleblock
REAL bb[4]
REAL * normlist
void enforcequality(struct mesh *m, struct behavior *b) void enforcequality(m
REAL ayybc[16]
vertex forg
void pointmarkerlist
int leftflag
REAL bct[8]
setapex(top, leftvertex)
REAL temp48[48]
void eventheapinsert(struct event **heap, int heapsize, struct event *newevent) void eventheapinsert(heap
vertex fapex
REAL bdet[32]
struct otri * testtri
REAL ** triangle
Definition triangle.cpp:508
INEXACT REAL detright
vertex segmentdest
char * infilename
b splitseg
void eventheapify(struct event **heap, int heapsize, int eventnum) void eventheapify(heap
REAL angle
REAL cheight
INEXACT REAL adxadx1
REAL dx
void farleft
REAL iccerrboundB
Definition triangle.cpp:650
REAL pivot1
INEXACT REAL bdxady1
INEXACT REAL bdxt_cdyt1
struct osub testsh
REAL t0
void vpointlist
vertex org1
REAL axtbc[8]
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis) void vertexmedian(sortarray
REAL divisor
struct splaynode newkey
enum locateresult searchpoint
void insertsegment(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark) void insertsegment(m
struct splaynode * lefttree
REAL dotproduct
REAL bxxca[16]
REAL split
struct osub * testsubseg
lprev(top, topleft)
vertex lowerleft
REAL ccwerrboundB
Definition triangle.cpp:649
int parent
REAL aytbc[8]
void innerright
void regionlist
newsplaynode
REAL ty
INEXACT REAL adxt_bdy1
INEXACT REAL adxt_cdyt1
void eventheap
int findex
vertex farleftapex
int aspectindex
REAL w[16]
int neighbor3
newbad
REAL cdxt_ady0
struct otri deltriright
INEXACT REAL bdxbdx1
void argv
REAL u[4]
REAL bdxbdx0
void rlist
REAL width
REAL etx
REAL clift
int checkseg4encroach(struct mesh *m, struct behavior *b, struct osub *testsubseg) int checkseg4encroach(m
REAL adxcdy
REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum) REAL counterclockwiseadapt(pa
void pointattriblist
INEXACT REAL s1
Two_Product_Presplit(e[0], b, bhi, blo, Q, hh)
REAL permanent
REAL adxadx0
vertex torg
strcat(b->outnodefilename, ".node")
REAL err1
INEXACT REAL aa3
void vnodefilename
struct otri searchedge
left
REAL bdxt_ady0
int clen
int C2length
REAL cdyt_bdx0
long totalsamplesleft
REAL o3derrboundC
Definition triangle.cpp:651
int temp8len
int neighbor1
struct splaynode * leftright
return newsubseg
tspivot(lefttri, leftsubseg)
REAL pivot2
struct otri newtopright
destT(horiz, leftvertex)
int plus1mod3[3]
Definition triangle.cpp:932
int bxtcatlen
REAL dyao2
vertex shorg
vertex mid1
REAL bhi
REAL aybc[8]
int notdone
REAL abtt[4]
INEXACT REAL adxt_bdyt1
REAL maxlen
int Dlength
int cytbblen
void check4deadevent(struct otri *checktri, struct event **freeevents, struct event **eventheap, int *heapsize) void check4deadevent(checktri
INEXACT REAL product1
REAL tj0
REAL ablen2
vertex deaddest
REAL dalen
char * findfield()
struct otri newbotleft newbotright
REAL axtbctt[8]
struct otri triangleloop
int at_blen
vertex checkdest
INEXACT REAL _i
REAL bdxady
REAL product0
REAL adxbdy0
REAL ** vnormlist
insertvertexresult
Definition triangle.cpp:381
@ SUCCESSFULVERTEX
Definition triangle.cpp:381
@ ENCROACHINGVERTEX
Definition triangle.cpp:381
@ VIOLATINGVERTEX
Definition triangle.cpp:381
@ DUPLICATEVERTEX
Definition triangle.cpp:382
int aroundvertex
REAL pc
triangle * prevlink
REAL bt_a[4]
int temp64len
int area vertex triorg
void numberofpoints
void makesubseg(struct mesh *m, struct osub *newsubseg) void makesubseg(m
dissolve(dissolveedge)
void triangledealloc(struct mesh *m, triangle *dyingtriangle) void triangledealloc(m
void tallyencs(struct mesh *m, struct behavior *b) void tallyencs(m
setvertex2tri(newvertex, encode(*splittri))
enum locateresult intersect
REAL cxtabt[16]
REAL cxxab[16]
void events
int cxtaalen
void in
REAL cdytail
struct timeval tv0 tv1 tv2 tv3 tv4 tv5 tv6
vertex checkapex
long vnodenumber
REAL dyb
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2) void segmentintersection(m
int subsegbytes
void readholes(struct mesh *m, struct behavior *b, FILE *polyfile, char *polyfilename, REAL **hlist, int *holes, REAL **rlist, int *regions) void readholes(m
farrightflag
long samplesperblock
struct otri deadtriangle
vertex p1
REAL leftccw
vertex lastvertex
vertex ndest
REAL oalen
REAL cdet[32]
REAL bxtcatt[8]
REAL avirt
REAL ccwerrboundC
Definition triangle.cpp:649
int triunsuitable()
struct event * nextevent
REAL C2[12]
vertex connectvertex
VOID * trimalloc(int size) VOID *trimalloc(size) int size
struct badtriang * dequeuebadtriang(struct mesh *m) struct badtriang *dequeuebadtriang(m) struct mesh *m
int bestnumber
void createeventheap(struct mesh *m, struct event ***eventheap, struct event **events, struct event **freeevents) void createeventheap(m
REAL * finother
void exactinit()
xac
void lastedge
struct flipstacker * newflip
int axtbclen
int number
REAL fnow
struct osub testsub
REAL dheight
REAL bdxt_cdyt0
eventx
REAL cdxt_adyt0
void farright
REAL estimate(int elen, REAL *e) REAL estimate(elen
int bcttlen
struct badsubseg * encloop
REAL dyoff
REAL ex
REAL dist1
void eventheapdelete(struct event **heap, int heapsize, int eventnum) void eventheapdelete(heap
long elefilename
Two_Diff_Tail(pa[0], pc[0], acx, acxtail)
struct otri * deltri
void median
int index
int ** neighborlist
int bytaalen
REAL ratiotable[16]
void holes
ady
int corners
int axtbblen
void conformingedge(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark) void conformingedge(m
slist
int nodemarkers
long vedgenumber
locateresult
Definition triangle.cpp:373
@ OUTSIDE
Definition triangle.cpp:373
@ INTRIANGLE
Definition triangle.cpp:373
@ ONVERTEX
Definition triangle.cpp:373
@ ONEDGE
Definition triangle.cpp:373
struct otri * flipedge
INEXACT REAL B3
REAL biggestangle
void edgefilename
REAL cyab[8]
int numberofpointattribs
struct osub checkmark
int queuenumber
INEXACT REAL adxbdy1
REAL searchdist
vertex innerrightapex
int dummy
int firstnode
struct otri tempedge
int cytablen
eventy
char inputline[INPUTLINESIZE]
struct otri inserttri
int ct_blen
REAL cdxtail
struct osub checkedge
Two_Product(acx, bcy, detleft, detlefttail)
long polyfilename
vertex getvertex(struct mesh *m, struct behavior *b, int number) vertex getvertex(m
xao
REAL o3derrboundB
Definition triangle.cpp:651
int C1length
long segmentnumber
REAL temp8[8]
REAL counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc) REAL counterclockwise(m
REAL acxtail
int coordindex
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws) void triangulatepolygon(m
triangle * dyingtriangle
struct splaynode splaytree
vertex checkvertex
REAL det
INEXACT REAL ca3
struct badsubseg * encroachedseg
REAL dyoa
vertex regionapex
void minedge
REAL temp16b[16]
triangle * triangletraverse(struct mesh *m) triangle *triangletraverse(m) struct mesh *m
void precisionerror()
void initializetrisubpools(struct mesh *m, struct behavior *b) void initializetrisubpools(m
REAL ti0
int bxtcclen
int rightofroot
increment
REAL axtcc[8]
long sweeplinedelaunay(struct mesh *m, struct behavior *b) long sweeplinedelaunay(m
REAL bxtcat[16]
int saveexact
REAL cdheighttail
REAL dodist
struct otri triangleloop trisym
void attribute
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri) void maketriangle(m
void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist) void writeneighbors(m
struct splaynode * splayinsert(struct mesh *m, struct splaynode *splayroot, struct otri *newkey, vertex searchpoint) struct splaynode *splayinsert(m
struct splaynode * circletopinsert(struct mesh *m, struct behavior *b, struct splaynode *splayroot, struct otri *newkey, vertex pa, vertex pb, vertex pc, REAL topy) struct splaynode *circletopinsert(m
struct otri toplcasing toprcasing
INEXACT REAL v3
int cytaalen
int bctlen
INEXACT REAL cdyt_bdx1
REAL dyda2
void enqapex
int axis
void nodefilename
vertex p3
vertex borg
void infecthull(struct mesh *m, struct behavior *b) void infecthull(m
vertex rightvertex
void checkdelaunay(struct mesh *m, struct behavior *b) void checkdelaunay(m
struct otri botlcasing botrcasing
int byycalen
REAL bdyt_adx0
vertex farrightpt
int acutebiggest
REAL temp64[64]
int vertexnumber
REAL dyda
void b int argc
REAL ety
xbc
struct otri oppotri oppooppotri
REAL nearestpoweroftwo
void finishfile(FILE *outfile, int argc, char **argv) void finishfile(outfile
long areafilename
vertex searchorg
int smallest
acx
INEXACT REAL bctt3
struct timezone tz
vertex nextapex
INEXACT REAL bdxt_cdy1
vertex deadapex
struct osub subsegloop
REAL temp16c[16]
int cxtabttlen
bcx
vertex endpoint1
INEXACT REAL detleft
long removebox(struct mesh *m, struct behavior *b) long removebox(m
int alen
vertex neworg
INEXACT REAL hh
vertex oppodest
struct splaynode searchvertex
vertex upperright
struct event ** freeevents
void neighborfilename
long holenumber
REAL cdyt_adx0
REAL * xi
int axtcclen
dxod
struct osub rightsubseg
REAL epsilon
Definition triangle.cpp:647
struct osub checksubseg
int maxevents
vertex base2
yao
void offfilename
REAL multiplier
struct otri checkneighbor
int segmentmarkerlist
REAL dyod2
int posexponent
lprevself(newbotright)
void vpointattriblist
REAL * finswap
INEXACT REAL t1
int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite) int rightofhyperbola(m
struct otri triangleleft
vertex killvertex
void vedgemarkerlist
REAL bt_c[4]
plist
INEXACT REAL ct_alarge
vertex norg
otricopy(besttri, testtri)
REAL ca[4]
triangle ptr
int aytbclen
int rightfinished
void enqorg
long delaunay(struct mesh *m, struct behavior *b) long delaunay(m
void splittri
bond(topleft, botlcasing)
bdy
vertex innerleftdest
REAL adheighttail
void parsecommandline(int argc, const char **argv, struct behavior *b) void parsecommandline(argc
int attribs
int acuteorg
void fixuptri
INEXACT REAL bdyt_cdx1
struct otri topleft topright
int triapex
INEXACT REAL catt3
sdissolve(opposubseg)
int cxxablen
int mirrorflag
void numbernodes(struct mesh *m, struct behavior *b) void numbernodes(m
REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent) REAL incircleadapt(pa
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark) void const rainededge(m
char workstring[FILENAMESIZE]
vertex eapex
INEXACT REAL cdxt_bdy1
vertex searchdest
INEXACT REAL bt_alarge
REAL cdxcdx0
vertex bapex
REAL cxab[8]
void highorder(struct mesh *m, struct behavior *b) void highorder(m
void triangleinit(struct mesh *m) void triangleinit(m) struct mesh *m
REAL * eta
void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments) void formskeleton(m
REAL odlen
int ii
void vertexsort(vertex *sortarray, int arraysize) void vertexsort(sortarray
vertex circumcenter
int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist, REAL *triangleattriblist, REAL *trianglearealist, int elements, int corners, int attribs, int *segmentlist, int *segmentmarkerlist, int numberofsegments) int reconstruct(m
REAL ahead
int aytbcttlen
vertex oppoapex
REAL bdyt_cdx0
int pivot
int cyyablen
REAL alift
REAL temp16a[16]
REAL bytcat[16]
int rightflag
triangle encodedtri
int leftside
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws) enum insertvertexresult insertvertex(m
vertex p[3]
INEXACT REAL cdxt_adyt1
snextself(opposubseg)
int wlength
triangle * vertexarray
REAL worstaspect
REAL edgelength[3]
REAL bdybdy0
REAL bxtaa[8]
vertex tdest
int attribindex
vertex enqdest
int ** edgemarkerlist
int end2
int cattlen
int leftfinished
long totalpopulation
REAL alo
vertex rightbasevertex
INEXACT REAL at_blarge
char * firsttri
REAL dxod2
int minus1mod3[3]
Definition triangle.cpp:933
long incrementaldelaunay(struct mesh *m, struct behavior *b) long incrementaldelaunay(m
int * pmlist
int expincrement
int bytcatlen
REAL dyao
vertex farleftpt
REAL cxtbb[8]
long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost) long removeghosts(m
subseg * subsegtraverse(struct mesh *m) subseg *subsegtraverse(m) struct mesh *m
long regionnumber
struct otri baseedge
struct otri dissolveedge
yab
lnext(top, topright)
vertex midvertex1
REAL orgorient
vertex endpoint2
struct otri sampletri
REAL ** subseg
Definition triangle.cpp:525
vertex vertexloop
REAL blo
vertex nextvertex
REAL shortest
void enqtri
vertex deadorg
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint) enum finddirectionresult finddirection(m
REAL abt[8]
void hlist
REAL dist
memptr
long outvertices
int offcenter
REAL s0
int k
INEXACT REAL cdycdy1
vertex testvertex
REAL smallestarea
REAL err3
char * foundvertex
void makevertexmap(struct mesh *m, struct behavior *b) void makevertexmap(m
struct osub hullsubseg
moveevent
int meshnumber
REAL detlefttail
REAL triminaltitude2
int collision
int incorners
REAL adyt_cdx0
void splitsubseg
REAL lefttest
int segmentlist
int horrors
struct otri * regiontris
REAL o3derrboundA
Definition triangle.cpp:651
REAL destlen
vertex firstvertex
void writeelements(struct mesh *m, struct behavior *b, int **trianglelist, REAL **triangleattriblist) void writeelements(m
void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, REAL **pointattriblist, int **pointmarkerlist) void writenodes(m
Two_Two_Diff(detleft, detlefttail, detright, detrighttail, B3, B[2], B[1], B[0])
struct otri lefttri righttri farlefttri farrighttri
vertex vertextraverse(struct mesh *m) vertex vertextraverse(m) struct mesh *m
int check4events
REAL C1[8]
struct otri gluetri
REAL segmentlength
INEXACT REAL ct_blarge
FILE * areafile
REAL dxa
void edgelist
REAL * h
REAL aheight
int temp16alen
int tendegree
bdheight
REAL cossquare
int blen
vertex markorg
int regions
REAL err2
void pointlist
int temp48len
getblock
int stopatsubsegment
long edgenumber
REAL bytcc[8]
REAL cytab[8]
struct osub opposubseg
void info()
REAL degconst
struct splaynode * righttree
void holelist
enum insertvertexresult segmentflaws
void arraysize vertex * sortarray
INEXACT REAL bvirt
REAL catt[4]
int abttlen
called dummytri
REAL aclen2
REAL bcxtail
REAL bxtca[8]
adheight
long hullsize
int eindex
char infilename char * string
vertex farvertex
int exponent
dxoa
xab
vertex tapex
REAL pb
vertex topvertex
enum insertvertexresult success
int abtlen
REAL adxt_cdyt0
INEXACT REAL bdyt_adx1
int angletable[18]
int cyablen
REAL bdxt_cdy0
void readnodes(struct mesh *m, struct behavior *b, char *nodefilename, char *polyfilename, FILE **polyfile) void readnodes(m
void argv FILE * outfile
vertex horg
REAL bytaa[8]
REAL resulterrbound
Definition triangle.cpp:648
int i
struct osub crosssubseg
struct otri leftcasing rightcasing
REAL cdxbdy0
REAL cat[8]
void internalerror()
int e
cdy
REAL _0
void writeedges(struct mesh *m, struct behavior *b, int **edgelist, int **edgemarkerlist) void writeedges(m
struct otri besttri
REAL * vertex
Definition triangle.cpp:542
REAL at_b[4]
REAL adxt_bdy0
REAL bcytail
vertexindex
vertex dest2
REAL * regionarray
REAL bdheighttail
unsigned long randomseed
Definition triangle.cpp:655
enum locateresult searchtri
void boundingbox(struct mesh *m, struct behavior *b) void boundingbox(m
long divconqdelaunay(struct mesh *m, struct behavior *b) long divconqdelaunay(m
vertex oppoorg
REAL temp32a[32]
int notfound
REAL bytcatt[8]
int temp16clen
char * readline()
REAL nonregular(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd) REAL nonregular(m
INEXACT REAL bc3
int arraysize
REAL pivotx
INEXACT REAL bdxcdy1
INEXACT REAL at_clarge
vertex nearvertex
vertex secondvertex
triangle ** regiontri
REAL biggestarea
REAL dist2
int enq
void checkmesh(struct mesh *m, struct behavior *b) void checkmesh(m
vertex newsite
int done
REAL adxt_cdy0
sym(topleft, toplcasing)
trisize
bcy
REAL cdxt_bdyt0
REAL adxtail
vertex temp
stpivot(testsym, neighbortri)
REAL bctt[4]
REAL detsum vertex pa
int bytcalen
int tridest
REAL denom
vertex startvertex
REAL area
REAL bdxcdy0
REAL cytabtt[8]
return newtriangle
void edgecount
int rightofchild
int triflaws
INEXACT REAL bdxt_ady1
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside) void delaunayfixup(m
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri) enum locateresult locate(m
REAL rightccw
REAL trilongest2
REAL adytail
REAL ccwerrboundA
Definition triangle.cpp:649
REAL abdet[64]
vertex leftvertex
result
int encroached
REAL aytcc[8]
triangle ** holetri
int bytcclen
struct otri botleft botright
REAL dxda2
int ct_alen
REAL iccerrboundA
Definition triangle.cpp:650
vertex hdest
INEXACT REAL bt_clarge
INEXACT REAL adxt_cdy1
int changemade
vertex first
setvertexmark(newvertex, markT(*splitsubseg))
void regionplague(struct mesh *m, struct behavior *b, REAL attribute, REAL area) void regionplague(m
INEXACT REAL _k
org(horiz, rightvertex)
long population
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright) void divconqrecurse(m
REAL bround
REAL detsum
xdo
void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri) void testtriangle(m
REAL cytabt[16]
INEXACT REAL bb3
REAL cdxt_bdy0
int errorflag
void alternateaxes(vertex *sortarray, int arraysize, int axis) void alternateaxes(sortarray
int aspecttable[16]
int moveleft
int fronttri
REAL bdytail
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark) void insertsubseg(m
REAL byca[8]
vertex edest
oprev(deltriright, righttri)
void splittriangle(struct mesh *m, struct behavior *b, struct badtriang *badtri) void splittriangle(m
REAL dyod
triangle nexttri
called is pointed to *void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes) void dummyinit(m
REAL cxtaa[8]
struct splaynode * splay(struct mesh *m, struct splaynode *splaytree, vertex searchpoint, struct otri *searchtri) struct splaynode *splay(m
int current
vertex midvertex2
void vertices
REAL axxbc[16]
void t struct mesh * m
REAL topy
REAL radconst
REAL orient3d(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight) REAL orient3d(m
vertex dest1
struct otri fartri
acy
REAL longest
int axtbctlen
apex(top, farvertex)
INEXACT REAL cdxbdy1
REAL dxoff
REAL axbc[8]
void heapsize
struct osub testsym
INEXACT REAL adyt_cdx1
decode(t->tri[0], printtri)
struct osub toplsubseg toprsubseg
REAL dya
int finlength
REAL apexlen
cdx
void syntax()
struct badsubseg * badsubsegtraverse(struct mesh *m) struct badsubseg *badsubsegtraverse(m) struct mesh *m
REAL cdxbdy
int neighbor2
REAL bc[4]
REAL cdxady0
int doflip
int numberofsegments
struct osub printsh
REAL adet[32]
vertex eventvertex
int eventnum
INEXACT REAL cdxcdx1
return newseg
void quality_statistics(struct mesh *m, struct behavior *b) void quality_statistics(m
REAL v[4]
INEXACT REAL bdxt_adyt1
REAL * talist
struct splaynode bottommost
void plague(struct mesh *m, struct behavior *b) void plague(m
void markhull(struct mesh *m, struct behavior *b) void markhull(m
vertex delvertex
int aytbblen
vertex innerleftapex
REAL iccerrboundC
Definition triangle.cpp:650
struct otri oppotri
int flen
yac
INEXACT REAL ti1
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark) int scoutsegment(m
int acuteorg2
INEXACT REAL adyady1
REAL aytbct[16]
REAL blift
fprintf(outfile, "# Generated by")
void subsegdealloc(struct mesh *m, subseg *dyingsubseg) void subsegdealloc(m
int acutedest2
REAL pd
REAL triarea
struct osub brokensubseg
void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri, REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest) void enqueuebadtri(m
REAL fin2[1152]
int bxxcalen
int triangleattriblist
int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h) int scale_expansion_zeroelim(elen
int cxablen
REAL bytca[8]
struct otri * startghost
struct otri top
vertex regiondest
b firstnumber
int cxtablen
gettimeofday & tv0
void triangulate()
void trifree()