Logo ROOT   6.16/01
Reference Guide
triangle.c
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/* Copyright 1993, 1995, 1997, 1998, 2002, 2005 */
18/* Jonathan Richard Shewchuk */
19/* 2360 Woolsey #H */
20/* Berkeley, California 94705-1927 */
21/* jrs@cs.berkeley.edu */
22/* */
23/* This program may be freely redistributed under the condition that the */
24/* copyright notices (including this entire header and the copyright */
25/* notice printed when the `-h' switch is selected) are not removed, and */
26/* no compensation is received. Private, research, and institutional */
27/* use is free. You may distribute modified versions of this code UNDER */
28/* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */
29/* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */
30/* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */
31/* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */
32/* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */
33/* WITH THE AUTHOR. (If you are not directly supplying this code to a */
34/* customer, and you are instead telling them how they can obtain it for */
35/* free, then you are not required to make any arrangement with me.) */
36/* */
37/* Hypertext instructions for Triangle are available on the Web at */
38/* */
39/* http://www.cs.cmu.edu/~quake/triangle.html */
40/* */
41/* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */
42/* whatsoever. This code is provided "as-is". Use at your own risk. */
43/* */
44/* Some of the references listed below are marked with an asterisk. [*] */
45/* These references are available for downloading from the Web page */
46/* */
47/* http://www.cs.cmu.edu/~quake/triangle.research.html */
48/* */
49/* Three papers discussing aspects of Triangle are available. A short */
50/* overview appears in "Triangle: Engineering a 2D Quality Mesh */
51/* Generator and Delaunay Triangulator," in Applied Computational */
52/* Geometry: Towards Geometric Engineering, Ming C. Lin and Dinesh */
53/* Manocha, editors, Lecture Notes in Computer Science volume 1148, */
54/* pages 203-222, Springer-Verlag, Berlin, May 1996 (from the First ACM */
55/* Workshop on Applied Computational Geometry). [*] */
56/* */
57/* The algorithms are discussed in the greatest detail in "Delaunay */
58/* Refinement Algorithms for Triangular Mesh Generation," Computational */
59/* Geometry: Theory and Applications 22(1-3):21-74, May 2002. [*] */
60/* */
61/* More detail about the data structures may be found in my dissertation: */
62/* "Delaunay Refinement Mesh Generation," Ph.D. thesis, Technical Report */
63/* CMU-CS-97-137, School of Computer Science, Carnegie Mellon University, */
64/* Pittsburgh, Pennsylvania, 18 May 1997. [*] */
65/* */
66/* Triangle was created as part of the Quake Project in the School of */
67/* Computer Science at Carnegie Mellon University. For further */
68/* information, see Hesheng Bao, Jacobo Bielak, Omar Ghattas, Loukas F. */
69/* Kallivokas, David R. O'Hallaron, Jonathan R. Shewchuk, and Jifeng Xu, */
70/* "Large-scale Simulation of Elastic Wave Propagation in Heterogeneous */
71/* Media on Parallel Computers," Computer Methods in Applied Mechanics */
72/* and Engineering 152(1-2):85-102, 22 January 1998. */
73/* */
74/* Triangle's Delaunay refinement algorithm for quality mesh generation is */
75/* a hybrid of one due to Jim Ruppert, "A Delaunay Refinement Algorithm */
76/* for Quality 2-Dimensional Mesh Generation," Journal of Algorithms */
77/* 18(3):548-585, May 1995 [*], and one due to L. Paul Chew, "Guaranteed- */
78/* Quality Mesh Generation for Curved Surfaces," Proceedings of the Ninth */
79/* Annual Symposium on Computational Geometry (San Diego, California), */
80/* pages 274-280, Association for Computing Machinery, May 1993, */
81/* http://portal.acm.org/citation.cfm?id=161150 . */
82/* */
83/* The Delaunay refinement algorithm has been modified so that it meshes */
84/* domains with small input angles well, as described in Gary L. Miller, */
85/* Steven E. Pav, and Noel J. Walkington, "When and Why Ruppert's */
86/* Algorithm Works," Twelfth International Meshing Roundtable, pages */
87/* 91-102, Sandia National Laboratories, September 2003. [*] */
88/* */
89/* My implementation of the divide-and-conquer and incremental Delaunay */
90/* triangulation algorithms follows closely the presentation of Guibas */
91/* and Stolfi, even though I use a triangle-based data structure instead */
92/* of their quad-edge data structure. (In fact, I originally implemented */
93/* Triangle using the quad-edge data structure, but the switch to a */
94/* triangle-based data structure sped Triangle by a factor of two.) The */
95/* mesh manipulation primitives and the two aforementioned Delaunay */
96/* triangulation algorithms are described by Leonidas J. Guibas and Jorge */
97/* Stolfi, "Primitives for the Manipulation of General Subdivisions and */
98/* the Computation of Voronoi Diagrams," ACM Transactions on Graphics */
99/* 4(2):74-123, April 1985, http://portal.acm.org/citation.cfm?id=282923 .*/
100/* */
101/* Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai */
102/* Lee and Bruce J. Schachter, "Two Algorithms for Constructing the */
103/* Delaunay Triangulation," International Journal of Computer and */
104/* Information Science 9(3):219-242, 1980. Triangle's improvement of the */
105/* divide-and-conquer algorithm by alternating between vertical and */
106/* horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and- */
107/* Conquer Algorithm for Constructing Delaunay Triangulations," */
108/* Algorithmica 2(2):137-151, 1987. */
109/* */
110/* The incremental insertion algorithm was first proposed by C. L. Lawson, */
111/* "Software for C1 Surface Interpolation," in Mathematical Software III, */
112/* John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977. */
113/* For point location, I use the algorithm of Ernst P. Mucke, Isaac */
114/* Saias, and Binhai Zhu, "Fast Randomized Point Location Without */
115/* Preprocessing in Two- and Three-Dimensional Delaunay Triangulations," */
116/* Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
117/* ACM, May 1996. [*] If I were to randomize the order of vertex */
118/* insertion (I currently don't bother), their result combined with the */
119/* result of Kenneth L. Clarkson and Peter W. Shor, "Applications of */
120/* Random Sampling in Computational Geometry II," Discrete & */
121/* Computational Geometry 4(1):387-421, 1989, would yield an expected */
122/* O(n^{4/3}) bound on running time. */
123/* */
124/* The O(n log n) sweepline Delaunay triangulation algorithm is taken from */
125/* Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams", */
126/* Algorithmica 2(2):153-174, 1987. A random sample of edges on the */
127/* boundary of the triangulation are maintained in a splay tree for the */
128/* purpose of point location. Splay trees are described by Daniel */
129/* Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
130/* Trees," Journal of the ACM 32(3):652-686, July 1985, */
131/* http://portal.acm.org/citation.cfm?id=3835 . */
132/* */
133/* The algorithms for exact computation of the signs of determinants are */
134/* described in Jonathan Richard Shewchuk, "Adaptive Precision Floating- */
135/* Point Arithmetic and Fast Robust Geometric Predicates," Discrete & */
136/* Computational Geometry 18(3):305-363, October 1997. (Also available */
137/* as Technical Report CMU-CS-96-140, School of Computer Science, */
138/* Carnegie Mellon University, Pittsburgh, Pennsylvania, May 1996.) [*] */
139/* An abbreviated version appears as Jonathan Richard Shewchuk, "Robust */
140/* Adaptive Floating-Point Geometric Predicates," Proceedings of the */
141/* Twelfth Annual Symposium on Computational Geometry, ACM, May 1996. [*] */
142/* Many of the ideas for my exact arithmetic routines originate with */
143/* Douglas M. Priest, "Algorithms for Arbitrary Precision Floating Point */
144/* Arithmetic," Tenth Symposium on Computer Arithmetic, pp. 132-143, IEEE */
145/* Computer Society Press, 1991. [*] Many of the ideas for the correct */
146/* evaluation of the signs of determinants are taken from Steven Fortune */
147/* and Christopher J. Van Wyk, "Efficient Exact Arithmetic for Computa- */
148/* tional Geometry," Proceedings of the Ninth Annual Symposium on */
149/* Computational Geometry, ACM, pp. 163-172, May 1993, and from Steven */
150/* Fortune, "Numerical Stability of Algorithms for 2D Delaunay Triangu- */
151/* lations," International Journal of Computational Geometry & Applica- */
152/* tions 5(1-2):193-213, March-June 1995. */
153/* */
154/* The method of inserting new vertices off-center (not precisely at the */
155/* circumcenter of every poor-quality triangle) is from Alper Ungor, */
156/* "Off-centers: A New Type of Steiner Points for Computing Size-Optimal */
157/* Quality-Guaranteed Delaunay Triangulations," Proceedings of LATIN */
158/* 2004 (Buenos Aires, Argentina), April 2004. */
159/* */
160/* For definitions of and results involving Delaunay triangulations, */
161/* constrained and conforming versions thereof, and other aspects of */
162/* triangular mesh generation, see the excellent survey by Marshall Bern */
163/* and David Eppstein, "Mesh Generation and Optimal Triangulation," in */
164/* Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang, */
165/* editors, World Scientific, Singapore, pp. 23-90, 1992. [*] */
166/* */
167/* The time for incrementally adding PSLG (planar straight line graph) */
168/* segments to create a constrained Delaunay triangulation is probably */
169/* O(t^2) per segment in the worst case and O(t) per segment in the */
170/* common case, where t is the number of triangles that intersect the */
171/* segment before it is inserted. This doesn't count point location, */
172/* which can be much more expensive. I could improve this to O(d log d) */
173/* time, but d is usually quite small, so it's not worth the bother. */
174/* (This note does not apply when the -s switch is used, invoking a */
175/* different method is used to insert segments.) */
176/* */
177/* The time for deleting a vertex from a Delaunay triangulation is O(d^2) */
178/* in the worst case and O(d) in the common case, where d is the degree */
179/* of the vertex being deleted. I could improve this to O(d log d) time, */
180/* but d is usually quite small, so it's not worth the bother. */
181/* */
182/* Ruppert's Delaunay refinement algorithm typically generates triangles */
183/* at a linear rate (constant time per triangle) after the initial */
184/* triangulation is formed. There may be pathological cases where */
185/* quadratic time is required, but these never arise in practice. */
186/* */
187/* The geometric predicates (circumcenter calculations, segment */
188/* intersection formulae, etc.) appear in my "Lecture Notes on Geometric */
189/* Robustness" at http://www.cs.berkeley.edu/~jrs/mesh . */
190/* */
191/* If you make any improvements to this code, please please please let me */
192/* know, so that I may obtain the improvements. Even if you don't change */
193/* the code, I'd still love to hear what it's being used for. */
194/* */
195/*****************************************************************************/
196
197/* If yours is not a Unix system, define the NO_TIMER compiler switch to */
198/* remove the Unix-specific timing code. */
199
200#define NO_TIMER
201
202/* To insert lots of self-checks for internal errors, define the SELF_CHECK */
203/* symbol. This will slow down the program significantly. It is best to */
204/* define the symbol using the -DSELF_CHECK compiler switch, but you could */
205/* write "#define SELF_CHECK" below. If you are modifying this code, I */
206/* recommend you turn self-checks on until your work is debugged. */
207
208/* #define SELF_CHECK */
209
210/* To compile Triangle as a callable object library (triangle.o), define the */
211/* TRILIBRARY symbol. Read the file triangle.h for details on how to call */
212/* the procedure triangulate() that results. */
213
214#define TRILIBRARY
215
216/* It is possible to generate a smaller version of Triangle using one or */
217/* both of the following symbols. Define the REDUCED symbol to eliminate */
218/* all features that are primarily of research interest; specifically, the */
219/* -i, -F, -s, and -C switches. Define the CDT_ONLY symbol to eliminate */
220/* all meshing algorithms above and beyond constrained Delaunay */
221/* triangulation; specifically, the -r, -q, -a, -u, -D, -S, and -s */
222/* switches. These reductions are most likely to be useful when */
223/* generating an object library (triangle.o) by defining the TRILIBRARY */
224/* symbol. */
225
226#define REDUCED
227#define CDT_ONLY
228
229/* On some machines, my exact arithmetic routines might be defeated by the */
230/* use of internal extended precision floating-point registers. The best */
231/* way to solve this problem is to set the floating-point registers to use */
232/* single or double precision internally. On 80x86 processors, this may */
233/* be accomplished by setting the CPU86 symbol for the Microsoft C */
234/* compiler, or the LINUX symbol for the gcc compiler running on Linux. */
235/* */
236/* An inferior solution is to declare certain values as `volatile', thus */
237/* forcing them to be stored to memory and rounded off. Unfortunately, */
238/* this solution might slow Triangle down quite a bit. To use volatile */
239/* values, write "#define INEXACT volatile" below. Normally, however, */
240/* INEXACT should be defined to be nothing. ("#define INEXACT".) */
241/* */
242/* For more discussion, see http://www.cs.cmu.edu/~quake/robust.pc.html . */
243/* For yet more discussion, see Section 5 of my paper, "Adaptive Precision */
244/* Floating-Point Arithmetic and Fast Robust Geometric Predicates" (also */
245/* available as Section 6.6 of my dissertation). */
246
247/* #define CPU86 */
248/* #define LINUX */
249
250#define INEXACT /* Nothing */
251/* #define INEXACT volatile */
252
253/* Maximum number of characters in a file name (including the null). */
254
255#define FILENAMESIZE 2048
256
257/* Maximum number of characters in a line read from a file (including the */
258/* null). */
259
260#define INPUTLINESIZE 1024
261
262/* For efficiency, a variety of data structures are allocated in bulk. The */
263/* following constants determine how many of each structure is allocated */
264/* at once. */
265
266#define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */
267#define SUBSEGPERBLOCK 508 /* Number of subsegments allocated at once. */
268#define VERTEXPERBLOCK 4092 /* Number of vertices allocated at once. */
269#define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */
270/* Number of encroached subsegments allocated at once. */
271#define BADSUBSEGPERBLOCK 252
272/* Number of skinny triangles allocated at once. */
273#define BADTRIPERBLOCK 4092
274/* Number of flipped triangles allocated at once. */
275#define FLIPSTACKERPERBLOCK 252
276/* Number of splay tree nodes allocated at once. */
277#define SPLAYNODEPERBLOCK 508
278
279/* The vertex types. A DEADVERTEX has been deleted entirely. An */
280/* UNDEADVERTEX is not part of the mesh, but is written to the output */
281/* .node file and affects the node indexing in the other output files. */
282
283#define INPUTVERTEX 0
284#define SEGMENTVERTEX 1
285#define FREEVERTEX 2
286#define DEADVERTEX -32768
287#define UNDEADVERTEX -32767
288
289/* Two constants for algorithms based on random sampling. Both constants */
290/* have been chosen empirically to optimize their respective algorithms. */
291
292/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */
293/* how large a random sample of triangles to inspect. */
294
295#define SAMPLEFACTOR 11
296
297/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
298/* of boundary edges should be maintained in the splay tree for point */
299/* location on the front. */
300
301#define SAMPLERATE 10
302
303/* A number that speaks for itself, every kissable digit. */
304
305#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
306
307/* Another fave. */
308
309#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
310
311/* And here's one for those of you who are intimidated by math. */
312
313#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
314
315#include <stdio.h>
316#include <stdlib.h>
317#include <string.h>
318#include <math.h>
319#ifndef NO_TIMER
320#include <sys/time.h>
321#endif /* not NO_TIMER */
322#ifdef CPU86
323#include <float.h>
324#endif /* CPU86 */
325#ifdef LINUX
326#include <fpu_control.h>
327#endif /* LINUX */
328#ifdef TRILIBRARY
329#include "triangle.h"
330#endif /* TRILIBRARY */
331
332/* A few forward declarations. */
333
334#ifndef TRILIBRARY
335char *readline();
336char *findfield();
337#endif /* not TRILIBRARY */
338
339/* Labels that signify the result of point location. The result of a */
340/* search indicates that the point falls in the interior of a triangle, on */
341/* an edge, on a vertex, or outside the mesh. */
342
344
345/* Labels that signify the result of vertex insertion. The result indicates */
346/* that the vertex was inserted with complete success, was inserted but */
347/* encroaches upon a subsegment, was not inserted because it lies on a */
348/* segment, or was not inserted because another vertex occupies the same */
349/* location. */
350
353
354/* Labels that signify the result of direction finding. The result */
355/* indicates that a segment connecting the two query points falls within */
356/* the direction triangle, along the left edge of the direction triangle, */
357/* or along the right edge of the direction triangle. */
358
360
361/*****************************************************************************/
362/* */
363/* The basic mesh data structures */
364/* */
365/* There are three: vertices, triangles, and subsegments (abbreviated */
366/* `subseg'). These three data structures, linked by pointers, comprise */
367/* the mesh. A vertex simply represents a mesh vertex and its properties. */
368/* A triangle is a triangle. A subsegment is a special data structure used */
369/* to represent an impenetrable edge of the mesh (perhaps on the outer */
370/* boundary, on the boundary of a hole, or part of an internal boundary */
371/* separating two triangulated regions). Subsegments represent boundaries, */
372/* defined by the user, that triangles may not lie across. */
373/* */
374/* A triangle consists of a list of three vertices, a list of three */
375/* adjoining triangles, a list of three adjoining subsegments (when */
376/* segments exist), an arbitrary number of optional user-defined */
377/* floating-point attributes, and an optional area constraint. The latter */
378/* is an upper bound on the permissible area of each triangle in a region, */
379/* used for mesh refinement. */
380/* */
381/* For a triangle on a boundary of the mesh, some or all of the neighboring */
382/* triangles may not be present. For a triangle in the interior of the */
383/* mesh, often no neighboring subsegments are present. Such absent */
384/* triangles and subsegments are never represented by NULL pointers; they */
385/* are represented by two special records: `dummytri', the triangle that */
386/* fills "outer space", and `dummysub', the omnipresent subsegment. */
387/* `dummytri' and `dummysub' are used for several reasons; for instance, */
388/* they can be dereferenced and their contents examined without violating */
389/* protected memory. */
390/* */
391/* However, it is important to understand that a triangle includes other */
392/* information as well. The pointers to adjoining vertices, triangles, and */
393/* subsegments are ordered in a way that indicates their geometric relation */
394/* to each other. Furthermore, each of these pointers contains orientation */
395/* information. Each pointer to an adjoining triangle indicates which face */
396/* of that triangle is contacted. Similarly, each pointer to an adjoining */
397/* subsegment indicates which side of that subsegment is contacted, and how */
398/* the subsegment is oriented relative to the triangle. */
399/* */
400/* The data structure representing a subsegment may be thought to be */
401/* abutting the edge of one or two triangle data structures: either */
402/* sandwiched between two triangles, or resting against one triangle on an */
403/* exterior boundary or hole boundary. */
404/* */
405/* A subsegment consists of a list of four vertices--the vertices of the */
406/* subsegment, and the vertices of the segment it is a part of--a list of */
407/* two adjoining subsegments, and a list of two adjoining triangles. One */
408/* of the two adjoining triangles may not be present (though there should */
409/* always be one), and neighboring subsegments might not be present. */
410/* Subsegments also store a user-defined integer "boundary marker". */
411/* Typically, this integer is used to indicate what boundary conditions are */
412/* to be applied at that location in a finite element simulation. */
413/* */
414/* Like triangles, subsegments maintain information about the relative */
415/* orientation of neighboring objects. */
416/* */
417/* Vertices are relatively simple. A vertex is a list of floating-point */
418/* numbers, starting with the x, and y coordinates, followed by an */
419/* arbitrary number of optional user-defined floating-point attributes, */
420/* followed by an integer boundary marker. During the segment insertion */
421/* phase, there is also a pointer from each vertex to a triangle that may */
422/* contain it. Each pointer is not always correct, but when one is, it */
423/* speeds up segment insertion. These pointers are assigned values once */
424/* at the beginning of the segment insertion phase, and are not used or */
425/* updated except during this phase. Edge flipping during segment */
426/* insertion will render some of them incorrect. Hence, don't rely upon */
427/* them for anything. */
428/* */
429/* Other than the exception mentioned above, vertices have no information */
430/* about what triangles, subfacets, or subsegments they are linked to. */
431/* */
432/*****************************************************************************/
433
434/*****************************************************************************/
435/* */
436/* Handles */
437/* */
438/* The oriented triangle (`otri') and oriented subsegment (`osub') data */
439/* structures defined below do not themselves store any part of the mesh. */
440/* The mesh itself is made of `triangle's, `subseg's, and `vertex's. */
441/* */
442/* Oriented triangles and oriented subsegments will usually be referred to */
443/* as "handles." A handle is essentially a pointer into the mesh; it */
444/* allows you to "hold" one particular part of the mesh. Handles are used */
445/* to specify the regions in which one is traversing and modifying the mesh.*/
446/* A single `triangle' may be held by many handles, or none at all. (The */
447/* latter case is not a memory leak, because the triangle is still */
448/* connected to other triangles in the mesh.) */
449/* */
450/* An `otri' is a handle that holds a triangle. It holds a specific edge */
451/* of the triangle. An `osub' is a handle that holds a subsegment. It */
452/* holds either the left or right side of the subsegment. */
453/* */
454/* Navigation about the mesh is accomplished through a set of mesh */
455/* manipulation primitives, further below. Many of these primitives take */
456/* a handle and produce a new handle that holds the mesh near the first */
457/* handle. Other primitives take two handles and glue the corresponding */
458/* parts of the mesh together. The orientation of the handles is */
459/* important. For instance, when two triangles are glued together by the */
460/* bond() primitive, they are glued at the edges on which the handles lie. */
461/* */
462/* Because vertices have no information about which triangles they are */
463/* attached to, I commonly represent a vertex by use of a handle whose */
464/* origin is the vertex. A single handle can simultaneously represent a */
465/* triangle, an edge, and a vertex. */
466/* */
467/*****************************************************************************/
468
469/* The triangle data structure. Each triangle contains three pointers to */
470/* adjoining triangles, plus three pointers to vertices, plus three */
471/* pointers to subsegments (declared below; these pointers are usually */
472/* `dummysub'). It may or may not also contain user-defined attributes */
473/* and/or a floating-point "area constraint." It may also contain extra */
474/* pointers for nodes, when the user asks for high-order elements. */
475/* Because the size and structure of a `triangle' is not decided until */
476/* runtime, I haven't simply declared the type `triangle' as a struct. */
477
478typedef REAL **triangle; /* Really: typedef triangle *triangle */
479
480/* An oriented triangle: includes a pointer to a triangle and orientation. */
481/* The orientation denotes an edge of the triangle. Hence, there are */
482/* three possible orientations. By convention, each edge always points */
483/* counterclockwise about the corresponding triangle. */
484
485struct otri {
486 triangle *tri;
487 int orient; /* Ranges from 0 to 2. */
488};
489
490/* The subsegment data structure. Each subsegment contains two pointers to */
491/* adjoining subsegments, plus four pointers to vertices, plus two */
492/* pointers to adjoining triangles, plus one boundary marker, plus one */
493/* segment number. */
494
495typedef REAL **subseg; /* Really: typedef subseg *subseg */
496
497/* An oriented subsegment: includes a pointer to a subsegment and an */
498/* orientation. The orientation denotes a side of the edge. Hence, there */
499/* are two possible orientations. By convention, the edge is always */
500/* directed so that the "side" denoted is the right side of the edge. */
501
502struct osub {
503 subseg *ss;
504 int ssorient; /* Ranges from 0 to 1. */
505};
506
507/* The vertex data structure. Each vertex is actually an array of REALs. */
508/* The number of REALs is unknown until runtime. An integer boundary */
509/* marker, and sometimes a pointer to a triangle, is appended after the */
510/* REALs. */
511
512typedef REAL *vertex;
513
514/* A queue used to store encroached subsegments. Each subsegment's vertices */
515/* are stored so that we can check whether a subsegment is still the same. */
516
517struct badsubseg {
518 subseg encsubseg; /* An encroached subsegment. */
519 vertex subsegorg, subsegdest; /* Its two vertices. */
520};
521
522/* A queue used to store bad triangles. The key is the square of the cosine */
523/* of the smallest angle of the triangle. Each triangle's vertices are */
524/* stored so that one can check whether a triangle is still the same. */
525
526struct badtriang {
527 triangle poortri; /* A skinny or too-large triangle. */
528 REAL key; /* cos^2 of smallest (apical) angle. */
529 vertex triangorg, triangdest, triangapex; /* Its three vertices. */
530 struct badtriang *nexttriang; /* Pointer to next bad triangle. */
531};
532
533/* A stack of triangles flipped during the most recent vertex insertion. */
534/* The stack is used to undo the vertex insertion if the vertex encroaches */
535/* upon a subsegment. */
536
537struct flipstacker {
538 triangle flippedtri; /* A recently flipped triangle. */
539 struct flipstacker *prevflip; /* Previous flip in the stack. */
540};
541
542/* A node in a heap used to store events for the sweepline Delaunay */
543/* algorithm. Nodes do not point directly to their parents or children in */
544/* the heap. Instead, each node knows its position in the heap, and can */
545/* look up its parent and children in a separate array. The `eventptr' */
546/* points either to a `vertex' or to a triangle (in encoded format, so */
547/* that an orientation is included). In the latter case, the origin of */
548/* the oriented triangle is the apex of a "circle event" of the sweepline */
549/* algorithm. To distinguish site events from circle events, all circle */
550/* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */
551
552struct event {
553 REAL xkey, ykey; /* Coordinates of the event. */
554 VOID *eventptr; /* Can be a vertex or the location of a circle event. */
555 int heapposition; /* Marks this event's position in the heap. */
556};
557
558/* A node in the splay tree. Each node holds an oriented ghost triangle */
559/* that represents a boundary edge of the growing triangulation. When a */
560/* circle event covers two boundary edges with a triangle, so that they */
561/* are no longer boundary edges, those edges are not immediately deleted */
562/* from the tree; rather, they are lazily deleted when they are next */
563/* encountered. (Since only a random sample of boundary edges are kept */
564/* in the tree, lazy deletion is faster.) `keydest' is used to verify */
565/* that a triangle is still the same as when it entered the splay tree; if */
566/* it has been rotated (due to a circle event), it no longer represents a */
567/* boundary edge and should be deleted. */
568
569struct splaynode {
570 struct otri keyedge; /* Lprev of an edge on the front. */
571 vertex keydest; /* Used to verify that splay node is still live. */
572 struct splaynode *lchild, *rchild; /* Children in splay tree. */
573};
574
575/* A type used to allocate memory. firstblock is the first block of items. */
576/* nowblock is the block from which items are currently being allocated. */
577/* nextitem points to the next slab of free memory for an item. */
578/* deaditemstack is the head of a linked list (stack) of deallocated items */
579/* that can be recycled. unallocateditems is the number of items that */
580/* remain to be allocated from nowblock. */
581/* */
582/* Traversal is the process of walking through the entire list of items, and */
583/* is separate from allocation. Note that a traversal will visit items on */
584/* the "deaditemstack" stack as well as live items. pathblock points to */
585/* the block currently being traversed. pathitem points to the next item */
586/* to be traversed. pathitemsleft is the number of items that remain to */
587/* be traversed in pathblock. */
588/* */
589/* alignbytes determines how new records should be aligned in memory. */
590/* itembytes is the length of a record in bytes (after rounding up). */
591/* itemsperblock is the number of items allocated at once in a single */
592/* block. itemsfirstblock is the number of items in the first block, */
593/* which can vary from the others. items is the number of currently */
594/* allocated items. maxitems is the maximum number of items that have */
595/* been allocated at once; it is the current number of items plus the */
596/* number of records kept on deaditemstack. */
597
598struct memorypool {
599 VOID **firstblock, **nowblock;
600 VOID *nextitem;
601 VOID *deaditemstack;
602 VOID **pathblock;
603 VOID *pathitem;
604 int alignbytes;
605 int itembytes;
606 int itemsperblock;
607 int itemsfirstblock;
608 long items, maxitems;
609 int unallocateditems;
610 int pathitemsleft;
611};
612
613
614/* Global constants. */
615
616REAL splitter; /* Used to split REAL factors for exact multiplication. */
617REAL epsilon; /* Floating-point machine epsilon. */
622
623/* Random number seed is not constant, but I've made it global anyway. */
624
625unsigned long randomseed; /* Current random number seed. */
626
627
628/* Mesh data structure. Triangle operates on only one mesh, but the mesh */
629/* structure is used (instead of global variables) to allow reentrancy. */
630
631struct mesh {
632
633/* Variables used to allocate memory for triangles, subsegments, vertices, */
634/* viri (triangles being eaten), encroached segments, bad (skinny or too */
635/* large) triangles, and splay tree nodes. */
636
637 struct memorypool triangles;
638 struct memorypool subsegs;
639 struct memorypool vertices;
640 struct memorypool viri;
641 struct memorypool badsubsegs;
642 struct memorypool badtriangles;
643 struct memorypool flipstackers;
644 struct memorypool splaynodes;
645
646/* Variables that maintain the bad triangle queues. The queues are */
647/* ordered from 4095 (highest priority) to 0 (lowest priority). */
648
649 struct badtriang *queuefront[4096];
650 struct badtriang *queuetail[4096];
651 int nextnonemptyq[4096];
652 int firstnonemptyq;
653
654/* Variable that maintains the stack of recently flipped triangles. */
655
656 struct flipstacker *lastflip;
657
658/* Other variables. */
659
660 REAL xmin, xmax, ymin, ymax; /* x and y bounds. */
661 REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */
662 int invertices; /* Number of input vertices. */
663 int inelements; /* Number of input triangles. */
664 int insegments; /* Number of input segments. */
665 int holes; /* Number of input holes. */
666 int regions; /* Number of input regions. */
667 int undeads; /* Number of input vertices that don't appear in the mesh. */
668 long edges; /* Number of output edges. */
669 int mesh_dim; /* Dimension (ought to be 2). */
670 int nextras; /* Number of attributes per vertex. */
671 int eextras; /* Number of attributes per triangle. */
672 long hullsize; /* Number of edges in convex hull. */
673 int steinerleft; /* Number of Steiner points not yet used. */
674 int vertexmarkindex; /* Index to find boundary marker of a vertex. */
675 int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */
676 int highorderindex; /* Index to find extra nodes for high-order elements. */
677 int elemattribindex; /* Index to find attributes of a triangle. */
678 int areaboundindex; /* Index to find area bound of a triangle. */
679 int checksegments; /* Are there segments in the triangulation yet? */
680 int checkquality; /* Has quality triangulation begun yet? */
681 int readnodefile; /* Has a .node file been read? */
682 long samples; /* Number of random samples for point location. */
683
684 long incirclecount; /* Number of incircle tests performed. */
685 long counterclockcount; /* Number of counterclockwise tests performed. */
686 long orient3dcount; /* Number of 3D orientation tests performed. */
687 long hyperbolacount; /* Number of right-of-hyperbola tests performed. */
688 long circumcentercount; /* Number of circumcenter calculations performed. */
689 long circletopcount; /* Number of circle top calculations performed. */
690
691/* Triangular bounding box vertices. */
692
693 vertex infvertex1, infvertex2, infvertex3;
694
695/* Pointer to the `triangle' that occupies all of "outer space." */
696
697 triangle *dummytri;
698 triangle *dummytribase; /* Keep base address so we can free() it later. */
699
700/* Pointer to the omnipresent subsegment. Referenced by any triangle or */
701/* subsegment that isn't really connected to a subsegment at that */
702/* location. */
703
704 subseg *dummysub;
705 subseg *dummysubbase; /* Keep base address so we can free() it later. */
706
707/* Pointer to a recently visited triangle. Improves point location if */
708/* proximate vertices are inserted sequentially. */
709
710 struct otri recenttri;
711
712}; /* End of `struct mesh'. */
713
714
715/* Data structure for command line switches and file names. This structure */
716/* is used (instead of global variables) to allow reentrancy. */
717
718struct behavior {
719
720/* Switches for the triangulator. */
721/* poly: -p switch. refine: -r switch. */
722/* quality: -q switch. */
723/* minangle: minimum angle bound, specified after -q switch. */
724/* goodangle: cosine squared of minangle. */
725/* offconstant: constant used to place off-center Steiner points. */
726/* vararea: -a switch without number. */
727/* fixedarea: -a switch with number. */
728/* maxarea: maximum area bound, specified after -a switch. */
729/* usertest: -u switch. */
730/* regionattrib: -A switch. convex: -c switch. */
731/* weighted: 1 for -w switch, 2 for -W switch. jettison: -j switch */
732/* firstnumber: inverse of -z switch. All items are numbered starting */
733/* from `firstnumber'. */
734/* edgesout: -e switch. voronoi: -v switch. */
735/* neighbors: -n switch. geomview: -g switch. */
736/* nobound: -B switch. nopolywritten: -P switch. */
737/* nonodewritten: -N switch. noelewritten: -E switch. */
738/* noiterationnum: -I switch. noholes: -O switch. */
739/* noexact: -X switch. */
740/* order: element order, specified after -o switch. */
741/* nobisect: count of how often -Y switch is selected. */
742/* steiner: maximum number of Steiner points, specified after -S switch. */
743/* incremental: -i switch. sweepline: -F switch. */
744/* dwyer: inverse of -l switch. */
745/* splitseg: -s switch. */
746/* conformdel: -D switch. docheck: -C switch. */
747/* quiet: -Q switch. verbose: count of how often -V switch is selected. */
748/* usesegments: -p, -r, -q, or -c switch; determines whether segments are */
749/* used at all. */
750/* */
751/* Read the instructions to find out the meaning of these switches. */
752
753 int poly, refine, quality, vararea, fixedarea, usertest;
754 int regionattrib, convex, weighted, jettison;
755 int firstnumber;
756 int edgesout, voronoi, neighbors, geomview;
757 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
758 int noholes, noexact, conformdel;
759 int incremental, sweepline, dwyer;
760 int splitseg;
761 int docheck;
762 int quiet, verbose;
763 int usesegments;
764 int order;
765 int nobisect;
766 int steiner;
767 REAL minangle, goodangle, offconstant;
768 REAL maxarea;
769
770/* Variables for file names. */
771
772#ifndef TRILIBRARY
773 char innodefilename[FILENAMESIZE];
774 char inelefilename[FILENAMESIZE];
775 char inpolyfilename[FILENAMESIZE];
776 char areafilename[FILENAMESIZE];
777 char outnodefilename[FILENAMESIZE];
778 char outelefilename[FILENAMESIZE];
779 char outpolyfilename[FILENAMESIZE];
780 char edgefilename[FILENAMESIZE];
781 char vnodefilename[FILENAMESIZE];
782 char vedgefilename[FILENAMESIZE];
783 char neighborfilename[FILENAMESIZE];
784 char offfilename[FILENAMESIZE];
785#endif /* not TRILIBRARY */
786
787}; /* End of `struct behavior'. */
788
789
790/*****************************************************************************/
791/* */
792/* Mesh manipulation primitives. Each triangle contains three pointers to */
793/* other triangles, with orientations. Each pointer points not to the */
794/* first byte of a triangle, but to one of the first three bytes of a */
795/* triangle. It is necessary to extract both the triangle itself and the */
796/* orientation. To save memory, I keep both pieces of information in one */
797/* pointer. To make this possible, I assume that all triangles are aligned */
798/* to four-byte boundaries. The decode() routine below decodes a pointer, */
799/* extracting an orientation (in the range 0 to 2) and a pointer to the */
800/* beginning of a triangle. The encode() routine compresses a pointer to a */
801/* triangle and an orientation into a single pointer. My assumptions that */
802/* triangles are four-byte-aligned and that the `unsigned long' type is */
803/* long enough to hold a pointer are two of the few kludges in this program.*/
804/* */
805/* Subsegments are manipulated similarly. A pointer to a subsegment */
806/* carries both an address and an orientation in the range 0 to 1. */
807/* */
808/* The other primitives take an oriented triangle or oriented subsegment, */
809/* and return an oriented triangle or oriented subsegment or vertex; or */
810/* they change the connections in the data structure. */
811/* */
812/* Below, triangles and subsegments are denoted by their vertices. The */
813/* triangle abc has origin (org) a, destination (dest) b, and apex (apex) */
814/* c. These vertices occur in counterclockwise order about the triangle. */
815/* The handle abc may simultaneously denote vertex a, edge ab, and triangle */
816/* abc. */
817/* */
818/* Similarly, the subsegment ab has origin (sorg) a and destination (sdest) */
819/* b. If ab is thought to be directed upward (with b directly above a), */
820/* then the handle ab is thought to grasp the right side of ab, and may */
821/* simultaneously denote vertex a and edge ab. */
822/* */
823/* An asterisk (*) denotes a vertex whose identity is unknown. */
824/* */
825/* Given this notation, a partial list of mesh manipulation primitives */
826/* follows. */
827/* */
828/* */
829/* For triangles: */
830/* */
831/* sym: Find the abutting triangle; same edge. */
832/* sym(abc) -> ba* */
833/* */
834/* lnext: Find the next edge (counterclockwise) of a triangle. */
835/* lnext(abc) -> bca */
836/* */
837/* lprev: Find the previous edge (clockwise) of a triangle. */
838/* lprev(abc) -> cab */
839/* */
840/* onext: Find the next edge counterclockwise with the same origin. */
841/* onext(abc) -> ac* */
842/* */
843/* oprev: Find the next edge clockwise with the same origin. */
844/* oprev(abc) -> a*b */
845/* */
846/* dnext: Find the next edge counterclockwise with the same destination. */
847/* dnext(abc) -> *ba */
848/* */
849/* dprev: Find the next edge clockwise with the same destination. */
850/* dprev(abc) -> cb* */
851/* */
852/* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */
853/* rnext(abc) -> *a* */
854/* */
855/* rprev: Find the previous edge (clockwise) of the adjacent triangle. */
856/* rprev(abc) -> b** */
857/* */
858/* org: Origin dest: Destination apex: Apex */
859/* org(abc) -> a dest(abc) -> b apex(abc) -> c */
860/* */
861/* bond: Bond two triangles together at the resepective handles. */
862/* bond(abc, bad) */
863/* */
864/* */
865/* For subsegments: */
866/* */
867/* ssym: Reverse the orientation of a subsegment. */
868/* ssym(ab) -> ba */
869/* */
870/* spivot: Find adjoining subsegment with the same origin. */
871/* spivot(ab) -> a* */
872/* */
873/* snext: Find next subsegment in sequence. */
874/* snext(ab) -> b* */
875/* */
876/* sorg: Origin sdest: Destination */
877/* sorg(ab) -> a sdest(ab) -> b */
878/* */
879/* sbond: Bond two subsegments together at the respective origins. */
880/* sbond(ab, ac) */
881/* */
882/* */
883/* For interacting tetrahedra and subfacets: */
884/* */
885/* tspivot: Find a subsegment abutting a triangle. */
886/* tspivot(abc) -> ba */
887/* */
888/* stpivot: Find a triangle abutting a subsegment. */
889/* stpivot(ab) -> ba* */
890/* */
891/* tsbond: Bond a triangle to a subsegment. */
892/* tsbond(abc, ba) */
893/* */
894/*****************************************************************************/
895
896/********* Mesh manipulation primitives begin here *********/
897/** **/
898/** **/
899
900/* Fast lookup arrays to speed some of the mesh manipulation primitives. */
901
902int plus1mod3[3] = {1, 2, 0};
903int minus1mod3[3] = {2, 0, 1};
904
905/********* Primitives for triangles *********/
906/* */
907/* */
908
909/* decode() converts a pointer to an oriented triangle. The orientation is */
910/* extracted from the two least significant bits of the pointer. */
911
912#define decode(ptr, otri) \
913 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
914 (otri).tri = (triangle *) \
915 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
916
917/* encode() compresses an oriented triangle into a single pointer. It */
918/* relies on the assumption that all triangles are aligned to four-byte */
919/* boundaries, so the two least significant bits of (otri).tri are zero. */
920
921#define encode(otri) \
922 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
923
924/* The following handle manipulation primitives are all described by Guibas */
925/* and Stolfi. However, Guibas and Stolfi use an edge-based data */
926/* structure, whereas I use a triangle-based data structure. */
927
928/* sym() finds the abutting triangle, on the same edge. Note that the edge */
929/* direction is necessarily reversed, because the handle specified by an */
930/* oriented triangle is directed counterclockwise around the triangle. */
931
932#define sym(otri1, otri2) \
933 ptr = (otri1).tri[(otri1).orient]; \
934 decode(ptr, otri2);
935
936#define symself(otri) \
937 ptr = (otri).tri[(otri).orient]; \
938 decode(ptr, otri);
939
940/* lnext() finds the next edge (counterclockwise) of a triangle. */
941
942#define lnext(otri1, otri2) \
943 (otri2).tri = (otri1).tri; \
944 (otri2).orient = plus1mod3[(otri1).orient]
945
946#define lnextself(otri) \
947 (otri).orient = plus1mod3[(otri).orient]
948
949/* lprev() finds the previous edge (clockwise) of a triangle. */
950
951#define lprev(otri1, otri2) \
952 (otri2).tri = (otri1).tri; \
953 (otri2).orient = minus1mod3[(otri1).orient]
954
955#define lprevself(otri) \
956 (otri).orient = minus1mod3[(otri).orient]
957
958/* onext() spins counterclockwise around a vertex; that is, it finds the */
959/* next edge with the same origin in the counterclockwise direction. This */
960/* edge is part of a different triangle. */
961
962#define onext(otri1, otri2) \
963 lprev(otri1, otri2); \
964 symself(otri2);
965
966#define onextself(otri) \
967 lprevself(otri); \
968 symself(otri);
969
970/* oprev() spins clockwise around a vertex; that is, it finds the next edge */
971/* with the same origin in the clockwise direction. This edge is part of */
972/* a different triangle. */
973
974#define oprev(otri1, otri2) \
975 sym(otri1, otri2); \
976 lnextself(otri2);
977
978#define oprevself(otri) \
979 symself(otri); \
980 lnextself(otri);
981
982/* dnext() spins counterclockwise around a vertex; that is, it finds the */
983/* next edge with the same destination in the counterclockwise direction. */
984/* This edge is part of a different triangle. */
985
986#define dnext(otri1, otri2) \
987 sym(otri1, otri2); \
988 lprevself(otri2);
989
990#define dnextself(otri) \
991 symself(otri); \
992 lprevself(otri);
993
994/* dprev() spins clockwise around a vertex; that is, it finds the next edge */
995/* with the same destination in the clockwise direction. This edge is */
996/* part of a different triangle. */
997
998#define dprev(otri1, otri2) \
999 lnext(otri1, otri2); \
1000 symself(otri2);
1001
1002#define dprevself(otri) \
1003 lnextself(otri); \
1004 symself(otri);
1005
1006/* rnext() moves one edge counterclockwise about the adjacent triangle. */
1007/* (It's best understood by reading Guibas and Stolfi. It involves */
1008/* changing triangles twice.) */
1009
1010#define rnext(otri1, otri2) \
1011 sym(otri1, otri2); \
1012 lnextself(otri2); \
1013 symself(otri2);
1014
1015#define rnextself(otri) \
1016 symself(otri); \
1017 lnextself(otri); \
1018 symself(otri);
1019
1020/* rprev() moves one edge clockwise about the adjacent triangle. */
1021/* (It's best understood by reading Guibas and Stolfi. It involves */
1022/* changing triangles twice.) */
1023
1024#define rprev(otri1, otri2) \
1025 sym(otri1, otri2); \
1026 lprevself(otri2); \
1027 symself(otri2);
1028
1029#define rprevself(otri) \
1030 symself(otri); \
1031 lprevself(otri); \
1032 symself(otri);
1033
1034/* These primitives determine or set the origin, destination, or apex of a */
1035/* triangle. */
1036
1037#define org(otri, vertexptr) \
1038 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
1039
1040#define dest(otri, vertexptr) \
1041 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
1042
1043#define apex(otri, vertexptr) \
1044 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
1045
1046#define setorg(otri, vertexptr) \
1047 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1048
1049#define setdest(otri, vertexptr) \
1050 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1051
1052#define setapex(otri, vertexptr) \
1053 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
1054
1055/* Bond two triangles together. */
1056
1057#define bond(otri1, otri2) \
1058 (otri1).tri[(otri1).orient] = encode(otri2); \
1059 (otri2).tri[(otri2).orient] = encode(otri1)
1060
1061/* Dissolve a bond (from one side). Note that the other triangle will still */
1062/* think it's connected to this triangle. Usually, however, the other */
1063/* triangle is being deleted entirely, or bonded to another triangle, so */
1064/* it doesn't matter. */
1065
1066#define dissolve(otri) \
1067 (otri).tri[(otri).orient] = (triangle) m->dummytri
1068
1069/* Copy an oriented triangle. */
1070
1071#define otricopy(otri1, otri2) \
1072 (otri2).tri = (otri1).tri; \
1073 (otri2).orient = (otri1).orient
1074
1075/* Test for equality of oriented triangles. */
1076
1077#define otriequal(otri1, otri2) \
1078 (((otri1).tri == (otri2).tri) && \
1079 ((otri1).orient == (otri2).orient))
1080
1081/* Primitives to infect or cure a triangle with the virus. These rely on */
1082/* the assumption that all subsegments are aligned to four-byte boundaries.*/
1083
1084#define infect(otri) \
1085 (otri).tri[6] = (triangle) \
1086 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
1087
1088#define uninfect(otri) \
1089 (otri).tri[6] = (triangle) \
1090 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
1091
1092/* Test a triangle for viral infection. */
1093
1094#define infected(otri) \
1095 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
1096
1097/* Check or set a triangle's attributes. */
1098
1099#define elemattribute(otri, attnum) \
1100 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
1101
1102#define setelemattribute(otri, attnum, value) \
1103 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
1104
1105/* Check or set a triangle's maximum area bound. */
1106
1107#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
1108
1109#define setareabound(otri, value) \
1110 ((REAL *) (otri).tri)[m->areaboundindex] = value
1111
1112/* Check or set a triangle's deallocation. Its second pointer is set to */
1113/* NULL to indicate that it is not allocated. (Its first pointer is used */
1114/* for the stack of dead items.) Its fourth pointer (its first vertex) */
1115/* is set to NULL in case a `badtriang' structure points to it. */
1116
1117#define deadtri(tria) ((tria)[1] == (triangle) NULL)
1118
1119#define killtri(tria) \
1120 (tria)[1] = (triangle) NULL; \
1121 (tria)[3] = (triangle) NULL
1122
1123/********* Primitives for subsegments *********/
1124/* */
1125/* */
1126
1127/* sdecode() converts a pointer to an oriented subsegment. The orientation */
1128/* is extracted from the least significant bit of the pointer. The two */
1129/* least significant bits (one for orientation, one for viral infection) */
1130/* are masked out to produce the real pointer. */
1131
1132#define sdecode(sptr, osub) \
1133 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
1134 (osub).ss = (subseg *) \
1135 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
1136
1137/* sencode() compresses an oriented subsegment into a single pointer. It */
1138/* relies on the assumption that all subsegments are aligned to two-byte */
1139/* boundaries, so the least significant bit of (osub).ss is zero. */
1140
1141#define sencode(osub) \
1142 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
1143
1144/* ssym() toggles the orientation of a subsegment. */
1145
1146#define ssym(osub1, osub2) \
1147 (osub2).ss = (osub1).ss; \
1148 (osub2).ssorient = 1 - (osub1).ssorient
1149
1150#define ssymself(osub) \
1151 (osub).ssorient = 1 - (osub).ssorient
1152
1153/* spivot() finds the other subsegment (from the same segment) that shares */
1154/* the same origin. */
1155
1156#define spivot(osub1, osub2) \
1157 sptr = (osub1).ss[(osub1).ssorient]; \
1158 sdecode(sptr, osub2)
1159
1160#define spivotself(osub) \
1161 sptr = (osub).ss[(osub).ssorient]; \
1162 sdecode(sptr, osub)
1163
1164/* snext() finds the next subsegment (from the same segment) in sequence; */
1165/* one whose origin is the input subsegment's destination. */
1166
1167#define snext(osub1, osub2) \
1168 sptr = (osub1).ss[1 - (osub1).ssorient]; \
1169 sdecode(sptr, osub2)
1170
1171#define snextself(osub) \
1172 sptr = (osub).ss[1 - (osub).ssorient]; \
1173 sdecode(sptr, osub)
1174
1175/* These primitives determine or set the origin or destination of a */
1176/* subsegment or the segment that includes it. */
1177
1178#define sorg(osub, vertexptr) \
1179 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
1180
1181#define sdest(osub, vertexptr) \
1182 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
1183
1184#define setsorg(osub, vertexptr) \
1185 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
1186
1187#define setsdest(osub, vertexptr) \
1188 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
1189
1190#define segorg(osub, vertexptr) \
1191 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
1192
1193#define segdest(osub, vertexptr) \
1194 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
1195
1196#define setsegorg(osub, vertexptr) \
1197 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
1198
1199#define setsegdest(osub, vertexptr) \
1200 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
1201
1202/* These primitives read or set a boundary marker. Boundary markers are */
1203/* used to hold user-defined tags for setting boundary conditions in */
1204/* finite element solvers. */
1205
1206#define mark(osub) (* (int *) ((osub).ss + 8))
1207
1208#define setmark(osub, value) \
1209 * (int *) ((osub).ss + 8) = value
1210
1211/* Bond two subsegments together. */
1212
1213#define sbond(osub1, osub2) \
1214 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
1215 (osub2).ss[(osub2).ssorient] = sencode(osub1)
1216
1217/* Dissolve a subsegment bond (from one side). Note that the other */
1218/* subsegment will still think it's connected to this subsegment. */
1219
1220#define sdissolve(osub) \
1221 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
1222
1223/* Copy a subsegment. */
1224
1225#define subsegcopy(osub1, osub2) \
1226 (osub2).ss = (osub1).ss; \
1227 (osub2).ssorient = (osub1).ssorient
1228
1229/* Test for equality of subsegments. */
1230
1231#define subsegequal(osub1, osub2) \
1232 (((osub1).ss == (osub2).ss) && \
1233 ((osub1).ssorient == (osub2).ssorient))
1234
1235/* Check or set a subsegment's deallocation. Its second pointer is set to */
1236/* NULL to indicate that it is not allocated. (Its first pointer is used */
1237/* for the stack of dead items.) Its third pointer (its first vertex) */
1238/* is set to NULL in case a `badsubseg' structure points to it. */
1239
1240#define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
1241
1242#define killsubseg(sub) \
1243 (sub)[1] = (subseg) NULL; \
1244 (sub)[2] = (subseg) NULL
1245
1246/********* Primitives for interacting triangles and subsegments *********/
1247/* */
1248/* */
1249
1250/* tspivot() finds a subsegment abutting a triangle. */
1251
1252#define tspivot(otri, osub) \
1253 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
1254 sdecode(sptr, osub)
1255
1256/* stpivot() finds a triangle abutting a subsegment. It requires that the */
1257/* variable `ptr' of type `triangle' be defined. */
1258
1259#define stpivot(osub, otri) \
1260 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
1261 decode(ptr, otri)
1262
1263/* Bond a triangle to a subsegment. */
1264
1265#define tsbond(otri, osub) \
1266 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
1267 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
1268
1269/* Dissolve a bond (from the triangle side). */
1270
1271#define tsdissolve(otri) \
1272 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
1273
1274/* Dissolve a bond (from the subsegment side). */
1275
1276#define stdissolve(osub) \
1277 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
1278
1279/********* Primitives for vertices *********/
1280/* */
1281/* */
1282
1283#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
1284
1285#define setvertexmark(vx, value) \
1286 ((int *) (vx))[m->vertexmarkindex] = value
1287
1288#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
1289
1290#define setvertextype(vx, value) \
1291 ((int *) (vx))[m->vertexmarkindex + 1] = value
1292
1293#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
1294
1295#define setvertex2tri(vx, value) \
1296 ((triangle *) (vx))[m->vertex2triindex] = value
1297
1298/** **/
1299/** **/
1300/********* Mesh manipulation primitives end here *********/
1301
1302/********* User-defined triangle evaluation routine begins here *********/
1303/** **/
1304/** **/
1305
1306/*****************************************************************************/
1307/* */
1308/* triunsuitable() Determine if a triangle is unsuitable, and thus must */
1309/* be further refined. */
1310/* */
1311/* You may write your own procedure that decides whether or not a selected */
1312/* triangle is too big (and needs to be refined). There are two ways to do */
1313/* this. */
1314/* */
1315/* (1) Modify the procedure `triunsuitable' below, then recompile */
1316/* Triangle. */
1317/* */
1318/* (2) Define the symbol EXTERNAL_TEST (either by adding the definition */
1319/* to this file, or by using the appropriate compiler switch). This way, */
1320/* you can compile triangle.c separately from your test. Write your own */
1321/* `triunsuitable' procedure in a separate C file (using the same prototype */
1322/* as below). Compile it and link the object code with triangle.o. */
1323/* */
1324/* This procedure returns 1 if the triangle is too large and should be */
1325/* refined; 0 otherwise. */
1326/* */
1327/*****************************************************************************/
1328
1329#ifdef EXTERNAL_TEST
1330
1331int triunsuitable();
1332
1333#else /* not EXTERNAL_TEST */
1334
1335#ifdef ANSI_DECLARATORS
1336int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area )
1337#else /* not ANSI_DECLARATORS */
1338int triunsuitable(triorg, tridest, triapex, area)
1339vertex triorg; /* The triangle's origin vertex. */
1340vertex tridest; /* The triangle's destination vertex. */
1341vertex triapex; /* The triangle's apex vertex. */
1342REAL area; /* The area of the triangle. */
1343#endif /* not ANSI_DECLARATORS */
1344
1345{
1346 REAL dxoa, dxda, dxod;
1347 REAL dyoa, dyda, dyod;
1348 REAL oalen, dalen, odlen;
1349 REAL maxlen;
1350
1351 (void)area; /*LM: added to suppress warning */
1352
1353 dxoa = triorg[0] - triapex[0];
1354 dyoa = triorg[1] - triapex[1];
1355 dxda = tridest[0] - triapex[0];
1356 dyda = tridest[1] - triapex[1];
1357 dxod = triorg[0] - tridest[0];
1358 dyod = triorg[1] - tridest[1];
1359 /* Find the squares of the lengths of the triangle's three edges. */
1360 oalen = dxoa * dxoa + dyoa * dyoa;
1361 dalen = dxda * dxda + dyda * dyda;
1362 odlen = dxod * dxod + dyod * dyod;
1363 /* Find the square of the length of the longest edge. */
1364 maxlen = (dalen > oalen) ? dalen : oalen;
1365 maxlen = (odlen > maxlen) ? odlen : maxlen;
1366
1367 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
1368 return 1;
1369 } else {
1370 return 0;
1371 }
1372}
1373
1374#endif /* not EXTERNAL_TEST */
1375
1376/** **/
1377/** **/
1378/********* User-defined triangle evaluation routine ends here *********/
1379
1380/********* Memory allocation and program exit wrappers begin here *********/
1381/** **/
1382/** **/
1383
1384#ifdef ANSI_DECLARATORS
1385void triexit(int status)
1386#else /* not ANSI_DECLARATORS */
1387void triexit(status)
1388int status;
1389#endif /* not ANSI_DECLARATORS */
1390
1391{
1392 exit(status);
1393}
1394
1395#ifdef ANSI_DECLARATORS
1396VOID *trimalloc(int size)
1397#else /* not ANSI_DECLARATORS */
1398VOID *trimalloc(size)
1399int size;
1400#endif /* not ANSI_DECLARATORS */
1401
1402{
1403 VOID *memptr;
1404
1405 memptr = (VOID *) malloc((unsigned int) size);
1406 if (memptr == (VOID *) NULL) {
1407 printf("Error: Out of memory.\n");
1408 triexit(1);
1409 }
1410 return(memptr);
1411}
1412
1413#ifdef ANSI_DECLARATORS
1414void trifree(VOID *memptr)
1415#else /* not ANSI_DECLARATORS */
1416void trifree(memptr)
1417VOID *memptr;
1418#endif /* not ANSI_DECLARATORS */
1419
1420{
1421 free(memptr);
1422}
1423
1424/** **/
1425/** **/
1426/********* Memory allocation and program exit wrappers end here *********/
1427
1428/********* User interaction routines begin here *********/
1429/** **/
1430/** **/
1431
1432/*****************************************************************************/
1433/* */
1434/* syntax() Print list of command line switches. */
1435/* */
1436/*****************************************************************************/
1437
1438#ifndef TRILIBRARY
1439
1440void syntax()
1441{
1442#ifdef CDT_ONLY
1443#ifdef REDUCED
1444 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
1445#else /* not REDUCED */
1446 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
1447#endif /* not REDUCED */
1448#else /* not CDT_ONLY */
1449#ifdef REDUCED
1450 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
1451#else /* not REDUCED */
1452 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
1453#endif /* not REDUCED */
1454#endif /* not CDT_ONLY */
1455
1456 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
1457#ifndef CDT_ONLY
1458 printf(" -r Refines a previously generated mesh.\n");
1459 printf(
1460 " -q Quality mesh generation. A minimum angle may be specified.\n");
1461 printf(" -a Applies a maximum triangle area constraint.\n");
1462 printf(" -u Applies a user-defined triangle constraint.\n");
1463#endif /* not CDT_ONLY */
1464 printf(
1465 " -A Applies attributes to identify triangles in certain regions.\n");
1466 printf(" -c Encloses the convex hull with segments.\n");
1467#ifndef CDT_ONLY
1468 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
1469#endif /* not CDT_ONLY */
1470/*
1471 printf(" -w Weighted Delaunay triangulation.\n");
1472 printf(" -W Regular triangulation (lower hull of a height field).\n");
1473*/
1474 printf(" -j Jettison unused vertices from output .node file.\n");
1475 printf(" -e Generates an edge list.\n");
1476 printf(" -v Generates a Voronoi diagram.\n");
1477 printf(" -n Generates a list of triangle neighbors.\n");
1478 printf(" -g Generates an .off file for Geomview.\n");
1479 printf(" -B Suppresses output of boundary information.\n");
1480 printf(" -P Suppresses output of .poly file.\n");
1481 printf(" -N Suppresses output of .node file.\n");
1482 printf(" -E Suppresses output of .ele file.\n");
1483 printf(" -I Suppresses mesh iteration numbers.\n");
1484 printf(" -O Ignores holes in .poly file.\n");
1485 printf(" -X Suppresses use of exact arithmetic.\n");
1486 printf(" -z Numbers all items starting from zero (rather than one).\n");
1487 printf(" -o2 Generates second-order subparametric elements.\n");
1488#ifndef CDT_ONLY
1489 printf(" -Y Suppresses boundary segment splitting.\n");
1490 printf(" -S Specifies maximum number of added Steiner points.\n");
1491#endif /* not CDT_ONLY */
1492#ifndef REDUCED
1493 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
1494 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
1495#endif /* not REDUCED */
1496 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
1497#ifndef REDUCED
1498#ifndef CDT_ONLY
1499 printf(
1500 " -s Force segments into mesh by splitting (instead of using CDT).\n");
1501#endif /* not CDT_ONLY */
1502 printf(" -C Check consistency of final mesh.\n");
1503#endif /* not REDUCED */
1504 printf(" -Q Quiet: No terminal output except errors.\n");
1505 printf(" -V Verbose: Detailed information on what I'm doing.\n");
1506 printf(" -h Help: Detailed instructions for Triangle.\n");
1507 triexit(0);
1508}
1509
1510#endif /* not TRILIBRARY */
1511
1512/*****************************************************************************/
1513/* */
1514/* info() Print out complete instructions. */
1515/* */
1516/*****************************************************************************/
1517
1518#ifndef TRILIBRARY
1519
1520void info()
1521{
1522 printf("Triangle\n");
1523 printf(
1524"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
1525 printf("Version 1.6\n\n");
1526 printf(
1527"Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
1528 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
1529 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
1530 printf(
1531"Created as part of the Quake project (tools for earthquake simulation).\n");
1532 printf(
1533"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
1534 printf("There is no warranty whatsoever. Use at your own risk.\n");
1535#ifdef SINGLE
1536 printf("This executable is compiled for single precision arithmetic.\n\n\n");
1537#else /* not SINGLE */
1538 printf("This executable is compiled for double precision arithmetic.\n\n\n");
1539#endif /* not SINGLE */
1540 printf(
1541"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
1542 printf(
1543"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
1544 printf(
1545"high-quality triangular meshes. The latter can be generated with no small\n"
1546);
1547 printf(
1548"or large angles, and are thus suitable for finite element analysis. If no\n"
1549);
1550 printf(
1551"command line switch is specified, your .node input file is read, and the\n");
1552 printf(
1553"Delaunay triangulation is returned in .node and .ele output files. The\n");
1554 printf("command syntax is:\n\n");
1555 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
1556 printf(
1557"Underscores indicate that numbers may optionally follow certain switches.\n");
1558 printf(
1559"Do not leave any space between a switch and its numeric parameter.\n");
1560 printf(
1561"input_file must be a file with extension .node, or extension .poly if the\n");
1562 printf(
1563"-p switch is used. If -r is used, you must supply .node and .ele files,\n");
1564 printf(
1565"and possibly a .poly file and an .area file as well. The formats of these\n"
1566);
1567 printf("files are described below.\n\n");
1568 printf("Command Line Switches:\n\n");
1569 printf(
1570" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
1571);
1572 printf(
1573" vertices, segments, holes, regional attributes, and regional area\n");
1574 printf(
1575" constraints. Generates a constrained Delaunay triangulation (CDT)\n"
1576);
1577 printf(
1578" fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
1579 printf(
1580" constrained Delaunay triangulation (CCDT). If you want a truly\n");
1581 printf(
1582" Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
1583 printf(
1584" well. When -p is not used, Triangle reads a .node file by default.\n"
1585);
1586 printf(
1587" -r Refines a previously generated mesh. The mesh is read from a .node\n"
1588);
1589 printf(
1590" file and an .ele file. If -p is also used, a .poly file is read\n");
1591 printf(
1592" and used to constrain segments in the mesh. If -a is also used\n");
1593 printf(
1594" (with no number following), an .area file is read and used to\n");
1595 printf(
1596" impose area constraints on the mesh. Further details on refinement\n"
1597);
1598 printf(" appear below.\n");
1599 printf(
1600" -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
1601 printf(
1602" Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
1603);
1604 printf(
1605" ensure that all angles are between 20 and 140 degrees. An\n");
1606 printf(
1607" alternative bound on the minimum angle, replacing 20 degrees, may\n");
1608 printf(
1609" be specified after the `q'. The specified angle may include a\n");
1610 printf(
1611" decimal point, but not exponential notation. Note that a bound of\n"
1612);
1613 printf(
1614" theta degrees on the smallest angle also implies a bound of\n");
1615 printf(
1616" (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
1617);
1618 printf(
1619" degrees or smaller, Triangle is mathematically guaranteed to\n");
1620 printf(
1621" terminate (assuming infinite precision arithmetic--Triangle may\n");
1622 printf(
1623" fail to terminate if you run out of precision). In practice,\n");
1624 printf(
1625" Triangle often succeeds for minimum angles up to 34 degrees. For\n");
1626 printf(
1627" some meshes, however, you might need to reduce the minimum angle to\n"
1628);
1629 printf(
1630" avoid problems associated with insufficient floating-point\n");
1631 printf(" precision.\n");
1632 printf(
1633" -a Imposes a maximum triangle area. If a number follows the `a', no\n");
1634 printf(
1635" triangle is generated whose area is larger than that number. If no\n"
1636);
1637 printf(
1638" number is specified, an .area file (if -r is used) or .poly file\n");
1639 printf(
1640" (if -r is not used) specifies a set of maximum area constraints.\n");
1641 printf(
1642" An .area file contains a separate area constraint for each\n");
1643 printf(
1644" triangle, and is useful for refining a finite element mesh based on\n"
1645);
1646 printf(
1647" a posteriori error estimates. A .poly file can optionally contain\n"
1648);
1649 printf(
1650" an area constraint for each segment-bounded region, thereby\n");
1651 printf(
1652" controlling triangle densities in a first triangulation of a PSLG.\n"
1653);
1654 printf(
1655" You can impose both a fixed area constraint and a varying area\n");
1656 printf(
1657" constraint by invoking the -a switch twice, once with and once\n");
1658 printf(
1659" without a number following. Each area specified may include a\n");
1660 printf(" decimal point.\n");
1661 printf(
1662" -u Imposes a user-defined constraint on triangle size. There are two\n"
1663);
1664 printf(
1665" ways to use this feature. One is to edit the triunsuitable()\n");
1666 printf(
1667" procedure in triangle.c to encode any constraint you like, then\n");
1668 printf(
1669" recompile Triangle. The other is to compile triangle.c with the\n");
1670 printf(
1671" EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
1672 printf(
1673" link Triangle with a separate object file that implements\n");
1674 printf(
1675" triunsuitable(). In either case, the -u switch causes the user-\n");
1676 printf(" defined test to be applied to every triangle.\n");
1677 printf(
1678" -A Assigns an additional floating-point attribute to each triangle\n");
1679 printf(
1680" that identifies what segment-bounded region each triangle belongs\n");
1681 printf(
1682" to. Attributes are assigned to regions by the .poly file. If a\n");
1683 printf(
1684" region is not explicitly marked by the .poly file, triangles in\n");
1685 printf(
1686" that region are assigned an attribute of zero. The -A switch has\n");
1687 printf(
1688" an effect only when the -p switch is used and the -r switch is not.\n"
1689);
1690 printf(
1691" -c Creates segments on the convex hull of the triangulation. If you\n");
1692 printf(
1693" are triangulating a vertex set, this switch causes a .poly file to\n"
1694);
1695 printf(
1696" be written, containing all edges of the convex hull. If you are\n");
1697 printf(
1698" triangulating a PSLG, this switch specifies that the whole convex\n");
1699 printf(
1700" hull of the PSLG should be triangulated, regardless of what\n");
1701 printf(
1702" segments the PSLG has. If you do not use this switch when\n");
1703 printf(
1704" triangulating a PSLG, Triangle assumes that you have identified the\n"
1705);
1706 printf(
1707" region to be triangulated by surrounding it with segments of the\n");
1708 printf(
1709" input PSLG. Beware: if you are not careful, this switch can cause\n"
1710);
1711 printf(
1712" the introduction of an extremely thin angle between a PSLG segment\n"
1713);
1714 printf(
1715" and a convex hull segment, which can cause overrefinement (and\n");
1716 printf(
1717" possibly failure if Triangle runs out of precision). If you are\n");
1718 printf(
1719" refining a mesh, the -c switch works differently: it causes a\n");
1720 printf(
1721" .poly file to be written containing the boundary edges of the mesh\n"
1722);
1723 printf(" (useful if no .poly file was read).\n");
1724 printf(
1725" -D Conforming Delaunay triangulation: use this switch if you want to\n"
1726);
1727 printf(
1728" ensure that all the triangles in the mesh are Delaunay, and not\n");
1729 printf(
1730" merely constrained Delaunay; or if you want to ensure that all the\n"
1731);
1732 printf(
1733" Voronoi vertices lie within the triangulation. (Some finite volume\n"
1734);
1735 printf(
1736" methods have this requirement.) This switch invokes Ruppert's\n");
1737 printf(
1738" original algorithm, which splits every subsegment whose diametral\n");
1739 printf(
1740" circle is encroached. It usually increases the number of vertices\n"
1741);
1742 printf(" and triangles.\n");
1743 printf(
1744" -j Jettisons vertices that are not part of the final triangulation\n");
1745 printf(
1746" from the output .node file. By default, Triangle copies all\n");
1747 printf(
1748" vertices in the input .node file to the output .node file, in the\n");
1749 printf(
1750" same order, so their indices do not change. The -j switch prevents\n"
1751);
1752 printf(
1753" duplicated input vertices, or vertices `eaten' by holes, from\n");
1754 printf(
1755" appearing in the output .node file. Thus, if two input vertices\n");
1756 printf(
1757" have exactly the same coordinates, only the first appears in the\n");
1758 printf(
1759" output. If any vertices are jettisoned, the vertex numbering in\n");
1760 printf(
1761" the output .node file differs from that of the input .node file.\n");
1762 printf(
1763" -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
1764 printf(
1765" -v Outputs the Voronoi diagram associated with the triangulation.\n");
1766 printf(
1767" Does not attempt to detect degeneracies, so some Voronoi vertices\n");
1768 printf(
1769" may be duplicated. See the discussion of Voronoi diagrams below.\n");
1770 printf(
1771" -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
1772 printf(" triangle.\n");
1773 printf(
1774" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
1775);
1776 printf(" viewing with the Geometry Center's Geomview package.\n");
1777 printf(
1778" -B No boundary markers in the output .node, .poly, and .edge output\n");
1779 printf(
1780" files. See the detailed discussion of boundary markers below.\n");
1781 printf(
1782" -P No output .poly file. Saves disk space, but you lose the ability\n");
1783 printf(
1784" to maintain constraining segments on later refinements of the mesh.\n"
1785);
1786 printf(" -N No output .node file.\n");
1787 printf(" -E No output .ele file.\n");
1788 printf(
1789" -I No iteration numbers. Suppresses the output of .node and .poly\n");
1790 printf(
1791" files, so your input files won't be overwritten. (If your input is\n"
1792);
1793 printf(
1794" a .poly file only, a .node file is written.) Cannot be used with\n");
1795 printf(
1796" the -r switch, because that would overwrite your input .ele file.\n");
1797 printf(
1798" Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
1799 printf(
1800" using a .node file for input, because no .node file is written, so\n"
1801);
1802 printf(" there is no record of any added Steiner points.\n");
1803 printf(" -O No holes. Ignores the holes in the .poly file.\n");
1804 printf(
1805" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
1806);
1807 printf(
1808" arithmetic for certain tests if it thinks the inexact tests are not\n"
1809);
1810 printf(
1811" accurate enough. Exact arithmetic ensures the robustness of the\n");
1812 printf(
1813" triangulation algorithms, despite floating-point roundoff error.\n");
1814 printf(
1815" Disabling exact arithmetic with the -X switch causes a small\n");
1816 printf(
1817" improvement in speed and creates the possibility that Triangle will\n"
1818);
1819 printf(" fail to produce a valid mesh. Not recommended.\n");
1820 printf(
1821" -z Numbers all items starting from zero (rather than one). Note that\n"
1822);
1823 printf(
1824" this switch is normally overridden by the value used to number the\n"
1825);
1826 printf(
1827" first vertex of the input .node or .poly file. However, this\n");
1828 printf(
1829" switch is useful when calling Triangle from another program.\n");
1830 printf(
1831" -o2 Generates second-order subparametric elements with six nodes each.\n"
1832);
1833 printf(
1834" -Y No new vertices on the boundary. This switch is useful when the\n");
1835 printf(
1836" mesh boundary must be preserved so that it conforms to some\n");
1837 printf(
1838" adjacent mesh. Be forewarned that you will probably sacrifice much\n"
1839);
1840 printf(
1841" of the quality of the mesh; Triangle will try, but the resulting\n");
1842 printf(
1843" mesh may contain poorly shaped triangles. Works well if all the\n");
1844 printf(
1845" boundary vertices are closely spaced. Specify this switch twice\n");
1846 printf(
1847" (`-YY') to prevent all segment splitting, including internal\n");
1848 printf(" boundaries.\n");
1849 printf(
1850" -S Specifies the maximum number of Steiner points (vertices that are\n");
1851 printf(
1852" not in the input, but are added to meet the constraints on minimum\n"
1853);
1854 printf(
1855" angle and maximum area). The default is to allow an unlimited\n");
1856 printf(
1857" number. If you specify this switch with no number after it,\n");
1858 printf(
1859" the limit is set to zero. Triangle always adds vertices at segment\n"
1860);
1861 printf(
1862" intersections, even if it needs to use more vertices than the limit\n"
1863);
1864 printf(
1865" you set. When Triangle inserts segments by splitting (-s), it\n");
1866 printf(
1867" always adds enough vertices to ensure that all the segments of the\n"
1868);
1869 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
1870 printf(
1871" -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
1872 printf(
1873" construct a Delaunay triangulation. Try it if the divide-and-\n");
1874 printf(" conquer algorithm fails.\n");
1875 printf(
1876" -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
1877 printf(
1878" triangulation. Warning: does not use exact arithmetic for all\n");
1879 printf(" calculations. An exact result is not guaranteed.\n");
1880 printf(
1881" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
1882 printf(
1883" default, Triangle alternates between vertical and horizontal cuts,\n"
1884);
1885 printf(
1886" which usually improve the speed except with vertex sets that are\n");
1887 printf(
1888" small or short and wide. This switch is primarily of theoretical\n");
1889 printf(" interest.\n");
1890 printf(
1891" -s Specifies that segments should be forced into the triangulation by\n"
1892);
1893 printf(
1894" recursively splitting them at their midpoints, rather than by\n");
1895 printf(
1896" generating a constrained Delaunay triangulation. Segment splitting\n"
1897);
1898 printf(
1899" is true to Ruppert's original algorithm, but can create needlessly\n"
1900);
1901 printf(
1902" small triangles. This switch is primarily of theoretical interest.\n"
1903);
1904 printf(
1905" -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
1906);
1907 printf(
1908" checking, even if the -X switch is used. Useful if you suspect\n");
1909 printf(" Triangle is buggy.\n");
1910 printf(
1911" -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
1912 printf(" unless an error occurs.\n");
1913 printf(
1914" -V Verbose: Gives detailed information about what Triangle is doing.\n"
1915);
1916 printf(
1917" Add more `V's for increasing amount of detail. `-V' is most\n");
1918 printf(
1919" useful; itgives information on algorithmic progress and much more\n");
1920 printf(
1921" detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
1922 printf(
1923" prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
1924);
1925 printf(" information only a debugger could love.\n");
1926 printf(" -h Help: Displays these instructions.\n");
1927 printf("\n");
1928 printf("Definitions:\n");
1929 printf("\n");
1930 printf(
1931" A Delaunay triangulation of a vertex set is a triangulation whose\n");
1932 printf(
1933" vertices are the vertex set, that covers the convex hull of the vertex\n");
1934 printf(
1935" set. A Delaunay triangulation has the property that no vertex lies\n");
1936 printf(
1937" inside the circumscribing circle (circle that passes through all three\n");
1938 printf(" vertices) of any triangle in the triangulation.\n\n");
1939 printf(
1940" A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
1941 printf(
1942" polygonal cells (some of which may be unbounded, meaning infinitely\n");
1943 printf(
1944" large), where each cell is the set of points in the plane that are closer\n"
1945);
1946 printf(
1947" to some input vertex than to any other input vertex. The Voronoi diagram\n"
1948);
1949 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
1950 printf(
1951" A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
1952 printf(
1953" Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
1954);
1955 printf(
1956" Segments may intersect each other only at their endpoints. The file\n");
1957 printf(" format for PSLGs (.poly files) is described below.\n\n");
1958 printf(
1959" A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
1960 printf(
1961" Delaunay triangulation, but each PSLG segment is present as a single edge\n"
1962);
1963 printf(
1964" of the CDT. (A constrained Delaunay triangulation is not truly a\n");
1965 printf(
1966" Delaunay triangulation, because some of its triangles might not be\n");
1967 printf(
1968" Delaunay.) By definition, a CDT does not have any vertices other than\n");
1969 printf(
1970" those specified in the input PSLG. Depending on context, a CDT might\n");
1971 printf(
1972" cover the convex hull of the PSLG, or it might cover only a segment-\n");
1973 printf(" bounded region (e.g. a polygon).\n\n");
1974 printf(
1975" A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
1976);
1977 printf(
1978" each triangle is truly Delaunay, and each PSLG segment is represented by\n"
1979);
1980 printf(
1981" a linear contiguous sequence of edges of the triangulation. New vertices\n"
1982);
1983 printf(
1984" (not part of the PSLG) may appear, and each input segment may have been\n");
1985 printf(
1986" subdivided into shorter edges (subsegments) by these additional vertices.\n"
1987);
1988 printf(
1989" The new vertices are frequently necessary to maintain the Delaunay\n");
1990 printf(" property while ensuring that every segment is represented.\n\n");
1991 printf(
1992" A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
1993 printf(
1994" triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
1995 printf(" vertices may appear, and input segments may be subdivided into\n");
1996 printf(
1997" subsegments, but not to guarantee that segments are respected; rather, to\n"
1998);
1999 printf(
2000" improve the quality of the triangles. The high-quality meshes produced\n");
2001 printf(
2002" by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
2003 printf(" with the -D switch.\n\n");
2004 printf("File Formats:\n\n");
2005 printf(
2006" All files may contain comments prefixed by the character '#'. Vertices,\n"
2007);
2008 printf(
2009" triangles, edges, holes, and maximum area constraints must be numbered\n");
2010 printf(
2011" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
2012 printf(
2013" input files must be consistent; if the vertices are numbered from 1, so\n");
2014 printf(
2015" must be all other objects. Triangle automatically detects your choice\n");
2016 printf(
2017" while reading the .node (or .poly) file. (When calling Triangle from\n");
2018 printf(
2019" another program, use the -z switch if you wish to number objects from\n");
2020 printf(" zero.) Examples of these file formats are given below.\n\n");
2021 printf(" .node files:\n");
2022 printf(
2023" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2024);
2025 printf(
2026" <# of boundary markers (0 or 1)>\n"
2027);
2028 printf(
2029" Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2030 printf("\n");
2031 printf(
2032" The attributes, which are typically floating-point values of physical\n");
2033 printf(
2034" quantities (such as mass or conductivity) associated with the nodes of\n"
2035);
2036 printf(
2037" a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
2038);
2039 printf(
2040" -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
2041);
2042 printf(" has attributes assigned to it by linear interpolation.\n\n");
2043 printf(
2044" If the fourth entry of the first line is `1', the last column of the\n");
2045 printf(
2046" remainder of the file is assumed to contain boundary markers. Boundary\n"
2047);
2048 printf(
2049" markers are used to identify boundary vertices and vertices resting on\n"
2050);
2051 printf(
2052" PSLG segments; a complete description appears in a section below. The\n"
2053);
2054 printf(
2055" .node file produced by Triangle contains boundary markers in the last\n");
2056 printf(" column unless they are suppressed by the -B switch.\n\n");
2057 printf(" .ele files:\n");
2058 printf(
2059" First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
2060 printf(
2061" Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
2062 printf("\n");
2063 printf(
2064" Nodes are indices into the corresponding .node file. The first three\n");
2065 printf(
2066" nodes are the corner vertices, and are listed in counterclockwise order\n"
2067);
2068 printf(
2069" around each triangle. (The remaining nodes, if any, depend on the type\n"
2070);
2071 printf(" of finite element used.)\n\n");
2072 printf(
2073" The attributes are just like those of .node files. Because there is no\n"
2074);
2075 printf(
2076" simple mapping from input to output triangles, Triangle attempts to\n");
2077 printf(
2078" interpolate attributes, and may cause a lot of diffusion of attributes\n"
2079);
2080 printf(
2081" among nearby triangles as the triangulation is refined. Attributes do\n"
2082);
2083 printf(" not diffuse across segments, so attributes used to identify\n");
2084 printf(" segment-bounded regions remain intact.\n\n");
2085 printf(
2086" In .ele files produced by Triangle, each triangular element has three\n");
2087 printf(
2088" nodes (vertices) unless the -o2 switch is used, in which case\n");
2089 printf(
2090" subparametric quadratic elements with six nodes each are generated.\n");
2091 printf(
2092" The first three nodes are the corners in counterclockwise order, and\n");
2093 printf(
2094" the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
2095 printf(
2096" opposite the first, second, and third vertices, respectively.\n");
2097 printf("\n");
2098 printf(" .poly files:\n");
2099 printf(
2100" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2101);
2102 printf(
2103" <# of boundary markers (0 or 1)>\n"
2104);
2105 printf(
2106" Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2107 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
2108 printf(
2109" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
2110 printf(" One line: <# of holes>\n");
2111 printf(" Following lines: <hole #> <x> <y>\n");
2112 printf(
2113" Optional line: <# of regional attributes and/or area constraints>\n");
2114 printf(
2115" Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
2116 printf("\n");
2117 printf(
2118" A .poly file represents a PSLG, as well as some additional information.\n"
2119);
2120 printf(
2121" The first section lists all the vertices, and is identical to the\n");
2122 printf(
2123" format of .node files. <# of vertices> may be set to zero to indicate\n"
2124);
2125 printf(
2126" that the vertices are listed in a separate .node file; .poly files\n");
2127 printf(
2128" produced by Triangle always have this format. A vertex set represented\n"
2129);
2130 printf(
2131" this way has the advantage that it may easily be triangulated with or\n");
2132 printf(
2133" without segments (depending on whether the -p switch is invoked).\n");
2134 printf("\n");
2135 printf(
2136" The second section lists the segments. Segments are edges whose\n");
2137 printf(
2138" presence in the triangulation is enforced. (Depending on the choice of\n"
2139);
2140 printf(
2141" switches, segment might be subdivided into smaller edges). Each\n");
2142 printf(
2143" segment is specified by listing the indices of its two endpoints. This\n"
2144);
2145 printf(
2146" means that you must include its endpoints in the vertex list. Each\n");
2147 printf(" segment, like each point, may have a boundary marker.\n\n");
2148 printf(
2149" If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
2150);
2151 printf(
2152" Delaunay triangulation (CDT), in which each segment appears as a single\n"
2153);
2154 printf(
2155" edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
2156);
2157 printf(
2158" produces a conforming constrained Delaunay triangulation (CCDT), in\n");
2159 printf(
2160" which segments may be subdivided into smaller edges. If -D is\n");
2161 printf(
2162" selected, Triangle produces a conforming Delaunay triangulation, so\n");
2163 printf(
2164" that every triangle is Delaunay, and not just constrained Delaunay.\n");
2165 printf("\n");
2166 printf(
2167" The third section lists holes (and concavities, if -c is selected) in\n");
2168 printf(
2169" the triangulation. Holes are specified by identifying a point inside\n");
2170 printf(
2171" each hole. After the triangulation is formed, Triangle creates holes\n");
2172 printf(
2173" by eating triangles, spreading out from each hole point until its\n");
2174 printf(
2175" progress is blocked by segments in the PSLG. You must be careful to\n");
2176 printf(
2177" enclose each hole in segments, or your whole triangulation might be\n");
2178 printf(
2179" eaten away. If the two triangles abutting a segment are eaten, the\n");
2180 printf(
2181" segment itself is also eaten. Do not place a hole directly on a\n");
2182 printf(" segment; if you do, Triangle chooses one side of the segment\n");
2183 printf(" arbitrarily.\n\n");
2184 printf(
2185" The optional fourth section lists regional attributes (to be assigned\n");
2186 printf(
2187" to all triangles in a region) and regional constraints on the maximum\n");
2188 printf(
2189" triangle area. Triangle reads this section only if the -A switch is\n");
2190 printf(
2191" used or the -a switch is used without a number following it, and the -r\n"
2192);
2193 printf(
2194" switch is not used. Regional attributes and area constraints are\n");
2195 printf(
2196" propagated in the same manner as holes: you specify a point for each\n");
2197 printf(
2198" attribute and/or constraint, and the attribute and/or constraint\n");
2199 printf(
2200" affects the whole region (bounded by segments) containing the point.\n");
2201 printf(
2202" If two values are written on a line after the x and y coordinate, the\n");
2203 printf(
2204" first such value is assumed to be a regional attribute (but is only\n");
2205 printf(
2206" applied if the -A switch is selected), and the second value is assumed\n"
2207);
2208 printf(
2209" to be a regional area constraint (but is only applied if the -a switch\n"
2210);
2211 printf(
2212" is selected). You may specify just one value after the coordinates,\n");
2213 printf(
2214" which can serve as both an attribute and an area constraint, depending\n"
2215);
2216 printf(
2217" on the choice of switches. If you are using the -A and -a switches\n");
2218 printf(
2219" simultaneously and wish to assign an attribute to some region without\n");
2220 printf(" imposing an area constraint, use a negative maximum area.\n\n");
2221 printf(
2222" When a triangulation is created from a .poly file, you must either\n");
2223 printf(
2224" enclose the entire region to be triangulated in PSLG segments, or\n");
2225 printf(
2226" use the -c switch, which automatically creates extra segments that\n");
2227 printf(
2228" enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
2229);
2230 printf(
2231" Triangle eats all triangles that are not enclosed by segments; if you\n");
2232 printf(
2233" are not careful, your whole triangulation may be eaten away. If you do\n"
2234);
2235 printf(
2236" use the -c switch, you can still produce concavities by the appropriate\n"
2237);
2238 printf(
2239" placement of holes just inside the boundary of the convex hull.\n");
2240 printf("\n");
2241 printf(
2242" An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
2243 printf(
2244" upon segments (except, of course, the endpoints of each segment). You\n"
2245);
2246 printf(
2247" aren't required to make your .poly files ideal, but you should be aware\n"
2248);
2249 printf(
2250" of what can go wrong. Segment intersections are relatively safe--\n");
2251 printf(
2252" Triangle calculates the intersection points for you and adds them to\n");
2253 printf(
2254" the triangulation--as long as your machine's floating-point precision\n");
2255 printf(
2256" doesn't become a problem. You are tempting the fates if you have three\n"
2257);
2258 printf(
2259" segments that cross at the same location, and expect Triangle to figure\n"
2260);
2261 printf(
2262" out where the intersection point is. Thanks to floating-point roundoff\n"
2263);
2264 printf(
2265" error, Triangle will probably decide that the three segments intersect\n"
2266);
2267 printf(
2268" at three different points, and you will find a minuscule triangle in\n");
2269 printf(
2270" your output--unless Triangle tries to refine the tiny triangle, uses\n");
2271 printf(
2272" up the last bit of machine precision, and fails to terminate at all.\n");
2273 printf(
2274" You're better off putting the intersection point in the input files,\n");
2275 printf(
2276" and manually breaking up each segment into two. Similarly, if you\n");
2277 printf(
2278" place a vertex at the middle of a segment, and hope that Triangle will\n"
2279);
2280 printf(
2281" break up the segment at that vertex, you might get lucky. On the other\n"
2282);
2283 printf(
2284" hand, Triangle might decide that the vertex doesn't lie precisely on\n");
2285 printf(
2286" the segment, and you'll have a needle-sharp triangle in your output--or\n"
2287);
2288 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
2289 printf("\n");
2290 printf(
2291" When Triangle reads a .poly file, it also writes a .poly file, which\n");
2292 printf(
2293" includes all the subsegments--the edges that are parts of input\n");
2294 printf(
2295" segments. If the -c switch is used, the output .poly file also\n");
2296 printf(
2297" includes all of the edges on the convex hull. Hence, the output .poly\n"
2298);
2299 printf(
2300" file is useful for finding edges associated with input segments and for\n"
2301);
2302 printf(
2303" setting boundary conditions in finite element simulations. Moreover,\n");
2304 printf(
2305" you will need the output .poly file if you plan to refine the output\n");
2306 printf(
2307" mesh, and don't want segments to be missing in later triangulations.\n");
2308 printf("\n");
2309 printf(" .area files:\n");
2310 printf(" First line: <# of triangles>\n");
2311 printf(" Following lines: <triangle #> <maximum area>\n");
2312 printf("\n");
2313 printf(
2314" An .area file associates with each triangle a maximum area that is used\n"
2315);
2316 printf(
2317" for mesh refinement. As with other file formats, every triangle must\n");
2318 printf(
2319" be represented, and the triangles must be numbered consecutively. A\n");
2320 printf(
2321" triangle may be left unconstrained by assigning it a negative maximum\n");
2322 printf(" area.\n\n");
2323 printf(" .edge files:\n");
2324 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
2325 printf(
2326" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
2327 printf("\n");
2328 printf(
2329" Endpoints are indices into the corresponding .node file. Triangle can\n"
2330);
2331 printf(
2332" produce .edge files (use the -e switch), but cannot read them. The\n");
2333 printf(
2334" optional column of boundary markers is suppressed by the -B switch.\n");
2335 printf("\n");
2336 printf(
2337" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
2338 printf(
2339" infinite ray with only one endpoint. For these edges, a different\n");
2340 printf(" format is used:\n\n");
2341 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
2342 printf(
2343" The `direction' is a floating-point vector that indicates the direction\n"
2344);
2345 printf(" of the infinite ray.\n\n");
2346 printf(" .neigh files:\n");
2347 printf(
2348" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
2349);
2350 printf(
2351" Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
2352 printf("\n");
2353 printf(
2354" Neighbors are indices into the corresponding .ele file. An index of -1\n"
2355);
2356 printf(
2357" indicates no neighbor (because the triangle is on an exterior\n");
2358 printf(
2359" boundary). The first neighbor of triangle i is opposite the first\n");
2360 printf(" corner of triangle i, and so on.\n\n");
2361 printf(
2362" Triangle can produce .neigh files (use the -n switch), but cannot read\n"
2363);
2364 printf(" them.\n\n");
2365 printf("Boundary Markers:\n\n");
2366 printf(
2367" Boundary markers are tags used mainly to identify which output vertices\n");
2368 printf(
2369" and edges are associated with which PSLG segment, and to identify which\n");
2370 printf(
2371" vertices and edges occur on a boundary of the triangulation. A common\n");
2372 printf(
2373" use is to determine where boundary conditions should be applied to a\n");
2374 printf(
2375" finite element mesh. You can prevent boundary markers from being written\n"
2376);
2377 printf(" into files produced by Triangle by using the -B switch.\n\n");
2378 printf(
2379" The boundary marker associated with each segment in an output .poly file\n"
2380);
2381 printf(" and each edge in an output .edge file is chosen as follows:\n");
2382 printf(
2383" - If an output edge is part or all of a PSLG segment with a nonzero\n");
2384 printf(
2385" boundary marker, then the edge is assigned the same marker.\n");
2386 printf(
2387" - Otherwise, if the edge lies on a boundary of the triangulation\n");
2388 printf(
2389" (even the boundary of a hole), then the edge is assigned the marker\n");
2390 printf(" one (1).\n");
2391 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
2392 printf(
2393" The boundary marker associated with each vertex in an output .node file\n");
2394 printf(" is chosen as follows:\n");
2395 printf(
2396" - If a vertex is assigned a nonzero boundary marker in the input file,\n"
2397);
2398 printf(
2399" then it is assigned the same marker in the output .node file.\n");
2400 printf(
2401" - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
2402 printf(
2403" endpoint of the segment) with a nonzero boundary marker, then the\n");
2404 printf(
2405" vertex is assigned the same marker. If the vertex lies on several\n");
2406 printf(" such segments, one of the markers is chosen arbitrarily.\n");
2407 printf(
2408" - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
2409 printf(" then the vertex is assigned the marker one (1).\n");
2410 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
2411 printf("\n");
2412 printf(
2413" If you want Triangle to determine for you which vertices and edges are on\n"
2414);
2415 printf(
2416" the boundary, assign them the boundary marker zero (or use no markers at\n"
2417);
2418 printf(
2419" all) in your input files. In the output files, all boundary vertices,\n");
2420 printf(" edges, and segments will be assigned the value one.\n\n");
2421 printf("Triangulation Iteration Numbers:\n\n");
2422 printf(
2423" Because Triangle can read and refine its own triangulations, input\n");
2424 printf(
2425" and output files have iteration numbers. For instance, Triangle might\n");
2426 printf(
2427" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
2428 printf(
2429" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
2430 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
2431 printf(
2432" their iteration number is zero; hence, Triangle might read the file\n");
2433 printf(
2434" points.node, triangulate it, and produce the files points.1.node and\n");
2435 printf(" points.1.ele.\n\n");
2436 printf(
2437" Iteration numbers allow you to create a sequence of successively finer\n");
2438 printf(
2439" meshes suitable for multigrid methods. They also allow you to produce a\n"
2440);
2441 printf(
2442" sequence of meshes using error estimate-driven mesh refinement.\n");
2443 printf("\n");
2444 printf(
2445" If you're not using refinement or quality meshing, and you don't like\n");
2446 printf(
2447" iteration numbers, use the -I switch to disable them. This switch also\n");
2448 printf(
2449" disables output of .node and .poly files to prevent your input files from\n"
2450);
2451 printf(
2452" being overwritten. (If the input is a .poly file that contains its own\n");
2453 printf(
2454" points, a .node file is written. This can be quite convenient for\n");
2455 printf(" computing CDTs or quality meshes.)\n\n");
2456 printf("Examples of How to Use Triangle:\n\n");
2457 printf(
2458" `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
2459);
2460 printf(
2461" triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
2462 printf(
2463" to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
2464 printf(
2465" instead. (No additional .node file is needed, so none is written.)\n");
2466 printf("\n");
2467 printf(
2468" `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
2469 printf(
2470" object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
2471);
2472 printf(
2473" its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
2474);
2475 printf(
2476" The segments are copied to object.2.poly, and all edges are written to\n");
2477 printf(" object.2.edge.\n\n");
2478 printf(
2479" `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
2480);
2481 printf(
2482" object.node), generates a mesh whose angles are all between 31.5 and 117\n"
2483);
2484 printf(
2485" degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
2486);
2487 printf(
2488" mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
2489 printf(" into multiple subsegments; these are written to object.1.poly.\n");
2490 printf("\n");
2491 printf(
2492" Here is a sample file `box.poly' describing a square with a square hole:\n"
2493);
2494 printf("\n");
2495 printf(
2496" # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
2497);
2498 printf(" 8 2 0 1\n");
2499 printf(" # Outer box has these vertices:\n");
2500 printf(" 1 0 0 0\n");
2501 printf(" 2 0 3 0\n");
2502 printf(" 3 3 0 0\n");
2503 printf(" 4 3 3 33 # A special marker for this vertex.\n");
2504 printf(" # Inner square has these vertices:\n");
2505 printf(" 5 1 1 0\n");
2506 printf(" 6 1 2 0\n");
2507 printf(" 7 2 1 0\n");
2508 printf(" 8 2 2 0\n");
2509 printf(" # Five segments with boundary markers.\n");
2510 printf(" 5 1\n");
2511 printf(" 1 1 2 5 # Left side of outer box.\n");
2512 printf(" # Square hole has these segments:\n");
2513 printf(" 2 5 7 0\n");
2514 printf(" 3 7 8 0\n");
2515 printf(" 4 8 6 10\n");
2516 printf(" 5 6 5 0\n");
2517 printf(" # One hole in the middle of the inner square.\n");
2518 printf(" 1\n");
2519 printf(" 1 1.5 1.5\n");
2520 printf("\n");
2521 printf(
2522" Note that some segments are missing from the outer square, so you must\n");
2523 printf(
2524" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
2525);
2526 printf(
2527" file `box.1.node', with twelve vertices. The last four vertices were\n");
2528 printf(
2529" added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
2530 printf(
2531" from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
2532 printf(
2533" other vertices but 4 have been marked to indicate that they lie on a\n");
2534 printf(" boundary.\n\n");
2535 printf(" 12 2 0 1\n");
2536 printf(" 1 0 0 5\n");
2537 printf(" 2 0 3 5\n");
2538 printf(" 3 3 0 1\n");
2539 printf(" 4 3 3 33\n");
2540 printf(" 5 1 1 1\n");
2541 printf(" 6 1 2 10\n");
2542 printf(" 7 2 1 1\n");
2543 printf(" 8 2 2 10\n");
2544 printf(" 9 0 1.5 5\n");
2545 printf(" 10 1.5 0 1\n");
2546 printf(" 11 3 1.5 1\n");
2547 printf(" 12 1.5 3 1\n");
2548 printf(" # Generated by triangle -pqc box.poly\n");
2549 printf("\n");
2550 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
2551 printf("\n");
2552 printf(" 12 3 0\n");
2553 printf(" 1 5 6 9\n");
2554 printf(" 2 10 3 7\n");
2555 printf(" 3 6 8 12\n");
2556 printf(" 4 9 1 5\n");
2557 printf(" 5 6 2 9\n");
2558 printf(" 6 7 3 11\n");
2559 printf(" 7 11 4 8\n");
2560 printf(" 8 7 5 10\n");
2561 printf(" 9 12 2 6\n");
2562 printf(" 10 8 7 11\n");
2563 printf(" 11 5 1 10\n");
2564 printf(" 12 8 4 12\n");
2565 printf(" # Generated by triangle -pqc box.poly\n\n");
2566 printf(
2567" Here is the output file `box.1.poly'. Note that segments have been added\n"
2568);
2569 printf(
2570" to represent the convex hull, and some segments have been subdivided by\n");
2571 printf(
2572" newly added vertices. Note also that <# of vertices> is set to zero to\n");
2573 printf(" indicate that the vertices should be read from the .node file.\n");
2574 printf("\n");
2575 printf(" 0 2 0 1\n");
2576 printf(" 12 1\n");
2577 printf(" 1 1 9 5\n");
2578 printf(" 2 5 7 1\n");
2579 printf(" 3 8 7 1\n");
2580 printf(" 4 6 8 10\n");
2581 printf(" 5 5 6 1\n");
2582 printf(" 6 3 10 1\n");
2583 printf(" 7 4 11 1\n");
2584 printf(" 8 2 12 1\n");
2585 printf(" 9 9 2 5\n");
2586 printf(" 10 10 1 1\n");
2587 printf(" 11 11 3 1\n");
2588 printf(" 12 12 4 1\n");
2589 printf(" 1\n");
2590 printf(" 1 1.5 1.5\n");
2591 printf(" # Generated by triangle -pqc box.poly\n");
2592 printf("\n");
2593 printf("Refinement and Area Constraints:\n");
2594 printf("\n");
2595 printf(
2596" The -r switch causes a mesh (.node and .ele files) to be read and\n");
2597 printf(
2598" refined. If the -p switch is also used, a .poly file is read and used to\n"
2599);
2600 printf(
2601" specify edges that are constrained and cannot be eliminated (although\n");
2602 printf(
2603" they can be subdivided into smaller edges) by the refinement process.\n");
2604 printf("\n");
2605 printf(
2606" When you refine a mesh, you generally want to impose tighter constraints.\n"
2607);
2608 printf(
2609" One way to accomplish this is to use -q with a larger angle, or -a\n");
2610 printf(
2611" followed by a smaller area than you used to generate the mesh you are\n");
2612 printf(
2613" refining. Another way to do this is to create an .area file, which\n");
2614 printf(
2615" specifies a maximum area for each triangle, and use the -a switch\n");
2616 printf(
2617" (without a number following). Each triangle's area constraint is applied\n"
2618);
2619 printf(
2620" to that triangle. Area constraints tend to diffuse as the mesh is\n");
2621 printf(
2622" refined, so if there are large variations in area constraint between\n");
2623 printf(
2624" adjacent triangles, you may not get the results you want. In that case,\n"
2625);
2626 printf(
2627" consider instead using the -u switch and writing a C procedure that\n");
2628 printf(" determines which triangles are too large.\n\n");
2629 printf(
2630" If you are refining a mesh composed of linear (three-node) elements, the\n"
2631);
2632 printf(
2633" output mesh contains all the nodes present in the input mesh, in the same\n"
2634);
2635 printf(
2636" order, with new nodes added at the end of the .node file. However, the\n");
2637 printf(
2638" refinement is not hierarchical: there is no guarantee that each output\n");
2639 printf(
2640" element is contained in a single input element. Often, an output element\n"
2641);
2642 printf(
2643" can overlap two or three input elements, and some input edges are not\n");
2644 printf(
2645" present in the output mesh. Hence, a sequence of refined meshes forms a\n"
2646);
2647 printf(
2648" hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
2649 printf(
2650" mesh of higher-order elements, the hierarchical property applies only to\n"
2651);
2652 printf(
2653" the nodes at the corners of an element; the midpoint nodes on each edge\n");
2654 printf(" are discarded before the mesh is refined.\n\n");
2655 printf(
2656" Maximum area constraints in .poly files operate differently from those in\n"
2657);
2658 printf(
2659" .area files. A maximum area in a .poly file applies to the whole\n");
2660 printf(
2661" (segment-bounded) region in which a point falls, whereas a maximum area\n");
2662 printf(
2663" in an .area file applies to only one triangle. Area constraints in .poly\n"
2664);
2665 printf(
2666" files are used only when a mesh is first generated, whereas area\n");
2667 printf(
2668" constraints in .area files are used only to refine an existing mesh, and\n"
2669);
2670 printf(
2671" are typically based on a posteriori error estimates resulting from a\n");
2672 printf(" finite element simulation on that mesh.\n\n");
2673 printf(
2674" `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
2675 printf(
2676" refines the triangulation to enforce a 25 degree minimum angle, and then\n"
2677);
2678 printf(
2679" writes the refined triangulation to object.2.node and object.2.ele.\n");
2680 printf("\n");
2681 printf(
2682" `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
2683);
2684 printf(
2685" After reconstructing the mesh and its subsegments, Triangle refines the\n");
2686 printf(
2687" mesh so that no triangle has area greater than 6.2, and furthermore the\n");
2688 printf(
2689" triangles satisfy the maximum area constraints in z.3.area. No angle\n");
2690 printf(
2691" bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
2692);
2693 printf(" z.4.poly.\n\n");
2694 printf(
2695" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
2696 printf(
2697" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
2698 printf(" suitable for multigrid.\n\n");
2699 printf("Convex Hulls and Mesh Boundaries:\n\n");
2700 printf(
2701" If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
2702 printf(
2703" hull as a by-product in the output .poly file if you use the -c switch.\n");
2704 printf(
2705" There are faster algorithms for finding a two-dimensional convex hull\n");
2706 printf(" than triangulation, of course, but this one comes for free.\n\n");
2707 printf(
2708" If the input is an unconstrained mesh (you are using the -r switch but\n");
2709 printf(
2710" not the -p switch), Triangle produces a list of its boundary edges\n");
2711 printf(
2712" (including hole boundaries) as a by-product when you use the -c switch.\n");
2713 printf(
2714" If you also use the -p switch, the output .poly file contains all the\n");
2715 printf(" segments from the input .poly file as well.\n\n");
2716 printf("Voronoi Diagrams:\n\n");
2717 printf(
2718" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
2719 printf(
2720" .v.edge. For example, `triangle -v points' reads points.node, produces\n");
2721 printf(
2722" its Delaunay triangulation in points.1.node and points.1.ele, and\n");
2723 printf(
2724" produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
2725);
2726 printf(
2727" .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
2728 printf(
2729" file contains a list of all Voronoi edges, some of which may be infinite\n"
2730);
2731 printf(
2732" rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
2733 printf(" vertices through Triangle, if so desired.)\n\n");
2734 printf(
2735" This implementation does not use exact arithmetic to compute the Voronoi\n"
2736);
2737 printf(
2738" vertices, and does not check whether neighboring vertices are identical.\n"
2739);
2740 printf(
2741" Be forewarned that if the Delaunay triangulation is degenerate or\n");
2742 printf(
2743" near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
2744 printf(" crossing edges.\n\n");
2745 printf(
2746" The result is a valid Voronoi diagram only if Triangle's output is a true\n"
2747);
2748 printf(
2749" Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
2750 printf(
2751" may contain crossing edges and other pathology) if the output is a CDT or\n"
2752);
2753 printf(
2754" CCDT, or if it has holes or concavities. If the triangulated domain is\n");
2755 printf(
2756" convex and has no holes, you can use -D switch to force Triangle to\n");
2757 printf(
2758" construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
2759 printf(" Voronoi diagram will be valid.\n\n");
2760 printf("Mesh Topology:\n\n");
2761 printf(
2762" You may wish to know which triangles are adjacent to a certain Delaunay\n");
2763 printf(
2764" edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
2765 printf(
2766" Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
2767 printf(
2768" each other. All of this information can be found by cross-referencing\n");
2769 printf(
2770" output files with the recollection that the Delaunay triangulation and\n");
2771 printf(" the Voronoi diagram are planar duals.\n\n");
2772 printf(
2773" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
2774 printf(
2775" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
2776 printf(
2777" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
2778 printf(
2779" vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
2780 printf(" of vertex k of the corresponding .node file.\n\n");
2781 printf(
2782" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
2783 printf(
2784" vertices of the corresponding Voronoi edge. If the endpoints of a\n");
2785 printf(
2786" Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
2787);
2788 printf(
2789" and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
2790);
2791 printf(
2792" respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
2793);
2794 printf(
2795" at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
2796);
2797 printf(
2798" a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
2799);
2800 printf(
2801" adjoin the right and left sides of the corresponding Voronoi edge,\n");
2802 printf(
2803" respectively. To find which Voronoi cells are adjacent to each other,\n");
2804 printf(" just read the list of Delaunay edges.\n\n");
2805 printf(
2806" Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
2807);
2808 printf(
2809" but you can reconstructed it straightforwardly. For instance, to find\n");
2810 printf(
2811" all the edges of Voronoi cell 1, search the output .edge file for every\n");
2812 printf(
2813" edge that has input vertex 1 as an endpoint. The corresponding dual\n");
2814 printf(
2815" edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
2816 printf("\n");
2817 printf(
2818" For each Voronoi vertex, the .neigh file gives a list of the three\n");
2819 printf(
2820" Voronoi vertices attached to it. You might find this more convenient\n");
2821 printf(" than the .v.edge file.\n\n");
2822 printf("Quadratic Elements:\n\n");
2823 printf(
2824" Triangle generates meshes with subparametric quadratic elements if the\n");
2825 printf(
2826" -o2 switch is specified. Quadratic elements have six nodes per element,\n"
2827);
2828 printf(
2829" rather than three. `Subparametric' means that the edges of the triangles\n"
2830);
2831 printf(
2832" are always straight, so that subparametric quadratic elements are\n");
2833 printf(
2834" geometrically identical to linear elements, even though they can be used\n"
2835);
2836 printf(
2837" with quadratic interpolating functions. The three extra nodes of an\n");
2838 printf(
2839" element fall at the midpoints of the three edges, with the fourth, fifth,\n"
2840);
2841 printf(
2842" and sixth nodes appearing opposite the first, second, and third corners\n");
2843 printf(" respectively.\n\n");
2844 printf("Domains with Small Angles:\n\n");
2845 printf(
2846" If two input segments adjoin each other at a small angle, clearly the -q\n"
2847);
2848 printf(
2849" switch cannot remove the small angle. Moreover, Triangle may have no\n");
2850 printf(
2851" choice but to generate additional triangles whose smallest angles are\n");
2852 printf(
2853" smaller than the specified bound. However, these triangles only appear\n");
2854 printf(
2855" between input segments separated by small angles. Moreover, if you\n");
2856 printf(
2857" request a minimum angle of theta degrees, Triangle will generally produce\n"
2858);
2859 printf(
2860" no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
2861);
2862 printf(" the minimum angle.\n\n");
2863 printf("Statistics:\n\n");
2864 printf(
2865" After generating a mesh, Triangle prints a count of entities in the\n");
2866 printf(
2867" output mesh, including the number of vertices, triangles, edges, exterior\n"
2868);
2869 printf(
2870" boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
2871 printf(
2872" including hole boundaries), interior boundary edges (i.e. subsegments of\n"
2873);
2874 printf(
2875" input segments not on the boundary), and total subsegments. If you've\n");
2876 printf(
2877" forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
2878);
2879 printf(
2880" with the -rNEP switches to read the mesh and print the statistics without\n"
2881);
2882 printf(
2883" writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
2884 printf("\n");
2885 printf(
2886" The -V switch produces extended statistics, including a rough estimate\n");
2887 printf(
2888" of memory use, the number of calls to geometric predicates, and\n");
2889 printf(
2890" histograms of the angles and the aspect ratios of the triangles in the\n");
2891 printf(" mesh.\n\n");
2892 printf("Exact Arithmetic:\n\n");
2893 printf(
2894" Triangle uses adaptive exact arithmetic to perform what computational\n");
2895 printf(
2896" geometers call the `orientation' and `incircle' tests. If the floating-\n"
2897);
2898 printf(
2899" point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
2900 printf(
2901" most workstations do), and does not use extended precision internal\n");
2902 printf(
2903" floating-point registers, then your output is guaranteed to be an\n");
2904 printf(
2905" absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
2906);
2907 printf(
2908" error notwithstanding. The word `adaptive' implies that these arithmetic\n"
2909);
2910 printf(
2911" routines compute the result only to the precision necessary to guarantee\n"
2912);
2913 printf(
2914" correctness, so they are usually nearly as fast as their approximate\n");
2915 printf(" counterparts.\n\n");
2916 printf(
2917" May CPUs, including Intel x86 processors, have extended precision\n");
2918 printf(
2919" floating-point registers. These must be reconfigured so their precision\n"
2920);
2921 printf(
2922" is reduced to memory precision. Triangle does this if it is compiled\n");
2923 printf(" correctly. See the makefile for details.\n\n");
2924 printf(
2925" The exact tests can be disabled with the -X switch. On most inputs, this\n"
2926);
2927 printf(
2928" switch reduces the computation time by about eight percent--it's not\n");
2929 printf(
2930" worth the risk. There are rare difficult inputs (having many collinear\n");
2931 printf(
2932" and cocircular vertices), however, for which the difference in speed\n");
2933 printf(
2934" could be a factor of two. Be forewarned that these are precisely the\n");
2935 printf(
2936" inputs most likely to cause errors if you use the -X switch. Hence, the\n"
2937);
2938 printf(" -X switch is not recommended.\n\n");
2939 printf(
2940" Unfortunately, the exact tests don't solve every numerical problem.\n");
2941 printf(
2942" Exact arithmetic is not used to compute the positions of new vertices,\n");
2943 printf(
2944" because the bit complexity of vertex coordinates would grow without\n");
2945 printf(
2946" bound. Hence, segment intersections aren't computed exactly; in very\n");
2947 printf(
2948" unusual cases, roundoff error in computing an intersection point might\n");
2949 printf(
2950" actually lead to an inverted triangle and an invalid triangulation.\n");
2951 printf(
2952" (This is one reason to specify your own intersection points in your .poly\n"
2953);
2954 printf(
2955" files.) Similarly, exact arithmetic is not used to compute the vertices\n"
2956);
2957 printf(" of the Voronoi diagram.\n\n");
2958 printf(
2959" Another pair of problems not solved by the exact arithmetic routines is\n");
2960 printf(
2961" underflow and overflow. If Triangle is compiled for double precision\n");
2962 printf(
2963" arithmetic, I believe that Triangle's geometric predicates work correctly\n"
2964);
2965 printf(
2966" if the exponent of every input coordinate falls in the range [-148, 201].\n"
2967);
2968 printf(
2969" Underflow can silently prevent the orientation and incircle tests from\n");
2970 printf(
2971" being performed exactly, while overflow typically causes a floating\n");
2972 printf(" exception.\n\n");
2973 printf("Calling Triangle from Another Program:\n\n");
2974 printf(" Read the file triangle.h for details.\n\n");
2975 printf("Troubleshooting:\n\n");
2976 printf(" Please read this section before mailing me bugs.\n\n");
2977 printf(" `My output mesh has no triangles!'\n\n");
2978 printf(
2979" If you're using a PSLG, you've probably failed to specify a proper set\n"
2980);
2981 printf(
2982" of bounding segments, or forgotten to use the -c switch. Or you may\n");
2983 printf(
2984" have placed a hole badly, thereby eating all your triangles. To test\n");
2985 printf(" these possibilities, try again with the -c and -O switches.\n");
2986 printf(
2987" Alternatively, all your input vertices may be collinear, in which case\n"
2988);
2989 printf(" you can hardly expect to triangulate them.\n\n");
2990 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
2991 printf(
2992" Bad things can happen when triangles get so small that the distance\n");
2993 printf(
2994" between their vertices isn't much larger than the precision of your\n");
2995 printf(
2996" machine's arithmetic. If you've compiled Triangle for single-precision\n"
2997);
2998 printf(
2999" arithmetic, you might do better by recompiling it for double-precision.\n"
3000);
3001 printf(
3002" Then again, you might just have to settle for more lenient constraints\n"
3003);
3004 printf(
3005" on the minimum angle and the maximum area than you had planned.\n");
3006 printf("\n");
3007 printf(
3008" You can minimize precision problems by ensuring that the origin lies\n");
3009 printf(
3010" inside your vertex set, or even inside the densest part of your\n");
3011 printf(
3012" mesh. If you're triangulating an object whose x-coordinates all fall\n");
3013 printf(
3014" between 6247133 and 6247134, you're not leaving much floating-point\n");
3015 printf(" precision for Triangle to work with.\n\n");
3016 printf(
3017" Precision problems can occur covertly if the input PSLG contains two\n");
3018 printf(
3019" segments that meet (or intersect) at an extremely small angle, or if\n");
3020 printf(
3021" such an angle is introduced by the -c switch. If you don't realize\n");
3022 printf(
3023" that a tiny angle is being formed, you might never discover why\n");
3024 printf(
3025" Triangle is crashing. To check for this possibility, use the -S switch\n"
3026);
3027 printf(
3028" (with an appropriate limit on the number of Steiner points, found by\n");
3029 printf(
3030" trial-and-error) to stop Triangle early, and view the output .poly file\n"
3031);
3032 printf(
3033" with Show Me (described below). Look carefully for regions where dense\n"
3034);
3035 printf(
3036" clusters of vertices are forming and for small angles between segments.\n"
3037);
3038 printf(
3039" Zoom in closely, as such segments might look like a single segment from\n"
3040);
3041 printf(" a distance.\n\n");
3042 printf(
3043" If some of the input values are too large, Triangle may suffer a\n");
3044 printf(
3045" floating exception due to overflow when attempting to perform an\n");
3046 printf(
3047" orientation or incircle test. (Read the section on exact arithmetic\n");
3048 printf(
3049" above.) Again, I recommend compiling Triangle for double (rather\n");
3050 printf(" than single) precision arithmetic.\n\n");
3051 printf(
3052" Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
3053 printf(
3054" -u) with an input that is not segment-bounded--that is, if your input\n");
3055 printf(
3056" is a vertex set, or you're using the -c switch. If the convex hull of\n"
3057);
3058 printf(
3059" your input vertices has collinear vertices on its boundary, an input\n");
3060 printf(
3061" vertex that you think lies on the convex hull might actually lie just\n");
3062 printf(
3063" inside the convex hull. If so, the vertex and the nearby convex hull\n");
3064 printf(
3065" edge form an extremely thin triangle. When Triangle tries to refine\n");
3066 printf(
3067" the mesh to enforce angle and area constraints, Triangle might generate\n"
3068);
3069 printf(
3070" extremely tiny triangles, or it might fail because of insufficient\n");
3071 printf(" floating-point precision.\n\n");
3072 printf(
3073" `The numbering of the output vertices doesn't match the input vertices.'\n"
3074);
3075 printf("\n");
3076 printf(
3077" You may have had duplicate input vertices, or you may have eaten some\n");
3078 printf(
3079" of your input vertices with a hole, or by placing them outside the area\n"
3080);
3081 printf(
3082" enclosed by segments. In any case, you can solve the problem by not\n");
3083 printf(" using the -j switch.\n\n");
3084 printf(
3085" `Triangle executes without incident, but when I look at the resulting\n");
3086 printf(
3087" mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
3088 printf("\n");
3089 printf(
3090" If you select the -X switch, Triangle occasionally makes mistakes due\n");
3091 printf(
3092" to floating-point roundoff error. Although these errors are rare,\n");
3093 printf(
3094" don't use the -X switch. If you still have problems, please report the\n"
3095);
3096 printf(" bug.\n\n");
3097 printf(
3098" `Triangle executes without incident, but when I look at the resulting\n");
3099 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
3100 printf(" inconsistencies.'\n");
3101 printf("\n");
3102 printf(
3103" If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
3104);
3105 printf(
3106" diagram if the domain you are triangulating is convex and free of\n");
3107 printf(
3108" holes, and you use the -D switch to construct a conforming Delaunay\n");
3109 printf(" triangulation (instead of a CDT or CCDT).\n\n");
3110 printf(
3111" Strange things can happen if you've taken liberties with your PSLG. Do\n");
3112 printf(
3113" you have a vertex lying in the middle of a segment? Triangle sometimes\n");
3114 printf(
3115" copes poorly with that sort of thing. Do you want to lay out a collinear\n"
3116);
3117 printf(
3118" row of evenly spaced, segment-connected vertices? Have you simply\n");
3119 printf(
3120" defined one long segment connecting the leftmost vertex to the rightmost\n"
3121);
3122 printf(
3123" vertex, and a bunch of vertices lying along it? This method occasionally\n"
3124);
3125 printf(
3126" works, especially with horizontal and vertical lines, but often it\n");
3127 printf(
3128" doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
3129);
3130 printf(" separate segment. If you don't like it, tough.\n\n");
3131 printf(
3132" Furthermore, if you have segments that intersect other than at their\n");
3133 printf(
3134" endpoints, try not to let the intersections fall extremely close to PSLG\n"
3135);
3136 printf(" vertices or each other.\n\n");
3137 printf(
3138" If you have problems refining a triangulation not produced by Triangle:\n");
3139 printf(
3140" Are you sure the triangulation is geometrically valid? Is it formatted\n");
3141 printf(
3142" correctly for Triangle? Are the triangles all listed so the first three\n"
3143);
3144 printf(
3145" vertices are their corners in counterclockwise order? Are all of the\n");
3146 printf(
3147" triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
3148);
3149 printf(" assumes that it starts with a CDT.\n\n");
3150 printf("Show Me:\n\n");
3151 printf(
3152" Triangle comes with a separate program named `Show Me', whose primary\n");
3153 printf(
3154" purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
3155);
3156 printf(
3157" purpose is to check the validity of your input files, and do so more\n");
3158 printf(
3159" thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
3160 printf(
3161" you have the X Windows system. Sorry, Microsoft Windows users.\n");
3162 printf("\n");
3163 printf("Triangle on the Web:\n");
3164 printf("\n");
3165 printf(" To see an illustrated version of these instructions, check out\n");
3166 printf("\n");
3167 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
3168 printf("\n");
3169 printf("A Brief Plea:\n");
3170 printf("\n");
3171 printf(
3172" If you use Triangle, and especially if you use it to accomplish real\n");
3173 printf(
3174" work, I would like very much to hear from you. A short letter or email\n");
3175 printf(
3176" (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
3177);
3178 printf(
3179" to me. The more people I know are using this program, the more easily I\n"
3180);
3181 printf(
3182" can justify spending time on improvements, which in turn will benefit\n");
3183 printf(
3184" you. Also, I can put you on a list to receive email whenever a new\n");
3185 printf(" version of Triangle is available.\n\n");
3186 printf(
3187" If you use a mesh generated by Triangle in a publication, please include\n"
3188);
3189 printf(
3190" an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
3191);
3192 printf(
3193" If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
3194 printf(
3195" ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
3196 printf(
3197" Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
3198 printf(
3199" Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
3200 printf(
3201" Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
3202 printf(
3203" Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
3204);
3205 printf(" Geometry.)'\n\n");
3206 printf("Research credit:\n\n");
3207 printf(
3208" Of course, I can take credit for only a fraction of the ideas that made\n");
3209 printf(
3210" this mesh generator possible. Triangle owes its existence to the efforts\n"
3211);
3212 printf(
3213" of many fine computational geometers and other researchers, including\n");
3214 printf(
3215" Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
3216);
3217 printf(
3218" Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
3219 printf(
3220" Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
3221 printf(
3222" Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
3223 printf(
3224" Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
3225);
3226 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
3227 printf(
3228" Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
3229 printf(" source code for references.\n\n");
3230 triexit(0);
3231}
3232
3233#endif /* not TRILIBRARY */
3234
3235/*****************************************************************************/
3236/* */
3237/* internalerror() Ask the user to send me the defective product. Exit. */
3238/* */
3239/*****************************************************************************/
3240
3242{
3243 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
3244 printf(" Include the message above, your input data set, and the exact\n");
3245 printf(" command line you used to run Triangle.\n");
3246 triexit(1);
3247}
3248
3249/*****************************************************************************/
3250/* */
3251/* parsecommandline() Read the command line, identify switches, and set */
3252/* up options and file names. */
3253/* */
3254/*****************************************************************************/
3255
3256#ifdef ANSI_DECLARATORS
3257void parsecommandline(int argc, char **argv, struct behavior *b)
3258#else /* not ANSI_DECLARATORS */
3259void parsecommandline(argc, argv, b)
3260int argc;
3261char **argv;
3262struct behavior *b;
3263#endif /* not ANSI_DECLARATORS */
3264
3265{
3266#ifdef TRILIBRARY
3267#define STARTINDEX 0
3268#else /* not TRILIBRARY */
3269#define STARTINDEX 1
3270 int increment;
3271 int meshnumber;
3272#endif /* not TRILIBRARY */
3273 /* int i, j, k; */
3274 int i, j;
3275 /* char workstring[FILENAMESIZE]; */
3276
3277 b->poly = b->refine = b->quality = 0;
3278 b->vararea = b->fixedarea = b->usertest = 0;
3279 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
3280 b->firstnumber = 1;
3281 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
3282 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
3283 b->noiterationnum = 0;
3284 b->noholes = b->noexact = 0;
3285 b->incremental = b->sweepline = 0;
3286 b->dwyer = 1;
3287 b->splitseg = 0;
3288 b->docheck = 0;
3289 b->nobisect = 0;
3290 b->conformdel = 0;
3291 b->steiner = -1;
3292 b->order = 1;
3293 b->minangle = 0.0;
3294 b->maxarea = -1.0;
3295 b->quiet = b->verbose = 0;
3296#ifndef TRILIBRARY
3297 b->innodefilename[0] = '\0';
3298#endif /* not TRILIBRARY */
3299
3300 for (i = STARTINDEX; i < argc; i++) {
3301#ifndef TRILIBRARY
3302 if (argv[i][0] == '-') {
3303#endif /* not TRILIBRARY */
3304 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
3305 if (argv[i][j] == 'p') {
3306 b->poly = 1;
3307 }
3308#ifndef CDT_ONLY
3309 if (argv[i][j] == 'r') {
3310 b->refine = 1;
3311 }
3312 if (argv[i][j] == 'q') {
3313 b->quality = 1;
3314 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3315 (argv[i][j + 1] == '.')) {
3316 k = 0;
3317 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3318 (argv[i][j + 1] == '.')) {
3319 j++;
3320 workstring[k] = argv[i][j];
3321 k++;
3322 }
3323 workstring[k] = '\0';
3324 b->minangle = (REAL) strtod(workstring, (char **) NULL);
3325 } else {
3326 b->minangle = 20.0;
3327 }
3328 }
3329 if (argv[i][j] == 'a') {
3330 b->quality = 1;
3331 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3332 (argv[i][j + 1] == '.')) {
3333 b->fixedarea = 1;
3334 k = 0;
3335 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3336 (argv[i][j + 1] == '.')) {
3337 j++;
3338 workstring[k] = argv[i][j];
3339 k++;
3340 }
3341 workstring[k] = '\0';
3342 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
3343 if (b->maxarea <= 0.0) {
3344 printf("Error: Maximum area must be greater than zero.\n");
3345 triexit(1);
3346 }
3347 } else {
3348 b->vararea = 1;
3349 }
3350 }
3351 if (argv[i][j] == 'u') {
3352 b->quality = 1;
3353 b->usertest = 1;
3354 }
3355#endif /* not CDT_ONLY */
3356 if (argv[i][j] == 'A') {
3357 b->regionattrib = 1;
3358 }
3359 if (argv[i][j] == 'c') {
3360 b->convex = 1;
3361 }
3362 if (argv[i][j] == 'w') {
3363 b->weighted = 1;
3364 }
3365 if (argv[i][j] == 'W') {
3366 b->weighted = 2;
3367 }
3368 if (argv[i][j] == 'j') {
3369 b->jettison = 1;
3370 }
3371 if (argv[i][j] == 'z') {
3372 b->firstnumber = 0;
3373 }
3374 if (argv[i][j] == 'e') {
3375 b->edgesout = 1;
3376 }
3377 if (argv[i][j] == 'v') {
3378 b->voronoi = 1;
3379 }
3380 if (argv[i][j] == 'n') {
3381 b->neighbors = 1;
3382 }
3383 if (argv[i][j] == 'g') {
3384 b->geomview = 1;
3385 }
3386 if (argv[i][j] == 'B') {
3387 b->nobound = 1;
3388 }
3389 if (argv[i][j] == 'P') {
3390 b->nopolywritten = 1;
3391 }
3392 if (argv[i][j] == 'N') {
3393 b->nonodewritten = 1;
3394 }
3395 if (argv[i][j] == 'E') {
3396 b->noelewritten = 1;
3397 }
3398#ifndef TRILIBRARY
3399 if (argv[i][j] == 'I') {
3400 b->noiterationnum = 1;
3401 }
3402#endif /* not TRILIBRARY */
3403 if (argv[i][j] == 'O') {
3404 b->noholes = 1;
3405 }
3406 if (argv[i][j] == 'X') {
3407 b->noexact = 1;
3408 }
3409 if (argv[i][j] == 'o') {
3410 if (argv[i][j + 1] == '2') {
3411 j++;
3412 b->order = 2;
3413 }
3414 }
3415#ifndef CDT_ONLY
3416 if (argv[i][j] == 'Y') {
3417 b->nobisect++;
3418 }
3419 if (argv[i][j] == 'S') {
3420 b->steiner = 0;
3421 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
3422 j++;
3423 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
3424 }
3425 }
3426#endif /* not CDT_ONLY */
3427#ifndef REDUCED
3428 if (argv[i][j] == 'i') {
3429 b->incremental = 1;
3430 }
3431 if (argv[i][j] == 'F') {
3432 b->sweepline = 1;
3433 }
3434#endif /* not REDUCED */
3435 if (argv[i][j] == 'l') {
3436 b->dwyer = 0;
3437 }
3438#ifndef REDUCED
3439#ifndef CDT_ONLY
3440 if (argv[i][j] == 's') {
3441 b->splitseg = 1;
3442 }
3443 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
3444 b->quality = 1;
3445 b->conformdel = 1;
3446 }
3447#endif /* not CDT_ONLY */
3448 if (argv[i][j] == 'C') {
3449 b->docheck = 1;
3450 }
3451#endif /* not REDUCED */
3452 if (argv[i][j] == 'Q') {
3453 b->quiet = 1;
3454 }
3455 if (argv[i][j] == 'V') {
3456 b->verbose++;
3457 }
3458#ifndef TRILIBRARY
3459 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
3460 (argv[i][j] == '?')) {
3461 info();
3462 }
3463#endif /* not TRILIBRARY */
3464 }
3465#ifndef TRILIBRARY
3466 } else {
3467 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
3468 b->innodefilename[FILENAMESIZE - 1] = '\0';
3469 }
3470#endif /* not TRILIBRARY */
3471 }
3472#ifndef TRILIBRARY
3473 if (b->innodefilename[0] == '\0') {
3474 syntax();
3475 }
3476 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
3477 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3478 }
3479 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
3480 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3481 b->poly = 1;
3482 }
3483#ifndef CDT_ONLY
3484 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
3485 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
3486 b->refine = 1;
3487 }
3488 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
3489 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3490 b->refine = 1;
3491 b->quality = 1;
3492 b->vararea = 1;
3493 }
3494#endif /* not CDT_ONLY */
3495#endif /* not TRILIBRARY */
3496 b->usesegments = b->poly || b->refine || b->quality || b->convex;
3497 b->goodangle = cos(b->minangle * PI / 180.0);
3498 if (b->goodangle == 1.0) {
3499 b->offconstant = 0.0;
3500 } else {
3501 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
3502 }
3503 b->goodangle *= b->goodangle;
3504 if (b->refine && b->noiterationnum) {
3505 printf(
3506 "Error: You cannot use the -I switch when refining a triangulation.\n");
3507 triexit(1);
3508 }
3509 /* Be careful not to allocate space for element area constraints that */
3510 /* will never be assigned any value (other than the default -1.0). */
3511 if (!b->refine && !b->poly) {
3512 b->vararea = 0;
3513 }
3514 /* Be careful not to add an extra attribute to each element unless the */
3515 /* input supports it (PSLG in, but not refining a preexisting mesh). */
3516 if (b->refine || !b->poly) {
3517 b->regionattrib = 0;
3518 }
3519 /* Regular/weighted triangulations are incompatible with PSLGs */
3520 /* and meshing. */
3521 if (b->weighted && (b->poly || b->quality)) {
3522 b->weighted = 0;
3523 if (!b->quiet) {
3524 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
3525 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
3526 );
3527 }
3528 }
3529 if (b->jettison && b->nonodewritten && !b->quiet) {
3530 printf("Warning: -j and -N switches are somewhat incompatible.\n");
3531 printf(" If any vertices are jettisoned, you will need the output\n");
3532 printf(" .node file to reconstruct the new node indices.");
3533 }
3534
3535#ifndef TRILIBRARY
3536 strcpy(b->inpolyfilename, b->innodefilename);
3537 strcpy(b->inelefilename, b->innodefilename);
3538 strcpy(b->areafilename, b->innodefilename);
3539 increment = 0;
3540 strcpy(workstring, b->innodefilename);
3541 j = 1;
3542 while (workstring[j] != '\0') {
3543 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
3544 increment = j + 1;
3545 }
3546 j++;
3547 }
3548 meshnumber = 0;
3549 if (increment > 0) {
3550 j = increment;
3551 do {
3552 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
3553 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
3554 } else {
3555 increment = 0;
3556 }
3557 j++;
3558 } while (workstring[j] != '\0');
3559 }
3560 if (b->noiterationnum) {
3561 strcpy(b->outnodefilename, b->innodefilename);
3562 strcpy(b->outelefilename, b->innodefilename);
3563 strcpy(b->edgefilename, b->innodefilename);
3564 strcpy(b->vnodefilename, b->innodefilename);
3565 strcpy(b->vedgefilename, b->innodefilename);
3566 strcpy(b->neighborfilename, b->innodefilename);
3567 strcpy(b->offfilename, b->innodefilename);
3568 strcat(b->outnodefilename, ".node");
3569 strcat(b->outelefilename, ".ele");
3570 strcat(b->edgefilename, ".edge");
3571 strcat(b->vnodefilename, ".v.node");
3572 strcat(b->vedgefilename, ".v.edge");
3573 strcat(b->neighborfilename, ".neigh");
3574 strcat(b->offfilename, ".off");
3575 } else if (increment == 0) {
3576 strcpy(b->outnodefilename, b->innodefilename);
3577 strcpy(b->outpolyfilename, b->innodefilename);
3578 strcpy(b->outelefilename, b->innodefilename);
3579 strcpy(b->edgefilename, b->innodefilename);
3580 strcpy(b->vnodefilename, b->innodefilename);
3581 strcpy(b->vedgefilename, b->innodefilename);
3582 strcpy(b->neighborfilename, b->innodefilename);
3583 strcpy(b->offfilename, b->innodefilename);
3584 strcat(b->outnodefilename, ".1.node");
3585 strcat(b->outpolyfilename, ".1.poly");
3586 strcat(b->outelefilename, ".1.ele");
3587 strcat(b->edgefilename, ".1.edge");
3588 strcat(b->vnodefilename, ".1.v.node");
3589 strcat(b->vedgefilename, ".1.v.edge");
3590 strcat(b->neighborfilename, ".1.neigh");
3591 strcat(b->offfilename, ".1.off");
3592 } else {
3593 workstring[increment] = '%';
3594 workstring[increment + 1] = 'd';
3595 workstring[increment + 2] = '\0';
3596 sprintf(b->outnodefilename, workstring, meshnumber + 1);
3597 strcpy(b->outpolyfilename, b->outnodefilename);
3598 strcpy(b->outelefilename, b->outnodefilename);
3599 strcpy(b->edgefilename, b->outnodefilename);
3600 strcpy(b->vnodefilename, b->outnodefilename);
3601 strcpy(b->vedgefilename, b->outnodefilename);
3602 strcpy(b->neighborfilename, b->outnodefilename);
3603 strcpy(b->offfilename, b->outnodefilename);
3604 strcat(b->outnodefilename, ".node");
3605 strcat(b->outpolyfilename, ".poly");
3606 strcat(b->outelefilename, ".ele");
3607 strcat(b->edgefilename, ".edge");
3608 strcat(b->vnodefilename, ".v.node");
3609 strcat(b->vedgefilename, ".v.edge");
3610 strcat(b->neighborfilename, ".neigh");
3611 strcat(b->offfilename, ".off");
3612 }
3613 strcat(b->innodefilename, ".node");
3614 strcat(b->inpolyfilename, ".poly");
3615 strcat(b->inelefilename, ".ele");
3616 strcat(b->areafilename, ".area");
3617#endif /* not TRILIBRARY */
3618}
3619
3620/** **/
3621/** **/
3622/********* User interaction routines begin here *********/
3623
3624/********* Debugging routines begin here *********/
3625/** **/
3626/** **/
3627
3628/*****************************************************************************/
3629/* */
3630/* printtriangle() Print out the details of an oriented triangle. */
3631/* */
3632/* I originally wrote this procedure to simplify debugging; it can be */
3633/* called directly from the debugger, and presents information about an */
3634/* oriented triangle in digestible form. It's also used when the */
3635/* highest level of verbosity (`-VVV') is specified. */
3636/* */
3637/*****************************************************************************/
3638
3639#ifdef ANSI_DECLARATORS
3640void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
3641#else /* not ANSI_DECLARATORS */
3642void printtriangle(m, b, t)
3643struct mesh *m;
3644struct behavior *b;
3645struct otri *t;
3646#endif /* not ANSI_DECLARATORS */
3647
3648{
3649 struct otri printtri;
3650 struct osub printsh;
3651 vertex printvertex;
3652
3653 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
3654 t->orient);
3655 decode(t->tri[0], printtri);
3656 if (printtri.tri == m->dummytri) {
3657 printf(" [0] = Outer space\n");
3658 } else {
3659 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
3660 printtri.orient);
3661 }
3662 decode(t->tri[1], printtri);
3663 if (printtri.tri == m->dummytri) {
3664 printf(" [1] = Outer space\n");
3665 } else {
3666 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
3667 printtri.orient);
3668 }
3669 decode(t->tri[2], printtri);
3670 if (printtri.tri == m->dummytri) {
3671 printf(" [2] = Outer space\n");
3672 } else {
3673 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
3674 printtri.orient);
3675 }
3676
3677 org(*t, printvertex);
3678 if (printvertex == (vertex) NULL)
3679 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
3680 else
3681 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
3682 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
3683 printvertex[0], printvertex[1]);
3684 dest(*t, printvertex);
3685 if (printvertex == (vertex) NULL)
3686 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
3687 else
3688 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
3689 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
3690 printvertex[0], printvertex[1]);
3691 apex(*t, printvertex);
3692 if (printvertex == (vertex) NULL)
3693 printf(" Apex [%d] = NULL\n", t->orient + 3);
3694 else
3695 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
3696 t->orient + 3, (unsigned long) printvertex,
3697 printvertex[0], printvertex[1]);
3698
3699 if (b->usesegments) {
3700 sdecode(t->tri[6], printsh);
3701 if (printsh.ss != m->dummysub) {
3702 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
3703 printsh.ssorient);
3704 }
3705 sdecode(t->tri[7], printsh);
3706 if (printsh.ss != m->dummysub) {
3707 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
3708 printsh.ssorient);
3709 }
3710 sdecode(t->tri[8], printsh);
3711 if (printsh.ss != m->dummysub) {
3712 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
3713 printsh.ssorient);
3714 }
3715 }
3716
3717 if (b->vararea) {
3718 printf(" Area constraint: %.4g\n", areabound(*t));
3719 }
3720}
3721
3722/*****************************************************************************/
3723/* */
3724/* printsubseg() Print out the details of an oriented subsegment. */
3725/* */
3726/* I originally wrote this procedure to simplify debugging; it can be */
3727/* called directly from the debugger, and presents information about an */
3728/* oriented subsegment in digestible form. It's also used when the highest */
3729/* level of verbosity (`-VVV') is specified. */
3730/* */
3731/*****************************************************************************/
3732
3733#ifdef ANSI_DECLARATORS
3734void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
3735#else /* not ANSI_DECLARATORS */
3736void printsubseg(m, b, s)
3737struct mesh *m;
3738struct behavior *b;
3739struct osub *s;
3740#endif /* not ANSI_DECLARATORS */
3741
3742{
3743 struct osub printsh;
3744 struct otri printtri;
3745 vertex printvertex;
3746
3747 (void)b; /*LM: added to suppress warning */
3748
3749 printf("subsegment x%lx with orientation %d and mark %d:\n",
3750 (unsigned long) s->ss, s->ssorient, mark(*s));
3751 sdecode(s->ss[0], printsh);
3752 if (printsh.ss == m->dummysub) {
3753 printf(" [0] = No subsegment\n");
3754 } else {
3755 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
3756 printsh.ssorient);
3757 }
3758 sdecode(s->ss[1], printsh);
3759 if (printsh.ss == m->dummysub) {
3760 printf(" [1] = No subsegment\n");
3761 } else {
3762 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
3763 printsh.ssorient);
3764 }
3765
3766 sorg(*s, printvertex);
3767 if (printvertex == (vertex) NULL)
3768 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
3769 else
3770 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
3771 2 + s->ssorient, (unsigned long) printvertex,
3772 printvertex[0], printvertex[1]);
3773 sdest(*s, printvertex);
3774 if (printvertex == (vertex) NULL)
3775 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
3776 else
3777 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
3778 3 - s->ssorient, (unsigned long) printvertex,
3779 printvertex[0], printvertex[1]);
3780
3781 decode(s->ss[6], printtri);
3782 if (printtri.tri == m->dummytri) {
3783 printf(" [6] = Outer space\n");
3784 } else {
3785 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
3786 printtri.orient);
3787 }
3788 decode(s->ss[7], printtri);
3789 if (printtri.tri == m->dummytri) {
3790 printf(" [7] = Outer space\n");
3791 } else {
3792 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
3793 printtri.orient);
3794 }
3795
3796 segorg(*s, printvertex);
3797 if (printvertex == (vertex) NULL)
3798 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
3799 else
3800 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
3801 4 + s->ssorient, (unsigned long) printvertex,
3802 printvertex[0], printvertex[1]);
3803 segdest(*s, printvertex);
3804 if (printvertex == (vertex) NULL)
3805 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
3806 else
3807 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
3808 5 - s->ssorient, (unsigned long) printvertex,
3809 printvertex[0], printvertex[1]);
3810}
3811
3812/** **/
3813/** **/
3814/********* Debugging routines end here *********/
3815
3816/********* Memory management routines begin here *********/
3817/** **/
3818/** **/
3819
3820/*****************************************************************************/
3821/* */
3822/* poolzero() Set all of a pool's fields to zero. */
3823/* */
3824/* This procedure should never be called on a pool that has any memory */
3825/* allocated to it, as that memory would leak. */
3826/* */
3827/*****************************************************************************/
3828
3829#ifdef ANSI_DECLARATORS
3830void poolzero(struct memorypool *pool)
3831#else /* not ANSI_DECLARATORS */
3832void poolzero(pool)
3833struct memorypool *pool;
3834#endif /* not ANSI_DECLARATORS */
3835
3836{
3837 pool->firstblock = (VOID **) NULL;
3838 pool->nowblock = (VOID **) NULL;
3839 pool->nextitem = (VOID *) NULL;
3840 pool->deaditemstack = (VOID *) NULL;
3841 pool->pathblock = (VOID **) NULL;
3842 pool->pathitem = (VOID *) NULL;
3843 pool->alignbytes = 0;
3844 pool->itembytes = 0;
3845 pool->itemsperblock = 0;
3846 pool->itemsfirstblock = 0;
3847 pool->items = 0;
3848 pool->maxitems = 0;
3849 pool->unallocateditems = 0;
3850 pool->pathitemsleft = 0;
3851}
3852
3853/*****************************************************************************/
3854/* */
3855/* poolrestart() Deallocate all items in a pool. */
3856/* */
3857/* The pool is returned to its starting state, except that no memory is */
3858/* freed to the operating system. Rather, the previously allocated blocks */
3859/* are ready to be reused. */
3860/* */
3861/*****************************************************************************/
3862
3863#ifdef ANSI_DECLARATORS
3864void poolrestart(struct memorypool *pool)
3865#else /* not ANSI_DECLARATORS */
3866void poolrestart(pool)
3867struct memorypool *pool;
3868#endif /* not ANSI_DECLARATORS */
3869
3870{
3871 unsigned long alignptr;
3872
3873 pool->items = 0;
3874 pool->maxitems = 0;
3875
3876 /* Set the currently active block. */
3877 pool->nowblock = pool->firstblock;
3878 /* Find the first item in the pool. Increment by the size of (VOID *). */
3879 alignptr = (unsigned long) (pool->nowblock + 1);
3880 /* Align the item on an `alignbytes'-byte boundary. */
3881 pool->nextitem = (VOID *)
3882 (alignptr + (unsigned long) pool->alignbytes -
3883 (alignptr % (unsigned long) pool->alignbytes));
3884 /* There are lots of unallocated items left in this block. */
3885 pool->unallocateditems = pool->itemsfirstblock;
3886 /* The stack of deallocated items is empty. */
3887 pool->deaditemstack = (VOID *) NULL;
3888}
3889
3890/*****************************************************************************/
3891/* */
3892/* poolinit() Initialize a pool of memory for allocation of items. */
3893/* */
3894/* This routine initializes the machinery for allocating items. A `pool' */
3895/* is created whose records have size at least `bytecount'. Items will be */
3896/* allocated in `itemcount'-item blocks. Each item is assumed to be a */
3897/* collection of words, and either pointers or floating-point values are */
3898/* assumed to be the "primary" word type. (The "primary" word type is used */
3899/* to determine alignment of items.) If `alignment' isn't zero, all items */
3900/* will be `alignment'-byte aligned in memory. `alignment' must be either */
3901/* a multiple or a factor of the primary word size; powers of two are safe. */
3902/* `alignment' is normally used to create a few unused bits at the bottom */
3903/* of each item's pointer, in which information may be stored. */
3904/* */
3905/* Don't change this routine unless you understand it. */
3906/* */
3907/*****************************************************************************/
3908
3909#ifdef ANSI_DECLARATORS
3910void poolinit(struct memorypool *pool, int bytecount, int itemcount,
3911 int firstitemcount, int alignment)
3912#else /* not ANSI_DECLARATORS */
3913void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
3914struct memorypool *pool;
3915int bytecount;
3916int itemcount;
3917int firstitemcount;
3918int alignment;
3919#endif /* not ANSI_DECLARATORS */
3920
3921{
3922 /* Find the proper alignment, which must be at least as large as: */
3923 /* - The parameter `alignment'. */
3924 /* - sizeof(VOID *), so the stack of dead items can be maintained */
3925 /* without unaligned accesses. */
3926 if (alignment > (int) sizeof(VOID *)) {
3927 pool->alignbytes = alignment;
3928 } else {
3929 pool->alignbytes = sizeof(VOID *);
3930 }
3931 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
3932 pool->alignbytes;
3933 pool->itemsperblock = itemcount;
3934 if (firstitemcount == 0) {
3935 pool->itemsfirstblock = itemcount;
3936 } else {
3937 pool->itemsfirstblock = firstitemcount;
3938 }
3939
3940 /* Allocate a block of items. Space for `itemsfirstblock' items and one */
3941 /* pointer (to point to the next block) are allocated, as well as space */
3942 /* to ensure alignment of the items. */
3943 pool->firstblock = (VOID **)
3944 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
3945 pool->alignbytes);
3946 /* Set the next block pointer to NULL. */
3947 *(pool->firstblock) = (VOID *) NULL;
3948 poolrestart(pool);
3949}
3950
3951/*****************************************************************************/
3952/* */
3953/* pooldeinit() Free to the operating system all memory taken by a pool. */
3954/* */
3955/*****************************************************************************/
3956
3957#ifdef ANSI_DECLARATORS
3958void pooldeinit(struct memorypool *pool)
3959#else /* not ANSI_DECLARATORS */
3960void pooldeinit(pool)
3961struct memorypool *pool;
3962#endif /* not ANSI_DECLARATORS */
3963
3964{
3965 while (pool->firstblock != (VOID **) NULL) {
3966 pool->nowblock = (VOID **) *(pool->firstblock);
3967 trifree((VOID *) pool->firstblock);
3968 pool->firstblock = pool->nowblock;
3969 }
3970}
3971
3972/*****************************************************************************/
3973/* */
3974/* poolalloc() Allocate space for an item. */
3975/* */
3976/*****************************************************************************/
3977
3978#ifdef ANSI_DECLARATORS
3979VOID *poolalloc(struct memorypool *pool)
3980#else /* not ANSI_DECLARATORS */
3981VOID *poolalloc(pool)
3982struct memorypool *pool;
3983#endif /* not ANSI_DECLARATORS */
3984
3985{
3986 VOID *newitem;
3987 VOID **newblock;
3988 unsigned long alignptr;
3989
3990 /* First check the linked list of dead items. If the list is not */
3991 /* empty, allocate an item from the list rather than a fresh one. */
3992 if (pool->deaditemstack != (VOID *) NULL) {
3993 newitem = pool->deaditemstack; /* Take first item in list. */
3994 pool->deaditemstack = * (VOID **) pool->deaditemstack;
3995 } else {
3996 /* Check if there are any free items left in the current block. */
3997 if (pool->unallocateditems == 0) {
3998 /* Check if another block must be allocated. */
3999 if (*(pool->nowblock) == (VOID *) NULL) {
4000 /* Allocate a new block of items, pointed to by the previous block. */
4001 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
4002 (int) sizeof(VOID *) +
4003 pool->alignbytes);
4004 *(pool->nowblock) = (VOID *) newblock;
4005 /* The next block pointer is NULL. */
4006 *newblock = (VOID *) NULL;
4007 }
4008
4009 /* Move to the new block. */
4010 pool->nowblock = (VOID **) *(pool->nowblock);
4011 /* Find the first item in the block. */
4012 /* Increment by the size of (VOID *). */
4013 alignptr = (unsigned long) (pool->nowblock + 1);
4014 /* Align the item on an `alignbytes'-byte boundary. */
4015 pool->nextitem = (VOID *)
4016 (alignptr + (unsigned long) pool->alignbytes -
4017 (alignptr % (unsigned long) pool->alignbytes));
4018 /* There are lots of unallocated items left in this block. */
4019 pool->unallocateditems = pool->itemsperblock;
4020 }
4021
4022 /* Allocate a new item. */
4023 newitem = pool->nextitem;
4024 /* Advance `nextitem' pointer to next free item in block. */
4025 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
4026 pool->unallocateditems--;
4027 pool->maxitems++;
4028 }
4029 pool->items++;
4030 return newitem;
4031}
4032
4033/*****************************************************************************/
4034/* */
4035/* pooldealloc() Deallocate space for an item. */
4036/* */
4037/* The deallocated space is stored in a queue for later reuse. */
4038/* */
4039/*****************************************************************************/
4040
4041#ifdef ANSI_DECLARATORS
4042void pooldealloc(struct memorypool *pool, VOID *dyingitem)
4043#else /* not ANSI_DECLARATORS */
4044void pooldealloc(pool, dyingitem)
4045struct memorypool *pool;
4046VOID *dyingitem;
4047#endif /* not ANSI_DECLARATORS */
4048
4049{
4050 /* Push freshly killed item onto stack. */
4051 *((VOID **) dyingitem) = pool->deaditemstack;
4052 pool->deaditemstack = dyingitem;
4053 pool->items--;
4054}
4055
4056/*****************************************************************************/
4057/* */
4058/* traversalinit() Prepare to traverse the entire list of items. */
4059/* */
4060/* This routine is used in conjunction with traverse(). */
4061/* */
4062/*****************************************************************************/
4063
4064#ifdef ANSI_DECLARATORS
4065void traversalinit(struct memorypool *pool)
4066#else /* not ANSI_DECLARATORS */
4067void traversalinit(pool)
4068struct memorypool *pool;
4069#endif /* not ANSI_DECLARATORS */
4070
4071{
4072 unsigned long alignptr;
4073
4074 /* Begin the traversal in the first block. */
4075 pool->pathblock = pool->firstblock;
4076 /* Find the first item in the block. Increment by the size of (VOID *). */
4077 alignptr = (unsigned long) (pool->pathblock + 1);
4078 /* Align with item on an `alignbytes'-byte boundary. */
4079 pool->pathitem = (VOID *)
4080 (alignptr + (unsigned long) pool->alignbytes -
4081 (alignptr % (unsigned long) pool->alignbytes));
4082 /* Set the number of items left in the current block. */
4083 pool->pathitemsleft = pool->itemsfirstblock;
4084}
4085
4086/*****************************************************************************/
4087/* */
4088/* traverse() Find the next item in the list. */
4089/* */
4090/* This routine is used in conjunction with traversalinit(). Be forewarned */
4091/* that this routine successively returns all items in the list, including */
4092/* deallocated ones on the deaditemqueue. It's up to you to figure out */
4093/* which ones are actually dead. Why? I don't want to allocate extra */
4094/* space just to demarcate dead items. It can usually be done more */
4095/* space-efficiently by a routine that knows something about the structure */
4096/* of the item. */
4097/* */
4098/*****************************************************************************/
4099
4100#ifdef ANSI_DECLARATORS
4101VOID *traverse(struct memorypool *pool)
4102#else /* not ANSI_DECLARATORS */
4103VOID *traverse(pool)
4104struct memorypool *pool;
4105#endif /* not ANSI_DECLARATORS */
4106
4107{
4108 VOID *newitem;
4109 unsigned long alignptr;
4110
4111 /* Stop upon exhausting the list of items. */
4112 if (pool->pathitem == pool->nextitem) {
4113 return (VOID *) NULL;
4114 }
4115
4116 /* Check whether any untraversed items remain in the current block. */
4117 if (pool->pathitemsleft == 0) {
4118 /* Find the next block. */
4119 pool->pathblock = (VOID **) *(pool->pathblock);
4120 /* Find the first item in the block. Increment by the size of (VOID *). */
4121 alignptr = (unsigned long) (pool->pathblock + 1);
4122 /* Align with item on an `alignbytes'-byte boundary. */
4123 pool->pathitem = (VOID *)
4124 (alignptr + (unsigned long) pool->alignbytes -
4125 (alignptr % (unsigned long) pool->alignbytes));
4126 /* Set the number of items left in the current block. */
4127 pool->pathitemsleft = pool->itemsperblock;
4128 }
4129
4130 newitem = pool->pathitem;
4131 /* Find the next item in the block. */
4132 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
4133 pool->pathitemsleft--;
4134 return newitem;
4135}
4136
4137/*****************************************************************************/
4138/* */
4139/* dummyinit() Initialize the triangle that fills "outer space" and the */
4140/* omnipresent subsegment. */
4141/* */
4142/* The triangle that fills "outer space," called `dummytri', is pointed to */
4143/* by every triangle and subsegment on a boundary (be it outer or inner) of */
4144/* the triangulation. Also, `dummytri' points to one of the triangles on */
4145/* the convex hull (until the holes and concavities are carved), making it */
4146/* possible to find a starting triangle for point location. */
4147/* */
4148/* The omnipresent subsegment, `dummysub', is pointed to by every triangle */
4149/* or subsegment that doesn't have a full complement of real subsegments */
4150/* to point to. */
4151/* */
4152/* `dummytri' and `dummysub' are generally required to fulfill only a few */
4153/* invariants: their vertices must remain NULL and `dummytri' must always */
4154/* be bonded (at offset zero) to some triangle on the convex hull of the */
4155/* mesh, via a boundary edge. Otherwise, the connections of `dummytri' and */
4156/* `dummysub' may change willy-nilly. This makes it possible to avoid */
4157/* writing a good deal of special-case code (in the edge flip, for example) */
4158/* for dealing with the boundary of the mesh, places where no subsegment is */
4159/* present, and so forth. Other entities are frequently bonded to */
4160/* `dummytri' and `dummysub' as if they were real mesh entities, with no */
4161/* harm done. */
4162/* */
4163/*****************************************************************************/
4164
4165#ifdef ANSI_DECLARATORS
4166void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
4167 int subsegbytes)
4168#else /* not ANSI_DECLARATORS */
4169void dummyinit(m, b, trianglebytes, subsegbytes)
4170struct mesh *m;
4171struct behavior *b;
4172int trianglebytes;
4173int subsegbytes;
4174#endif /* not ANSI_DECLARATORS */
4175
4176{
4177 unsigned long alignptr;
4178
4179 /* Set up `dummytri', the `triangle' that occupies "outer space." */
4180 m->dummytribase = (triangle *) trimalloc(trianglebytes +
4181 m->triangles.alignbytes);
4182 /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
4183 alignptr = (unsigned long) m->dummytribase;
4184 m->dummytri = (triangle *)
4185 (alignptr + (unsigned long) m->triangles.alignbytes -
4186 (alignptr % (unsigned long) m->triangles.alignbytes));
4187 /* Initialize the three adjoining triangles to be "outer space." These */
4188 /* will eventually be changed by various bonding operations, but their */
4189 /* values don't really matter, as long as they can legally be */
4190 /* dereferenced. */
4191 m->dummytri[0] = (triangle) m->dummytri;
4192 m->dummytri[1] = (triangle) m->dummytri;
4193 m->dummytri[2] = (triangle) m->dummytri;
4194 /* Three NULL vertices. */
4195 m->dummytri[3] = (triangle) NULL;
4196 m->dummytri[4] = (triangle) NULL;
4197 m->dummytri[5] = (triangle) NULL;
4198
4199 if (b->usesegments) {
4200 /* Set up `dummysub', the omnipresent subsegment pointed to by any */
4201 /* triangle side or subsegment end that isn't attached to a real */
4202 /* subsegment. */
4203 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
4204 m->subsegs.alignbytes);
4205 /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
4206 alignptr = (unsigned long) m->dummysubbase;
4207 m->dummysub = (subseg *)
4208 (alignptr + (unsigned long) m->subsegs.alignbytes -
4209 (alignptr % (unsigned long) m->subsegs.alignbytes));
4210 /* Initialize the two adjoining subsegments to be the omnipresent */
4211 /* subsegment. These will eventually be changed by various bonding */
4212 /* operations, but their values don't really matter, as long as they */
4213 /* can legally be dereferenced. */
4214 m->dummysub[0] = (subseg) m->dummysub;
4215 m->dummysub[1] = (subseg) m->dummysub;
4216 /* Four NULL vertices. */
4217 m->dummysub[2] = (subseg) NULL;
4218 m->dummysub[3] = (subseg) NULL;
4219 m->dummysub[4] = (subseg) NULL;
4220 m->dummysub[5] = (subseg) NULL;
4221 /* Initialize the two adjoining triangles to be "outer space." */
4222 m->dummysub[6] = (subseg) m->dummytri;
4223 m->dummysub[7] = (subseg) m->dummytri;
4224 /* Set the boundary marker to zero. */
4225 * (int *) (m->dummysub + 8) = 0;
4226
4227 /* Initialize the three adjoining subsegments of `dummytri' to be */
4228 /* the omnipresent subsegment. */
4229 m->dummytri[6] = (triangle) m->dummysub;
4230 m->dummytri[7] = (triangle) m->dummysub;
4231 m->dummytri[8] = (triangle) m->dummysub;
4232 }
4233}
4234
4235/*****************************************************************************/
4236/* */
4237/* initializevertexpool() Calculate the size of the vertex data structure */
4238/* and initialize its memory pool. */
4239/* */
4240/* This routine also computes the `vertexmarkindex' and `vertex2triindex' */
4241/* indices used to find values within each vertex. */
4242/* */
4243/*****************************************************************************/
4244
4245#ifdef ANSI_DECLARATORS
4246void initializevertexpool(struct mesh *m, struct behavior *b)
4247#else /* not ANSI_DECLARATORS */
4249struct mesh *m;
4250struct behavior *b;
4251#endif /* not ANSI_DECLARATORS */
4252
4253{
4254 int vertexsize;
4255
4256 /* The index within each vertex at which the boundary marker is found, */
4257 /* followed by the vertex type. Ensure the vertex marker is aligned to */
4258 /* a sizeof(int)-byte address. */
4259 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
4260 sizeof(int) - 1) /
4261 sizeof(int);
4262 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
4263 if (b->poly) {
4264 /* The index within each vertex at which a triangle pointer is found. */
4265 /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
4266 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
4267 sizeof(triangle);
4268 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
4269 }
4270
4271 /* Initialize the pool of vertices. */
4272 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
4273 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
4274 sizeof(REAL));
4275}
4276
4277/*****************************************************************************/
4278/* */
4279/* initializetrisubpools() Calculate the sizes of the triangle and */
4280/* subsegment data structures and initialize */
4281/* their memory pools. */
4282/* */
4283/* This routine also computes the `highorderindex', `elemattribindex', and */
4284/* `areaboundindex' indices used to find values within each triangle. */
4285/* */
4286/*****************************************************************************/
4287
4288#ifdef ANSI_DECLARATORS
4289void initializetrisubpools(struct mesh *m, struct behavior *b)
4290#else /* not ANSI_DECLARATORS */
4292struct mesh *m;
4293struct behavior *b;
4294#endif /* not ANSI_DECLARATORS */
4295
4296{
4297 int trisize;
4298
4299 /* The index within each triangle at which the extra nodes (above three) */
4300 /* associated with high order elements are found. There are three */
4301 /* pointers to other triangles, three pointers to corners, and possibly */
4302 /* three pointers to subsegments before the extra nodes. */
4303 m->highorderindex = 6 + (b->usesegments * 3);
4304 /* The number of bytes occupied by a triangle. */
4305 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
4306 sizeof(triangle);
4307 /* The index within each triangle at which its attributes are found, */
4308 /* where the index is measured in REALs. */
4309 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
4310 /* The index within each triangle at which the maximum area constraint */
4311 /* is found, where the index is measured in REALs. Note that if the */
4312 /* `regionattrib' flag is set, an additional attribute will be added. */
4313 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
4314 /* If triangle attributes or an area bound are needed, increase the number */
4315 /* of bytes occupied by a triangle. */
4316 if (b->vararea) {
4317 trisize = (m->areaboundindex + 1) * sizeof(REAL);
4318 } else if (m->eextras + b->regionattrib > 0) {
4319 trisize = m->areaboundindex * sizeof(REAL);
4320 }
4321 /* If a Voronoi diagram or triangle neighbor graph is requested, make */
4322 /* sure there's room to store an integer index in each triangle. This */
4323 /* integer index can occupy the same space as the subsegment pointers */
4324 /* or attributes or area constraint or extra nodes. */
4325 if ((b->voronoi || b->neighbors) &&
4326 (trisize < (int) ( 6 * sizeof(triangle) + sizeof(int)))) {
4327 trisize = 6 * sizeof(triangle) + sizeof(int);
4328 }
4329
4330 /* Having determined the memory size of a triangle, initialize the pool. */
4331 poolinit(&m->triangles, trisize, TRIPERBLOCK,
4332 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
4333 TRIPERBLOCK, 4);
4334
4335 if (b->usesegments) {
4336 /* Initialize the pool of subsegments. Take into account all eight */
4337 /* pointers and one boundary marker. */
4338 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
4340
4341 /* Initialize the "outer space" triangle and omnipresent subsegment. */
4342 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
4343 } else {
4344 /* Initialize the "outer space" triangle. */
4345 dummyinit(m, b, m->triangles.itembytes, 0);
4346 }
4347}
4348
4349/*****************************************************************************/
4350/* */
4351/* triangledealloc() Deallocate space for a triangle, marking it dead. */
4352/* */
4353/*****************************************************************************/
4354
4355#ifdef ANSI_DECLARATORS
4356void triangledealloc(struct mesh *m, triangle *dyingtriangle)
4357#else /* not ANSI_DECLARATORS */
4358void triangledealloc(m, dyingtriangle)
4359struct mesh *m;
4360triangle *dyingtriangle;
4361#endif /* not ANSI_DECLARATORS */
4362
4363{
4364 /* Mark the triangle as dead. This makes it possible to detect dead */
4365 /* triangles when traversing the list of all triangles. */
4366 killtri(dyingtriangle);
4367 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
4368}
4369
4370/*****************************************************************************/
4371/* */
4372/* triangletraverse() Traverse the triangles, skipping dead ones. */
4373/* */
4374/*****************************************************************************/
4375
4376#ifdef ANSI_DECLARATORS
4378#else /* not ANSI_DECLARATORS */
4380struct mesh *m;
4381#endif /* not ANSI_DECLARATORS */
4382
4383{
4384 triangle *newtriangle;
4385
4386 do {
4387 newtriangle = (triangle *) traverse(&m->triangles);
4388 if (newtriangle == (triangle *) NULL) {
4389 return (triangle *) NULL;
4390 }
4391 } while (deadtri(newtriangle)); /* Skip dead ones. */
4392 return newtriangle;
4393}
4394
4395/*****************************************************************************/
4396/* */
4397/* subsegdealloc() Deallocate space for a subsegment, marking it dead. */
4398/* */
4399/*****************************************************************************/
4400
4401#ifdef ANSI_DECLARATORS
4402void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
4403#else /* not ANSI_DECLARATORS */
4404void subsegdealloc(m, dyingsubseg)
4405struct mesh *m;
4406subseg *dyingsubseg;
4407#endif /* not ANSI_DECLARATORS */
4408
4409{
4410 /* Mark the subsegment as dead. This makes it possible to detect dead */
4411 /* subsegments when traversing the list of all subsegments. */
4412 killsubseg(dyingsubseg);
4413 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
4414}
4415
4416/*****************************************************************************/
4417/* */
4418/* subsegtraverse() Traverse the subsegments, skipping dead ones. */
4419/* */
4420/*****************************************************************************/
4421
4422#ifdef ANSI_DECLARATORS
4424#else /* not ANSI_DECLARATORS */
4426struct mesh *m;
4427#endif /* not ANSI_DECLARATORS */
4428
4429{
4430 subseg *newsubseg;
4431
4432 do {
4433 newsubseg = (subseg *) traverse(&m->subsegs);
4434 if (newsubseg == (subseg *) NULL) {
4435 return (subseg *) NULL;
4436 }
4437 } while (deadsubseg(newsubseg)); /* Skip dead ones. */
4438 return newsubseg;
4439}
4440
4441/*****************************************************************************/
4442/* */
4443/* vertexdealloc() Deallocate space for a vertex, marking it dead. */
4444/* */
4445/*****************************************************************************/
4446
4447#ifdef ANSI_DECLARATORS
4448void vertexdealloc(struct mesh *m, vertex dyingvertex)
4449#else /* not ANSI_DECLARATORS */
4450void vertexdealloc(m, dyingvertex)
4451struct mesh *m;
4452vertex dyingvertex;
4453#endif /* not ANSI_DECLARATORS */
4454
4455{
4456 /* Mark the vertex as dead. This makes it possible to detect dead */
4457 /* vertices when traversing the list of all vertices. */
4458 setvertextype(dyingvertex, DEADVERTEX);
4459 pooldealloc(&m->vertices, (VOID *) dyingvertex);
4460}
4461
4462/*****************************************************************************/
4463/* */
4464/* vertextraverse() Traverse the vertices, skipping dead ones. */
4465/* */
4466/*****************************************************************************/
4467
4468#ifdef ANSI_DECLARATORS
4470#else /* not ANSI_DECLARATORS */
4472struct mesh *m;
4473#endif /* not ANSI_DECLARATORS */
4474
4475{
4476 vertex newvertex;
4477
4478 do {
4479 newvertex = (vertex) traverse(&m->vertices);
4480 if (newvertex == (vertex) NULL) {
4481 return (vertex) NULL;
4482 }
4483 } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */
4484 return newvertex;
4485}
4486
4487/*****************************************************************************/
4488/* */
4489/* badsubsegdealloc() Deallocate space for a bad subsegment, marking it */
4490/* dead. */
4491/* */
4492/*****************************************************************************/
4493
4494#ifndef CDT_ONLY
4495
4496#ifdef ANSI_DECLARATORS
4497void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
4498#else /* not ANSI_DECLARATORS */
4499void badsubsegdealloc(m, dyingseg)
4500struct mesh *m;
4501struct badsubseg *dyingseg;
4502#endif /* not ANSI_DECLARATORS */
4503
4504{
4505 /* Set subsegment's origin to NULL. This makes it possible to detect dead */
4506 /* badsubsegs when traversing the list of all badsubsegs . */
4507 dyingseg->subsegorg = (vertex) NULL;
4508 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
4509}
4510
4511#endif /* not CDT_ONLY */
4512
4513/*****************************************************************************/
4514/* */
4515/* badsubsegtraverse() Traverse the bad subsegments, skipping dead ones. */
4516/* */
4517/*****************************************************************************/
4518
4519#ifndef CDT_ONLY
4520
4521#ifdef ANSI_DECLARATORS
4522struct badsubseg *badsubsegtraverse(struct mesh *m)
4523#else /* not ANSI_DECLARATORS */
4524struct badsubseg *badsubsegtraverse(m)
4525struct mesh *m;
4526#endif /* not ANSI_DECLARATORS */
4527
4528{
4529 struct badsubseg *newseg;
4530
4531 do {
4532 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
4533 if (newseg == (struct badsubseg *) NULL) {
4534 return (struct badsubseg *) NULL;
4535 }
4536 } while (newseg->subsegorg == (vertex) NULL); /* Skip dead ones. */
4537 return newseg;
4538}
4539
4540#endif /* not CDT_ONLY */
4541
4542/*****************************************************************************/
4543/* */
4544/* getvertex() Get a specific vertex, by number, from the list. */
4545/* */
4546/* The first vertex is number 'firstnumber'. */
4547/* */
4548/* Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */
4549/* is large). I don't care to take the trouble to make it work in constant */
4550/* time. */
4551/* */
4552/*****************************************************************************/
4553
4554#ifdef ANSI_DECLARATORS
4555vertex getvertex(struct mesh *m, struct behavior *b, int number)
4556#else /* not ANSI_DECLARATORS */
4557vertex getvertex(m, b, number)
4558struct mesh *m;
4559struct behavior *b;
4560int number;
4561#endif /* not ANSI_DECLARATORS */
4562
4563{
4564 VOID **getblock;
4565 char *foundvertex;
4566 unsigned long alignptr;
4567 int current;
4568
4569 getblock = m->vertices.firstblock;
4570 current = b->firstnumber;
4571
4572 /* Find the right block. */
4573 if (current + m->vertices.itemsfirstblock <= number) {
4574 getblock = (VOID **) *getblock;
4575 current += m->vertices.itemsfirstblock;
4576 while (current + m->vertices.itemsperblock <= number) {
4577 getblock = (VOID **) *getblock;
4578 current += m->vertices.itemsperblock;
4579 }
4580 }
4581
4582 /* Now find the right vertex. */
4583 alignptr = (unsigned long) (getblock + 1);
4584 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
4585 (alignptr % (unsigned long) m->vertices.alignbytes));
4586 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
4587}
4588
4589/*****************************************************************************/
4590/* */
4591/* triangledeinit() Free all remaining allocated memory. */
4592/* */
4593/*****************************************************************************/
4594
4595#ifdef ANSI_DECLARATORS
4596void triangledeinit(struct mesh *m, struct behavior *b)
4597#else /* not ANSI_DECLARATORS */
4598void triangledeinit(m, b)
4599struct mesh *m;
4600struct behavior *b;
4601#endif /* not ANSI_DECLARATORS */
4602
4603{
4604 pooldeinit(&m->triangles);
4605 trifree((VOID *) m->dummytribase);
4606 if (b->usesegments) {
4607 pooldeinit(&m->subsegs);
4608 trifree((VOID *) m->dummysubbase);
4609 }
4610 pooldeinit(&m->vertices);
4611#ifndef CDT_ONLY
4612 if (b->quality) {
4613 pooldeinit(&m->badsubsegs);
4614 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
4615 pooldeinit(&m->badtriangles);
4616 pooldeinit(&m->flipstackers);
4617 }
4618 }
4619#endif /* not CDT_ONLY */
4620}
4621
4622/** **/
4623/** **/
4624/********* Memory management routines end here *********/
4625
4626/********* Constructors begin here *********/
4627/** **/
4628/** **/
4629
4630/*****************************************************************************/
4631/* */
4632/* maketriangle() Create a new triangle with orientation zero. */
4633/* */
4634/*****************************************************************************/
4635
4636#ifdef ANSI_DECLARATORS
4637void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
4638#else /* not ANSI_DECLARATORS */
4639void maketriangle(m, b, newotri)
4640struct mesh *m;
4641struct behavior *b;
4642struct otri *newotri;
4643#endif /* not ANSI_DECLARATORS */
4644
4645{
4646 int i;
4647
4648 newotri->tri = (triangle *) poolalloc(&m->triangles);
4649 /* Initialize the three adjoining triangles to be "outer space". */
4650 newotri->tri[0] = (triangle) m->dummytri;
4651 newotri->tri[1] = (triangle) m->dummytri;
4652 newotri->tri[2] = (triangle) m->dummytri;
4653 /* Three NULL vertices. */
4654 newotri->tri[3] = (triangle) NULL;
4655 newotri->tri[4] = (triangle) NULL;
4656 newotri->tri[5] = (triangle) NULL;
4657 if (b->usesegments) {
4658 /* Initialize the three adjoining subsegments to be the omnipresent */
4659 /* subsegment. */
4660 newotri->tri[6] = (triangle) m->dummysub;
4661 newotri->tri[7] = (triangle) m->dummysub;
4662 newotri->tri[8] = (triangle) m->dummysub;
4663 }
4664 for (i = 0; i < m->eextras; i++) {
4665 setelemattribute(*newotri, i, 0.0);
4666 }
4667 if (b->vararea) {
4668 setareabound(*newotri, -1.0);
4669 }
4670
4671 newotri->orient = 0;
4672}
4673
4674/*****************************************************************************/
4675/* */
4676/* makesubseg() Create a new subsegment with orientation zero. */
4677/* */
4678/*****************************************************************************/
4679
4680#ifdef ANSI_DECLARATORS
4681void makesubseg(struct mesh *m, struct osub *newsubseg)
4682#else /* not ANSI_DECLARATORS */
4683void makesubseg(m, newsubseg)
4684struct mesh *m;
4685struct osub *newsubseg;
4686#endif /* not ANSI_DECLARATORS */
4687
4688{
4689 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
4690 /* Initialize the two adjoining subsegments to be the omnipresent */
4691 /* subsegment. */
4692 newsubseg->ss[0] = (subseg) m->dummysub;
4693 newsubseg->ss[1] = (subseg) m->dummysub;
4694 /* Four NULL vertices. */
4695 newsubseg->ss[2] = (subseg) NULL;
4696 newsubseg->ss[3] = (subseg) NULL;
4697 newsubseg->ss[4] = (subseg) NULL;
4698 newsubseg->ss[5] = (subseg) NULL;
4699 /* Initialize the two adjoining triangles to be "outer space." */
4700 newsubseg->ss[6] = (subseg) m->dummytri;
4701 newsubseg->ss[7] = (subseg) m->dummytri;
4702 /* Set the boundary marker to zero. */
4703 setmark(*newsubseg, 0);
4704
4705 newsubseg->ssorient = 0;
4706}
4707
4708/** **/
4709/** **/
4710/********* Constructors end here *********/
4711
4712/********* Geometric primitives begin here *********/
4713/** **/
4714/** **/
4715
4716/* The adaptive exact arithmetic geometric predicates implemented herein are */
4717/* described in detail in my paper, "Adaptive Precision Floating-Point */
4718/* Arithmetic and Fast Robust Geometric Predicates." See the header for a */
4719/* full citation. */
4720
4721/* Which of the following two methods of finding the absolute values is */
4722/* fastest is compiler-dependent. A few compilers can inline and optimize */
4723/* the fabs() call; but most will incur the overhead of a function call, */
4724/* which is disastrously slow. A faster way on IEEE machines might be to */
4725/* mask the appropriate bit, but that's difficult to do in C without */
4726/* forcing the value to be stored to memory (rather than be kept in the */
4727/* register to which the optimizer assigned it). */
4728
4729#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
4730/* #define Absolute(a) fabs(a) */
4731
4732/* Many of the operations are broken up into two pieces, a main part that */
4733/* performs an approximate operation, and a "tail" that computes the */
4734/* roundoff error of that operation. */
4735/* */
4736/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */
4737/* Split(), and Two_Product() are all implemented as described in the */
4738/* reference. Each of these macros requires certain variables to be */
4739/* defined in the calling routine. The variables `bvirt', `c', `abig', */
4740/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */
4741/* they store the result of an operation that may incur roundoff error. */
4742/* The input parameter `x' (or the highest numbered `x_' parameter) must */
4743/* also be declared `INEXACT'. */
4744
4745#define Fast_Two_Sum_Tail(a, b, x, y) \
4746 bvirt = x - a; \
4747 y = b - bvirt
4748
4749#define Fast_Two_Sum(a, b, x, y) \
4750 x = (REAL) (a + b); \
4751 Fast_Two_Sum_Tail(a, b, x, y)
4752
4753#define Two_Sum_Tail(a, b, x, y) \
4754 bvirt = (REAL) (x - a); \
4755 avirt = x - bvirt; \
4756 bround = b - bvirt; \
4757 around = a - avirt; \
4758 y = around + bround
4759
4760#define Two_Sum(a, b, x, y) \
4761 x = (REAL) (a + b); \
4762 Two_Sum_Tail(a, b, x, y)
4763
4764#define Two_Diff_Tail(a, b, x, y) \
4765 bvirt = (REAL) (a - x); \
4766 avirt = x + bvirt; \
4767 bround = bvirt - b; \
4768 around = a - avirt; \
4769 y = around + bround
4770
4771#define Two_Diff(a, b, x, y) \
4772 x = (REAL) (a - b); \
4773 Two_Diff_Tail(a, b, x, y)
4774
4775#define Split(a, ahi, alo) \
4776 c = (REAL) (splitter * a); \
4777 abig = (REAL) (c - a); \
4778 ahi = c - abig; \
4779 alo = a - ahi
4780
4781#define Two_Product_Tail(a, b, x, y) \
4782 Split(a, ahi, alo); \
4783 Split(b, bhi, blo); \
4784 err1 = x - (ahi * bhi); \
4785 err2 = err1 - (alo * bhi); \
4786 err3 = err2 - (ahi * blo); \
4787 y = (alo * blo) - err3
4788
4789#define Two_Product(a, b, x, y) \
4790 x = (REAL) (a * b); \
4791 Two_Product_Tail(a, b, x, y)
4792
4793/* Two_Product_Presplit() is Two_Product() where one of the inputs has */
4794/* already been split. Avoids redundant splitting. */
4795
4796#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
4797 x = (REAL) (a * b); \
4798 Split(a, ahi, alo); \
4799 err1 = x - (ahi * bhi); \
4800 err2 = err1 - (alo * bhi); \
4801 err3 = err2 - (ahi * blo); \
4802 y = (alo * blo) - err3
4803
4804/* Square() can be done more quickly than Two_Product(). */
4805
4806#define Square_Tail(a, x, y) \
4807 Split(a, ahi, alo); \
4808 err1 = x - (ahi * ahi); \
4809 err3 = err1 - ((ahi + ahi) * alo); \
4810 y = (alo * alo) - err3
4811
4812#define Square(a, x, y) \
4813 x = (REAL) (a * a); \
4814 Square_Tail(a, x, y)
4815
4816/* Macros for summing expansions of various fixed lengths. These are all */
4817/* unrolled versions of Expansion_Sum(). */
4818
4819#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
4820 Two_Sum(a0, b , _i, x0); \
4821 Two_Sum(a1, _i, x2, x1)
4822
4823#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
4824 Two_Diff(a0, b , _i, x0); \
4825 Two_Sum( a1, _i, x2, x1)
4826
4827#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
4828 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
4829 Two_One_Sum(_j, _0, b1, x3, x2, x1)
4830
4831#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
4832 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
4833 Two_One_Diff(_j, _0, b1, x3, x2, x1)
4834
4835/* Macro for multiplying a two-component expansion by a single component. */
4836
4837#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
4838 Split(b, bhi, blo); \
4839 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
4840 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
4841 Two_Sum(_i, _0, _k, x1); \
4842 Fast_Two_Sum(_j, _k, x3, x2)
4843
4844/*****************************************************************************/
4845/* */
4846/* exactinit() Initialize the variables used for exact arithmetic. */
4847/* */
4848/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
4849/* floating-point arithmetic. `epsilon' bounds the relative roundoff */
4850/* error. It is used for floating-point error analysis. */
4851/* */
4852/* `splitter' is used to split floating-point numbers into two half- */
4853/* length significands for exact multiplication. */
4854/* */
4855/* I imagine that a highly optimizing compiler might be too smart for its */
4856/* own good, and somehow cause this routine to fail, if it pretends that */
4857/* floating-point arithmetic is too much like real arithmetic. */
4858/* */
4859/* Don't change this routine unless you fully understand it. */
4860/* */
4861/*****************************************************************************/
4862
4864{
4865 REAL half;
4866 REAL check, lastcheck;
4867 int every_other;
4868#ifdef LINUX
4869 int cword;
4870#endif /* LINUX */
4871
4872#ifdef CPU86
4873#ifdef SINGLE
4874 _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */
4875#else /* not SINGLE */
4876 _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */
4877#endif /* not SINGLE */
4878#endif /* CPU86 */
4879#ifdef LINUX
4880#ifdef SINGLE
4881 /* cword = 4223; */
4882 cword = 4210; /* set FPU control word for single precision */
4883#else /* not SINGLE */
4884 /* cword = 4735; */
4885 cword = 4722; /* set FPU control word for double precision */
4886#endif /* not SINGLE */
4887 _FPU_SETCW(cword);
4888#endif /* LINUX */
4889
4890 every_other = 1;
4891 half = 0.5;
4892 epsilon = 1.0;
4893 splitter = 1.0;
4894 check = 1.0;
4895 /* Repeatedly divide `epsilon' by two until it is too small to add to */
4896 /* one without causing roundoff. (Also check if the sum is equal to */
4897 /* the previous sum, for machines that round up instead of using exact */
4898 /* rounding. Not that these routines will work on such machines.) */
4899 do {
4900 lastcheck = check;
4901 epsilon *= half;
4902 if (every_other) {
4903 splitter *= 2.0;
4904 }
4905 every_other = !every_other;
4906 check = 1.0 + epsilon;
4907 } while ((check != 1.0) && (check != lastcheck));
4908 splitter += 1.0;
4909 /* Error bounds for orientation and incircle tests. */
4910 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
4911 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
4912 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
4913 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
4914 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
4915 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
4916 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
4917 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
4918 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
4919 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
4920}
4921
4922/*****************************************************************************/
4923/* */
4924/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
4925/* components from the output expansion. */
4926/* */
4927/* Sets h = e + f. See my Robust Predicates paper for details. */
4928/* */
4929/* If round-to-even is used (as with IEEE 754), maintains the strongly */
4930/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
4931/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
4932/* properties. */
4933/* */
4934/*****************************************************************************/
4935
4936#ifdef ANSI_DECLARATORS
4937int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
4938#else /* not ANSI_DECLARATORS */
4939int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */
4940int elen;
4941REAL *e;
4942int flen;
4943REAL *f;
4944REAL *h;
4945#endif /* not ANSI_DECLARATORS */
4946
4947{
4948 REAL Q;
4949 INEXACT REAL Qnew;
4950 INEXACT REAL hh;
4951 INEXACT REAL bvirt;
4952 REAL avirt, bround, around;
4953 int eindex, findex, hindex;
4954 REAL enow, fnow;
4955
4956 enow = e[0];
4957 fnow = f[0];
4958 eindex = findex = 0;
4959 if ((fnow > enow) == (fnow > -enow)) {
4960 Q = enow;
4961 enow = e[++eindex];
4962 } else {
4963 Q = fnow;
4964 fnow = f[++findex];
4965 }
4966 hindex = 0;
4967 if ((eindex < elen) && (findex < flen)) {
4968 if ((fnow > enow) == (fnow > -enow)) {
4969 Fast_Two_Sum(enow, Q, Qnew, hh);
4970 enow = e[++eindex];
4971 } else {
4972 Fast_Two_Sum(fnow, Q, Qnew, hh);
4973 fnow = f[++findex];
4974 }
4975 Q = Qnew;
4976 if (hh != 0.0) {
4977 h[hindex++] = hh;
4978 }
4979 while ((eindex < elen) && (findex < flen)) {
4980 if ((fnow > enow) == (fnow > -enow)) {
4981 Two_Sum(Q, enow, Qnew, hh);
4982 enow = e[++eindex];
4983 } else {
4984 Two_Sum(Q, fnow, Qnew, hh);
4985 fnow = f[++findex];
4986 }
4987 Q = Qnew;
4988 if (hh != 0.0) {
4989 h[hindex++] = hh;
4990 }
4991 }
4992 }
4993 while (eindex < elen) {
4994 Two_Sum(Q, enow, Qnew, hh);
4995 enow = e[++eindex];
4996 Q = Qnew;
4997 if (hh != 0.0) {
4998 h[hindex++] = hh;
4999 }
5000 }
5001 while (findex < flen) {
5002 Two_Sum(Q, fnow, Qnew, hh);
5003 fnow = f[++findex];
5004 Q = Qnew;
5005 if (hh != 0.0) {
5006 h[hindex++] = hh;
5007 }
5008 }
5009 if ((Q != 0.0) || (hindex == 0)) {
5010 h[hindex++] = Q;
5011 }
5012 return hindex;
5013}
5014
5015/*****************************************************************************/
5016/* */
5017/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */
5018/* eliminating zero components from the */
5019/* output expansion. */
5020/* */
5021/* Sets h = be. See my Robust Predicates paper for details. */
5022/* */
5023/* Maintains the nonoverlapping property. If round-to-even is used (as */
5024/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
5025/* properties as well. (That is, if e has one of these properties, so */
5026/* will h.) */
5027/* */
5028/*****************************************************************************/
5029
5030#ifdef ANSI_DECLARATORS
5032#else /* not ANSI_DECLARATORS */
5033int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */
5034int elen;
5035REAL *e;
5036REAL b;
5037REAL *h;
5038#endif /* not ANSI_DECLARATORS */
5039
5040{
5041 INEXACT REAL Q, sum;
5042 REAL hh;
5043 INEXACT REAL product1;
5044 REAL product0;
5045 int eindex, hindex;
5046 REAL enow;
5047 INEXACT REAL bvirt;
5048 REAL avirt, bround, around;
5049 INEXACT REAL c;
5050 INEXACT REAL abig;
5051 REAL ahi, alo, bhi, blo;
5052 REAL err1, err2, err3;
5053
5054 Split(b, bhi, blo);
5055 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
5056 hindex = 0;
5057 if (hh != 0) {
5058 h[hindex++] = hh;
5059 }
5060 for (eindex = 1; eindex < elen; eindex++) {
5061 enow = e[eindex];
5062 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
5063 Two_Sum(Q, product0, sum, hh);
5064 if (hh != 0) {
5065 h[hindex++] = hh;
5066 }
5067 Fast_Two_Sum(product1, sum, Q, hh);
5068 if (hh != 0) {
5069 h[hindex++] = hh;
5070 }
5071 }
5072 if ((Q != 0.0) || (hindex == 0)) {
5073 h[hindex++] = Q;
5074 }
5075 return hindex;
5076}
5077
5078/*****************************************************************************/
5079/* */
5080/* estimate() Produce a one-word estimate of an expansion's value. */
5081/* */
5082/* See my Robust Predicates paper for details. */
5083/* */
5084/*****************************************************************************/
5085
5086#ifdef ANSI_DECLARATORS
5087REAL estimate(int elen, REAL *e)
5088#else /* not ANSI_DECLARATORS */
5089REAL estimate(elen, e)
5090int elen;
5091REAL *e;
5092#endif /* not ANSI_DECLARATORS */
5093
5094{
5095 REAL Q;
5096 int eindex;
5097
5098 Q = e[0];
5099 for (eindex = 1; eindex < elen; eindex++) {
5100 Q += e[eindex];
5101 }
5102 return Q;
5103}
5104
5105/*****************************************************************************/
5106/* */
5107/* counterclockwise() Return a positive value if the points pa, pb, and */
5108/* pc occur in counterclockwise order; a negative */
5109/* value if they occur in clockwise order; and zero */
5110/* if they are collinear. The result is also a rough */
5111/* approximation of twice the signed area of the */
5112/* triangle defined by the three points. */
5113/* */
5114/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5115/* result returned is the determinant of a matrix. This determinant is */
5116/* computed adaptively, in the sense that exact arithmetic is used only to */
5117/* the degree it is needed to ensure that the returned value has the */
5118/* correct sign. Hence, this function is usually quite fast, but will run */
5119/* more slowly when the input points are collinear or nearly so. */
5120/* */
5121/* See my Robust Predicates paper for details. */
5122/* */
5123/*****************************************************************************/
5124
5125#ifdef ANSI_DECLARATORS
5127#else /* not ANSI_DECLARATORS */
5128REAL counterclockwiseadapt(pa, pb, pc, detsum)
5129vertex pa;
5130vertex pb;
5131vertex pc;
5132REAL detsum;
5133#endif /* not ANSI_DECLARATORS */
5134
5135{
5136 INEXACT REAL acx, acy, bcx, bcy;
5137 REAL acxtail, acytail, bcxtail, bcytail;
5138 INEXACT REAL detleft, detright;
5139 REAL detlefttail, detrighttail;
5140 REAL det, errbound;
5141 REAL B[4], C1[8], C2[12], D[16];
5142 INEXACT REAL B3;
5143 int C1length, C2length, Dlength;
5144 REAL u[4];
5145 INEXACT REAL u3;
5146 INEXACT REAL s1, t1;
5147 REAL s0, t0;
5148
5149 INEXACT REAL bvirt;
5150 REAL avirt, bround, around;
5151 INEXACT REAL c;
5152 INEXACT REAL abig;
5153 REAL ahi, alo, bhi, blo;
5154 REAL err1, err2, err3;
5155 INEXACT REAL _i, _j;
5156 REAL _0;
5157
5158 acx = (REAL) (pa[0] - pc[0]);
5159 bcx = (REAL) (pb[0] - pc[0]);
5160 acy = (REAL) (pa[1] - pc[1]);
5161 bcy = (REAL) (pb[1] - pc[1]);
5162
5163 Two_Product(acx, bcy, detleft, detlefttail);
5164 Two_Product(acy, bcx, detright, detrighttail);
5165
5166 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
5167 B3, B[2], B[1], B[0]);
5168 B[3] = B3;
5169
5170 det = estimate(4, B);
5171 errbound = ccwerrboundB * detsum;
5172 if ((det >= errbound) || (-det >= errbound)) {
5173 return det;
5174 }
5175
5176 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
5177 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
5178 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
5179 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
5180
5181 if ((acxtail == 0.0) && (acytail == 0.0)
5182 && (bcxtail == 0.0) && (bcytail == 0.0)) {
5183 return det;
5184 }
5185
5186 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
5187 det += (acx * bcytail + bcy * acxtail)
5188 - (acy * bcxtail + bcx * acytail);
5189 if ((det >= errbound) || (-det >= errbound)) {
5190 return det;
5191 }
5192
5193 Two_Product(acxtail, bcy, s1, s0);
5194 Two_Product(acytail, bcx, t1, t0);
5195 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5196 u[3] = u3;
5197 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
5198
5199 Two_Product(acx, bcytail, s1, s0);
5200 Two_Product(acy, bcxtail, t1, t0);
5201 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5202 u[3] = u3;
5203 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
5204
5205 Two_Product(acxtail, bcytail, s1, s0);
5206 Two_Product(acytail, bcxtail, t1, t0);
5207 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5208 u[3] = u3;
5209 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
5210
5211 return(D[Dlength - 1]);
5212}
5213
5214#ifdef ANSI_DECLARATORS
5215REAL counterclockwise(struct mesh *m, struct behavior *b,
5216 vertex pa, vertex pb, vertex pc)
5217#else /* not ANSI_DECLARATORS */
5218REAL counterclockwise(m, b, pa, pb, pc)
5219struct mesh *m;
5220struct behavior *b;
5221vertex pa;
5222vertex pb;
5223vertex pc;
5224#endif /* not ANSI_DECLARATORS */
5225
5226{
5227 REAL detleft, detright, det;
5228 REAL detsum, errbound;
5229
5230 m->counterclockcount++;
5231
5232 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
5233 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
5234 det = detleft - detright;
5235
5236 if (b->noexact) {
5237 return det;
5238 }
5239
5240 if (detleft > 0.0) {
5241 if (detright <= 0.0) {
5242 return det;
5243 } else {
5244 detsum = detleft + detright;
5245 }
5246 } else if (detleft < 0.0) {
5247 if (detright >= 0.0) {
5248 return det;
5249 } else {
5250 detsum = -detleft - detright;
5251 }
5252 } else {
5253 return det;
5254 }
5255
5256 errbound = ccwerrboundA * detsum;
5257 if ((det >= errbound) || (-det >= errbound)) {
5258 return det;
5259 }
5260
5261 return counterclockwiseadapt(pa, pb, pc, detsum);
5262}
5263
5264/*****************************************************************************/
5265/* */
5266/* incircle() Return a positive value if the point pd lies inside the */
5267/* circle passing through pa, pb, and pc; a negative value if */
5268/* it lies outside; and zero if the four points are cocircular.*/
5269/* The points pa, pb, and pc must be in counterclockwise */
5270/* order, or the sign of the result will be reversed. */
5271/* */
5272/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5273/* result returned is the determinant of a matrix. This determinant is */
5274/* computed adaptively, in the sense that exact arithmetic is used only to */
5275/* the degree it is needed to ensure that the returned value has the */
5276/* correct sign. Hence, this function is usually quite fast, but will run */
5277/* more slowly when the input points are cocircular or nearly so. */
5278/* */
5279/* See my Robust Predicates paper for details. */
5280/* */
5281/*****************************************************************************/
5282
5283#ifdef ANSI_DECLARATORS
5285#else /* not ANSI_DECLARATORS */
5286REAL incircleadapt(pa, pb, pc, pd, permanent)
5287vertex pa;
5288vertex pb;
5289vertex pc;
5290vertex pd;
5291REAL permanent;
5292#endif /* not ANSI_DECLARATORS */
5293
5294{
5295 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
5296 REAL det, errbound;
5297
5298 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5299 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5300 REAL bc[4], ca[4], ab[4];
5301 INEXACT REAL bc3, ca3, ab3;
5302 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
5303 int axbclen, axxbclen, aybclen, ayybclen, alen;
5304 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
5305 int bxcalen, bxxcalen, bycalen, byycalen, blen;
5306 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
5307 int cxablen, cxxablen, cyablen, cyyablen, clen;
5308 REAL abdet[64];
5309 int ablen;
5310 REAL fin1[1152], fin2[1152];
5311 REAL *finnow, *finother, *finswap;
5312 int finlength;
5313
5314 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
5315 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
5316 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
5317 REAL aa[4], bb[4], cc[4];
5318 INEXACT REAL aa3, bb3, cc3;
5319 INEXACT REAL ti1, tj1;
5320 REAL ti0, tj0;
5321 REAL u[4], v[4];
5322 INEXACT REAL u3, v3;
5323 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
5324 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
5325 int temp8len, temp16alen, temp16blen, temp16clen;
5326 int temp32alen, temp32blen, temp48len, temp64len;
5327 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
5328 int axtbblen, axtcclen, aytbblen, aytcclen;
5329 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
5330 int bxtaalen, bxtcclen, bytaalen, bytcclen;
5331 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
5332 int cxtaalen, cxtbblen, cytaalen, cytbblen;
5333 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
5334 int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
5335 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
5336 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
5337 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
5338 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
5339 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
5340 REAL abt[8], bct[8], cat[8];
5341 int abtlen, bctlen, catlen;
5342 REAL abtt[4], bctt[4], catt[4];
5343 int abttlen, bcttlen, cattlen;
5344 INEXACT REAL abtt3, bctt3, catt3;
5345 REAL negate;
5346
5347 INEXACT REAL bvirt;
5348 REAL avirt, bround, around;
5349 INEXACT REAL c;
5350 INEXACT REAL abig;
5351 REAL ahi, alo, bhi, blo;
5352 REAL err1, err2, err3;
5353 INEXACT REAL _i, _j;
5354 REAL _0;
5355
5356 adx = (REAL) (pa[0] - pd[0]);
5357 bdx = (REAL) (pb[0] - pd[0]);
5358 cdx = (REAL) (pc[0] - pd[0]);
5359 ady = (REAL) (pa[1] - pd[1]);
5360 bdy = (REAL) (pb[1] - pd[1]);
5361 cdy = (REAL) (pc[1] - pd[1]);
5362
5363 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
5364 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
5365 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
5366 bc[3] = bc3;
5367 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
5368 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
5369 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
5370 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
5371 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
5372
5373 Two_Product(cdx, ady, cdxady1, cdxady0);
5374 Two_Product(adx, cdy, adxcdy1, adxcdy0);
5375 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
5376 ca[3] = ca3;
5377 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
5378 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
5379 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
5380 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
5381 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
5382
5383 Two_Product(adx, bdy, adxbdy1, adxbdy0);
5384 Two_Product(bdx, ady, bdxady1, bdxady0);
5385 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
5386 ab[3] = ab3;
5387 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
5388 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
5389 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
5390 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
5391 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
5392
5393 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
5394 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
5395
5396 det = estimate(finlength, fin1);
5397 errbound = iccerrboundB * permanent;
5398 if ((det >= errbound) || (-det >= errbound)) {
5399 return det;
5400 }
5401
5402 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
5403 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
5404 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
5405 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
5406 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
5407 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
5408 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
5409 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
5410 return det;
5411 }
5412
5413 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
5414 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
5415 - (bdy * cdxtail + cdx * bdytail))
5416 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
5417 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
5418 - (cdy * adxtail + adx * cdytail))
5419 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
5420 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
5421 - (ady * bdxtail + bdx * adytail))
5422 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
5423 if ((det >= errbound) || (-det >= errbound)) {
5424 return det;
5425 }
5426
5427 finnow = fin1;
5428 finother = fin2;
5429
5430 if ((bdxtail != 0.0) || (bdytail != 0.0)
5431 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5432 Square(adx, adxadx1, adxadx0);
5433 Square(ady, adyady1, adyady0);
5434 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
5435 aa[3] = aa3;
5436 }
5437 if ((cdxtail != 0.0) || (cdytail != 0.0)
5438 || (adxtail != 0.0) || (adytail != 0.0)) {
5439 Square(bdx, bdxbdx1, bdxbdx0);
5440 Square(bdy, bdybdy1, bdybdy0);
5441 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
5442 bb[3] = bb3;
5443 }
5444 if ((adxtail != 0.0) || (adytail != 0.0)
5445 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5446 Square(cdx, cdxcdx1, cdxcdx0);
5447 Square(cdy, cdycdy1, cdycdy0);
5448 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
5449 cc[3] = cc3;
5450 }
5451
5452 if (adxtail != 0.0) {
5453 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
5454 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
5455 temp16a);
5456
5457 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
5458 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
5459
5460 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
5461 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
5462
5463 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5464 temp16blen, temp16b, temp32a);
5465 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5466 temp32alen, temp32a, temp48);
5467 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5468 temp48, finother);
5469 finswap = finnow; finnow = finother; finother = finswap;
5470 }
5471 if (adytail != 0.0) {
5472 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
5473 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
5474 temp16a);
5475
5476 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
5477 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
5478
5479 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
5480 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
5481
5482 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5483 temp16blen, temp16b, temp32a);
5484 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5485 temp32alen, temp32a, temp48);
5486 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5487 temp48, finother);
5488 finswap = finnow; finnow = finother; finother = finswap;
5489 }
5490 if (bdxtail != 0.0) {
5491 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
5492 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
5493 temp16a);
5494
5495 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
5496 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
5497
5498 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
5499 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
5500
5501 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5502 temp16blen, temp16b, temp32a);
5503 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5504 temp32alen, temp32a, temp48);
5505 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5506 temp48, finother);
5507 finswap = finnow; finnow = finother; finother = finswap;
5508 }
5509 if (bdytail != 0.0) {
5510 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
5511 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
5512 temp16a);
5513
5514 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
5515 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
5516
5517 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
5518 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
5519
5520 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5521 temp16blen, temp16b, temp32a);
5522 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5523 temp32alen, temp32a, temp48);
5524 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5525 temp48, finother);
5526 finswap = finnow; finnow = finother; finother = finswap;
5527 }
5528 if (cdxtail != 0.0) {
5529 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
5530 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
5531 temp16a);
5532
5533 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
5534 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
5535
5536 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
5537 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
5538
5539 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5540 temp16blen, temp16b, temp32a);
5541 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5542 temp32alen, temp32a, temp48);
5543 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5544 temp48, finother);
5545 finswap = finnow; finnow = finother; finother = finswap;
5546 }
5547 if (cdytail != 0.0) {
5548 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
5549 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
5550 temp16a);
5551
5552 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
5553 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
5554
5555 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
5556 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
5557
5558 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5559 temp16blen, temp16b, temp32a);
5560 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5561 temp32alen, temp32a, temp48);
5562 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5563 temp48, finother);
5564 finswap = finnow; finnow = finother; finother = finswap;
5565 }
5566
5567 if ((adxtail != 0.0) || (adytail != 0.0)) {
5568 if ((bdxtail != 0.0) || (bdytail != 0.0)
5569 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5570 Two_Product(bdxtail, cdy, ti1, ti0);
5571 Two_Product(bdx, cdytail, tj1, tj0);
5572 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5573 u[3] = u3;
5574 negate = -bdy;
5575 Two_Product(cdxtail, negate, ti1, ti0);
5576 negate = -bdytail;
5577 Two_Product(cdx, negate, tj1, tj0);
5578 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5579 v[3] = v3;
5580 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
5581
5582 Two_Product(bdxtail, cdytail, ti1, ti0);
5583 Two_Product(cdxtail, bdytail, tj1, tj0);
5584 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
5585 bctt[3] = bctt3;
5586 bcttlen = 4;
5587 } else {
5588 bct[0] = 0.0;
5589 bctlen = 1;
5590 bctt[0] = 0.0;
5591 bcttlen = 1;
5592 }
5593
5594 if (adxtail != 0.0) {
5595 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
5596 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
5597 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
5598 temp32a);
5599 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5600 temp32alen, temp32a, temp48);
5601 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5602 temp48, finother);
5603 finswap = finnow; finnow = finother; finother = finswap;
5604 if (bdytail != 0.0) {
5605 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
5606 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
5607 temp16a);
5608 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5609 temp16a, finother);
5610 finswap = finnow; finnow = finother; finother = finswap;
5611 }
5612 if (cdytail != 0.0) {
5613 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
5614 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
5615 temp16a);
5616 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5617 temp16a, finother);
5618 finswap = finnow; finnow = finother; finother = finswap;
5619 }
5620
5621 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
5622 temp32a);
5623 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
5624 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
5625 temp16a);
5626 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
5627 temp16b);
5628 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5629 temp16blen, temp16b, temp32b);
5630 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5631 temp32blen, temp32b, temp64);
5632 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5633 temp64, finother);
5634 finswap = finnow; finnow = finother; finother = finswap;
5635 }
5636 if (adytail != 0.0) {
5637 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
5638 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
5639 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
5640 temp32a);
5641 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5642 temp32alen, temp32a, temp48);
5643 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5644 temp48, finother);
5645 finswap = finnow; finnow = finother; finother = finswap;
5646
5647
5648 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
5649 temp32a);
5650 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
5651 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
5652 temp16a);
5653 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
5654 temp16b);
5655 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5656 temp16blen, temp16b, temp32b);
5657 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5658 temp32blen, temp32b, temp64);
5659 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5660 temp64, finother);
5661 finswap = finnow; finnow = finother; finother = finswap;
5662 }
5663 }
5664 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
5665 if ((cdxtail != 0.0) || (cdytail != 0.0)
5666 || (adxtail != 0.0) || (adytail != 0.0)) {
5667 Two_Product(cdxtail, ady, ti1, ti0);
5668 Two_Product(cdx, adytail, tj1, tj0);
5669 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5670 u[3] = u3;
5671 negate = -cdy;
5672 Two_Product(adxtail, negate, ti1, ti0);
5673 negate = -cdytail;
5674 Two_Product(adx, negate, tj1, tj0);
5675 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5676 v[3] = v3;
5677 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
5678
5679 Two_Product(cdxtail, adytail, ti1, ti0);
5680 Two_Product(adxtail, cdytail, tj1, tj0);
5681 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
5682 catt[3] = catt3;
5683 cattlen = 4;
5684 } else {
5685 cat[0] = 0.0;
5686 catlen = 1;
5687 catt[0] = 0.0;
5688 cattlen = 1;
5689 }
5690
5691 if (bdxtail != 0.0) {
5692 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
5693 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
5694 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
5695 temp32a);
5696 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5697 temp32alen, temp32a, temp48);
5698 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5699 temp48, finother);
5700 finswap = finnow; finnow = finother; finother = finswap;
5701 if (cdytail != 0.0) {
5702 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
5703 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
5704 temp16a);
5705 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5706 temp16a, finother);
5707 finswap = finnow; finnow = finother; finother = finswap;
5708 }
5709 if (adytail != 0.0) {
5710 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
5711 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
5712 temp16a);
5713 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5714 temp16a, finother);
5715 finswap = finnow; finnow = finother; finother = finswap;
5716 }
5717
5718 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
5719 temp32a);
5720 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
5721 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
5722 temp16a);
5723 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
5724 temp16b);
5725 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5726 temp16blen, temp16b, temp32b);
5727 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5728 temp32blen, temp32b, temp64);
5729 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5730 temp64, finother);
5731 finswap = finnow; finnow = finother; finother = finswap;
5732 }
5733 if (bdytail != 0.0) {
5734 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
5735 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
5736 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
5737 temp32a);
5738 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5739 temp32alen, temp32a, temp48);
5740 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5741 temp48, finother);
5742 finswap = finnow; finnow = finother; finother = finswap;
5743
5744
5745 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
5746 temp32a);
5747 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
5748 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
5749 temp16a);
5750 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
5751 temp16b);
5752 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5753 temp16blen, temp16b, temp32b);
5754 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5755 temp32blen, temp32b, temp64);
5756 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5757 temp64, finother);
5758 finswap = finnow; finnow = finother; finother = finswap;
5759 }
5760 }
5761 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
5762 if ((adxtail != 0.0) || (adytail != 0.0)
5763 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5764 Two_Product(adxtail, bdy, ti1, ti0);
5765 Two_Product(adx, bdytail, tj1, tj0);
5766 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5767 u[3] = u3;
5768 negate = -ady;
5769 Two_Product(bdxtail, negate, ti1, ti0);
5770 negate = -adytail;
5771 Two_Product(bdx, negate, tj1, tj0);
5772 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5773 v[3] = v3;
5774 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
5775
5776 Two_Product(adxtail, bdytail, ti1, ti0);
5777 Two_Product(bdxtail, adytail, tj1, tj0);
5778 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
5779 abtt[3] = abtt3;
5780 abttlen = 4;
5781 } else {
5782 abt[0] = 0.0;
5783 abtlen = 1;
5784 abtt[0] = 0.0;
5785 abttlen = 1;
5786 }
5787
5788 if (cdxtail != 0.0) {
5789 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
5790 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
5791 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
5792 temp32a);
5793 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5794 temp32alen, temp32a, temp48);
5795 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5796 temp48, finother);
5797 finswap = finnow; finnow = finother; finother = finswap;
5798 if (adytail != 0.0) {
5799 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
5800 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
5801 temp16a);
5802 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5803 temp16a, finother);
5804 finswap = finnow; finnow = finother; finother = finswap;
5805 }
5806 if (bdytail != 0.0) {
5807 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
5808 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
5809 temp16a);
5810 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5811 temp16a, finother);
5812 finswap = finnow; finnow = finother; finother = finswap;
5813 }
5814
5815 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
5816 temp32a);
5817 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
5818 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
5819 temp16a);
5820 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
5821 temp16b);
5822 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5823 temp16blen, temp16b, temp32b);
5824 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5825 temp32blen, temp32b, temp64);
5826 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5827 temp64, finother);
5828 finswap = finnow; finnow = finother; finother = finswap;
5829 }
5830 if (cdytail != 0.0) {
5831 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
5832 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
5833 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
5834 temp32a);
5835 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5836 temp32alen, temp32a, temp48);
5837 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5838 temp48, finother);
5839 finswap = finnow; finnow = finother; finother = finswap;
5840
5841
5842 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
5843 temp32a);
5844 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
5845 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
5846 temp16a);
5847 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
5848 temp16b);
5849 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5850 temp16blen, temp16b, temp32b);
5851 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5852 temp32blen, temp32b, temp64);
5853 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5854 temp64, finother);
5855 finswap = finnow; finnow = finother; finother = finswap;
5856 }
5857 }
5858
5859 return finnow[finlength - 1];
5860}
5861
5862#ifdef ANSI_DECLARATORS
5863REAL incircle(struct mesh *m, struct behavior *b,
5864 vertex pa, vertex pb, vertex pc, vertex pd)
5865#else /* not ANSI_DECLARATORS */
5866REAL incircle(m, b, pa, pb, pc, pd)
5867struct mesh *m;
5868struct behavior *b;
5869vertex pa;
5870vertex pb;
5871vertex pc;
5872vertex pd;
5873#endif /* not ANSI_DECLARATORS */
5874
5875{
5876 REAL adx, bdx, cdx, ady, bdy, cdy;
5877 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
5878 REAL alift, blift, clift;
5879 REAL det;
5880 REAL permanent, errbound;
5881
5882 m->incirclecount++;
5883
5884 adx = pa[0] - pd[0];
5885 bdx = pb[0] - pd[0];
5886 cdx = pc[0] - pd[0];
5887 ady = pa[1] - pd[1];
5888 bdy = pb[1] - pd[1];
5889 cdy = pc[1] - pd[1];
5890
5891 bdxcdy = bdx * cdy;
5892 cdxbdy = cdx * bdy;
5893 alift = adx * adx + ady * ady;
5894
5895 cdxady = cdx * ady;
5896 adxcdy = adx * cdy;
5897 blift = bdx * bdx + bdy * bdy;
5898
5899 adxbdy = adx * bdy;
5900 bdxady = bdx * ady;
5901 clift = cdx * cdx + cdy * cdy;
5902
5903 det = alift * (bdxcdy - cdxbdy)
5904 + blift * (cdxady - adxcdy)
5905 + clift * (adxbdy - bdxady);
5906
5907 if (b->noexact) {
5908 return det;
5909 }
5910
5911 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
5912 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
5913 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
5914 errbound = iccerrboundA * permanent;
5915 if ((det > errbound) || (-det > errbound)) {
5916 return det;
5917 }
5918
5919 return incircleadapt(pa, pb, pc, pd, permanent);
5920}
5921
5922/*****************************************************************************/
5923/* */
5924/* orient3d() Return a positive value if the point pd lies below the */
5925/* plane passing through pa, pb, and pc; "below" is defined so */
5926/* that pa, pb, and pc appear in counterclockwise order when */
5927/* viewed from above the plane. Returns a negative value if */
5928/* pd lies above the plane. Returns zero if the points are */
5929/* coplanar. The result is also a rough approximation of six */
5930/* times the signed volume of the tetrahedron defined by the */
5931/* four points. */
5932/* */
5933/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5934/* result returned is the determinant of a matrix. This determinant is */
5935/* computed adaptively, in the sense that exact arithmetic is used only to */
5936/* the degree it is needed to ensure that the returned value has the */
5937/* correct sign. Hence, this function is usually quite fast, but will run */
5938/* more slowly when the input points are coplanar or nearly so. */
5939/* */
5940/* See my Robust Predicates paper for details. */
5941/* */
5942/*****************************************************************************/
5943
5944#ifdef ANSI_DECLARATORS
5946 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
5947 REAL permanent)
5948#else /* not ANSI_DECLARATORS */
5949REAL orient3dadapt(pa, pb, pc, pd,
5950 aheight, bheight, cheight, dheight, permanent)
5951vertex pa;
5952vertex pb;
5953vertex pc;
5954vertex pd;
5955REAL aheight;
5956REAL bheight;
5957REAL cheight;
5958REAL dheight;
5959REAL permanent;
5960#endif /* not ANSI_DECLARATORS */
5961
5962{
5963 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
5964 REAL det, errbound;
5965
5966 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5967 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5968 REAL bc[4], ca[4], ab[4];
5969 INEXACT REAL bc3, ca3, ab3;
5970 REAL adet[8], bdet[8], cdet[8];
5971 int alen, blen, clen;
5972 REAL abdet[16];
5973 int ablen;
5974 REAL *finnow, *finother, *finswap;
5975 REAL fin1[192], fin2[192];
5976 int finlength;
5977
5978 REAL adxtail, bdxtail, cdxtail;
5979 REAL adytail, bdytail, cdytail;
5980 REAL adheighttail, bdheighttail, cdheighttail;
5981 INEXACT REAL at_blarge, at_clarge;
5982 INEXACT REAL bt_clarge, bt_alarge;
5983 INEXACT REAL ct_alarge, ct_blarge;
5984 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
5985 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
5986 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
5987 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
5988 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
5989 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
5990 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
5991 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
5992 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
5993 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
5994 REAL bct[8], cat[8], abt[8];
5995 int bctlen, catlen, abtlen;
5996 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
5997 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
5998 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
5999 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
6000 REAL u[4], v[12], w[16];
6001 INEXACT REAL u3;
6002 int vlength, wlength;
6003 REAL negate;
6004
6005 INEXACT REAL bvirt;
6006 REAL avirt, bround, around;
6007 INEXACT REAL c;
6008 INEXACT REAL abig;
6009 REAL ahi, alo, bhi, blo;
6010 REAL err1, err2, err3;
6011 INEXACT REAL _i, _j, _k;
6012 REAL _0;
6013
6014 adx = (REAL) (pa[0] - pd[0]);
6015 bdx = (REAL) (pb[0] - pd[0]);
6016 cdx = (REAL) (pc[0] - pd[0]);
6017 ady = (REAL) (pa[1] - pd[1]);
6018 bdy = (REAL) (pb[1] - pd[1]);
6019 cdy = (REAL) (pc[1] - pd[1]);
6020 adheight = (REAL) (aheight - dheight);
6021 bdheight = (REAL) (bheight - dheight);
6022 cdheight = (REAL) (cheight - dheight);
6023
6024 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
6025 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
6026 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
6027 bc[3] = bc3;
6028 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
6029
6030 Two_Product(cdx, ady, cdxady1, cdxady0);
6031 Two_Product(adx, cdy, adxcdy1, adxcdy0);
6032 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
6033 ca[3] = ca3;
6034 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
6035
6036 Two_Product(adx, bdy, adxbdy1, adxbdy0);
6037 Two_Product(bdx, ady, bdxady1, bdxady0);
6038 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
6039 ab[3] = ab3;
6040 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
6041
6042 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
6043 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
6044
6045 det = estimate(finlength, fin1);
6046 errbound = o3derrboundB * permanent;
6047 if ((det >= errbound) || (-det >= errbound)) {
6048 return det;
6049 }
6050
6051 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
6052 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
6053 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
6054 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
6055 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
6056 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
6057 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
6058 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
6059 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
6060
6061 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
6062 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
6063 (adheighttail == 0.0) &&
6064 (bdheighttail == 0.0) &&
6065 (cdheighttail == 0.0)) {
6066 return det;
6067 }
6068
6069 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
6070 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
6071 (bdy * cdxtail + cdx * bdytail)) +
6072 adheighttail * (bdx * cdy - bdy * cdx)) +
6073 (bdheight * ((cdx * adytail + ady * cdxtail) -
6074 (cdy * adxtail + adx * cdytail)) +
6075 bdheighttail * (cdx * ady - cdy * adx)) +
6076 (cdheight * ((adx * bdytail + bdy * adxtail) -
6077 (ady * bdxtail + bdx * adytail)) +
6078 cdheighttail * (adx * bdy - ady * bdx));
6079 if ((det >= errbound) || (-det >= errbound)) {
6080 return det;
6081 }
6082
6083 finnow = fin1;
6084 finother = fin2;
6085
6086 if (adxtail == 0.0) {
6087 if (adytail == 0.0) {
6088 at_b[0] = 0.0;
6089 at_blen = 1;
6090 at_c[0] = 0.0;
6091 at_clen = 1;
6092 } else {
6093 negate = -adytail;
6094 Two_Product(negate, bdx, at_blarge, at_b[0]);
6095 at_b[1] = at_blarge;
6096 at_blen = 2;
6097 Two_Product(adytail, cdx, at_clarge, at_c[0]);
6098 at_c[1] = at_clarge;
6099 at_clen = 2;
6100 }
6101 } else {
6102 if (adytail == 0.0) {
6103 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
6104 at_b[1] = at_blarge;
6105 at_blen = 2;
6106 negate = -adxtail;
6107 Two_Product(negate, cdy, at_clarge, at_c[0]);
6108 at_c[1] = at_clarge;
6109 at_clen = 2;
6110 } else {
6111 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
6112 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
6113 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
6114 at_blarge, at_b[2], at_b[1], at_b[0]);
6115 at_b[3] = at_blarge;
6116 at_blen = 4;
6117 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
6118 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
6119 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
6120 at_clarge, at_c[2], at_c[1], at_c[0]);
6121 at_c[3] = at_clarge;
6122 at_clen = 4;
6123 }
6124 }
6125 if (bdxtail == 0.0) {
6126 if (bdytail == 0.0) {
6127 bt_c[0] = 0.0;
6128 bt_clen = 1;
6129 bt_a[0] = 0.0;
6130 bt_alen = 1;
6131 } else {
6132 negate = -bdytail;
6133 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
6134 bt_c[1] = bt_clarge;
6135 bt_clen = 2;
6136 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
6137 bt_a[1] = bt_alarge;
6138 bt_alen = 2;
6139 }
6140 } else {
6141 if (bdytail == 0.0) {
6142 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
6143 bt_c[1] = bt_clarge;
6144 bt_clen = 2;
6145 negate = -bdxtail;
6146 Two_Product(negate, ady, bt_alarge, bt_a[0]);
6147 bt_a[1] = bt_alarge;
6148 bt_alen = 2;
6149 } else {
6150 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
6151 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
6152 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
6153 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
6154 bt_c[3] = bt_clarge;
6155 bt_clen = 4;
6156 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
6157 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
6158 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
6159 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
6160 bt_a[3] = bt_alarge;
6161 bt_alen = 4;
6162 }
6163 }
6164 if (cdxtail == 0.0) {
6165 if (cdytail == 0.0) {
6166 ct_a[0] = 0.0;
6167 ct_alen = 1;
6168 ct_b[0] = 0.0;
6169 ct_blen = 1;
6170 } else {
6171 negate = -cdytail;
6172 Two_Product(negate, adx, ct_alarge, ct_a[0]);
6173 ct_a[1] = ct_alarge;
6174 ct_alen = 2;
6175 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
6176 ct_b[1] = ct_blarge;
6177 ct_blen = 2;
6178 }
6179 } else {
6180 if (cdytail == 0.0) {
6181 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
6182 ct_a[1] = ct_alarge;
6183 ct_alen = 2;
6184 negate = -cdxtail;
6185 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
6186 ct_b[1] = ct_blarge;
6187 ct_blen = 2;
6188 } else {
6189 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
6190 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
6191 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
6192 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
6193 ct_a[3] = ct_alarge;
6194 ct_alen = 4;
6195 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
6196 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
6197 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
6198 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
6199 ct_b[3] = ct_blarge;
6200 ct_blen = 4;
6201 }
6202 }
6203
6204 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
6205 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
6206 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6207 finother);
6208 finswap = finnow; finnow = finother; finother = finswap;
6209
6210 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
6211 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
6212 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6213 finother);
6214 finswap = finnow; finnow = finother; finother = finswap;
6215
6216 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
6217 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
6218 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6219 finother);
6220 finswap = finnow; finnow = finother; finother = finswap;
6221
6222 if (adheighttail != 0.0) {
6223 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
6224 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6225 finother);
6226 finswap = finnow; finnow = finother; finother = finswap;
6227 }
6228 if (bdheighttail != 0.0) {
6229 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
6230 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6231 finother);
6232 finswap = finnow; finnow = finother; finother = finswap;
6233 }
6234 if (cdheighttail != 0.0) {
6235 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
6236 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6237 finother);
6238 finswap = finnow; finnow = finother; finother = finswap;
6239 }
6240
6241 if (adxtail != 0.0) {
6242 if (bdytail != 0.0) {
6243 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
6244 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
6245 u[3] = u3;
6246 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6247 finother);
6248 finswap = finnow; finnow = finother; finother = finswap;
6249 if (cdheighttail != 0.0) {
6250 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
6251 u3, u[2], u[1], u[0]);
6252 u[3] = u3;
6253 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6254 finother);
6255 finswap = finnow; finnow = finother; finother = finswap;
6256 }
6257 }
6258 if (cdytail != 0.0) {
6259 negate = -adxtail;
6260 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
6261 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
6262 u[3] = u3;
6263 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6264 finother);
6265 finswap = finnow; finnow = finother; finother = finswap;
6266 if (bdheighttail != 0.0) {
6267 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
6268 u3, u[2], u[1], u[0]);
6269 u[3] = u3;
6270 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6271 finother);
6272 finswap = finnow; finnow = finother; finother = finswap;
6273 }
6274 }
6275 }
6276 if (bdxtail != 0.0) {
6277 if (cdytail != 0.0) {
6278 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
6279 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
6280 u[3] = u3;
6281 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6282 finother);
6283 finswap = finnow; finnow = finother; finother = finswap;
6284 if (adheighttail != 0.0) {
6285 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
6286 u3, u[2], u[1], u[0]);
6287 u[3] = u3;
6288 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6289 finother);
6290 finswap = finnow; finnow = finother; finother = finswap;
6291 }
6292 }
6293 if (adytail != 0.0) {
6294 negate = -bdxtail;
6295 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
6296 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
6297 u[3] = u3;
6298 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6299 finother);
6300 finswap = finnow; finnow = finother; finother = finswap;
6301 if (cdheighttail != 0.0) {
6302 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
6303 u3, u[2], u[1], u[0]);
6304 u[3] = u3;
6305 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6306 finother);
6307 finswap = finnow; finnow = finother; finother = finswap;
6308 }
6309 }
6310 }
6311 if (cdxtail != 0.0) {
6312 if (adytail != 0.0) {
6313 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
6314 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
6315 u[3] = u3;
6316 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6317 finother);
6318 finswap = finnow; finnow = finother; finother = finswap;
6319 if (bdheighttail != 0.0) {
6320 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
6321 u3, u[2], u[1], u[0]);
6322 u[3] = u3;
6323 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6324 finother);
6325 finswap = finnow; finnow = finother; finother = finswap;
6326 }
6327 }
6328 if (bdytail != 0.0) {
6329 negate = -cdxtail;
6330 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
6331 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
6332 u[3] = u3;
6333 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6334 finother);
6335 finswap = finnow; finnow = finother; finother = finswap;
6336 if (adheighttail != 0.0) {
6337 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
6338 u3, u[2], u[1], u[0]);
6339 u[3] = u3;
6340 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6341 finother);
6342 finswap = finnow; finnow = finother; finother = finswap;
6343 }
6344 }
6345 }
6346
6347 if (adheighttail != 0.0) {
6348 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
6349 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6350 finother);
6351 finswap = finnow; finnow = finother; finother = finswap;
6352 }
6353 if (bdheighttail != 0.0) {
6354 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
6355 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6356 finother);
6357 finswap = finnow; finnow = finother; finother = finswap;
6358 }
6359 if (cdheighttail != 0.0) {
6360 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
6361 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6362 finother);
6363 finswap = finnow; finnow = finother; finother = finswap;
6364 }
6365
6366 return finnow[finlength - 1];
6367}
6368
6369#ifdef ANSI_DECLARATORS
6370REAL orient3d(struct mesh *m, struct behavior *b,
6371 vertex pa, vertex pb, vertex pc, vertex pd,
6372 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
6373#else /* not ANSI_DECLARATORS */
6374REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
6375struct mesh *m;
6376struct behavior *b;
6377vertex pa;
6378vertex pb;
6379vertex pc;
6380vertex pd;
6381REAL aheight;
6382REAL bheight;
6383REAL cheight;
6384REAL dheight;
6385#endif /* not ANSI_DECLARATORS */
6386
6387{
6388 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6389 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
6390 REAL det;
6391 REAL permanent, errbound;
6392
6393 m->orient3dcount++;
6394
6395 adx = pa[0] - pd[0];
6396 bdx = pb[0] - pd[0];
6397 cdx = pc[0] - pd[0];
6398 ady = pa[1] - pd[1];
6399 bdy = pb[1] - pd[1];
6400 cdy = pc[1] - pd[1];
6401 adheight = aheight - dheight;
6402 bdheight = bheight - dheight;
6403 cdheight = cheight - dheight;
6404
6405 bdxcdy = bdx * cdy;
6406 cdxbdy = cdx * bdy;
6407
6408 cdxady = cdx * ady;
6409 adxcdy = adx * cdy;
6410
6411 adxbdy = adx * bdy;
6412 bdxady = bdx * ady;
6413
6414 det = adheight * (bdxcdy - cdxbdy)
6415 + bdheight * (cdxady - adxcdy)
6416 + cdheight * (adxbdy - bdxady);
6417
6418 if (b->noexact) {
6419 return det;
6420 }
6421
6422 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
6423 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
6424 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
6425 errbound = o3derrboundA * permanent;
6426 if ((det > errbound) || (-det > errbound)) {
6427 return det;
6428 }
6429
6430 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
6431 permanent);
6432}
6433
6434/*****************************************************************************/
6435/* */
6436/* nonregular() Return a positive value if the point pd is incompatible */
6437/* with the circle or plane passing through pa, pb, and pc */
6438/* (meaning that pd is inside the circle or below the */
6439/* plane); a negative value if it is compatible; and zero if */
6440/* the four points are cocircular/coplanar. The points pa, */
6441/* pb, and pc must be in counterclockwise order, or the sign */
6442/* of the result will be reversed. */
6443/* */
6444/* If the -w switch is used, the points are lifted onto the parabolic */
6445/* lifting map, then they are dropped according to their weights, then the */
6446/* 3D orientation test is applied. If the -W switch is used, the points' */
6447/* heights are already provided, so the 3D orientation test is applied */
6448/* directly. If neither switch is used, the incircle test is applied. */
6449/* */
6450/*****************************************************************************/
6451
6452#ifdef ANSI_DECLARATORS
6453REAL nonregular(struct mesh *m, struct behavior *b,
6454 vertex pa, vertex pb, vertex pc, vertex pd)
6455#else /* not ANSI_DECLARATORS */
6456REAL nonregular(m, b, pa, pb, pc, pd)
6457struct mesh *m;
6458struct behavior *b;
6459vertex pa;
6460vertex pb;
6461vertex pc;
6462vertex pd;
6463#endif /* not ANSI_DECLARATORS */
6464
6465{
6466 if (b->weighted == 0) {
6467 return incircle(m, b, pa, pb, pc, pd);
6468 } else if (b->weighted == 1) {
6469 return orient3d(m, b, pa, pb, pc, pd,
6470 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
6471 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
6472 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
6473 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
6474 } else {
6475 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
6476 }
6477}
6478
6479/*****************************************************************************/
6480/* */
6481/* findcircumcenter() Find the circumcenter of a triangle. */
6482/* */
6483/* The result is returned both in terms of x-y coordinates and xi-eta */
6484/* (barycentric) coordinates. The xi-eta coordinate system is defined in */
6485/* terms of the triangle: the origin of the triangle is the origin of the */
6486/* coordinate system; the destination of the triangle is one unit along the */
6487/* xi axis; and the apex of the triangle is one unit along the eta axis. */
6488/* This procedure also returns the square of the length of the triangle's */
6489/* shortest edge. */
6490/* */
6491/*****************************************************************************/
6492
6493#ifdef ANSI_DECLARATORS
6494void findcircumcenter(struct mesh *m, struct behavior *b,
6495 vertex torg, vertex tdest, vertex tapex,
6496 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
6497#else /* not ANSI_DECLARATORS */
6498void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
6499 offcenter)
6500struct mesh *m;
6501struct behavior *b;
6502vertex torg;
6503vertex tdest;
6504vertex tapex;
6505vertex circumcenter;
6506REAL *xi;
6507REAL *eta;
6508int offcenter;
6509#endif /* not ANSI_DECLARATORS */
6510
6511{
6512 REAL xdo, ydo, xao, yao;
6513 REAL dodist, aodist, dadist;
6514 REAL denominator;
6515 REAL dx, dy, dxoff, dyoff;
6516
6517 m->circumcentercount++;
6518
6519 /* Compute the circumcenter of the triangle. */
6520 xdo = tdest[0] - torg[0];
6521 ydo = tdest[1] - torg[1];
6522 xao = tapex[0] - torg[0];
6523 yao = tapex[1] - torg[1];
6524 dodist = xdo * xdo + ydo * ydo;
6525 aodist = xao * xao + yao * yao;
6526 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
6527 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
6528 if (b->noexact) {
6529 denominator = 0.5 / (xdo * yao - xao * ydo);
6530 } else {
6531 /* Use the counterclockwise() routine to ensure a positive (and */
6532 /* reasonably accurate) result, avoiding any possibility of */
6533 /* division by zero. */
6534 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
6535 /* Don't count the above as an orientation test. */
6536 m->counterclockcount--;
6537 }
6538 dx = (yao * dodist - ydo * aodist) * denominator;
6539 dy = (xdo * aodist - xao * dodist) * denominator;
6540
6541 /* Find the (squared) length of the triangle's shortest edge. This */
6542 /* serves as a conservative estimate of the insertion radius of the */
6543 /* circumcenter's parent. The estimate is used to ensure that */
6544 /* the algorithm terminates even if very small angles appear in */
6545 /* the input PSLG. */
6546 if ((dodist < aodist) && (dodist < dadist)) {
6547 if (offcenter && (b->offconstant > 0.0)) {
6548 /* Find the position of the off-center, as described by Alper Ungor. */
6549 dxoff = 0.5 * xdo - b->offconstant * ydo;
6550 dyoff = 0.5 * ydo + b->offconstant * xdo;
6551 /* If the off-center is closer to the origin than the */
6552 /* circumcenter, use the off-center instead. */
6553 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6554 dx = dxoff;
6555 dy = dyoff;
6556 }
6557 }
6558 } else if (aodist < dadist) {
6559 if (offcenter && (b->offconstant > 0.0)) {
6560 dxoff = 0.5 * xao + b->offconstant * yao;
6561 dyoff = 0.5 * yao - b->offconstant * xao;
6562 /* If the off-center is closer to the origin than the */
6563 /* circumcenter, use the off-center instead. */
6564 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6565 dx = dxoff;
6566 dy = dyoff;
6567 }
6568 }
6569 } else {
6570 if (offcenter && (b->offconstant > 0.0)) {
6571 dxoff = 0.5 * (tapex[0] - tdest[0]) -
6572 b->offconstant * (tapex[1] - tdest[1]);
6573 dyoff = 0.5 * (tapex[1] - tdest[1]) +
6574 b->offconstant * (tapex[0] - tdest[0]);
6575 /* If the off-center is closer to the destination than the */
6576 /* circumcenter, use the off-center instead. */
6577 if (dxoff * dxoff + dyoff * dyoff <
6578 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
6579 dx = xdo + dxoff;
6580 dy = ydo + dyoff;
6581 }
6582 }
6583 }
6584
6585 circumcenter[0] = torg[0] + dx;
6586 circumcenter[1] = torg[1] + dy;
6587
6588 /* To interpolate vertex attributes for the new vertex inserted at */
6589 /* the circumcenter, define a coordinate system with a xi-axis, */
6590 /* directed from the triangle's origin to its destination, and */
6591 /* an eta-axis, directed from its origin to its apex. */
6592 /* Calculate the xi and eta coordinates of the circumcenter. */
6593 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
6594 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
6595}
6596
6597/** **/
6598/** **/
6599/********* Geometric primitives end here *********/
6600
6601/*****************************************************************************/
6602/* */
6603/* triangleinit() Initialize some variables. */
6604/* */
6605/*****************************************************************************/
6606
6607#ifdef ANSI_DECLARATORS
6608void triangleinit(struct mesh *m)
6609#else /* not ANSI_DECLARATORS */
6610void triangleinit(m)
6611struct mesh *m;
6612#endif /* not ANSI_DECLARATORS */
6613
6614{
6615 poolzero(&m->vertices);
6616 poolzero(&m->triangles);
6617 poolzero(&m->subsegs);
6618 poolzero(&m->viri);
6619 poolzero(&m->badsubsegs);
6620 poolzero(&m->badtriangles);
6621 poolzero(&m->flipstackers);
6622 poolzero(&m->splaynodes);
6623
6624 m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */
6625 m->undeads = 0; /* No eliminated input vertices yet. */
6626 m->samples = 1; /* Point location should take at least one sample. */
6627 m->checksegments = 0; /* There are no segments in the triangulation yet. */
6628 m->checkquality = 0; /* The quality triangulation stage has not begun. */
6629 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
6630 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
6631 randomseed = 1;
6632
6633 exactinit(); /* Initialize exact arithmetic constants. */
6634}
6635
6636/*****************************************************************************/
6637/* */
6638/* randomnation() Generate a random number between 0 and `choices' - 1. */
6639/* */
6640/* This is a simple linear congruential random number generator. Hence, it */
6641/* is a bad random number generator, but good enough for most randomized */
6642/* geometric algorithms. */
6643/* */
6644/*****************************************************************************/
6645
6646#ifdef ANSI_DECLARATORS
6647unsigned long randomnation(unsigned int choices)
6648#else /* not ANSI_DECLARATORS */
6649unsigned long randomnation(choices)
6650unsigned int choices;
6651#endif /* not ANSI_DECLARATORS */
6652
6653{
6654 randomseed = (randomseed * 1366l + 150889l) % 714025l;
6655 return randomseed / (714025l / choices + 1);
6656}
6657
6658/********* Mesh quality testing routines begin here *********/
6659/** **/
6660/** **/
6661
6662/*****************************************************************************/
6663/* */
6664/* checkmesh() Test the mesh for topological consistency. */
6665/* */
6666/*****************************************************************************/
6667
6668#ifndef REDUCED
6669
6670#ifdef ANSI_DECLARATORS
6671void checkmesh(struct mesh *m, struct behavior *b)
6672#else /* not ANSI_DECLARATORS */
6673void checkmesh(m, b)
6674struct mesh *m;
6675struct behavior *b;
6676#endif /* not ANSI_DECLARATORS */
6677
6678{
6679 struct otri triangleloop;
6680 struct otri oppotri, oppooppotri;
6681 vertex triorg, tridest, triapex;
6682 vertex oppoorg, oppodest;
6683 int horrors;
6684 int saveexact;
6685 triangle ptr; /* Temporary variable used by sym(). */
6686
6687 /* Temporarily turn on exact arithmetic if it's off. */
6688 saveexact = b->noexact;
6689 b->noexact = 0;
6690 if (!b->quiet) {
6691 printf(" Checking consistency of mesh...\n");
6692 }
6693 horrors = 0;
6694 /* Run through the list of triangles, checking each one. */
6695 traversalinit(&m->triangles);
6696 triangleloop.tri = triangletraverse(m);
6697 while (triangleloop.tri != (triangle *) NULL) {
6698 /* Check all three edges of the triangle. */
6699 for (triangleloop.orient = 0; triangleloop.orient < 3;
6700 triangleloop.orient++) {
6701 org(triangleloop, triorg);
6702 dest(triangleloop, tridest);
6703 if (triangleloop.orient == 0) { /* Only test for inversion once. */
6704 /* Test if the triangle is flat or inverted. */
6705 apex(triangleloop, triapex);
6706 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
6707 printf(" !! !! Inverted ");
6708 printtriangle(m, b, &triangleloop);
6709 horrors++;
6710 }
6711 }
6712 /* Find the neighboring triangle on this edge. */
6713 sym(triangleloop, oppotri);
6714 if (oppotri.tri != m->dummytri) {
6715 /* Check that the triangle's neighbor knows it's a neighbor. */
6716 sym(oppotri, oppooppotri);
6717 if ((triangleloop.tri != oppooppotri.tri)
6718 || (triangleloop.orient != oppooppotri.orient)) {
6719 printf(" !! !! Asymmetric triangle-triangle bond:\n");
6720 if (triangleloop.tri == oppooppotri.tri) {
6721 printf(" (Right triangle, wrong orientation)\n");
6722 }
6723 printf(" First ");
6724 printtriangle(m, b, &triangleloop);
6725 printf(" Second (nonreciprocating) ");
6726 printtriangle(m, b, &oppotri);
6727 horrors++;
6728 }
6729 /* Check that both triangles agree on the identities */
6730 /* of their shared vertices. */
6731 org(oppotri, oppoorg);
6732 dest(oppotri, oppodest);
6733 if ((triorg != oppodest) || (tridest != oppoorg)) {
6734 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
6735 );
6736 printf(" First mismatched ");
6737 printtriangle(m, b, &triangleloop);
6738 printf(" Second mismatched ");
6739 printtriangle(m, b, &oppotri);
6740 horrors++;
6741 }
6742 }
6743 }
6744 triangleloop.tri = triangletraverse(m);
6745 }
6746 if (horrors == 0) {
6747 if (!b->quiet) {
6748 printf(" In my studied opinion, the mesh appears to be consistent.\n");
6749 }
6750 } else if (horrors == 1) {
6751 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
6752 } else {
6753 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
6754 }
6755 /* Restore the status of exact arithmetic. */
6756 b->noexact = saveexact;
6757}
6758
6759#endif /* not REDUCED */
6760
6761/*****************************************************************************/
6762/* */
6763/* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */
6764/* */
6765/*****************************************************************************/
6766
6767#ifndef REDUCED
6768
6769#ifdef ANSI_DECLARATORS
6770void checkdelaunay(struct mesh *m, struct behavior *b)
6771#else /* not ANSI_DECLARATORS */
6772void checkdelaunay(m, b)
6773struct mesh *m;
6774struct behavior *b;
6775#endif /* not ANSI_DECLARATORS */
6776
6777{
6778 struct otri triangleloop;
6779 struct otri oppotri;
6780 struct osub opposubseg;
6781 vertex triorg, tridest, triapex;
6782 vertex oppoapex;
6783 int shouldbedelaunay;
6784 int horrors;
6785 int saveexact;
6786 triangle ptr; /* Temporary variable used by sym(). */
6787 subseg sptr; /* Temporary variable used by tspivot(). */
6788
6789 /* Temporarily turn on exact arithmetic if it's off. */
6790 saveexact = b->noexact;
6791 b->noexact = 0;
6792 if (!b->quiet) {
6793 printf(" Checking Delaunay property of mesh...\n");
6794 }
6795 horrors = 0;
6796 /* Run through the list of triangles, checking each one. */
6797 traversalinit(&m->triangles);
6798 triangleloop.tri = triangletraverse(m);
6799 while (triangleloop.tri != (triangle *) NULL) {
6800 /* Check all three edges of the triangle. */
6801 for (triangleloop.orient = 0; triangleloop.orient < 3;
6802 triangleloop.orient++) {
6803 org(triangleloop, triorg);
6804 dest(triangleloop, tridest);
6805 apex(triangleloop, triapex);
6806 sym(triangleloop, oppotri);
6807 apex(oppotri, oppoapex);
6808 /* Only test that the edge is locally Delaunay if there is an */
6809 /* adjoining triangle whose pointer is larger (to ensure that */
6810 /* each pair isn't tested twice). */
6811 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
6812 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
6813 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
6814 (triorg != m->infvertex3) &&
6815 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
6816 (tridest != m->infvertex3) &&
6817 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
6818 (triapex != m->infvertex3) &&
6819 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
6820 (oppoapex != m->infvertex3);
6821 if (m->checksegments && shouldbedelaunay) {
6822 /* If a subsegment separates the triangles, then the edge is */
6823 /* constrained, so no local Delaunay test should be done. */
6824 tspivot(triangleloop, opposubseg);
6825 if (opposubseg.ss != m->dummysub){
6826 shouldbedelaunay = 0;
6827 }
6828 }
6829 if (shouldbedelaunay) {
6830 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
6831 if (!b->weighted) {
6832 printf(" !! !! Non-Delaunay pair of triangles:\n");
6833 printf(" First non-Delaunay ");
6834 printtriangle(m, b, &triangleloop);
6835 printf(" Second non-Delaunay ");
6836 } else {
6837 printf(" !! !! Non-regular pair of triangles:\n");
6838 printf(" First non-regular ");
6839 printtriangle(m, b, &triangleloop);
6840 printf(" Second non-regular ");
6841 }
6842 printtriangle(m, b, &oppotri);
6843 horrors++;
6844 }
6845 }
6846 }
6847 triangleloop.tri = triangletraverse(m);
6848 }
6849 if (horrors == 0) {
6850 if (!b->quiet) {
6851 printf(
6852 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
6853 }
6854 } else if (horrors == 1) {
6855 printf(
6856 " !! !! !! !! Precisely one terrifying transgression identified.\n");
6857 } else {
6858 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
6859 }
6860 /* Restore the status of exact arithmetic. */
6861 b->noexact = saveexact;
6862}
6863
6864#endif /* not REDUCED */
6865
6866/*****************************************************************************/
6867/* */
6868/* enqueuebadtriang() Add a bad triangle data structure to the end of a */
6869/* queue. */
6870/* */
6871/* The queue is actually a set of 4096 queues. I use multiple queues to */
6872/* give priority to smaller angles. I originally implemented a heap, but */
6873/* the queues are faster by a larger margin than I'd suspected. */
6874/* */
6875/*****************************************************************************/
6876
6877#ifndef CDT_ONLY
6878
6879#ifdef ANSI_DECLARATORS
6880void enqueuebadtriang(struct mesh *m, struct behavior *b,
6881 struct badtriang *badtri)
6882#else /* not ANSI_DECLARATORS */
6883void enqueuebadtriang(m, b, badtri)
6884struct mesh *m;
6885struct behavior *b;
6886struct badtriang *badtri;
6887#endif /* not ANSI_DECLARATORS */
6888
6889{
6890 REAL length, multiplier;
6891 int exponent, expincrement;
6892 int queuenumber;
6893 int posexponent;
6894 int i;
6895
6896 if (b->verbose > 2) {
6897 printf(" Queueing bad triangle:\n");
6898 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
6899 badtri->triangorg[0], badtri->triangorg[1],
6900 badtri->triangdest[0], badtri->triangdest[1],
6901 badtri->triangapex[0], badtri->triangapex[1]);
6902 }
6903
6904 /* Determine the appropriate queue to put the bad triangle into. */
6905 /* Recall that the key is the square of its shortest edge length. */
6906 if (badtri->key >= 1.0) {
6907 length = badtri->key;
6908 posexponent = 1;
6909 } else {
6910 /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */
6911 /* fact and use the reciprocal of `badtri->key', which is > 1.0. */
6912 length = 1.0 / badtri->key;
6913 posexponent = 0;
6914 }
6915 /* `length' is approximately 2.0 to what exponent? The following code */
6916 /* determines the answer in time logarithmic in the exponent. */
6917 exponent = 0;
6918 while (length > 2.0) {
6919 /* Find an approximation by repeated squaring of two. */
6920 expincrement = 1;
6921 multiplier = 0.5;
6922 while (length * multiplier * multiplier > 1.0) {
6923 expincrement *= 2;
6924 multiplier *= multiplier;
6925 }
6926 /* Reduce the value of `length', then iterate if necessary. */
6927 exponent += expincrement;
6928 length *= multiplier;
6929 }
6930 /* `length' is approximately squareroot(2.0) to what exponent? */
6931 exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
6932 /* `exponent' is now in the range 0...2047 for IEEE double precision. */
6933 /* Choose a queue in the range 0...4095. The shortest edges have the */
6934 /* highest priority (queue 4095). */
6935 if (posexponent) {
6936 queuenumber = 2047 - exponent;
6937 } else {
6938 queuenumber = 2048 + exponent;
6939 }
6940
6941 /* Are we inserting into an empty queue? */
6942 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
6943 /* Yes, we are inserting into an empty queue. */
6944 /* Will this become the highest-priority queue? */
6945 if (queuenumber > m->firstnonemptyq) {
6946 /* Yes, this is the highest-priority queue. */
6947 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
6948 m->firstnonemptyq = queuenumber;
6949 } else {
6950 /* No, this is not the highest-priority queue. */
6951 /* Find the queue with next higher priority. */
6952 i = queuenumber + 1;
6953 while (m->queuefront[i] == (struct badtriang *) NULL) {
6954 i++;
6955 }
6956 /* Mark the newly nonempty queue as following a higher-priority queue. */
6957 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
6958 m->nextnonemptyq[i] = queuenumber;
6959 }
6960 /* Put the bad triangle at the beginning of the (empty) queue. */
6961 m->queuefront[queuenumber] = badtri;
6962 } else {
6963 /* Add the bad triangle to the end of an already nonempty queue. */
6964 m->queuetail[queuenumber]->nexttriang = badtri;
6965 }
6966 /* Maintain a pointer to the last triangle of the queue. */
6967 m->queuetail[queuenumber] = badtri;
6968 /* Newly enqueued bad triangle has no successor in the queue. */
6969 badtri->nexttriang = (struct badtriang *) NULL;
6970}
6971
6972#endif /* not CDT_ONLY */
6973
6974/*****************************************************************************/
6975/* */
6976/* enqueuebadtri() Add a bad triangle to the end of a queue. */
6977/* */
6978/* Allocates a badtriang data structure for the triangle, then passes it to */
6979/* enqueuebadtriang(). */
6980/* */
6981/*****************************************************************************/
6982
6983#ifndef CDT_ONLY
6984
6985#ifdef ANSI_DECLARATORS
6986void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
6987 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
6988#else /* not ANSI_DECLARATORS */
6989void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
6990struct mesh *m;
6991struct behavior *b;
6992struct otri *enqtri;
6993REAL minedge;
6994vertex enqapex;
6995vertex enqorg;
6996vertex enqdest;
6997#endif /* not ANSI_DECLARATORS */
6998
6999{
7000 struct badtriang *newbad;
7001
7002 /* Allocate space for the bad triangle. */
7003 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
7004 newbad->poortri = encode(*enqtri);
7005 newbad->key = minedge;
7006 newbad->triangapex = enqapex;
7007 newbad->triangorg = enqorg;
7008 newbad->triangdest = enqdest;
7009 enqueuebadtriang(m, b, newbad);
7010}
7011
7012#endif /* not CDT_ONLY */
7013
7014/*****************************************************************************/
7015/* */
7016/* dequeuebadtriang() Remove a triangle from the front of the queue. */
7017/* */
7018/*****************************************************************************/
7019
7020#ifndef CDT_ONLY
7021
7022#ifdef ANSI_DECLARATORS
7023struct badtriang *dequeuebadtriang(struct mesh *m)
7024#else /* not ANSI_DECLARATORS */
7025struct badtriang *dequeuebadtriang(m)
7026struct mesh *m;
7027#endif /* not ANSI_DECLARATORS */
7028
7029{
7030 struct badtriang *result;
7031
7032 /* If no queues are nonempty, return NULL. */
7033 if (m->firstnonemptyq < 0) {
7034 return (struct badtriang *) NULL;
7035 }
7036 /* Find the first triangle of the highest-priority queue. */
7037 result = m->queuefront[m->firstnonemptyq];
7038 /* Remove the triangle from the queue. */
7039 m->queuefront[m->firstnonemptyq] = result->nexttriang;
7040 /* If this queue is now empty, note the new highest-priority */
7041 /* nonempty queue. */
7042 if (result == m->queuetail[m->firstnonemptyq]) {
7043 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
7044 }
7045 return result;
7046}
7047
7048#endif /* not CDT_ONLY */
7049
7050/*****************************************************************************/
7051/* */
7052/* checkseg4encroach() Check a subsegment to see if it is encroached; add */
7053/* it to the list if it is. */
7054/* */
7055/* A subsegment is encroached if there is a vertex in its diametral lens. */
7056/* For Ruppert's algorithm (-D switch), the "diametral lens" is the */
7057/* diametral circle. For Chew's algorithm (default), the diametral lens is */
7058/* just big enough to enclose two isosceles triangles whose bases are the */
7059/* subsegment. Each of the two isosceles triangles has two angles equal */
7060/* to `b->minangle'. */
7061/* */
7062/* Chew's algorithm does not require diametral lenses at all--but they save */
7063/* time. Any vertex inside a subsegment's diametral lens implies that the */
7064/* triangle adjoining the subsegment will be too skinny, so it's only a */
7065/* matter of time before the encroaching vertex is deleted by Chew's */
7066/* algorithm. It's faster to simply not insert the doomed vertex in the */
7067/* first place, which is why I use diametral lenses with Chew's algorithm. */
7068/* */
7069/* Returns a nonzero value if the subsegment is encroached. */
7070/* */
7071/*****************************************************************************/
7072
7073#ifndef CDT_ONLY
7074
7075#ifdef ANSI_DECLARATORS
7076int checkseg4encroach(struct mesh *m, struct behavior *b,
7077 struct osub *testsubseg)
7078#else /* not ANSI_DECLARATORS */
7079int checkseg4encroach(m, b, testsubseg)
7080struct mesh *m;
7081struct behavior *b;
7082struct osub *testsubseg;
7083#endif /* not ANSI_DECLARATORS */
7084
7085{
7086 struct otri neighbortri;
7087 struct osub testsym;
7088 struct badsubseg *encroachedseg;
7089 REAL dotproduct;
7090 int encroached;
7091 int sides;
7092 vertex eorg, edest, eapex;
7093 triangle ptr; /* Temporary variable used by stpivot(). */
7094
7095 encroached = 0;
7096 sides = 0;
7097
7098 sorg(*testsubseg, eorg);
7099 sdest(*testsubseg, edest);
7100 /* Check one neighbor of the subsegment. */
7101 stpivot(*testsubseg, neighbortri);
7102 /* Does the neighbor exist, or is this a boundary edge? */
7103 if (neighbortri.tri != m->dummytri) {
7104 sides++;
7105 /* Find a vertex opposite this subsegment. */
7106 apex(neighbortri, eapex);
7107 /* Check whether the apex is in the diametral lens of the subsegment */
7108 /* (the diametral circle if `conformdel' is set). A dot product */
7109 /* of two sides of the triangle is used to check whether the angle */
7110 /* at the apex is greater than (180 - 2 `minangle') degrees (for */
7111 /* lenses; 90 degrees for diametral circles). */
7112 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7113 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7114 if (dotproduct < 0.0) {
7115 if (b->conformdel ||
7116 (dotproduct * dotproduct >=
7117 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7118 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7119 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7120 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7121 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7122 encroached = 1;
7123 }
7124 }
7125 }
7126 /* Check the other neighbor of the subsegment. */
7127 ssym(*testsubseg, testsym);
7128 stpivot(testsym, neighbortri);
7129 /* Does the neighbor exist, or is this a boundary edge? */
7130 if (neighbortri.tri != m->dummytri) {
7131 sides++;
7132 /* Find the other vertex opposite this subsegment. */
7133 apex(neighbortri, eapex);
7134 /* Check whether the apex is in the diametral lens of the subsegment */
7135 /* (or the diametral circle, if `conformdel' is set). */
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 ||
7140 (dotproduct * dotproduct >=
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 += 2;
7147 }
7148 }
7149 }
7150
7151 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
7152 if (b->verbose > 2) {
7153 printf(
7154 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
7155 eorg[0], eorg[1], edest[0], edest[1]);
7156 }
7157 /* Add the subsegment to the list of encroached subsegments. */
7158 /* Be sure to get the orientation right. */
7159 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
7160 if (encroached == 1) {
7161 encroachedseg->encsubseg = sencode(*testsubseg);
7162 encroachedseg->subsegorg = eorg;
7163 encroachedseg->subsegdest = edest;
7164 } else {
7165 encroachedseg->encsubseg = sencode(testsym);
7166 encroachedseg->subsegorg = edest;
7167 encroachedseg->subsegdest = eorg;
7168 }
7169 }
7170
7171 return encroached;
7172}
7173
7174#endif /* not CDT_ONLY */
7175
7176/*****************************************************************************/
7177/* */
7178/* testtriangle() Test a triangle for quality and size. */
7179/* */
7180/* Tests a triangle to see if it satisfies the minimum angle condition and */
7181/* the maximum area condition. Triangles that aren't up to spec are added */
7182/* to the bad triangle queue. */
7183/* */
7184/*****************************************************************************/
7185
7186#ifndef CDT_ONLY
7187
7188#ifdef ANSI_DECLARATORS
7189void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
7190#else /* not ANSI_DECLARATORS */
7191void testtriangle(m, b, testtri)
7192struct mesh *m;
7193struct behavior *b;
7194struct otri *testtri;
7195#endif /* not ANSI_DECLARATORS */
7196
7197{
7198 struct otri tri1, tri2;
7199 struct osub testsub;
7200 vertex torg, tdest, tapex;
7201 vertex base1, base2;
7202 vertex org1, dest1, org2, dest2;
7203 vertex joinvertex;
7204 REAL dxod, dyod, dxda, dyda, dxao, dyao;
7205 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
7206 REAL apexlen, orglen, destlen, minedge;
7207 REAL angle;
7208 REAL area;
7209 REAL dist1, dist2;
7210 subseg sptr; /* Temporary variable used by tspivot(). */
7211 triangle ptr; /* Temporary variable used by oprev() and dnext(). */
7212
7213 org(*testtri, torg);
7214 dest(*testtri, tdest);
7215 apex(*testtri, tapex);
7216 dxod = torg[0] - tdest[0];
7217 dyod = torg[1] - tdest[1];
7218 dxda = tdest[0] - tapex[0];
7219 dyda = tdest[1] - tapex[1];
7220 dxao = tapex[0] - torg[0];
7221 dyao = tapex[1] - torg[1];
7222 dxod2 = dxod * dxod;
7223 dyod2 = dyod * dyod;
7224 dxda2 = dxda * dxda;
7225 dyda2 = dyda * dyda;
7226 dxao2 = dxao * dxao;
7227 dyao2 = dyao * dyao;
7228 /* Find the lengths of the triangle's three edges. */
7229 apexlen = dxod2 + dyod2;
7230 orglen = dxda2 + dyda2;
7231 destlen = dxao2 + dyao2;
7232
7233 if ((apexlen < orglen) && (apexlen < destlen)) {
7234 /* The edge opposite the apex is shortest. */
7235 minedge = apexlen;
7236 /* Find the square of the cosine of the angle at the apex. */
7237 angle = dxda * dxao + dyda * dyao;
7238 angle = angle * angle / (orglen * destlen);
7239 base1 = torg;
7240 base2 = tdest;
7241 otricopy(*testtri, tri1);
7242 } else if (orglen < destlen) {
7243 /* The edge opposite the origin is shortest. */
7244 minedge = orglen;
7245 /* Find the square of the cosine of the angle at the origin. */
7246 angle = dxod * dxao + dyod * dyao;
7247 angle = angle * angle / (apexlen * destlen);
7248 base1 = tdest;
7249 base2 = tapex;
7250 lnext(*testtri, tri1);
7251 } else {
7252 /* The edge opposite the destination is shortest. */
7253 minedge = destlen;
7254 /* Find the square of the cosine of the angle at the destination. */
7255 angle = dxod * dxda + dyod * dyda;
7256 angle = angle * angle / (apexlen * orglen);
7257 base1 = tapex;
7258 base2 = torg;
7259 lprev(*testtri, tri1);
7260 }
7261
7262 if (b->vararea || b->fixedarea || b->usertest) {
7263 /* Check whether the area is larger than permitted. */
7264 area = 0.5 * (dxod * dyda - dyod * dxda);
7265 if (b->fixedarea && (area > b->maxarea)) {
7266 /* Add this triangle to the list of bad triangles. */
7267 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7268 return;
7269 }
7270
7271 /* Nonpositive area constraints are treated as unconstrained. */
7272 if ((b->vararea) && (area > areabound(*testtri)) &&
7273 (areabound(*testtri) > 0.0)) {
7274 /* Add this triangle to the list of bad triangles. */
7275 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7276 return;
7277 }
7278
7279 if (b->usertest) {
7280 /* Check whether the user thinks this triangle is too large. */
7281 if (triunsuitable(torg, tdest, tapex, area)) {
7282 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7283 return;
7284 }
7285 }
7286 }
7287
7288 /* Check whether the angle is smaller than permitted. */
7289 if (angle > b->goodangle) {
7290 /* Use the rules of Miller, Pav, and Walkington to decide that certain */
7291 /* triangles should not be split, even if they have bad angles. */
7292 /* A skinny triangle is not split if its shortest edge subtends a */
7293 /* small input angle, and both endpoints of the edge lie on a */
7294 /* concentric circular shell. For convenience, I make a small */
7295 /* adjustment to that rule: I check if the endpoints of the edge */
7296 /* both lie in segment interiors, equidistant from the apex where */
7297 /* the two segments meet. */
7298 /* First, check if both points lie in segment interiors. */
7299 if ((vertextype(base1) == SEGMENTVERTEX) &&
7300 (vertextype(base2) == SEGMENTVERTEX)) {
7301 /* Check if both points lie in a common segment. If they do, the */
7302 /* skinny triangle is enqueued to be split as usual. */
7303 tspivot(tri1, testsub);
7304 if (testsub.ss == m->dummysub) {
7305 /* No common segment. Find a subsegment that contains `torg'. */
7306 otricopy(tri1, tri2);
7307 do {
7308 oprevself(tri1);
7309 tspivot(tri1, testsub);
7310 } while (testsub.ss == m->dummysub);
7311 /* Find the endpoints of the containing segment. */
7312 segorg(testsub, org1);
7313 segdest(testsub, dest1);
7314 /* Find a subsegment that contains `tdest'. */
7315 do {
7316 dnextself(tri2);
7317 tspivot(tri2, testsub);
7318 } while (testsub.ss == m->dummysub);
7319 /* Find the endpoints of the containing segment. */
7320 segorg(testsub, org2);
7321 segdest(testsub, dest2);
7322 /* Check if the two containing segments have an endpoint in common. */
7323 joinvertex = (vertex) NULL;
7324 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
7325 joinvertex = dest1;
7326 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
7327 joinvertex = org1;
7328 }
7329 if (joinvertex != (vertex) NULL) {
7330 /* Compute the distance from the common endpoint (of the two */
7331 /* segments) to each of the endpoints of the shortest edge. */
7332 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
7333 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
7334 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
7335 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
7336 /* If the two distances are equal, don't split the triangle. */
7337 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
7338 /* Return now to avoid enqueueing the bad triangle. */
7339 return;
7340 }
7341 }
7342 }
7343 }
7344
7345 /* Add this triangle to the list of bad triangles. */
7346 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7347 }
7348}
7349
7350#endif /* not CDT_ONLY */
7351
7352/** **/
7353/** **/
7354/********* Mesh quality testing routines end here *********/
7355
7356/********* Point location routines begin here *********/
7357/** **/
7358/** **/
7359
7360/*****************************************************************************/
7361/* */
7362/* makevertexmap() Construct a mapping from vertices to triangles to */
7363/* improve the speed of point location for segment */
7364/* insertion. */
7365/* */
7366/* Traverses all the triangles, and provides each corner of each triangle */
7367/* with a pointer to that triangle. Of course, pointers will be */
7368/* overwritten by other pointers because (almost) each vertex is a corner */
7369/* of several triangles, but in the end every vertex will point to some */
7370/* triangle that contains it. */
7371/* */
7372/*****************************************************************************/
7373
7374#ifdef ANSI_DECLARATORS
7375void makevertexmap(struct mesh *m, struct behavior *b)
7376#else /* not ANSI_DECLARATORS */
7377void makevertexmap(m, b)
7378struct mesh *m;
7379struct behavior *b;
7380#endif /* not ANSI_DECLARATORS */
7381
7382{
7383 struct otri triangleloop;
7384 vertex triorg;
7385
7386 if (b->verbose) {
7387 printf(" Constructing mapping from vertices to triangles.\n");
7388 }
7389 traversalinit(&m->triangles);
7390 triangleloop.tri = triangletraverse(m);
7391 while (triangleloop.tri != (triangle *) NULL) {
7392 /* Check all three vertices of the triangle. */
7393 for (triangleloop.orient = 0; triangleloop.orient < 3;
7394 triangleloop.orient++) {
7395 org(triangleloop, triorg);
7396 setvertex2tri(triorg, encode(triangleloop));
7397 }
7398 triangleloop.tri = triangletraverse(m);
7399 }
7400}
7401
7402/*****************************************************************************/
7403/* */
7404/* preciselocate() Find a triangle or edge containing a given point. */
7405/* */
7406/* Begins its search from `searchtri'. It is important that `searchtri' */
7407/* be a handle with the property that `searchpoint' is strictly to the left */
7408/* of the edge denoted by `searchtri', or is collinear with that edge and */
7409/* does not intersect that edge. (In particular, `searchpoint' should not */
7410/* be the origin or destination of that edge.) */
7411/* */
7412/* These conditions are imposed because preciselocate() is normally used in */
7413/* one of two situations: */
7414/* */
7415/* (1) To try to find the location to insert a new point. Normally, we */
7416/* know an edge that the point is strictly to the left of. In the */
7417/* incremental Delaunay algorithm, that edge is a bounding box edge. */
7418/* In Ruppert's Delaunay refinement algorithm for quality meshing, */
7419/* that edge is the shortest edge of the triangle whose circumcenter */
7420/* is being inserted. */
7421/* */
7422/* (2) To try to find an existing point. In this case, any edge on the */
7423/* convex hull is a good starting edge. You must screen out the */
7424/* possibility that the vertex sought is an endpoint of the starting */
7425/* edge before you call preciselocate(). */
7426/* */
7427/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7428/* */
7429/* This implementation differs from that given by Guibas and Stolfi. It */
7430/* walks from triangle to triangle, crossing an edge only if `searchpoint' */
7431/* is on the other side of the line containing that edge. After entering */
7432/* a triangle, there are two edges by which one can leave that triangle. */
7433/* If both edges are valid (`searchpoint' is on the other side of both */
7434/* edges), one of the two is chosen by drawing a line perpendicular to */
7435/* the entry edge (whose endpoints are `forg' and `fdest') passing through */
7436/* `fapex'. Depending on which side of this perpendicular `searchpoint' */
7437/* falls on, an exit edge is chosen. */
7438/* */
7439/* This implementation is empirically faster than the Guibas and Stolfi */
7440/* point location routine (which I originally used), which tends to spiral */
7441/* in toward its target. */
7442/* */
7443/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7444/* is a handle whose origin is the existing vertex. */
7445/* */
7446/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7447/* handle whose primary edge is the edge on which the point lies. */
7448/* */
7449/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7450/* `searchtri' is a handle on the triangle that contains the point. */
7451/* */
7452/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7453/* handle whose primary edge the point is to the right of. This might */
7454/* occur when the circumcenter of a triangle falls just slightly outside */
7455/* the mesh due to floating-point roundoff error. It also occurs when */
7456/* seeking a hole or region point that a foolish user has placed outside */
7457/* the mesh. */
7458/* */
7459/* If `stopatsubsegment' is nonzero, the search will stop if it tries to */
7460/* walk through a subsegment, and will return OUTSIDE. */
7461/* */
7462/* WARNING: This routine is designed for convex triangulations, and will */
7463/* not generally work after the holes and concavities have been carved. */
7464/* However, it can still be used to find the circumcenter of a triangle, as */
7465/* long as the search is begun from the triangle in question. */
7466/* */
7467/*****************************************************************************/
7468
7469#ifdef ANSI_DECLARATORS
7470enum locateresult preciselocate(struct mesh *m, struct behavior *b,
7471 vertex searchpoint, struct otri *searchtri,
7472 int stopatsubsegment)
7473#else /* not ANSI_DECLARATORS */
7474enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
7475struct mesh *m;
7476struct behavior *b;
7477vertex searchpoint;
7478struct otri *searchtri;
7479int stopatsubsegment;
7480#endif /* not ANSI_DECLARATORS */
7481
7482{
7483 struct otri backtracktri;
7484 struct osub checkedge;
7485 vertex forg, fdest, fapex;
7486 REAL orgorient, destorient;
7487 int moveleft;
7488 triangle ptr; /* Temporary variable used by sym(). */
7489 subseg sptr; /* Temporary variable used by tspivot(). */
7490
7491 if (b->verbose > 2) {
7492 printf(" Searching for point (%.12g, %.12g).\n",
7493 searchpoint[0], searchpoint[1]);
7494 }
7495 /* Where are we? */
7496 org(*searchtri, forg);
7497 dest(*searchtri, fdest);
7498 apex(*searchtri, fapex);
7499 while (1) {
7500 if (b->verbose > 2) {
7501 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7502 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
7503 }
7504 /* Check whether the apex is the point we seek. */
7505 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
7506 lprevself(*searchtri);
7507 return ONVERTEX;
7508 }
7509 /* Does the point lie on the other side of the line defined by the */
7510 /* triangle edge opposite the triangle's destination? */
7511 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
7512 /* Does the point lie on the other side of the line defined by the */
7513 /* triangle edge opposite the triangle's origin? */
7514 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
7515 if (destorient > 0.0) {
7516 if (orgorient > 0.0) {
7517 /* Move left if the inner product of (fapex - searchpoint) and */
7518 /* (fdest - forg) is positive. This is equivalent to drawing */
7519 /* a line perpendicular to the line (forg, fdest) and passing */
7520 /* through `fapex', and determining which side of this line */
7521 /* `searchpoint' falls on. */
7522 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
7523 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
7524 } else {
7525 moveleft = 1;
7526 }
7527 } else {
7528 if (orgorient > 0.0) {
7529 moveleft = 0;
7530 } else {
7531 /* The point we seek must be on the boundary of or inside this */
7532 /* triangle. */
7533 if (destorient == 0.0) {
7534 lprevself(*searchtri);
7535 return ONEDGE;
7536 }
7537 if (orgorient == 0.0) {
7538 lnextself(*searchtri);
7539 return ONEDGE;
7540 }
7541 return INTRIANGLE;
7542 }
7543 }
7544
7545 /* Move to another triangle. Leave a trace `backtracktri' in case */
7546 /* floating-point roundoff or some such bogey causes us to walk */
7547 /* off a boundary of the triangulation. */
7548 if (moveleft) {
7549 lprev(*searchtri, backtracktri);
7550 fdest = fapex;
7551 } else {
7552 lnext(*searchtri, backtracktri);
7553 forg = fapex;
7554 }
7555 sym(backtracktri, *searchtri);
7556
7557 if (m->checksegments && stopatsubsegment) {
7558 /* Check for walking through a subsegment. */
7559 tspivot(backtracktri, checkedge);
7560 if (checkedge.ss != m->dummysub) {
7561 /* Go back to the last triangle. */
7562 otricopy(backtracktri, *searchtri);
7563 return OUTSIDE;
7564 }
7565 }
7566 /* Check for walking right out of the triangulation. */
7567 if (searchtri->tri == m->dummytri) {
7568 /* Go back to the last triangle. */
7569 otricopy(backtracktri, *searchtri);
7570 return OUTSIDE;
7571 }
7572
7573 apex(*searchtri, fapex);
7574 }
7575}
7576
7577/*****************************************************************************/
7578/* */
7579/* locate() Find a triangle or edge containing a given point. */
7580/* */
7581/* Searching begins from one of: the input `searchtri', a recently */
7582/* encountered triangle `recenttri', or from a triangle chosen from a */
7583/* random sample. The choice is made by determining which triangle's */
7584/* origin is closest to the point we are searching for. Normally, */
7585/* `searchtri' should be a handle on the convex hull of the triangulation. */
7586/* */
7587/* Details on the random sampling method can be found in the Mucke, Saias, */
7588/* and Zhu paper cited in the header of this code. */
7589/* */
7590/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7591/* */
7592/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7593/* is a handle whose origin is the existing vertex. */
7594/* */
7595/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7596/* handle whose primary edge is the edge on which the point lies. */
7597/* */
7598/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7599/* `searchtri' is a handle on the triangle that contains the point. */
7600/* */
7601/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7602/* handle whose primary edge the point is to the right of. This might */
7603/* occur when the circumcenter of a triangle falls just slightly outside */
7604/* the mesh due to floating-point roundoff error. It also occurs when */
7605/* seeking a hole or region point that a foolish user has placed outside */
7606/* the mesh. */
7607/* */
7608/* WARNING: This routine is designed for convex triangulations, and will */
7609/* not generally work after the holes and concavities have been carved. */
7610/* */
7611/*****************************************************************************/
7612
7613#ifdef ANSI_DECLARATORS
7614enum locateresult locate(struct mesh *m, struct behavior *b,
7615 vertex searchpoint, struct otri *searchtri)
7616#else /* not ANSI_DECLARATORS */
7617enum locateresult locate(m, b, searchpoint, searchtri)
7618struct mesh *m;
7619struct behavior *b;
7620vertex searchpoint;
7621struct otri *searchtri;
7622#endif /* not ANSI_DECLARATORS */
7623
7624{
7625 VOID **sampleblock;
7626 char *firsttri;
7627 struct otri sampletri;
7628 vertex torg, tdest;
7629 unsigned long alignptr;
7630 REAL searchdist, dist;
7631 REAL ahead;
7632 long samplesperblock, totalsamplesleft, samplesleft;
7633 long population, totalpopulation;
7634 triangle ptr; /* Temporary variable used by sym(). */
7635
7636 if (b->verbose > 2) {
7637 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
7638 searchpoint[0], searchpoint[1]);
7639 }
7640 /* Record the distance from the suggested starting triangle to the */
7641 /* point we seek. */
7642 org(*searchtri, torg);
7643 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7644 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7645 if (b->verbose > 2) {
7646 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
7647 torg[0], torg[1]);
7648 }
7649
7650 /* If a recently encountered triangle has been recorded and has not been */
7651 /* deallocated, test it as a good starting point. */
7652 if (m->recenttri.tri != (triangle *) NULL) {
7653 if (!deadtri(m->recenttri.tri)) {
7654 org(m->recenttri, torg);
7655 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7656 otricopy(m->recenttri, *searchtri);
7657 return ONVERTEX;
7658 }
7659 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7660 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7661 if (dist < searchdist) {
7662 otricopy(m->recenttri, *searchtri);
7663 searchdist = dist;
7664 if (b->verbose > 2) {
7665 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
7666 torg[0], torg[1]);
7667 }
7668 }
7669 }
7670 }
7671
7672 /* The number of random samples taken is proportional to the cube root of */
7673 /* the number of triangles in the mesh. The next bit of code assumes */
7674 /* that the number of triangles increases monotonically (or at least */
7675 /* doesn't decrease enough to matter). */
7676 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
7677 m->triangles.items) {
7678 m->samples++;
7679 }
7680
7681 /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */
7682 /* from each block of triangles (except the first)--until we meet the */
7683 /* sample quota. The ceiling means that blocks at the end might be */
7684 /* neglected, but I don't care. */
7685 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
7686 /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */
7687 /* from the first block of triangles. */
7688 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
7689 m->triangles.maxitems + 1;
7690 totalsamplesleft = m->samples;
7691 population = m->triangles.itemsfirstblock;
7692 totalpopulation = m->triangles.maxitems;
7693 sampleblock = m->triangles.firstblock;
7694 sampletri.orient = 0;
7695 while (totalsamplesleft > 0) {
7696 /* If we're in the last block, `population' needs to be corrected. */
7697 if (population > totalpopulation) {
7698 population = totalpopulation;
7699 }
7700 /* Find a pointer to the first triangle in the block. */
7701 alignptr = (unsigned long) (sampleblock + 1);
7702 firsttri = (char *) (alignptr +
7703 (unsigned long) m->triangles.alignbytes -
7704 (alignptr %
7705 (unsigned long) m->triangles.alignbytes));
7706
7707 /* Choose `samplesleft' randomly sampled triangles in this block. */
7708 do {
7709 sampletri.tri = (triangle *) (firsttri +
7710 (randomnation((unsigned int) population) *
7711 m->triangles.itembytes));
7712 if (!deadtri(sampletri.tri)) {
7713 org(sampletri, torg);
7714 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7715 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7716 if (dist < searchdist) {
7717 otricopy(sampletri, *searchtri);
7718 searchdist = dist;
7719 if (b->verbose > 2) {
7720 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
7721 torg[0], torg[1]);
7722 }
7723 }
7724 }
7725
7726 samplesleft--;
7727 totalsamplesleft--;
7728 } while ((samplesleft > 0) && (totalsamplesleft > 0));
7729
7730 if (totalsamplesleft > 0) {
7731 sampleblock = (VOID **) *sampleblock;
7732 samplesleft = samplesperblock;
7733 totalpopulation -= population;
7734 population = TRIPERBLOCK;
7735 }
7736 }
7737
7738 /* Where are we? */
7739 org(*searchtri, torg);
7740 dest(*searchtri, tdest);
7741 /* Check the starting triangle's vertices. */
7742 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7743 return ONVERTEX;
7744 }
7745 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
7746 lnextself(*searchtri);
7747 return ONVERTEX;
7748 }
7749 /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
7750 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
7751 if (ahead < 0.0) {
7752 /* Turn around so that `searchpoint' is to the left of the */
7753 /* edge specified by `searchtri'. */
7754 symself(*searchtri);
7755 } else if (ahead == 0.0) {
7756 /* Check if `searchpoint' is between `torg' and `tdest'. */
7757 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
7758 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
7759 return ONEDGE;
7760 }
7761 }
7762 return preciselocate(m, b, searchpoint, searchtri, 0);
7763}
7764
7765/** **/
7766/** **/
7767/********* Point location routines end here *********/
7768
7769/********* Mesh transformation routines begin here *********/
7770/** **/
7771/** **/
7772
7773/*****************************************************************************/
7774/* */
7775/* insertsubseg() Create a new subsegment and insert it between two */
7776/* triangles. */
7777/* */
7778/* The new subsegment is inserted at the edge described by the handle */
7779/* `tri'. Its vertices are properly initialized. The marker `subsegmark' */
7780/* is applied to the subsegment and, if appropriate, its vertices. */
7781/* */
7782/*****************************************************************************/
7783
7784#ifdef ANSI_DECLARATORS
7785void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
7786 int subsegmark)
7787#else /* not ANSI_DECLARATORS */
7788void insertsubseg(m, b, tri, subsegmark)
7789struct mesh *m;
7790struct behavior *b;
7791struct otri *tri; /* Edge at which to insert the new subsegment. */
7792int subsegmark; /* Marker for the new subsegment. */
7793#endif /* not ANSI_DECLARATORS */
7794
7795{
7796 struct otri oppotri;
7797 struct osub newsubseg;
7798 vertex triorg, tridest;
7799 triangle ptr; /* Temporary variable used by sym(). */
7800 subseg sptr; /* Temporary variable used by tspivot(). */
7801
7802 org(*tri, triorg);
7803 dest(*tri, tridest);
7804 /* Mark vertices if possible. */
7805 if (vertexmark(triorg) == 0) {
7806 setvertexmark(triorg, subsegmark);
7807 }
7808 if (vertexmark(tridest) == 0) {
7809 setvertexmark(tridest, subsegmark);
7810 }
7811 /* Check if there's already a subsegment here. */
7812 tspivot(*tri, newsubseg);
7813 if (newsubseg.ss == m->dummysub) {
7814 /* Make new subsegment and initialize its vertices. */
7815 makesubseg(m, &newsubseg);
7816 setsorg(newsubseg, tridest);
7817 setsdest(newsubseg, triorg);
7818 setsegorg(newsubseg, tridest);
7819 setsegdest(newsubseg, triorg);
7820 /* Bond new subsegment to the two triangles it is sandwiched between. */
7821 /* Note that the facing triangle `oppotri' might be equal to */
7822 /* `dummytri' (outer space), but the new subsegment is bonded to it */
7823 /* all the same. */
7824 tsbond(*tri, newsubseg);
7825 sym(*tri, oppotri);
7826 ssymself(newsubseg);
7827 tsbond(oppotri, newsubseg);
7828 setmark(newsubseg, subsegmark);
7829 if (b->verbose > 2) {
7830 printf(" Inserting new ");
7831 printsubseg(m, b, &newsubseg);
7832 }
7833 } else {
7834 if (mark(newsubseg) == 0) {
7835 setmark(newsubseg, subsegmark);
7836 }
7837 }
7838}
7839
7840/*****************************************************************************/
7841/* */
7842/* Terminology */
7843/* */
7844/* A "local transformation" replaces a small set of triangles with another */
7845/* set of triangles. This may or may not involve inserting or deleting a */
7846/* vertex. */
7847/* */
7848/* The term "casing" is used to describe the set of triangles that are */
7849/* attached to the triangles being transformed, but are not transformed */
7850/* themselves. Think of the casing as a fixed hollow structure inside */
7851/* which all the action happens. A "casing" is only defined relative to */
7852/* a single transformation; each occurrence of a transformation will */
7853/* involve a different casing. */
7854/* */
7855/*****************************************************************************/
7856
7857/*****************************************************************************/
7858/* */
7859/* flip() Transform two triangles to two different triangles by flipping */
7860/* an edge counterclockwise within a quadrilateral. */
7861/* */
7862/* Imagine the original triangles, abc and bad, oriented so that the */
7863/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
7864/* and the vertex a on the right. The vertex c lies below the edge, and */
7865/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
7866/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
7867/* */
7868/* The triangles abc and bad are deleted and replaced by the triangles cdb */
7869/* and dca. The triangles that represent abc and bad are NOT deallocated; */
7870/* they are reused for dca and cdb, respectively. Hence, any handles that */
7871/* may have held the original triangles are still valid, although not */
7872/* directed as they were before. */
7873/* */
7874/* Upon completion of this routine, the `flipedge' handle holds the edge */
7875/* dc of triangle dca, and is directed down, from vertex d to vertex c. */
7876/* (Hence, the two triangles have rotated counterclockwise.) */
7877/* */
7878/* WARNING: This transformation is geometrically valid only if the */
7879/* quadrilateral adbc is convex. Furthermore, this transformation is */
7880/* valid only if there is not a subsegment between the triangles abc and */
7881/* bad. This routine does not check either of these preconditions, and */
7882/* it is the responsibility of the calling routine to ensure that they are */
7883/* met. If they are not, the streets shall be filled with wailing and */
7884/* gnashing of teeth. */
7885/* */
7886/*****************************************************************************/
7887
7888#ifdef ANSI_DECLARATORS
7889void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
7890#else /* not ANSI_DECLARATORS */
7891void flip(m, b, flipedge)
7892struct mesh *m;
7893struct behavior *b;
7894struct otri *flipedge; /* Handle for the triangle abc. */
7895#endif /* not ANSI_DECLARATORS */
7896
7897{
7898 struct otri botleft, botright;
7899 struct otri topleft, topright;
7900 struct otri top;
7901 struct otri botlcasing, botrcasing;
7902 struct otri toplcasing, toprcasing;
7903 struct osub botlsubseg, botrsubseg;
7904 struct osub toplsubseg, toprsubseg;
7905 vertex leftvertex, rightvertex, botvertex;
7906 vertex farvertex;
7907 triangle ptr; /* Temporary variable used by sym(). */
7908 subseg sptr; /* Temporary variable used by tspivot(). */
7909
7910 /* Identify the vertices of the quadrilateral. */
7911 org(*flipedge, rightvertex);
7912 dest(*flipedge, leftvertex);
7913 apex(*flipedge, botvertex);
7914 sym(*flipedge, top);
7915#ifdef SELF_CHECK
7916 if (top.tri == m->dummytri) {
7917 printf("Internal error in flip(): Attempt to flip on boundary.\n");
7918 lnextself(*flipedge);
7919 return;
7920 }
7921 if (m->checksegments) {
7922 tspivot(*flipedge, toplsubseg);
7923 if (toplsubseg.ss != m->dummysub) {
7924 printf("Internal error in flip(): Attempt to flip a segment.\n");
7925 lnextself(*flipedge);
7926 return;
7927 }
7928 }
7929#endif /* SELF_CHECK */
7930 apex(top, farvertex);
7931
7932 /* Identify the casing of the quadrilateral. */
7933 lprev(top, topleft);
7934 sym(topleft, toplcasing);
7935 lnext(top, topright);
7936 sym(topright, toprcasing);
7937 lnext(*flipedge, botleft);
7938 sym(botleft, botlcasing);
7939 lprev(*flipedge, botright);
7940 sym(botright, botrcasing);
7941 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
7942 bond(topleft, botlcasing);
7943 bond(botleft, botrcasing);
7944 bond(botright, toprcasing);
7945 bond(topright, toplcasing);
7946
7947 if (m->checksegments) {
7948 /* Check for subsegments and rebond them to the quadrilateral. */
7949 tspivot(topleft, toplsubseg);
7950 tspivot(botleft, botlsubseg);
7951 tspivot(botright, botrsubseg);
7952 tspivot(topright, toprsubseg);
7953 if (toplsubseg.ss == m->dummysub) {
7954 tsdissolve(topright);
7955 } else {
7956 tsbond(topright, toplsubseg);
7957 }
7958 if (botlsubseg.ss == m->dummysub) {
7959 tsdissolve(topleft);
7960 } else {
7961 tsbond(topleft, botlsubseg);
7962 }
7963 if (botrsubseg.ss == m->dummysub) {
7964 tsdissolve(botleft);
7965 } else {
7966 tsbond(botleft, botrsubseg);
7967 }
7968 if (toprsubseg.ss == m->dummysub) {
7969 tsdissolve(botright);
7970 } else {
7971 tsbond(botright, toprsubseg);
7972 }
7973 }
7974
7975 /* New vertex assignments for the rotated quadrilateral. */
7976 setorg(*flipedge, farvertex);
7977 setdest(*flipedge, botvertex);
7978 setapex(*flipedge, rightvertex);
7979 setorg(top, botvertex);
7980 setdest(top, farvertex);
7981 setapex(top, leftvertex);
7982 if (b->verbose > 2) {
7983 printf(" Edge flip results in left ");
7984 printtriangle(m, b, &top);
7985 printf(" and right ");
7986 printtriangle(m, b, flipedge);
7987 }
7988}
7989
7990/*****************************************************************************/
7991/* */
7992/* unflip() Transform two triangles to two different triangles by */
7993/* flipping an edge clockwise within a quadrilateral. Reverses */
7994/* the flip() operation so that the data structures representing */
7995/* the triangles are back where they were before the flip(). */
7996/* */
7997/* Imagine the original triangles, abc and bad, oriented so that the */
7998/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
7999/* and the vertex a on the right. The vertex c lies below the edge, and */
8000/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
8001/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
8002/* */
8003/* The triangles abc and bad are deleted and replaced by the triangles cdb */
8004/* and dca. The triangles that represent abc and bad are NOT deallocated; */
8005/* they are reused for cdb and dca, respectively. Hence, any handles that */
8006/* may have held the original triangles are still valid, although not */
8007/* directed as they were before. */
8008/* */
8009/* Upon completion of this routine, the `flipedge' handle holds the edge */
8010/* cd of triangle cdb, and is directed up, from vertex c to vertex d. */
8011/* (Hence, the two triangles have rotated clockwise.) */
8012/* */
8013/* WARNING: This transformation is geometrically valid only if the */
8014/* quadrilateral adbc is convex. Furthermore, this transformation is */
8015/* valid only if there is not a subsegment between the triangles abc and */
8016/* bad. This routine does not check either of these preconditions, and */
8017/* it is the responsibility of the calling routine to ensure that they are */
8018/* met. If they are not, the streets shall be filled with wailing and */
8019/* gnashing of teeth. */
8020/* */
8021/*****************************************************************************/
8022
8023#ifdef ANSI_DECLARATORS
8024void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
8025#else /* not ANSI_DECLARATORS */
8026void unflip(m, b, flipedge)
8027struct mesh *m;
8028struct behavior *b;
8029struct otri *flipedge; /* Handle for the triangle abc. */
8030#endif /* not ANSI_DECLARATORS */
8031
8032{
8033 struct otri botleft, botright;
8034 struct otri topleft, topright;
8035 struct otri top;
8036 struct otri botlcasing, botrcasing;
8037 struct otri toplcasing, toprcasing;
8038 struct osub botlsubseg, botrsubseg;
8039 struct osub toplsubseg, toprsubseg;
8040 vertex leftvertex, rightvertex, botvertex;
8041 vertex farvertex;
8042 triangle ptr; /* Temporary variable used by sym(). */
8043 subseg sptr; /* Temporary variable used by tspivot(). */
8044
8045 /* Identify the vertices of the quadrilateral. */
8046 org(*flipedge, rightvertex);
8047 dest(*flipedge, leftvertex);
8048 apex(*flipedge, botvertex);
8049 sym(*flipedge, top);
8050#ifdef SELF_CHECK
8051 if (top.tri == m->dummytri) {
8052 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
8053 lnextself(*flipedge);
8054 return;
8055 }
8056 if (m->checksegments) {
8057 tspivot(*flipedge, toplsubseg);
8058 if (toplsubseg.ss != m->dummysub) {
8059 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
8060 lnextself(*flipedge);
8061 return;
8062 }
8063 }
8064#endif /* SELF_CHECK */
8065 apex(top, farvertex);
8066
8067 /* Identify the casing of the quadrilateral. */
8068 lprev(top, topleft);
8069 sym(topleft, toplcasing);
8070 lnext(top, topright);
8071 sym(topright, toprcasing);
8072 lnext(*flipedge, botleft);
8073 sym(botleft, botlcasing);
8074 lprev(*flipedge, botright);
8075 sym(botright, botrcasing);
8076 /* Rotate the quadrilateral one-quarter turn clockwise. */
8077 bond(topleft, toprcasing);
8078 bond(botleft, toplcasing);
8079 bond(botright, botlcasing);
8080 bond(topright, botrcasing);
8081
8082 if (m->checksegments) {
8083 /* Check for subsegments and rebond them to the quadrilateral. */
8084 tspivot(topleft, toplsubseg);
8085 tspivot(botleft, botlsubseg);
8086 tspivot(botright, botrsubseg);
8087 tspivot(topright, toprsubseg);
8088 if (toplsubseg.ss == m->dummysub) {
8089 tsdissolve(botleft);
8090 } else {
8091 tsbond(botleft, toplsubseg);
8092 }
8093 if (botlsubseg.ss == m->dummysub) {
8094 tsdissolve(botright);
8095 } else {
8096 tsbond(botright, botlsubseg);
8097 }
8098 if (botrsubseg.ss == m->dummysub) {
8099 tsdissolve(topright);
8100 } else {
8101 tsbond(topright, botrsubseg);
8102 }
8103 if (toprsubseg.ss == m->dummysub) {
8104 tsdissolve(topleft);
8105 } else {
8106 tsbond(topleft, toprsubseg);
8107 }
8108 }
8109
8110 /* New vertex assignments for the rotated quadrilateral. */
8111 setorg(*flipedge, botvertex);
8112 setdest(*flipedge, farvertex);
8113 setapex(*flipedge, leftvertex);
8114 setorg(top, farvertex);
8115 setdest(top, botvertex);
8116 setapex(top, rightvertex);
8117 if (b->verbose > 2) {
8118 printf(" Edge unflip results in left ");
8119 printtriangle(m, b, flipedge);
8120 printf(" and right ");
8121 printtriangle(m, b, &top);
8122 }
8123}
8124
8125/*****************************************************************************/
8126/* */
8127/* insertvertex() Insert a vertex into a Delaunay triangulation, */
8128/* performing flips as necessary to maintain the Delaunay */
8129/* property. */
8130/* */
8131/* The point `insertvertex' is located. If `searchtri.tri' is not NULL, */
8132/* the search for the containing triangle begins from `searchtri'. If */
8133/* `searchtri.tri' is NULL, a full point location procedure is called. */
8134/* If `insertvertex' is found inside a triangle, the triangle is split into */
8135/* three; if `insertvertex' lies on an edge, the edge is split in two, */
8136/* thereby splitting the two adjacent triangles into four. Edge flips are */
8137/* used to restore the Delaunay property. If `insertvertex' lies on an */
8138/* existing vertex, no action is taken, and the value DUPLICATEVERTEX is */
8139/* returned. On return, `searchtri' is set to a handle whose origin is the */
8140/* existing vertex. */
8141/* */
8142/* Normally, the parameter `splitseg' is set to NULL, implying that no */
8143/* subsegment should be split. In this case, if `insertvertex' is found to */
8144/* lie on a segment, no action is taken, and the value VIOLATINGVERTEX is */
8145/* returned. On return, `searchtri' is set to a handle whose primary edge */
8146/* is the violated subsegment. */
8147/* */
8148/* If the calling routine wishes to split a subsegment by inserting a */
8149/* vertex in it, the parameter `splitseg' should be that subsegment. In */
8150/* this case, `searchtri' MUST be the triangle handle reached by pivoting */
8151/* from that subsegment; no point location is done. */
8152/* */
8153/* `segmentflaws' and `triflaws' are flags that indicate whether or not */
8154/* there should be checks for the creation of encroached subsegments or bad */
8155/* quality triangles. If a newly inserted vertex encroaches upon */
8156/* subsegments, these subsegments are added to the list of subsegments to */
8157/* be split if `segmentflaws' is set. If bad triangles are created, these */
8158/* are added to the queue if `triflaws' is set. */
8159/* */
8160/* If a duplicate vertex or violated segment does not prevent the vertex */
8161/* from being inserted, the return value will be ENCROACHINGVERTEX if the */
8162/* vertex encroaches upon a subsegment (and checking is enabled), or */
8163/* SUCCESSFULVERTEX otherwise. In either case, `searchtri' is set to a */
8164/* handle whose origin is the newly inserted vertex. */
8165/* */
8166/* insertvertex() does not use flip() for reasons of speed; some */
8167/* information can be reused from edge flip to edge flip, like the */
8168/* locations of subsegments. */
8169/* */
8170/*****************************************************************************/
8171
8172#ifdef ANSI_DECLARATORS
8173enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
8174 vertex newvertex, struct otri *searchtri,
8175 struct osub *splitseg,
8176 int segmentflaws, int triflaws )
8177#else /* not ANSI_DECLARATORS */
8178enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
8179 segmentflaws, triflaws)
8180struct mesh *m;
8181struct behavior *b;
8182vertex newvertex;
8183struct otri *searchtri;
8184struct osub *splitseg;
8185int segmentflaws;
8186int triflaws;
8187#endif /* not ANSI_DECLARATORS */
8188
8189{
8190
8191 struct otri horiz;
8192 struct otri top;
8193 struct otri botleft, botright;
8194 struct otri topleft, topright;
8195 struct otri newbotleft, newbotright;
8196 struct otri newtopright;
8197 struct otri botlcasing, botrcasing;
8198 struct otri toplcasing, toprcasing;
8199 struct otri testtri;
8200 struct osub botlsubseg, botrsubseg;
8201 struct osub toplsubseg, toprsubseg;
8202 struct osub brokensubseg;
8203 struct osub checksubseg;
8204 struct osub rightsubseg;
8205 struct osub newsubseg;
8206 struct badsubseg *encroached;
8207 struct flipstacker *newflip;
8208 vertex first;
8209 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
8210 vertex segmentorg, segmentdest;
8211 REAL attrib;
8212 REAL area;
8213 enum insertvertexresult success;
8214 enum locateresult intersect;
8215 int doflip;
8216 int mirrorflag;
8217 int enq;
8218 int i;
8219 triangle ptr; /* Temporary variable used by sym(). */
8220 subseg sptr; /* Temporary variable used by spivot() and tspivot(). */
8221
8222
8223 (void)triflaws; /*LM: added to suppress warning */
8224
8225 if (b->verbose > 1) {
8226 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
8227 }
8228
8229 if (splitseg == (struct osub *) NULL) {
8230 /* Find the location of the vertex to be inserted. Check if a good */
8231 /* starting triangle has already been provided by the caller. */
8232 if (searchtri->tri == m->dummytri) {
8233 /* Find a boundary triangle. */
8234 horiz.tri = m->dummytri;
8235 horiz.orient = 0;
8236 symself(horiz);
8237 /* Search for a triangle containing `newvertex'. */
8238 intersect = locate(m, b, newvertex, &horiz);
8239 } else {
8240 /* Start searching from the triangle provided by the caller. */
8241 otricopy(*searchtri, horiz);
8242 intersect = preciselocate(m, b, newvertex, &horiz, 1);
8243 }
8244 } else {
8245 /* The calling routine provides the subsegment in which */
8246 /* the vertex is inserted. */
8247 otricopy(*searchtri, horiz);
8248 intersect = ONEDGE;
8249 }
8250
8251 if (intersect == ONVERTEX) {
8252 /* There's already a vertex there. Return in `searchtri' a triangle */
8253 /* whose origin is the existing vertex. */
8254 otricopy(horiz, *searchtri);
8255 otricopy(horiz, m->recenttri);
8256 return DUPLICATEVERTEX;
8257 }
8258 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
8259 /* The vertex falls on an edge or boundary. */
8260 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
8261 /* Check whether the vertex falls on a subsegment. */
8262 tspivot(horiz, brokensubseg);
8263 if (brokensubseg.ss != m->dummysub) {
8264 /* The vertex falls on a subsegment, and hence will not be inserted. */
8265 if (segmentflaws) {
8266 enq = b->nobisect != 2;
8267 if (enq && (b->nobisect == 1)) {
8268 /* This subsegment may be split only if it is an */
8269 /* internal boundary. */
8270 sym(horiz, testtri);
8271 enq = testtri.tri != m->dummytri;
8272 }
8273 if (enq) {
8274 /* Add the subsegment to the list of encroached subsegments. */
8275 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
8276 encroached->encsubseg = sencode(brokensubseg);
8277 sorg(brokensubseg, encroached->subsegorg);
8278 sdest(brokensubseg, encroached->subsegdest);
8279 if (b->verbose > 2) {
8280 printf(
8281 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
8282 encroached->subsegorg[0], encroached->subsegorg[1],
8283 encroached->subsegdest[0], encroached->subsegdest[1]);
8284 }
8285 }
8286 }
8287 /* Return a handle whose primary edge contains the vertex, */
8288 /* which has not been inserted. */
8289 otricopy(horiz, *searchtri);
8290 otricopy(horiz, m->recenttri);
8291 return VIOLATINGVERTEX;
8292 }
8293 }
8294
8295 /* Insert the vertex on an edge, dividing one triangle into two (if */
8296 /* the edge lies on a boundary) or two triangles into four. */
8297 lprev(horiz, botright);
8298 sym(botright, botrcasing);
8299 sym(horiz, topright);
8300 /* Is there a second triangle? (Or does this edge lie on a boundary?) */
8301 mirrorflag = topright.tri != m->dummytri;
8302 if (mirrorflag) {
8303 lnextself(topright);
8304 sym(topright, toprcasing);
8305 maketriangle(m, b, &newtopright);
8306 } else {
8307 /* Splitting a boundary edge increases the number of boundary edges. */
8308 m->hullsize++;
8309 }
8310 maketriangle(m, b, &newbotright);
8311
8312 /* Set the vertices of changed and new triangles. */
8313 org(horiz, rightvertex);
8314 dest(horiz, leftvertex);
8315 apex(horiz, botvertex);
8316 setorg(newbotright, botvertex);
8317 setdest(newbotright, rightvertex);
8318 setapex(newbotright, newvertex);
8319 setorg(horiz, newvertex);
8320 for (i = 0; i < m->eextras; i++) {
8321 /* Set the element attributes of a new triangle. */
8322 setelemattribute(newbotright, i, elemattribute(botright, i));
8323 }
8324 if (b->vararea) {
8325 /* Set the area constraint of a new triangle. */
8326 setareabound(newbotright, areabound(botright));
8327 }
8328 if (mirrorflag) {
8329 dest(topright, topvertex);
8330 setorg(newtopright, rightvertex);
8331 setdest(newtopright, topvertex);
8332 setapex(newtopright, newvertex);
8333 setorg(topright, newvertex);
8334 for (i = 0; i < m->eextras; i++) {
8335 /* Set the element attributes of another new triangle. */
8336 setelemattribute(newtopright, i, elemattribute(topright, i));
8337 }
8338 if (b->vararea) {
8339 /* Set the area constraint of another new triangle. */
8340 setareabound(newtopright, areabound(topright));
8341 }
8342 }
8343
8344 /* There may be subsegments that need to be bonded */
8345 /* to the new triangle(s). */
8346 if (m->checksegments) {
8347 tspivot(botright, botrsubseg);
8348 if (botrsubseg.ss != m->dummysub) {
8349 tsdissolve(botright);
8350 tsbond(newbotright, botrsubseg);
8351 }
8352 if (mirrorflag) {
8353 tspivot(topright, toprsubseg);
8354 if (toprsubseg.ss != m->dummysub) {
8355 tsdissolve(topright);
8356 tsbond(newtopright, toprsubseg);
8357 }
8358 }
8359 }
8360
8361 /* Bond the new triangle(s) to the surrounding triangles. */
8362 bond(newbotright, botrcasing);
8363 lprevself(newbotright);
8364 bond(newbotright, botright);
8365 lprevself(newbotright);
8366 if (mirrorflag) {
8367 bond(newtopright, toprcasing);
8368 lnextself(newtopright);
8369 bond(newtopright, topright);
8370 lnextself(newtopright);
8371 bond(newtopright, newbotright);
8372 }
8373
8374 if (splitseg != (struct osub *) NULL) {
8375 /* Split the subsegment into two. */
8376 setsdest(*splitseg, newvertex);
8377 segorg(*splitseg, segmentorg);
8378 segdest(*splitseg, segmentdest);
8379 ssymself(*splitseg);
8380 spivot(*splitseg, rightsubseg);
8381 insertsubseg(m, b, &newbotright, mark(*splitseg));
8382 tspivot(newbotright, newsubseg);
8383 setsegorg(newsubseg, segmentorg);
8384 setsegdest(newsubseg, segmentdest);
8385 sbond(*splitseg, newsubseg);
8386 ssymself(newsubseg);
8387 sbond(newsubseg, rightsubseg);
8388 ssymself(*splitseg);
8389 /* Transfer the subsegment's boundary marker to the vertex */
8390 /* if required. */
8391 if (vertexmark(newvertex) == 0) {
8392 setvertexmark(newvertex, mark(*splitseg));
8393 }
8394 }
8395
8396 if (m->checkquality) {
8397 poolrestart(&m->flipstackers);
8398 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8399 m->lastflip->flippedtri = encode(horiz);
8400 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
8401 }
8402
8403#ifdef SELF_CHECK
8404 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
8405 printf("Internal error in insertvertex():\n");
8406 printf(
8407 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
8408 }
8409 if (mirrorflag) {
8410 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
8411 printf("Internal error in insertvertex():\n");
8412 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
8413 }
8414 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
8415 printf("Internal error in insertvertex():\n");
8416 printf(
8417 " Clockwise triangle after edge vertex insertion (top right).\n");
8418 }
8419 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
8420 printf("Internal error in insertvertex():\n");
8421 printf(
8422 " Clockwise triangle after edge vertex insertion (top left).\n");
8423 }
8424 }
8425 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
8426 printf("Internal error in insertvertex():\n");
8427 printf(
8428 " Clockwise triangle after edge vertex insertion (bottom left).\n");
8429 }
8430 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
8431 printf("Internal error in insertvertex():\n");
8432 printf(
8433 " Clockwise triangle after edge vertex insertion (bottom right).\n");
8434 }
8435#endif /* SELF_CHECK */
8436 if (b->verbose > 2) {
8437 printf(" Updating bottom left ");
8438 printtriangle(m, b, &botright);
8439 if (mirrorflag) {
8440 printf(" Updating top left ");
8441 printtriangle(m, b, &topright);
8442 printf(" Creating top right ");
8443 printtriangle(m, b, &newtopright);
8444 }
8445 printf(" Creating bottom right ");
8446 printtriangle(m, b, &newbotright);
8447 }
8448
8449 /* Position `horiz' on the first edge to check for */
8450 /* the Delaunay property. */
8451 lnextself(horiz);
8452 } else {
8453 /* Insert the vertex in a triangle, splitting it into three. */
8454 lnext(horiz, botleft);
8455 lprev(horiz, botright);
8456 sym(botleft, botlcasing);
8457 sym(botright, botrcasing);
8458 maketriangle(m, b, &newbotleft);
8459 maketriangle(m, b, &newbotright);
8460
8461 /* Set the vertices of changed and new triangles. */
8462 org(horiz, rightvertex);
8463 dest(horiz, leftvertex);
8464 apex(horiz, botvertex);
8465 setorg(newbotleft, leftvertex);
8466 setdest(newbotleft, botvertex);
8467 setapex(newbotleft, newvertex);
8468 setorg(newbotright, botvertex);
8469 setdest(newbotright, rightvertex);
8470 setapex(newbotright, newvertex);
8471 setapex(horiz, newvertex);
8472 for (i = 0; i < m->eextras; i++) {
8473 /* Set the element attributes of the new triangles. */
8474 attrib = elemattribute(horiz, i);
8475 setelemattribute(newbotleft, i, attrib);
8476 setelemattribute(newbotright, i, attrib);
8477 }
8478 if (b->vararea) {
8479 /* Set the area constraint of the new triangles. */
8480 area = areabound(horiz);
8481 setareabound(newbotleft, area);
8482 setareabound(newbotright, area);
8483 }
8484
8485 /* There may be subsegments that need to be bonded */
8486 /* to the new triangles. */
8487 if (m->checksegments) {
8488 tspivot(botleft, botlsubseg);
8489 if (botlsubseg.ss != m->dummysub) {
8490 tsdissolve(botleft);
8491 tsbond(newbotleft, botlsubseg);
8492 }
8493 tspivot(botright, botrsubseg);
8494 if (botrsubseg.ss != m->dummysub) {
8495 tsdissolve(botright);
8496 tsbond(newbotright, botrsubseg);
8497 }
8498 }
8499
8500 /* Bond the new triangles to the surrounding triangles. */
8501 bond(newbotleft, botlcasing);
8502 bond(newbotright, botrcasing);
8503 lnextself(newbotleft);
8504 lprevself(newbotright);
8505 bond(newbotleft, newbotright);
8506 lnextself(newbotleft);
8507 bond(botleft, newbotleft);
8508 lprevself(newbotright);
8509 bond(botright, newbotright);
8510
8511 if (m->checkquality) {
8512 poolrestart(&m->flipstackers);
8513 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8514 m->lastflip->flippedtri = encode(horiz);
8515 m->lastflip->prevflip = (struct flipstacker *) NULL;
8516 }
8517
8518#ifdef SELF_CHECK
8519 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
8520 printf("Internal error in insertvertex():\n");
8521 printf(" Clockwise triangle prior to vertex insertion.\n");
8522 }
8523 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
8524 printf("Internal error in insertvertex():\n");
8525 printf(" Clockwise triangle after vertex insertion (top).\n");
8526 }
8527 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
8528 printf("Internal error in insertvertex():\n");
8529 printf(" Clockwise triangle after vertex insertion (left).\n");
8530 }
8531 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
8532 printf("Internal error in insertvertex():\n");
8533 printf(" Clockwise triangle after vertex insertion (right).\n");
8534 }
8535#endif /* SELF_CHECK */
8536 if (b->verbose > 2) {
8537 printf(" Updating top ");
8538 printtriangle(m, b, &horiz);
8539 printf(" Creating left ");
8540 printtriangle(m, b, &newbotleft);
8541 printf(" Creating right ");
8542 printtriangle(m, b, &newbotright);
8543 }
8544 }
8545
8546 /* The insertion is successful by default, unless an encroached */
8547 /* subsegment is found. */
8548 success = SUCCESSFULVERTEX;
8549 /* Circle around the newly inserted vertex, checking each edge opposite */
8550 /* it for the Delaunay property. Non-Delaunay edges are flipped. */
8551 /* `horiz' is always the edge being checked. `first' marks where to */
8552 /* stop circling. */
8553 org(horiz, first);
8554 rightvertex = first;
8555 dest(horiz, leftvertex);
8556 /* Circle until finished. */
8557 while (1) {
8558 /* By default, the edge will be flipped. */
8559 doflip = 1;
8560
8561 if (m->checksegments) {
8562 /* Check for a subsegment, which cannot be flipped. */
8563 tspivot(horiz, checksubseg);
8564 if (checksubseg.ss != m->dummysub) {
8565 /* The edge is a subsegment and cannot be flipped. */
8566 doflip = 0;
8567#ifndef CDT_ONLY
8568 if (segmentflaws) {
8569 /* Does the new vertex encroach upon this subsegment? */
8570 if (checkseg4encroach(m, b, &checksubseg)) {
8571 success = ENCROACHINGVERTEX;
8572 }
8573 }
8574#endif /* not CDT_ONLY */
8575 }
8576 }
8577
8578 if (doflip) {
8579 /* Check if the edge is a boundary edge. */
8580 sym(horiz, top);
8581 if (top.tri == m->dummytri) {
8582 /* The edge is a boundary edge and cannot be flipped. */
8583 doflip = 0;
8584 } else {
8585 /* Find the vertex on the other side of the edge. */
8586 apex(top, farvertex);
8587 /* In the incremental Delaunay triangulation algorithm, any of */
8588 /* `leftvertex', `rightvertex', and `farvertex' could be vertices */
8589 /* of the triangular bounding box. These vertices must be */
8590 /* treated as if they are infinitely distant, even though their */
8591 /* "coordinates" are not. */
8592 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
8593 (leftvertex == m->infvertex3)) {
8594 /* `leftvertex' is infinitely distant. Check the convexity of */
8595 /* the boundary of the triangulation. 'farvertex' might be */
8596 /* infinite as well, but trust me, this same condition should */
8597 /* be applied. */
8598 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
8599 > 0.0;
8600 } else if ((rightvertex == m->infvertex1) ||
8601 (rightvertex == m->infvertex2) ||
8602 (rightvertex == m->infvertex3)) {
8603 /* `rightvertex' is infinitely distant. Check the convexity of */
8604 /* the boundary of the triangulation. 'farvertex' might be */
8605 /* infinite as well, but trust me, this same condition should */
8606 /* be applied. */
8607 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
8608 > 0.0;
8609 } else if ((farvertex == m->infvertex1) ||
8610 (farvertex == m->infvertex2) ||
8611 (farvertex == m->infvertex3)) {
8612 /* `farvertex' is infinitely distant and cannot be inside */
8613 /* the circumcircle of the triangle `horiz'. */
8614 doflip = 0;
8615 } else {
8616 /* Test whether the edge is locally Delaunay. */
8617 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
8618 farvertex) > 0.0;
8619 }
8620 if (doflip) {
8621 /* We made it! Flip the edge `horiz' by rotating its containing */
8622 /* quadrilateral (the two triangles adjacent to `horiz'). */
8623 /* Identify the casing of the quadrilateral. */
8624 lprev(top, topleft);
8625 sym(topleft, toplcasing);
8626 lnext(top, topright);
8627 sym(topright, toprcasing);
8628 lnext(horiz, botleft);
8629 sym(botleft, botlcasing);
8630 lprev(horiz, botright);
8631 sym(botright, botrcasing);
8632 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
8633 bond(topleft, botlcasing);
8634 bond(botleft, botrcasing);
8635 bond(botright, toprcasing);
8636 bond(topright, toplcasing);
8637 if (m->checksegments) {
8638 /* Check for subsegments and rebond them to the quadrilateral. */
8639 tspivot(topleft, toplsubseg);
8640 tspivot(botleft, botlsubseg);
8641 tspivot(botright, botrsubseg);
8642 tspivot(topright, toprsubseg);
8643 if (toplsubseg.ss == m->dummysub) {
8644 tsdissolve(topright);
8645 } else {
8646 tsbond(topright, toplsubseg);
8647 }
8648 if (botlsubseg.ss == m->dummysub) {
8649 tsdissolve(topleft);
8650 } else {
8651 tsbond(topleft, botlsubseg);
8652 }
8653 if (botrsubseg.ss == m->dummysub) {
8654 tsdissolve(botleft);
8655 } else {
8656 tsbond(botleft, botrsubseg);
8657 }
8658 if (toprsubseg.ss == m->dummysub) {
8659 tsdissolve(botright);
8660 } else {
8661 tsbond(botright, toprsubseg);
8662 }
8663 }
8664 /* New vertex assignments for the rotated quadrilateral. */
8665 setorg(horiz, farvertex);
8666 setdest(horiz, newvertex);
8667 setapex(horiz, rightvertex);
8668 setorg(top, newvertex);
8669 setdest(top, farvertex);
8670 setapex(top, leftvertex);
8671 for (i = 0; i < m->eextras; i++) {
8672 /* Take the average of the two triangles' attributes. */
8673 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
8674 setelemattribute(top, i, attrib);
8675 setelemattribute(horiz, i, attrib);
8676 }
8677 if (b->vararea) {
8678 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
8679 area = -1.0;
8680 } else {
8681 /* Take the average of the two triangles' area constraints. */
8682 /* This prevents small area constraints from migrating a */
8683 /* long, long way from their original location due to flips. */
8684 area = 0.5 * (areabound(top) + areabound(horiz));
8685 }
8686 setareabound(top, area);
8687 setareabound(horiz, area);
8688 }
8689
8690 if (m->checkquality) {
8691 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8692 newflip->flippedtri = encode(horiz);
8693 newflip->prevflip = m->lastflip;
8694 m->lastflip = newflip;
8695 }
8696
8697#ifdef SELF_CHECK
8698 if (newvertex != (vertex) NULL) {
8699 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
8700 0.0) {
8701 printf("Internal error in insertvertex():\n");
8702 printf(" Clockwise triangle prior to edge flip (bottom).\n");
8703 }
8704 /* The following test has been removed because constrainededge() */
8705 /* sometimes generates inverted triangles that insertvertex() */
8706 /* removes. */
8707/*
8708 if (counterclockwise(m, b, rightvertex, farvertex, leftvertex) <
8709 0.0) {
8710 printf("Internal error in insertvertex():\n");
8711 printf(" Clockwise triangle prior to edge flip (top).\n");
8712 }
8713*/
8714 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
8715 0.0) {
8716 printf("Internal error in insertvertex():\n");
8717 printf(" Clockwise triangle after edge flip (left).\n");
8718 }
8719 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
8720 0.0) {
8721 printf("Internal error in insertvertex():\n");
8722 printf(" Clockwise triangle after edge flip (right).\n");
8723 }
8724 }
8725#endif /* SELF_CHECK */
8726 if (b->verbose > 2) {
8727 printf(" Edge flip results in left ");
8728 lnextself(topleft);
8729 printtriangle(m, b, &topleft);
8730 printf(" and right ");
8731 printtriangle(m, b, &horiz);
8732 }
8733 /* On the next iterations, consider the two edges that were */
8734 /* exposed (this is, are now visible to the newly inserted */
8735 /* vertex) by the edge flip. */
8736 lprevself(horiz);
8737 leftvertex = farvertex;
8738 }
8739 }
8740 }
8741 if (!doflip) {
8742 /* The handle `horiz' is accepted as locally Delaunay. */
8743#ifndef CDT_ONLY
8744 if (triflaws) {
8745 /* Check the triangle `horiz' for quality. */
8746 testtriangle(m, b, &horiz);
8747 }
8748#endif /* not CDT_ONLY */
8749 /* Look for the next edge around the newly inserted vertex. */
8750 lnextself(horiz);
8751 sym(horiz, testtri);
8752 /* Check for finishing a complete revolution about the new vertex, or */
8753 /* falling outside of the triangulation. The latter will happen */
8754 /* when a vertex is inserted at a boundary. */
8755 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
8756 /* We're done. Return a triangle whose origin is the new vertex. */
8757 lnext(horiz, *searchtri);
8758 lnext(horiz, m->recenttri);
8759 return success;
8760 }
8761 /* Finish finding the next edge around the newly inserted vertex. */
8762 lnext(testtri, horiz);
8763 rightvertex = leftvertex;
8764 dest(horiz, leftvertex);
8765 }
8766 }
8767}
8768
8769/*****************************************************************************/
8770/* */
8771/* triangulatepolygon() Find the Delaunay triangulation of a polygon that */
8772/* has a certain "nice" shape. This includes the */
8773/* polygons that result from deletion of a vertex or */
8774/* insertion of a segment. */
8775/* */
8776/* This is a conceptually difficult routine. The starting assumption is */
8777/* that we have a polygon with n sides. n - 1 of these sides are currently */
8778/* represented as edges in the mesh. One side, called the "base", need not */
8779/* be. */
8780/* */
8781/* Inside the polygon is a structure I call a "fan", consisting of n - 1 */
8782/* triangles that share a common origin. For each of these triangles, the */
8783/* edge opposite the origin is one of the sides of the polygon. The */
8784/* primary edge of each triangle is the edge directed from the origin to */
8785/* the destination; note that this is not the same edge that is a side of */
8786/* the polygon. `firstedge' is the primary edge of the first triangle. */
8787/* From there, the triangles follow in counterclockwise order about the */
8788/* polygon, until `lastedge', the primary edge of the last triangle. */
8789/* `firstedge' and `lastedge' are probably connected to other triangles */
8790/* beyond the extremes of the fan, but their identity is not important, as */
8791/* long as the fan remains connected to them. */
8792/* */
8793/* Imagine the polygon oriented so that its base is at the bottom. This */
8794/* puts `firstedge' on the far right, and `lastedge' on the far left. */
8795/* The right vertex of the base is the destination of `firstedge', and the */
8796/* left vertex of the base is the apex of `lastedge'. */
8797/* */
8798/* The challenge now is to find the right sequence of edge flips to */
8799/* transform the fan into a Delaunay triangulation of the polygon. Each */
8800/* edge flip effectively removes one triangle from the fan, committing it */
8801/* to the polygon. The resulting polygon has one fewer edge. If `doflip' */
8802/* is set, the final flip will be performed, resulting in a fan of one */
8803/* (useless?) triangle. If `doflip' is not set, the final flip is not */
8804/* performed, resulting in a fan of two triangles, and an unfinished */
8805/* triangular polygon that is not yet filled out with a single triangle. */
8806/* On completion of the routine, `lastedge' is the last remaining triangle, */
8807/* or the leftmost of the last two. */
8808/* */
8809/* Although the flips are performed in the order described above, the */
8810/* decisions about what flips to perform are made in precisely the reverse */
8811/* order. The recursive triangulatepolygon() procedure makes a decision, */
8812/* uses up to two recursive calls to triangulate the "subproblems" */
8813/* (polygons with fewer edges), and then performs an edge flip. */
8814/* */
8815/* The "decision" it makes is which vertex of the polygon should be */
8816/* connected to the base. This decision is made by testing every possible */
8817/* vertex. Once the best vertex is found, the two edges that connect this */
8818/* vertex to the base become the bases for two smaller polygons. These */
8819/* are triangulated recursively. Unfortunately, this approach can take */
8820/* O(n^2) time not only in the worst case, but in many common cases. It's */
8821/* rarely a big deal for vertex deletion, where n is rarely larger than */
8822/* ten, but it could be a big deal for segment insertion, especially if */
8823/* there's a lot of long segments that each cut many triangles. I ought to */
8824/* code a faster algorithm some day. */
8825/* */
8826/* The `edgecount' parameter is the number of sides of the polygon, */
8827/* including its base. `triflaws' is a flag that determines whether the */
8828/* new triangles should be tested for quality, and enqueued if they are */
8829/* bad. */
8830/* */
8831/*****************************************************************************/
8832
8833#ifdef ANSI_DECLARATORS
8834void triangulatepolygon(struct mesh *m, struct behavior *b,
8835 struct otri *firstedge, struct otri *lastedge,
8836 int edgecount, int doflip, int triflaws)
8837#else /* not ANSI_DECLARATORS */
8838void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
8839struct mesh *m;
8840struct behavior *b;
8841struct otri *firstedge;
8842struct otri *lastedge;
8843int edgecount;
8844int doflip;
8845int triflaws;
8846#endif /* not ANSI_DECLARATORS */
8847
8848{
8849 struct otri testtri;
8850 struct otri besttri;
8851 struct otri tempedge;
8852 vertex leftbasevertex, rightbasevertex;
8853 vertex testvertex;
8854 vertex bestvertex;
8855 int bestnumber;
8856 int i;
8857 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8858
8859 /* Identify the base vertices. */
8860 apex(*lastedge, leftbasevertex);
8861 dest(*firstedge, rightbasevertex);
8862 if (b->verbose > 2) {
8863 printf(" Triangulating interior polygon at edge\n");
8864 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
8865 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
8866 }
8867 /* Find the best vertex to connect the base to. */
8868 onext(*firstedge, besttri);
8869 dest(besttri, bestvertex);
8870 otricopy(besttri, testtri);
8871 bestnumber = 1;
8872 for (i = 2; i <= edgecount - 2; i++) {
8873 onextself(testtri);
8874 dest(testtri, testvertex);
8875 /* Is this a better vertex? */
8876 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
8877 testvertex) > 0.0) {
8878 otricopy(testtri, besttri);
8879 bestvertex = testvertex;
8880 bestnumber = i;
8881 }
8882 }
8883 if (b->verbose > 2) {
8884 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
8885 bestvertex[1]);
8886 }
8887 if (bestnumber > 1) {
8888 /* Recursively triangulate the smaller polygon on the right. */
8889 oprev(besttri, tempedge);
8890 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
8891 triflaws);
8892 }
8893 if (bestnumber < edgecount - 2) {
8894 /* Recursively triangulate the smaller polygon on the left. */
8895 sym(besttri, tempedge);
8896 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
8897 triflaws);
8898 /* Find `besttri' again; it may have been lost to edge flips. */
8899 sym(tempedge, besttri);
8900 }
8901 if (doflip) {
8902 /* Do one final edge flip. */
8903 flip(m, b, &besttri);
8904#ifndef CDT_ONLY
8905 if (triflaws) {
8906 /* Check the quality of the newly committed triangle. */
8907 sym(besttri, testtri);
8908 testtriangle(m, b, &testtri);
8909 }
8910#endif /* not CDT_ONLY */
8911 }
8912 /* Return the base triangle. */
8913 otricopy(besttri, *lastedge);
8914}
8915
8916/*****************************************************************************/
8917/* */
8918/* deletevertex() Delete a vertex from a Delaunay triangulation, ensuring */
8919/* that the triangulation remains Delaunay. */
8920/* */
8921/* The origin of `deltri' is deleted. The union of the triangles adjacent */
8922/* to this vertex is a polygon, for which the Delaunay triangulation is */
8923/* found. Two triangles are removed from the mesh. */
8924/* */
8925/* Only interior vertices that do not lie on segments or boundaries may be */
8926/* deleted. */
8927/* */
8928/*****************************************************************************/
8929
8930#ifndef CDT_ONLY
8931
8932#ifdef ANSI_DECLARATORS
8933void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
8934#else /* not ANSI_DECLARATORS */
8935void deletevertex(m, b, deltri)
8936struct mesh *m;
8937struct behavior *b;
8938struct otri *deltri;
8939#endif /* not ANSI_DECLARATORS */
8940
8941{
8942 struct otri countingtri;
8943 struct otri firstedge, lastedge;
8944 struct otri deltriright;
8945 struct otri lefttri, righttri;
8946 struct otri leftcasing, rightcasing;
8947 struct osub leftsubseg, rightsubseg;
8948 vertex delvertex;
8949 vertex neworg;
8950 int edgecount;
8951 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8952 subseg sptr; /* Temporary variable used by tspivot(). */
8953
8954 org(*deltri, delvertex);
8955 if (b->verbose > 1) {
8956 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
8957 }
8958 vertexdealloc(m, delvertex);
8959
8960 /* Count the degree of the vertex being deleted. */
8961 onext(*deltri, countingtri);
8962 edgecount = 1;
8963 while (!otriequal(*deltri, countingtri)) {
8964#ifdef SELF_CHECK
8965 if (countingtri.tri == m->dummytri) {
8966 printf("Internal error in deletevertex():\n");
8967 printf(" Attempt to delete boundary vertex.\n");
8968 internalerror();
8969 }
8970#endif /* SELF_CHECK */
8971 edgecount++;
8972 onextself(countingtri);
8973 }
8974
8975#ifdef SELF_CHECK
8976 if (edgecount < 3) {
8977 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
8978 edgecount);
8979 internalerror();
8980 }
8981#endif /* SELF_CHECK */
8982 if (edgecount > 3) {
8983 /* Triangulate the polygon defined by the union of all triangles */
8984 /* adjacent to the vertex being deleted. Check the quality of */
8985 /* the resulting triangles. */
8986 onext(*deltri, firstedge);
8987 oprev(*deltri, lastedge);
8988 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
8989 !b->nobisect);
8990 }
8991 /* Splice out two triangles. */
8992 lprev(*deltri, deltriright);
8993 dnext(*deltri, lefttri);
8994 sym(lefttri, leftcasing);
8995 oprev(deltriright, righttri);
8996 sym(righttri, rightcasing);
8997 bond(*deltri, leftcasing);
8998 bond(deltriright, rightcasing);
8999 tspivot(lefttri, leftsubseg);
9000 if (leftsubseg.ss != m->dummysub) {
9001 tsbond(*deltri, leftsubseg);
9002 }
9003 tspivot(righttri, rightsubseg);
9004 if (rightsubseg.ss != m->dummysub) {
9005 tsbond(deltriright, rightsubseg);
9006 }
9007
9008 /* Set the new origin of `deltri' and check its quality. */
9009 org(lefttri, neworg);
9010 setorg(*deltri, neworg);
9011 if (!b->nobisect) {
9012 testtriangle(m, b, deltri);
9013 }
9014
9015 /* Delete the two spliced-out triangles. */
9016 triangledealloc(m, lefttri.tri);
9017 triangledealloc(m, righttri.tri);
9018}
9019
9020#endif /* not CDT_ONLY */
9021
9022/*****************************************************************************/
9023/* */
9024/* undovertex() Undo the most recent vertex insertion. */
9025/* */
9026/* Walks through the list of transformations (flips and a vertex insertion) */
9027/* in the reverse of the order in which they were done, and undoes them. */
9028/* The inserted vertex is removed from the triangulation and deallocated. */
9029/* Two triangles (possibly just one) are also deallocated. */
9030/* */
9031/*****************************************************************************/
9032
9033#ifndef CDT_ONLY
9034
9035#ifdef ANSI_DECLARATORS
9036void undovertex(struct mesh *m, struct behavior *b)
9037#else /* not ANSI_DECLARATORS */
9038void undovertex(m, b)
9039struct mesh *m;
9040struct behavior *b;
9041#endif /* not ANSI_DECLARATORS */
9042
9043{
9044 struct otri fliptri;
9045 struct otri botleft, botright, topright;
9046 struct otri botlcasing, botrcasing, toprcasing;
9047 struct otri gluetri;
9048 struct osub botlsubseg, botrsubseg, toprsubseg;
9049 vertex botvertex, rightvertex;
9050 triangle ptr; /* Temporary variable used by sym(). */
9051 subseg sptr; /* Temporary variable used by tspivot(). */
9052
9053 /* Walk through the list of transformations (flips and a vertex insertion) */
9054 /* in the reverse of the order in which they were done, and undo them. */
9055 while (m->lastflip != (struct flipstacker *) NULL) {
9056 /* Find a triangle involved in the last unreversed transformation. */
9057 decode(m->lastflip->flippedtri, fliptri);
9058
9059 /* We are reversing one of three transformations: a trisection of one */
9060 /* triangle into three (by inserting a vertex in the triangle), a */
9061 /* bisection of two triangles into four (by inserting a vertex in an */
9062 /* edge), or an edge flip. */
9063 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
9064 /* Restore a triangle that was split into three triangles, */
9065 /* so it is again one triangle. */
9066 dprev(fliptri, botleft);
9067 lnextself(botleft);
9068 onext(fliptri, botright);
9069 lprevself(botright);
9070 sym(botleft, botlcasing);
9071 sym(botright, botrcasing);
9072 dest(botleft, botvertex);
9073
9074 setapex(fliptri, botvertex);
9075 lnextself(fliptri);
9076 bond(fliptri, botlcasing);
9077 tspivot(botleft, botlsubseg);
9078 tsbond(fliptri, botlsubseg);
9079 lnextself(fliptri);
9080 bond(fliptri, botrcasing);
9081 tspivot(botright, botrsubseg);
9082 tsbond(fliptri, botrsubseg);
9083
9084 /* Delete the two spliced-out triangles. */
9085 triangledealloc(m, botleft.tri);
9086 triangledealloc(m, botright.tri);
9087 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
9088 /* Restore two triangles that were split into four triangles, */
9089 /* so they are again two triangles. */
9090 lprev(fliptri, gluetri);
9091 sym(gluetri, botright);
9092 lnextself(botright);
9093 sym(botright, botrcasing);
9094 dest(botright, rightvertex);
9095
9096 setorg(fliptri, rightvertex);
9097 bond(gluetri, botrcasing);
9098 tspivot(botright, botrsubseg);
9099 tsbond(gluetri, botrsubseg);
9100
9101 /* Delete the spliced-out triangle. */
9102 triangledealloc(m, botright.tri);
9103
9104 sym(fliptri, gluetri);
9105 if (gluetri.tri != m->dummytri) {
9106 lnextself(gluetri);
9107 dnext(gluetri, topright);
9108 sym(topright, toprcasing);
9109
9110 setorg(gluetri, rightvertex);
9111 bond(gluetri, toprcasing);
9112 tspivot(topright, toprsubseg);
9113 tsbond(gluetri, toprsubseg);
9114
9115 /* Delete the spliced-out triangle. */
9116 triangledealloc(m, topright.tri);
9117 }
9118
9119 /* This is the end of the list, sneakily encoded. */
9120 m->lastflip->prevflip = (struct flipstacker *) NULL;
9121 } else {
9122 /* Undo an edge flip. */
9123 unflip(m, b, &fliptri);
9124 }
9125
9126 /* Go on and process the next transformation. */
9127 m->lastflip = m->lastflip->prevflip;
9128 }
9129}
9130
9131#endif /* not CDT_ONLY */
9132
9133/** **/
9134/** **/
9135/********* Mesh transformation routines end here *********/
9136
9137/********* Divide-and-conquer Delaunay triangulation begins here *********/
9138/** **/
9139/** **/
9140
9141/*****************************************************************************/
9142/* */
9143/* The divide-and-conquer bounding box */
9144/* */
9145/* I originally implemented the divide-and-conquer and incremental Delaunay */
9146/* triangulations using the edge-based data structure presented by Guibas */
9147/* and Stolfi. Switching to a triangle-based data structure doubled the */
9148/* speed. However, I had to think of a few extra tricks to maintain the */
9149/* elegance of the original algorithms. */
9150/* */
9151/* The "bounding box" used by my variant of the divide-and-conquer */
9152/* algorithm uses one triangle for each edge of the convex hull of the */
9153/* triangulation. These bounding triangles all share a common apical */
9154/* vertex, which is represented by NULL and which represents nothing. */
9155/* The bounding triangles are linked in a circular fan about this NULL */
9156/* vertex, and the edges on the convex hull of the triangulation appear */
9157/* opposite the NULL vertex. You might find it easiest to imagine that */
9158/* the NULL vertex is a point in 3D space behind the center of the */
9159/* triangulation, and that the bounding triangles form a sort of cone. */
9160/* */
9161/* This bounding box makes it easy to represent degenerate cases. For */
9162/* instance, the triangulation of two vertices is a single edge. This edge */
9163/* is represented by two bounding box triangles, one on each "side" of the */
9164/* edge. These triangles are also linked together in a fan about the NULL */
9165/* vertex. */
9166/* */
9167/* The bounding box also makes it easy to traverse the convex hull, as the */
9168/* divide-and-conquer algorithm needs to do. */
9169/* */
9170/*****************************************************************************/
9171
9172/*****************************************************************************/
9173/* */
9174/* vertexsort() Sort an array of vertices by x-coordinate, using the */
9175/* y-coordinate as a secondary key. */
9176/* */
9177/* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */
9178/* the usual quicksort mistakes. */
9179/* */
9180/*****************************************************************************/
9181
9182#ifdef ANSI_DECLARATORS
9183void vertexsort(vertex *sortarray, int arraysize)
9184#else /* not ANSI_DECLARATORS */
9185void vertexsort(sortarray, arraysize)
9186vertex *sortarray;
9187int arraysize;
9188#endif /* not ANSI_DECLARATORS */
9189
9190{
9191 int left, right;
9192 int pivot;
9193 REAL pivotx, pivoty;
9194 vertex temp;
9195
9196 if (arraysize == 2) {
9197 /* Recursive base case. */
9198 if ((sortarray[0][0] > sortarray[1][0]) ||
9199 ((sortarray[0][0] == sortarray[1][0]) &&
9200 (sortarray[0][1] > sortarray[1][1]))) {
9201 temp = sortarray[1];
9202 sortarray[1] = sortarray[0];
9203 sortarray[0] = temp;
9204 }
9205 return;
9206 }
9207 /* Choose a random pivot to split the array. */
9208 pivot = (int) randomnation((unsigned int) arraysize);
9209 pivotx = sortarray[pivot][0];
9210 pivoty = sortarray[pivot][1];
9211 /* Split the array. */
9212 left = -1;
9213 right = arraysize;
9214 while (left < right) {
9215 /* Search for a vertex whose x-coordinate is too large for the left. */
9216 do {
9217 left++;
9218 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
9219 ((sortarray[left][0] == pivotx) &&
9220 (sortarray[left][1] < pivoty))));
9221 /* Search for a vertex whose x-coordinate is too small for the right. */
9222 do {
9223 right--;
9224 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
9225 ((sortarray[right][0] == pivotx) &&
9226 (sortarray[right][1] > pivoty))));
9227 if (left < right) {
9228 /* Swap the left and right vertices. */
9229 temp = sortarray[left];
9230 sortarray[left] = sortarray[right];
9231 sortarray[right] = temp;
9232 }
9233 }
9234 if (left > 1) {
9235 /* Recursively sort the left subset. */
9236 vertexsort(sortarray, left);
9237 }
9238 if (right < arraysize - 2) {
9239 /* Recursively sort the right subset. */
9240 vertexsort(&sortarray[right + 1], arraysize - right - 1);
9241 }
9242}
9243
9244/*****************************************************************************/
9245/* */
9246/* vertexmedian() An order statistic algorithm, almost. Shuffles an */
9247/* array of vertices so that the first `median' vertices */
9248/* occur lexicographically before the remaining vertices. */
9249/* */
9250/* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */
9251/* if axis == 1. Very similar to the vertexsort() procedure, but runs in */
9252/* randomized linear time. */
9253/* */
9254/*****************************************************************************/
9255
9256#ifdef ANSI_DECLARATORS
9257void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
9258#else /* not ANSI_DECLARATORS */
9259void vertexmedian(sortarray, arraysize, median, axis)
9260vertex *sortarray;
9261int arraysize;
9262int median;
9263int axis;
9264#endif /* not ANSI_DECLARATORS */
9265
9266{
9267 int left, right;
9268 int pivot;
9269 REAL pivot1, pivot2;
9270 vertex temp;
9271
9272 if (arraysize == 2) {
9273 /* Recursive base case. */
9274 if ((sortarray[0][axis] > sortarray[1][axis]) ||
9275 ((sortarray[0][axis] == sortarray[1][axis]) &&
9276 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
9277 temp = sortarray[1];
9278 sortarray[1] = sortarray[0];
9279 sortarray[0] = temp;
9280 }
9281 return;
9282 }
9283 /* Choose a random pivot to split the array. */
9284 pivot = (int) randomnation((unsigned int) arraysize);
9285 pivot1 = sortarray[pivot][axis];
9286 pivot2 = sortarray[pivot][1 - axis];
9287 /* Split the array. */
9288 left = -1;
9289 right = arraysize;
9290 while (left < right) {
9291 /* Search for a vertex whose x-coordinate is too large for the left. */
9292 do {
9293 left++;
9294 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
9295 ((sortarray[left][axis] == pivot1) &&
9296 (sortarray[left][1 - axis] < pivot2))));
9297 /* Search for a vertex whose x-coordinate is too small for the right. */
9298 do {
9299 right--;
9300 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
9301 ((sortarray[right][axis] == pivot1) &&
9302 (sortarray[right][1 - axis] > pivot2))));
9303 if (left < right) {
9304 /* Swap the left and right vertices. */
9305 temp = sortarray[left];
9306 sortarray[left] = sortarray[right];
9307 sortarray[right] = temp;
9308 }
9309 }
9310 /* Unlike in vertexsort(), at most one of the following */
9311 /* conditionals is true. */
9312 if (left > median) {
9313 /* Recursively shuffle the left subset. */
9314 vertexmedian(sortarray, left, median, axis);
9315 }
9316 if (right < median - 1) {
9317 /* Recursively shuffle the right subset. */
9318 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
9319 median - right - 1, axis);
9320 }
9321}
9322
9323/*****************************************************************************/
9324/* */
9325/* alternateaxes() Sorts the vertices as appropriate for the divide-and- */
9326/* conquer algorithm with alternating cuts. */
9327/* */
9328/* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */
9329/* For the base case, subsets containing only two or three vertices are */
9330/* always sorted by x-coordinate. */
9331/* */
9332/*****************************************************************************/
9333
9334#ifdef ANSI_DECLARATORS
9335void alternateaxes(vertex *sortarray, int arraysize, int axis)
9336#else /* not ANSI_DECLARATORS */
9337void alternateaxes(sortarray, arraysize, axis)
9338vertex *sortarray;
9339int arraysize;
9340int axis;
9341#endif /* not ANSI_DECLARATORS */
9342
9343{
9344 int divider;
9345
9346 divider = arraysize >> 1;
9347 if (arraysize <= 3) {
9348 /* Recursive base case: subsets of two or three vertices will be */
9349 /* handled specially, and should always be sorted by x-coordinate. */
9350 axis = 0;
9351 }
9352 /* Partition with a horizontal or vertical cut. */
9353 vertexmedian(sortarray, arraysize, divider, axis);
9354 /* Recursively partition the subsets with a cross cut. */
9355 if (arraysize - divider >= 2) {
9356 if (divider >= 2) {
9357 alternateaxes(sortarray, divider, 1 - axis);
9358 }
9359 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
9360 }
9361}
9362
9363/*****************************************************************************/
9364/* */
9365/* mergehulls() Merge two adjacent Delaunay triangulations into a */
9366/* single Delaunay triangulation. */
9367/* */
9368/* This is similar to the algorithm given by Guibas and Stolfi, but uses */
9369/* a triangle-based, rather than edge-based, data structure. */
9370/* */
9371/* The algorithm walks up the gap between the two triangulations, knitting */
9372/* them together. As they are merged, some of their bounding triangles */
9373/* are converted into real triangles of the triangulation. The procedure */
9374/* pulls each hull's bounding triangles apart, then knits them together */
9375/* like the teeth of two gears. The Delaunay property determines, at each */
9376/* step, whether the next "tooth" is a bounding triangle of the left hull */
9377/* or the right. When a bounding triangle becomes real, its apex is */
9378/* changed from NULL to a real vertex. */
9379/* */
9380/* Only two new triangles need to be allocated. These become new bounding */
9381/* triangles at the top and bottom of the seam. They are used to connect */
9382/* the remaining bounding triangles (those that have not been converted */
9383/* into real triangles) into a single fan. */
9384/* */
9385/* On entry, `farleft' and `innerleft' are bounding triangles of the left */
9386/* triangulation. The origin of `farleft' is the leftmost vertex, and */
9387/* the destination of `innerleft' is the rightmost vertex of the */
9388/* triangulation. Similarly, `innerright' and `farright' are bounding */
9389/* triangles of the right triangulation. The origin of `innerright' and */
9390/* destination of `farright' are the leftmost and rightmost vertices. */
9391/* */
9392/* On completion, the origin of `farleft' is the leftmost vertex of the */
9393/* merged triangulation, and the destination of `farright' is the rightmost */
9394/* vertex. */
9395/* */
9396/*****************************************************************************/
9397
9398#ifdef ANSI_DECLARATORS
9399void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
9400 struct otri *innerleft, struct otri *innerright,
9401 struct otri *farright, int axis)
9402#else /* not ANSI_DECLARATORS */
9403void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
9404struct mesh *m;
9405struct behavior *b;
9406struct otri *farleft;
9407struct otri *innerleft;
9408struct otri *innerright;
9409struct otri *farright;
9410int axis;
9411#endif /* not ANSI_DECLARATORS */
9412
9413{
9414 struct otri leftcand, rightcand;
9415 struct otri baseedge;
9416 struct otri nextedge;
9417 struct otri sidecasing, topcasing, outercasing;
9418 struct otri checkedge;
9419 vertex innerleftdest;
9420 vertex innerrightorg;
9421 vertex innerleftapex, innerrightapex;
9422 vertex farleftpt, farrightpt;
9423 vertex farleftapex, farrightapex;
9424 vertex lowerleft, lowerright;
9425 vertex upperleft, upperright;
9426 vertex nextapex;
9427 vertex checkvertex;
9428 int changemade;
9429 int badedge;
9430 int leftfinished, rightfinished;
9431 triangle ptr; /* Temporary variable used by sym(). */
9432
9433 dest(*innerleft, innerleftdest);
9434 apex(*innerleft, innerleftapex);
9435 org(*innerright, innerrightorg);
9436 apex(*innerright, innerrightapex);
9437 /* Special treatment for horizontal cuts. */
9438 if (b->dwyer && (axis == 1)) {
9439 org(*farleft, farleftpt);
9440 apex(*farleft, farleftapex);
9441 dest(*farright, farrightpt);
9442 apex(*farright, farrightapex);
9443 /* The pointers to the extremal vertices are shifted to point to the */
9444 /* topmost and bottommost vertex of each hull, rather than the */
9445 /* leftmost and rightmost vertices. */
9446 while (farleftapex[1] < farleftpt[1]) {
9447 lnextself(*farleft);
9448 symself(*farleft);
9449 farleftpt = farleftapex;
9450 apex(*farleft, farleftapex);
9451 }
9452 sym(*innerleft, checkedge);
9453 apex(checkedge, checkvertex);
9454 while (checkvertex[1] > innerleftdest[1]) {
9455 lnext(checkedge, *innerleft);
9456 innerleftapex = innerleftdest;
9457 innerleftdest = checkvertex;
9458 sym(*innerleft, checkedge);
9459 apex(checkedge, checkvertex);
9460 }
9461 while (innerrightapex[1] < innerrightorg[1]) {
9462 lnextself(*innerright);
9463 symself(*innerright);
9464 innerrightorg = innerrightapex;
9465 apex(*innerright, innerrightapex);
9466 }
9467 sym(*farright, checkedge);
9468 apex(checkedge, checkvertex);
9469 while (checkvertex[1] > farrightpt[1]) {
9470 lnext(checkedge, *farright);
9471 farrightapex = farrightpt;
9472 farrightpt = checkvertex;
9473 sym(*farright, checkedge);
9474 apex(checkedge, checkvertex);
9475 }
9476 }
9477 /* Find a line tangent to and below both hulls. */
9478 do {
9479 changemade = 0;
9480 /* Make innerleftdest the "bottommost" vertex of the left hull. */
9481 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
9482 0.0) {
9483 lprevself(*innerleft);
9484 symself(*innerleft);
9485 innerleftdest = innerleftapex;
9486 apex(*innerleft, innerleftapex);
9487 changemade = 1;
9488 }
9489 /* Make innerrightorg the "bottommost" vertex of the right hull. */
9490 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
9491 0.0) {
9492 lnextself(*innerright);
9493 symself(*innerright);
9494 innerrightorg = innerrightapex;
9495 apex(*innerright, innerrightapex);
9496 changemade = 1;
9497 }
9498 } while (changemade);
9499 /* Find the two candidates to be the next "gear tooth." */
9500 sym(*innerleft, leftcand);
9501 sym(*innerright, rightcand);
9502 /* Create the bottom new bounding triangle. */
9503 maketriangle(m, b, &baseedge);
9504 /* Connect it to the bounding boxes of the left and right triangulations. */
9505 bond(baseedge, *innerleft);
9506 lnextself(baseedge);
9507 bond(baseedge, *innerright);
9508 lnextself(baseedge);
9509 setorg(baseedge, innerrightorg);
9510 setdest(baseedge, innerleftdest);
9511 /* Apex is intentionally left NULL. */
9512 if (b->verbose > 2) {
9513 printf(" Creating base bounding ");
9514 printtriangle(m, b, &baseedge);
9515 }
9516 /* Fix the extreme triangles if necessary. */
9517 org(*farleft, farleftpt);
9518 if (innerleftdest == farleftpt) {
9519 lnext(baseedge, *farleft);
9520 }
9521 dest(*farright, farrightpt);
9522 if (innerrightorg == farrightpt) {
9523 lprev(baseedge, *farright);
9524 }
9525 /* The vertices of the current knitting edge. */
9526 lowerleft = innerleftdest;
9527 lowerright = innerrightorg;
9528 /* The candidate vertices for knitting. */
9529 apex(leftcand, upperleft);
9530 apex(rightcand, upperright);
9531 /* Walk up the gap between the two triangulations, knitting them together. */
9532 while (1) {
9533 /* Have we reached the top? (This isn't quite the right question, */
9534 /* because even though the left triangulation might seem finished now, */
9535 /* moving up on the right triangulation might reveal a new vertex of */
9536 /* the left triangulation. And vice-versa.) */
9537 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
9538 0.0;
9539 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
9540 <= 0.0;
9541 if (leftfinished && rightfinished) {
9542 /* Create the top new bounding triangle. */
9543 maketriangle(m, b, &nextedge);
9544 setorg(nextedge, lowerleft);
9545 setdest(nextedge, lowerright);
9546 /* Apex is intentionally left NULL. */
9547 /* Connect it to the bounding boxes of the two triangulations. */
9548 bond(nextedge, baseedge);
9549 lnextself(nextedge);
9550 bond(nextedge, rightcand);
9551 lnextself(nextedge);
9552 bond(nextedge, leftcand);
9553 if (b->verbose > 2) {
9554 printf(" Creating top bounding ");
9555 printtriangle(m, b, &nextedge);
9556 }
9557 /* Special treatment for horizontal cuts. */
9558 if (b->dwyer && (axis == 1)) {
9559 org(*farleft, farleftpt);
9560 apex(*farleft, farleftapex);
9561 dest(*farright, farrightpt);
9562 apex(*farright, farrightapex);
9563 sym(*farleft, checkedge);
9564 apex(checkedge, checkvertex);
9565 /* The pointers to the extremal vertices are restored to the */
9566 /* leftmost and rightmost vertices (rather than topmost and */
9567 /* bottommost). */
9568 while (checkvertex[0] < farleftpt[0]) {
9569 lprev(checkedge, *farleft);
9570 farleftapex = farleftpt;
9571 farleftpt = checkvertex;
9572 sym(*farleft, checkedge);
9573 apex(checkedge, checkvertex);
9574 }
9575 while (farrightapex[0] > farrightpt[0]) {
9576 lprevself(*farright);
9577 symself(*farright);
9578 farrightpt = farrightapex;
9579 apex(*farright, farrightapex);
9580 }
9581 }
9582 return;
9583 }
9584 /* Consider eliminating edges from the left triangulation. */
9585 if (!leftfinished) {
9586 /* What vertex would be exposed if an edge were deleted? */
9587 lprev(leftcand, nextedge);
9588 symself(nextedge);
9589 apex(nextedge, nextapex);
9590 /* If nextapex is NULL, then no vertex would be exposed; the */
9591 /* triangulation would have been eaten right through. */
9592 if (nextapex != (vertex) NULL) {
9593 /* Check whether the edge is Delaunay. */
9594 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
9595 0.0;
9596 while (badedge) {
9597 /* Eliminate the edge with an edge flip. As a result, the */
9598 /* left triangulation will have one more boundary triangle. */
9599 lnextself(nextedge);
9600 sym(nextedge, topcasing);
9601 lnextself(nextedge);
9602 sym(nextedge, sidecasing);
9603 bond(nextedge, topcasing);
9604 bond(leftcand, sidecasing);
9605 lnextself(leftcand);
9606 sym(leftcand, outercasing);
9607 lprevself(nextedge);
9608 bond(nextedge, outercasing);
9609 /* Correct the vertices to reflect the edge flip. */
9610 setorg(leftcand, lowerleft);
9611 setdest(leftcand, NULL);
9612 setapex(leftcand, nextapex);
9613 setorg(nextedge, NULL);
9614 setdest(nextedge, upperleft);
9615 setapex(nextedge, nextapex);
9616 /* Consider the newly exposed vertex. */
9617 upperleft = nextapex;
9618 /* What vertex would be exposed if another edge were deleted? */
9619 otricopy(sidecasing, nextedge);
9620 apex(nextedge, nextapex);
9621 if (nextapex != (vertex) NULL) {
9622 /* Check whether the edge is Delaunay. */
9623 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
9624 nextapex) > 0.0;
9625 } else {
9626 /* Avoid eating right through the triangulation. */
9627 badedge = 0;
9628 }
9629 }
9630 }
9631 }
9632 /* Consider eliminating edges from the right triangulation. */
9633 if (!rightfinished) {
9634 /* What vertex would be exposed if an edge were deleted? */
9635 lnext(rightcand, nextedge);
9636 symself(nextedge);
9637 apex(nextedge, nextapex);
9638 /* If nextapex is NULL, then no vertex would be exposed; the */
9639 /* triangulation would have been eaten right through. */
9640 if (nextapex != (vertex) NULL) {
9641 /* Check whether the edge is Delaunay. */
9642 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
9643 0.0;
9644 while (badedge) {
9645 /* Eliminate the edge with an edge flip. As a result, the */
9646 /* right triangulation will have one more boundary triangle. */
9647 lprevself(nextedge);
9648 sym(nextedge, topcasing);
9649 lprevself(nextedge);
9650 sym(nextedge, sidecasing);
9651 bond(nextedge, topcasing);
9652 bond(rightcand, sidecasing);
9653 lprevself(rightcand);
9654 sym(rightcand, outercasing);
9655 lnextself(nextedge);
9656 bond(nextedge, outercasing);
9657 /* Correct the vertices to reflect the edge flip. */
9658 setorg(rightcand, NULL);
9659 setdest(rightcand, lowerright);
9660 setapex(rightcand, nextapex);
9661 setorg(nextedge, upperright);
9662 setdest(nextedge, NULL);
9663 setapex(nextedge, nextapex);
9664 /* Consider the newly exposed vertex. */
9665 upperright = nextapex;
9666 /* What vertex would be exposed if another edge were deleted? */
9667 otricopy(sidecasing, nextedge);
9668 apex(nextedge, nextapex);
9669 if (nextapex != (vertex) NULL) {
9670 /* Check whether the edge is Delaunay. */
9671 badedge = incircle(m, b, lowerleft, lowerright, upperright,
9672 nextapex) > 0.0;
9673 } else {
9674 /* Avoid eating right through the triangulation. */
9675 badedge = 0;
9676 }
9677 }
9678 }
9679 }
9680 if (leftfinished || (!rightfinished &&
9681 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
9682 0.0))) {
9683 /* Knit the triangulations, adding an edge from `lowerleft' */
9684 /* to `upperright'. */
9685 bond(baseedge, rightcand);
9686 lprev(rightcand, baseedge);
9687 setdest(baseedge, lowerleft);
9688 lowerright = upperright;
9689 sym(baseedge, rightcand);
9690 apex(rightcand, upperright);
9691 } else {
9692 /* Knit the triangulations, adding an edge from `upperleft' */
9693 /* to `lowerright'. */
9694 bond(baseedge, leftcand);
9695 lnext(leftcand, baseedge);
9696 setorg(baseedge, lowerright);
9697 lowerleft = upperleft;
9698 sym(baseedge, leftcand);
9699 apex(leftcand, upperleft);
9700 }
9701 if (b->verbose > 2) {
9702 printf(" Connecting ");
9703 printtriangle(m, b, &baseedge);
9704 }
9705 }
9706}
9707
9708/*****************************************************************************/
9709/* */
9710/* divconqrecurse() Recursively form a Delaunay triangulation by the */
9711/* divide-and-conquer method. */
9712/* */
9713/* Recursively breaks down the problem into smaller pieces, which are */
9714/* knitted together by mergehulls(). The base cases (problems of two or */
9715/* three vertices) are handled specially here. */
9716/* */
9717/* On completion, `farleft' and `farright' are bounding triangles such that */
9718/* the origin of `farleft' is the leftmost vertex (breaking ties by */
9719/* choosing the highest leftmost vertex), and the destination of */
9720/* `farright' is the rightmost vertex (breaking ties by choosing the */
9721/* lowest rightmost vertex). */
9722/* */
9723/*****************************************************************************/
9724
9725#ifdef ANSI_DECLARATORS
9726void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
9727 int vertices, int axis,
9728 struct otri *farleft, struct otri *farright)
9729#else /* not ANSI_DECLARATORS */
9730void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
9731struct mesh *m;
9732struct behavior *b;
9733vertex *sortarray;
9734int vertices;
9735int axis;
9736struct otri *farleft;
9737struct otri *farright;
9738#endif /* not ANSI_DECLARATORS */
9739
9740{
9741 struct otri midtri, tri1, tri2, tri3;
9742 struct otri innerleft, innerright;
9743 REAL area;
9744 int divider;
9745
9746 if (b->verbose > 2) {
9747 printf(" Triangulating %d vertices.\n", vertices);
9748 }
9749 if (vertices == 2) {
9750 /* The triangulation of two vertices is an edge. An edge is */
9751 /* represented by two bounding triangles. */
9752 maketriangle(m, b, farleft);
9753 setorg(*farleft, sortarray[0]);
9754 setdest(*farleft, sortarray[1]);
9755 /* The apex is intentionally left NULL. */
9756 maketriangle(m, b, farright);
9757 setorg(*farright, sortarray[1]);
9758 setdest(*farright, sortarray[0]);
9759 /* The apex is intentionally left NULL. */
9760 bond(*farleft, *farright);
9761 lprevself(*farleft);
9762 lnextself(*farright);
9763 bond(*farleft, *farright);
9764 lprevself(*farleft);
9765 lnextself(*farright);
9766 bond(*farleft, *farright);
9767 if (b->verbose > 2) {
9768 printf(" Creating ");
9769 printtriangle(m, b, farleft);
9770 printf(" Creating ");
9771 printtriangle(m, b, farright);
9772 }
9773 /* Ensure that the origin of `farleft' is sortarray[0]. */
9774 lprev(*farright, *farleft);
9775 return;
9776 } else if (vertices == 3) {
9777 /* The triangulation of three vertices is either a triangle (with */
9778 /* three bounding triangles) or two edges (with four bounding */
9779 /* triangles). In either case, four triangles are created. */
9780 maketriangle(m, b, &midtri);
9781 maketriangle(m, b, &tri1);
9782 maketriangle(m, b, &tri2);
9783 maketriangle(m, b, &tri3);
9784 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
9785 if (area == 0.0) {
9786 /* Three collinear vertices; the triangulation is two edges. */
9787 setorg(midtri, sortarray[0]);
9788 setdest(midtri, sortarray[1]);
9789 setorg(tri1, sortarray[1]);
9790 setdest(tri1, sortarray[0]);
9791 setorg(tri2, sortarray[2]);
9792 setdest(tri2, sortarray[1]);
9793 setorg(tri3, sortarray[1]);
9794 setdest(tri3, sortarray[2]);
9795 /* All apices are intentionally left NULL. */
9796 bond(midtri, tri1);
9797 bond(tri2, tri3);
9798 lnextself(midtri);
9799 lprevself(tri1);
9800 lnextself(tri2);
9801 lprevself(tri3);
9802 bond(midtri, tri3);
9803 bond(tri1, tri2);
9804 lnextself(midtri);
9805 lprevself(tri1);
9806 lnextself(tri2);
9807 lprevself(tri3);
9808 bond(midtri, tri1);
9809 bond(tri2, tri3);
9810 /* Ensure that the origin of `farleft' is sortarray[0]. */
9811 otricopy(tri1, *farleft);
9812 /* Ensure that the destination of `farright' is sortarray[2]. */
9813 otricopy(tri2, *farright);
9814 } else {
9815 /* The three vertices are not collinear; the triangulation is one */
9816 /* triangle, namely `midtri'. */
9817 setorg(midtri, sortarray[0]);
9818 setdest(tri1, sortarray[0]);
9819 setorg(tri3, sortarray[0]);
9820 /* Apices of tri1, tri2, and tri3 are left NULL. */
9821 if (area > 0.0) {
9822 /* The vertices are in counterclockwise order. */
9823 setdest(midtri, sortarray[1]);
9824 setorg(tri1, sortarray[1]);
9825 setdest(tri2, sortarray[1]);
9826 setapex(midtri, sortarray[2]);
9827 setorg(tri2, sortarray[2]);
9828 setdest(tri3, sortarray[2]);
9829 } else {
9830 /* The vertices are in clockwise order. */
9831 setdest(midtri, sortarray[2]);
9832 setorg(tri1, sortarray[2]);
9833 setdest(tri2, sortarray[2]);
9834 setapex(midtri, sortarray[1]);
9835 setorg(tri2, sortarray[1]);
9836 setdest(tri3, sortarray[1]);
9837 }
9838 /* The topology does not depend on how the vertices are ordered. */
9839 bond(midtri, tri1);
9840 lnextself(midtri);
9841 bond(midtri, tri2);
9842 lnextself(midtri);
9843 bond(midtri, tri3);
9844 lprevself(tri1);
9845 lnextself(tri2);
9846 bond(tri1, tri2);
9847 lprevself(tri1);
9848 lprevself(tri3);
9849 bond(tri1, tri3);
9850 lnextself(tri2);
9851 lprevself(tri3);
9852 bond(tri2, tri3);
9853 /* Ensure that the origin of `farleft' is sortarray[0]. */
9854 otricopy(tri1, *farleft);
9855 /* Ensure that the destination of `farright' is sortarray[2]. */
9856 if (area > 0.0) {
9857 otricopy(tri2, *farright);
9858 } else {
9859 lnext(*farleft, *farright);
9860 }
9861 }
9862 if (b->verbose > 2) {
9863 printf(" Creating ");
9864 printtriangle(m, b, &midtri);
9865 printf(" Creating ");
9866 printtriangle(m, b, &tri1);
9867 printf(" Creating ");
9868 printtriangle(m, b, &tri2);
9869 printf(" Creating ");
9870 printtriangle(m, b, &tri3);
9871 }
9872 return;
9873 } else {
9874 /* Split the vertices in half. */
9875 divider = vertices >> 1;
9876 /* Recursively triangulate each half. */
9877 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
9878 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
9879 &innerright, farright);
9880 if (b->verbose > 1) {
9881 printf(" Joining triangulations with %d and %d vertices.\n", divider,
9882 vertices - divider);
9883 }
9884 /* Merge the two triangulations into one. */
9885 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
9886 }
9887}
9888
9889#ifdef ANSI_DECLARATORS
9890long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
9891#else /* not ANSI_DECLARATORS */
9892long removeghosts(m, b, startghost)
9893struct mesh *m;
9894struct behavior *b;
9895struct otri *startghost;
9896#endif /* not ANSI_DECLARATORS */
9897
9898{
9899 struct otri searchedge;
9900 struct otri dissolveedge;
9901 struct otri deadtriangle;
9902 vertex markorg;
9903 long hullsize;
9904 triangle ptr; /* Temporary variable used by sym(). */
9905
9906 if (b->verbose) {
9907 printf(" Removing ghost triangles.\n");
9908 }
9909 /* Find an edge on the convex hull to start point location from. */
9910 lprev(*startghost, searchedge);
9911 symself(searchedge);
9912 m->dummytri[0] = encode(searchedge);
9913 /* Remove the bounding box and count the convex hull edges. */
9914 otricopy(*startghost, dissolveedge);
9915 hullsize = 0;
9916 do {
9917 hullsize++;
9918 lnext(dissolveedge, deadtriangle);
9919 lprevself(dissolveedge);
9920 symself(dissolveedge);
9921 /* If no PSLG is involved, set the boundary markers of all the vertices */
9922 /* on the convex hull. If a PSLG is used, this step is done later. */
9923 if (!b->poly) {
9924 /* Watch out for the case where all the input vertices are collinear. */
9925 if (dissolveedge.tri != m->dummytri) {
9926 org(dissolveedge, markorg);
9927 if (vertexmark(markorg) == 0) {
9928 setvertexmark(markorg, 1);
9929 }
9930 }
9931 }
9932 /* Remove a bounding triangle from a convex hull triangle. */
9933 dissolve(dissolveedge);
9934 /* Find the next bounding triangle. */
9935 sym(deadtriangle, dissolveedge);
9936 /* Delete the bounding triangle. */
9937 triangledealloc(m, deadtriangle.tri);
9938 } while (!otriequal(dissolveedge, *startghost));
9939 return hullsize;
9940}
9941
9942/*****************************************************************************/
9943/* */
9944/* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */
9945/* conquer method. */
9946/* */
9947/* Sorts the vertices, calls a recursive procedure to triangulate them, and */
9948/* removes the bounding box, setting boundary markers as appropriate. */
9949/* */
9950/*****************************************************************************/
9951
9952#ifdef ANSI_DECLARATORS
9953long divconqdelaunay(struct mesh *m, struct behavior *b)
9954#else /* not ANSI_DECLARATORS */
9955long divconqdelaunay(m, b)
9956struct mesh *m;
9957struct behavior *b;
9958#endif /* not ANSI_DECLARATORS */
9959
9960{
9961 vertex *sortarray;
9962 struct otri hullleft, hullright;
9963 int divider;
9964 int i, j;
9965
9966 if (b->verbose) {
9967 printf(" Sorting vertices.\n");
9968 }
9969
9970 /* Allocate an array of pointers to vertices for sorting. */
9971 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
9972 traversalinit(&m->vertices);
9973 for (i = 0; i < m->invertices; i++) {
9974 sortarray[i] = vertextraverse(m);
9975 }
9976 /* Sort the vertices. */
9977 vertexsort(sortarray, m->invertices);
9978 /* Discard duplicate vertices, which can really mess up the algorithm. */
9979 i = 0;
9980 for (j = 1; j < m->invertices; j++) {
9981 if ((sortarray[i][0] == sortarray[j][0])
9982 && (sortarray[i][1] == sortarray[j][1])) {
9983 if (!b->quiet) {
9984 printf(
9985"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
9986 sortarray[j][0], sortarray[j][1]);
9987 }
9988 setvertextype(sortarray[j], UNDEADVERTEX);
9989 m->undeads++;
9990 } else {
9991 i++;
9992 sortarray[i] = sortarray[j];
9993 }
9994 }
9995 i++;
9996 if (b->dwyer) {
9997 /* Re-sort the array of vertices to accommodate alternating cuts. */
9998 divider = i >> 1;
9999 if (i - divider >= 2) {
10000 if (divider >= 2) {
10001 alternateaxes(sortarray, divider, 1);
10002 }
10003 alternateaxes(&sortarray[divider], i - divider, 1);
10004 }
10005 }
10006
10007 if (b->verbose) {
10008 printf(" Forming triangulation.\n");
10009 }
10010
10011 /* Form the Delaunay triangulation. */
10012 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10013 trifree((VOID *) sortarray);
10014
10015 return removeghosts(m, b, &hullleft);
10016}
10017
10018/** **/
10019/** **/
10020/********* Divide-and-conquer Delaunay triangulation ends here *********/
10021
10022/********* Incremental Delaunay triangulation begins here *********/
10023/** **/
10024/** **/
10025
10026/*****************************************************************************/
10027/* */
10028/* boundingbox() Form an "infinite" bounding triangle to insert vertices */
10029/* into. */
10030/* */
10031/* The vertices at "infinity" are assigned finite coordinates, which are */
10032/* used by the point location routines, but (mostly) ignored by the */
10033/* Delaunay edge flip routines. */
10034/* */
10035/*****************************************************************************/
10036
10037#ifndef REDUCED
10038
10039#ifdef ANSI_DECLARATORS
10040void boundingbox(struct mesh *m, struct behavior *b)
10041#else /* not ANSI_DECLARATORS */
10042void boundingbox(m, b)
10043struct mesh *m;
10044struct behavior *b;
10045#endif /* not ANSI_DECLARATORS */
10046
10047{
10048 struct otri inftri; /* Handle for the triangular bounding box. */
10049 REAL width;
10050
10051 if (b->verbose) {
10052 printf(" Creating triangular bounding box.\n");
10053 }
10054 /* Find the width (or height, whichever is larger) of the triangulation. */
10055 width = m->xmax - m->xmin;
10056 if (m->ymax - m->ymin > width) {
10057 width = m->ymax - m->ymin;
10058 }
10059 if (width == 0.0) {
10060 width = 1.0;
10061 }
10062 /* Create the vertices of the bounding box. */
10063 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10064 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10065 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10066 m->infvertex1[0] = m->xmin - 50.0 * width;
10067 m->infvertex1[1] = m->ymin - 40.0 * width;
10068 m->infvertex2[0] = m->xmax + 50.0 * width;
10069 m->infvertex2[1] = m->ymin - 40.0 * width;
10070 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10071 m->infvertex3[1] = m->ymax + 60.0 * width;
10072
10073 /* Create the bounding box. */
10074 maketriangle(m, b, &inftri);
10075 setorg(inftri, m->infvertex1);
10076 setdest(inftri, m->infvertex2);
10077 setapex(inftri, m->infvertex3);
10078 /* Link dummytri to the bounding box so we can always find an */
10079 /* edge to begin searching (point location) from. */
10080 m->dummytri[0] = (triangle) inftri.tri;
10081 if (b->verbose > 2) {
10082 printf(" Creating ");
10083 printtriangle(m, b, &inftri);
10084 }
10085}
10086
10087#endif /* not REDUCED */
10088
10089/*****************************************************************************/
10090/* */
10091/* removebox() Remove the "infinite" bounding triangle, setting boundary */
10092/* markers as appropriate. */
10093/* */
10094/* The triangular bounding box has three boundary triangles (one for each */
10095/* side of the bounding box), and a bunch of triangles fanning out from */
10096/* the three bounding box vertices (one triangle for each edge of the */
10097/* convex hull of the inner mesh). This routine removes these triangles. */
10098/* */
10099/* Returns the number of edges on the convex hull of the triangulation. */
10100/* */
10101/*****************************************************************************/
10102
10103#ifndef REDUCED
10104
10105#ifdef ANSI_DECLARATORS
10106long removebox(struct mesh *m, struct behavior *b)
10107#else /* not ANSI_DECLARATORS */
10108long removebox(m, b)
10109struct mesh *m;
10110struct behavior *b;
10111#endif /* not ANSI_DECLARATORS */
10112
10113{
10114 struct otri deadtriangle;
10115 struct otri searchedge;
10116 struct otri checkedge;
10117 struct otri nextedge, finaledge, dissolveedge;
10118 vertex markorg;
10119 long hullsize;
10120 triangle ptr; /* Temporary variable used by sym(). */
10121
10122 if (b->verbose) {
10123 printf(" Removing triangular bounding box.\n");
10124 }
10125 /* Find a boundary triangle. */
10126 nextedge.tri = m->dummytri;
10127 nextedge.orient = 0;
10128 symself(nextedge);
10129 /* Mark a place to stop. */
10130 lprev(nextedge, finaledge);
10131 lnextself(nextedge);
10132 symself(nextedge);
10133 /* Find a triangle (on the boundary of the vertex set) that isn't */
10134 /* a bounding box triangle. */
10135 lprev(nextedge, searchedge);
10136 symself(searchedge);
10137 /* Check whether nextedge is another boundary triangle */
10138 /* adjacent to the first one. */
10139 lnext(nextedge, checkedge);
10140 symself(checkedge);
10141 if (checkedge.tri == m->dummytri) {
10142 /* Go on to the next triangle. There are only three boundary */
10143 /* triangles, and this next triangle cannot be the third one, */
10144 /* so it's safe to stop here. */
10145 lprevself(searchedge);
10146 symself(searchedge);
10147 }
10148 /* Find a new boundary edge to search from, as the current search */
10149 /* edge lies on a bounding box triangle and will be deleted. */
10150 m->dummytri[0] = encode(searchedge);
10151 hullsize = -2l;
10152 while (!otriequal(nextedge, finaledge)) {
10153 hullsize++;
10154 lprev(nextedge, dissolveedge);
10155 symself(dissolveedge);
10156 /* If not using a PSLG, the vertices should be marked now. */
10157 /* (If using a PSLG, markhull() will do the job.) */
10158 if (!b->poly) {
10159 /* Be careful! One must check for the case where all the input */
10160 /* vertices are collinear, and thus all the triangles are part of */
10161 /* the bounding box. Otherwise, the setvertexmark() call below */
10162 /* will cause a bad pointer reference. */
10163 if (dissolveedge.tri != m->dummytri) {
10164 org(dissolveedge, markorg);
10165 if (vertexmark(markorg) == 0) {
10166 setvertexmark(markorg, 1);
10167 }
10168 }
10169 }
10170 /* Disconnect the bounding box triangle from the mesh triangle. */
10171 dissolve(dissolveedge);
10172 lnext(nextedge, deadtriangle);
10173 sym(deadtriangle, nextedge);
10174 /* Get rid of the bounding box triangle. */
10175 triangledealloc(m, deadtriangle.tri);
10176 /* Do we need to turn the corner? */
10177 if (nextedge.tri == m->dummytri) {
10178 /* Turn the corner. */
10179 otricopy(dissolveedge, nextedge);
10180 }
10181 }
10182 triangledealloc(m, finaledge.tri);
10183
10184 trifree((VOID *) m->infvertex1); /* Deallocate the bounding box vertices. */
10185 trifree((VOID *) m->infvertex2);
10186 trifree((VOID *) m->infvertex3);
10187
10188 return hullsize;
10189}
10190
10191#endif /* not REDUCED */
10192
10193/*****************************************************************************/
10194/* */
10195/* incrementaldelaunay() Form a Delaunay triangulation by incrementally */
10196/* inserting vertices. */
10197/* */
10198/* Returns the number of edges on the convex hull of the triangulation. */
10199/* */
10200/*****************************************************************************/
10201
10202#ifndef REDUCED
10203
10204#ifdef ANSI_DECLARATORS
10205long incrementaldelaunay(struct mesh *m, struct behavior *b)
10206#else /* not ANSI_DECLARATORS */
10207long incrementaldelaunay(m, b)
10208struct mesh *m;
10209struct behavior *b;
10210#endif /* not ANSI_DECLARATORS */
10211
10212{
10213 struct otri starttri;
10214 vertex vertexloop;
10215
10216 /* Create a triangular bounding box. */
10217 boundingbox(m, b);
10218 if (b->verbose) {
10219 printf(" Incrementally inserting vertices.\n");
10220 }
10221 traversalinit(&m->vertices);
10222 vertexloop = vertextraverse(m);
10223 while (vertexloop != (vertex) NULL) {
10224 starttri.tri = m->dummytri;
10225 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10226 == DUPLICATEVERTEX) {
10227 if (!b->quiet) {
10228 printf(
10229"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10230 vertexloop[0], vertexloop[1]);
10231 }
10232 setvertextype(vertexloop, UNDEADVERTEX);
10233 m->undeads++;
10234 }
10235 vertexloop = vertextraverse(m);
10236 }
10237 /* Remove the bounding box. */
10238 return removebox(m, b);
10239}
10240
10241#endif /* not REDUCED */
10242
10243/** **/
10244/** **/
10245/********* Incremental Delaunay triangulation ends here *********/
10246
10247/********* Sweepline Delaunay triangulation begins here *********/
10248/** **/
10249/** **/
10250
10251#ifndef REDUCED
10252
10253#ifdef ANSI_DECLARATORS
10254void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10255#else /* not ANSI_DECLARATORS */
10256void eventheapinsert(heap, heapsize, newevent)
10257struct event **heap;
10258int heapsize;
10259struct event *newevent;
10260#endif /* not ANSI_DECLARATORS */
10261
10262{
10263 REAL eventx, eventy;
10264 int eventnum;
10265 int parent;
10266 int notdone;
10267
10268 eventx = newevent->xkey;
10269 eventy = newevent->ykey;
10270 eventnum = heapsize;
10271 notdone = eventnum > 0;
10272 while (notdone) {
10273 parent = (eventnum - 1) >> 1;
10274 if ((heap[parent]->ykey < eventy) ||
10275 ((heap[parent]->ykey == eventy)
10276 && (heap[parent]->xkey <= eventx))) {
10277 notdone = 0;
10278 } else {
10279 heap[eventnum] = heap[parent];
10280 heap[eventnum]->heapposition = eventnum;
10281
10282 eventnum = parent;
10283 notdone = eventnum > 0;
10284 }
10285 }
10286 heap[eventnum] = newevent;
10287 newevent->heapposition = eventnum;
10288}
10289
10290#endif /* not REDUCED */
10291
10292#ifndef REDUCED
10293
10294#ifdef ANSI_DECLARATORS
10295void eventheapify(struct event **heap, int heapsize, int eventnum)
10296#else /* not ANSI_DECLARATORS */
10297void eventheapify(heap, heapsize, eventnum)
10298struct event **heap;
10299int heapsize;
10300int eventnum;
10301#endif /* not ANSI_DECLARATORS */
10302
10303{
10304 struct event *thisevent;
10305 REAL eventx, eventy;
10306 int leftchild, rightchild;
10307 int smallest;
10308 int notdone;
10309
10310 thisevent = heap[eventnum];
10311 eventx = thisevent->xkey;
10312 eventy = thisevent->ykey;
10313 leftchild = 2 * eventnum + 1;
10314 notdone = leftchild < heapsize;
10315 while (notdone) {
10316 if ((heap[leftchild]->ykey < eventy) ||
10317 ((heap[leftchild]->ykey == eventy)
10318 && (heap[leftchild]->xkey < eventx))) {
10319 smallest = leftchild;
10320 } else {
10321 smallest = eventnum;
10322 }
10323 rightchild = leftchild + 1;
10324 if (rightchild < heapsize) {
10325 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10326 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10327 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10328 smallest = rightchild;
10329 }
10330 }
10331 if (smallest == eventnum) {
10332 notdone = 0;
10333 } else {
10334 heap[eventnum] = heap[smallest];
10335 heap[eventnum]->heapposition = eventnum;
10336 heap[smallest] = thisevent;
10337 thisevent->heapposition = smallest;
10338
10339 eventnum = smallest;
10340 leftchild = 2 * eventnum + 1;
10341 notdone = leftchild < heapsize;
10342 }
10343 }
10344}
10345
10346#endif /* not REDUCED */
10347
10348#ifndef REDUCED
10349
10350#ifdef ANSI_DECLARATORS
10351void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10352#else /* not ANSI_DECLARATORS */
10353void eventheapdelete(heap, heapsize, eventnum)
10354struct event **heap;
10355int heapsize;
10356int eventnum;
10357#endif /* not ANSI_DECLARATORS */
10358
10359{
10360 struct event *moveevent;
10361 REAL eventx, eventy;
10362 int parent;
10363 int notdone;
10364
10365 moveevent = heap[heapsize - 1];
10366 if (eventnum > 0) {
10367 eventx = moveevent->xkey;
10368 eventy = moveevent->ykey;
10369 do {
10370 parent = (eventnum - 1) >> 1;
10371 if ((heap[parent]->ykey < eventy) ||
10372 ((heap[parent]->ykey == eventy)
10373 && (heap[parent]->xkey <= eventx))) {
10374 notdone = 0;
10375 } else {
10376 heap[eventnum] = heap[parent];
10377 heap[eventnum]->heapposition = eventnum;
10378
10379 eventnum = parent;
10380 notdone = eventnum > 0;
10381 }
10382 } while (notdone);
10383 }
10384 heap[eventnum] = moveevent;
10385 moveevent->heapposition = eventnum;
10386 eventheapify(heap, heapsize - 1, eventnum);
10387}
10388
10389#endif /* not REDUCED */
10390
10391#ifndef REDUCED
10392
10393#ifdef ANSI_DECLARATORS
10394void createeventheap(struct mesh *m, struct event ***eventheap,
10395 struct event **events, struct event **freeevents)
10396#else /* not ANSI_DECLARATORS */
10397void createeventheap(m, eventheap, events, freeevents)
10398struct mesh *m;
10399struct event ***eventheap;
10400struct event **events;
10401struct event **freeevents;
10402#endif /* not ANSI_DECLARATORS */
10403
10404{
10405 vertex thisvertex;
10406 int maxevents;
10407 int i;
10408
10409 maxevents = (3 * m->invertices) / 2;
10410 *eventheap = (struct event **) trimalloc(maxevents *
10411 (int) sizeof(struct event *));
10412 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10413 traversalinit(&m->vertices);
10414 for (i = 0; i < m->invertices; i++) {
10415 thisvertex = vertextraverse(m);
10416 (*events)[i].eventptr = (VOID *) thisvertex;
10417 (*events)[i].xkey = thisvertex[0];
10418 (*events)[i].ykey = thisvertex[1];
10419 eventheapinsert(*eventheap, i, *events + i);
10420 }
10421 *freeevents = (struct event *) NULL;
10422 for (i = maxevents - 1; i >= m->invertices; i--) {
10423 (*events)[i].eventptr = (VOID *) *freeevents;
10424 *freeevents = *events + i;
10425 }
10426}
10427
10428#endif /* not REDUCED */
10429
10430#ifndef REDUCED
10431
10432#ifdef ANSI_DECLARATORS
10433int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10434#else /* not ANSI_DECLARATORS */
10435int rightofhyperbola(m, fronttri, newsite)
10436struct mesh *m;
10437struct otri *fronttri;
10438vertex newsite;
10439#endif /* not ANSI_DECLARATORS */
10440
10441{
10442 vertex leftvertex, rightvertex;
10443 REAL dxa, dya, dxb, dyb;
10444
10445 m->hyperbolacount++;
10446
10447 dest(*fronttri, leftvertex);
10448 apex(*fronttri, rightvertex);
10449 if ((leftvertex[1] < rightvertex[1]) ||
10450 ((leftvertex[1] == rightvertex[1]) &&
10451 (leftvertex[0] < rightvertex[0]))) {
10452 if (newsite[0] >= rightvertex[0]) {
10453 return 1;
10454 }
10455 } else {
10456 if (newsite[0] <= leftvertex[0]) {
10457 return 0;
10458 }
10459 }
10460 dxa = leftvertex[0] - newsite[0];
10461 dya = leftvertex[1] - newsite[1];
10462 dxb = rightvertex[0] - newsite[0];
10463 dyb = rightvertex[1] - newsite[1];
10464 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10465}
10466
10467#endif /* not REDUCED */
10468
10469#ifndef REDUCED
10470
10471#ifdef ANSI_DECLARATORS
10472REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10473#else /* not ANSI_DECLARATORS */
10474REAL circletop(m, pa, pb, pc, ccwabc)
10475struct mesh *m;
10476vertex pa;
10477vertex pb;
10478vertex pc;
10479REAL ccwabc;
10480#endif /* not ANSI_DECLARATORS */
10481
10482{
10483 REAL xac, yac, xbc, ybc, xab, yab;
10484 REAL aclen2, bclen2, ablen2;
10485
10486 m->circletopcount++;
10487
10488 xac = pa[0] - pc[0];
10489 yac = pa[1] - pc[1];
10490 xbc = pb[0] - pc[0];
10491 ybc = pb[1] - pc[1];
10492 xab = pa[0] - pb[0];
10493 yab = pa[1] - pb[1];
10494 aclen2 = xac * xac + yac * yac;
10495 bclen2 = xbc * xbc + ybc * ybc;
10496 ablen2 = xab * xab + yab * yab;
10497 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10498 / (2.0 * ccwabc);
10499}
10500
10501#endif /* not REDUCED */
10502
10503#ifndef REDUCED
10504
10505#ifdef ANSI_DECLARATORS
10506void check4deadevent(struct otri *checktri, struct event **freeevents,
10507 struct event **eventheap, int *heapsize)
10508#else /* not ANSI_DECLARATORS */
10509void check4deadevent(checktri, freeevents, eventheap, heapsize)
10510struct otri *checktri;
10511struct event **freeevents;
10512struct event **eventheap;
10513int *heapsize;
10514#endif /* not ANSI_DECLARATORS */
10515
10516{
10517 struct event *deadevent;
10518 vertex eventvertex;
10519 int eventnum;
10520
10521 org(*checktri, eventvertex);
10522 if (eventvertex != (vertex) NULL) {
10523 deadevent = (struct event *) eventvertex;
10524 eventnum = deadevent->heapposition;
10525 deadevent->eventptr = (VOID *) *freeevents;
10526 *freeevents = deadevent;
10527 eventheapdelete(eventheap, *heapsize, eventnum);
10528 (*heapsize)--;
10529 setorg(*checktri, NULL);
10530 }
10531}
10532
10533#endif /* not REDUCED */
10534
10535#ifndef REDUCED
10536
10537#ifdef ANSI_DECLARATORS
10538struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10539 vertex searchpoint, struct otri *searchtri)
10540#else /* not ANSI_DECLARATORS */
10541struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10542struct mesh *m;
10543struct splaynode *splaytree;
10544vertex searchpoint;
10545struct otri *searchtri;
10546#endif /* not ANSI_DECLARATORS */
10547
10548{
10549 struct splaynode *child, *grandchild;
10550 struct splaynode *lefttree, *righttree;
10551 struct splaynode *leftright;
10552 vertex checkvertex;
10553 int rightofroot, rightofchild;
10554
10555 if (splaytree == (struct splaynode *) NULL) {
10556 return (struct splaynode *) NULL;
10557 }
10558 dest(splaytree->keyedge, checkvertex);
10559 if (checkvertex == splaytree->keydest) {
10560 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10561 if (rightofroot) {
10562 otricopy(splaytree->keyedge, *searchtri);
10563 child = splaytree->rchild;
10564 } else {
10565 child = splaytree->lchild;
10566 }
10567 if (child == (struct splaynode *) NULL) {
10568 return splaytree;
10569 }
10570 dest(child->keyedge, checkvertex);
10571 if (checkvertex != child->keydest) {
10572 child = splay(m, child, searchpoint, searchtri);
10573 if (child == (struct splaynode *) NULL) {
10574 if (rightofroot) {
10575 splaytree->rchild = (struct splaynode *) NULL;
10576 } else {
10577 splaytree->lchild = (struct splaynode *) NULL;
10578 }
10579 return splaytree;
10580 }
10581 }
10582 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10583 if (rightofchild) {
10584 otricopy(child->keyedge, *searchtri);
10585 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10586 child->rchild = grandchild;
10587 } else {
10588 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10589 child->lchild = grandchild;
10590 }
10591 if (grandchild == (struct splaynode *) NULL) {
10592 if (rightofroot) {
10593 splaytree->rchild = child->lchild;
10594 child->lchild = splaytree;
10595 } else {
10596 splaytree->lchild = child->rchild;
10597 child->rchild = splaytree;
10598 }
10599 return child;
10600 }
10601 if (rightofchild) {
10602 if (rightofroot) {
10603 splaytree->rchild = child->lchild;
10604 child->lchild = splaytree;
10605 } else {
10606 splaytree->lchild = grandchild->rchild;
10607 grandchild->rchild = splaytree;
10608 }
10609 child->rchild = grandchild->lchild;
10610 grandchild->lchild = child;
10611 } else {
10612 if (rightofroot) {
10613 splaytree->rchild = grandchild->lchild;
10614 grandchild->lchild = splaytree;
10615 } else {
10616 splaytree->lchild = child->rchild;
10617 child->rchild = splaytree;
10618 }
10619 child->lchild = grandchild->rchild;
10620 grandchild->rchild = child;
10621 }
10622 return grandchild;
10623 } else {
10624 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10625 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10626
10627 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10628 if (lefttree == (struct splaynode *) NULL) {
10629 return righttree;
10630 } else if (righttree == (struct splaynode *) NULL) {
10631 return lefttree;
10632 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10633 lefttree->rchild = righttree->lchild;
10634 righttree->lchild = lefttree;
10635 return righttree;
10636 } else if (righttree->lchild == (struct splaynode *) NULL) {
10637 righttree->lchild = lefttree->rchild;
10638 lefttree->rchild = righttree;
10639 return lefttree;
10640 } else {
10641/* printf("Holy Toledo!!!\n"); */
10642 leftright = lefttree->rchild;
10643 while (leftright->rchild != (struct splaynode *) NULL) {
10644 leftright = leftright->rchild;
10645 }
10646 leftright->rchild = righttree;
10647 return lefttree;
10648 }
10649 }
10650}
10651
10652#endif /* not REDUCED */
10653
10654#ifndef REDUCED
10655
10656#ifdef ANSI_DECLARATORS
10657struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10658 struct otri *newkey, vertex searchpoint)
10659#else /* not ANSI_DECLARATORS */
10660struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10661struct mesh *m;
10662struct splaynode *splayroot;
10663struct otri *newkey;
10664vertex searchpoint;
10665#endif /* not ANSI_DECLARATORS */
10666
10667{
10668 struct splaynode *newsplaynode;
10669
10670 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10671 otricopy(*newkey, newsplaynode->keyedge);
10672 dest(*newkey, newsplaynode->keydest);
10673 if (splayroot == (struct splaynode *) NULL) {
10674 newsplaynode->lchild = (struct splaynode *) NULL;
10675 newsplaynode->rchild = (struct splaynode *) NULL;
10676 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10677 newsplaynode->lchild = splayroot;
10678 newsplaynode->rchild = splayroot->rchild;
10679 splayroot->rchild = (struct splaynode *) NULL;
10680 } else {
10681 newsplaynode->lchild = splayroot->lchild;
10682 newsplaynode->rchild = splayroot;
10683 splayroot->lchild = (struct splaynode *) NULL;
10684 }
10685 return newsplaynode;
10686}
10687
10688#endif /* not REDUCED */
10689
10690#ifndef REDUCED
10691
10692#ifdef ANSI_DECLARATORS
10693struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10694 struct splaynode *splayroot,
10695 struct otri *newkey,
10696 vertex pa, vertex pb, vertex pc, REAL topy)
10697#else /* not ANSI_DECLARATORS */
10698struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10699struct mesh *m;
10700struct behavior *b;
10701struct splaynode *splayroot;
10702struct otri *newkey;
10703vertex pa;
10704vertex pb;
10705vertex pc;
10706REAL topy;
10707#endif /* not ANSI_DECLARATORS */
10708
10709{
10710 REAL ccwabc;
10711 REAL xac, yac, xbc, ybc;
10712 REAL aclen2, bclen2;
10713 REAL searchpoint[2];
10714 struct otri dummytri;
10715
10716 ccwabc = counterclockwise(m, b, pa, pb, pc);
10717 xac = pa[0] - pc[0];
10718 yac = pa[1] - pc[1];
10719 xbc = pb[0] - pc[0];
10720 ybc = pb[1] - pc[1];
10721 aclen2 = xac * xac + yac * yac;
10722 bclen2 = xbc * xbc + ybc * ybc;
10723 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10724 searchpoint[1] = topy;
10725 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10726 newkey, (vertex) searchpoint);
10727}
10728
10729#endif /* not REDUCED */
10730
10731#ifndef REDUCED
10732
10733#ifdef ANSI_DECLARATORS
10734struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10735 struct otri *bottommost, vertex searchvertex,
10736 struct otri *searchtri, int *farright)
10737#else /* not ANSI_DECLARATORS */
10738struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10739 searchtri, farright)
10740struct mesh *m;
10741struct splaynode *splayroot;
10742struct otri *bottommost;
10743vertex searchvertex;
10744struct otri *searchtri;
10745int *farright;
10746#endif /* not ANSI_DECLARATORS */
10747
10748{
10749 int farrightflag;
10750 triangle ptr; /* Temporary variable used by onext(). */
10751
10752 otricopy(*bottommost, *searchtri);
10753 splayroot = splay(m, splayroot, searchvertex, searchtri);
10754
10755 farrightflag = 0;
10756 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10757 onextself(*searchtri);
10758 farrightflag = otriequal(*searchtri, *bottommost);
10759 }
10760 *farright = farrightflag;
10761 return splayroot;
10762}
10763
10764#endif /* not REDUCED */
10765
10766#ifndef REDUCED
10767
10768#ifdef ANSI_DECLARATORS
10769long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10770#else /* not ANSI_DECLARATORS */
10771long sweeplinedelaunay(m, b)
10772struct mesh *m;
10773struct behavior *b;
10774#endif /* not ANSI_DECLARATORS */
10775
10776{
10777 struct event **eventheap;
10778 struct event *events;
10779 struct event *freeevents;
10780 struct event *nextevent;
10781 struct event *newevent;
10782 struct splaynode *splayroot;
10783 struct otri bottommost;
10784 struct otri searchtri;
10785 struct otri fliptri;
10786 struct otri lefttri, righttri, farlefttri, farrighttri;
10787 struct otri inserttri;
10788 vertex firstvertex, secondvertex;
10789 vertex nextvertex, lastvertex;
10790 vertex connectvertex;
10791 vertex leftvertex, midvertex, rightvertex;
10792 REAL lefttest, righttest;
10793 int heapsize;
10794 int check4events, farrightflag;
10795 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
10796
10797 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10799 splayroot = (struct splaynode *) NULL;
10800
10801 if (b->verbose) {
10802 printf(" Placing vertices in event heap.\n");
10803 }
10804 createeventheap(m, &eventheap, &events, &freeevents);
10805 heapsize = m->invertices;
10806
10807 if (b->verbose) {
10808 printf(" Forming triangulation.\n");
10809 }
10810 maketriangle(m, b, &lefttri);
10811 maketriangle(m, b, &righttri);
10812 bond(lefttri, righttri);
10813 lnextself(lefttri);
10814 lprevself(righttri);
10815 bond(lefttri, righttri);
10816 lnextself(lefttri);
10817 lprevself(righttri);
10818 bond(lefttri, righttri);
10819 firstvertex = (vertex) eventheap[0]->eventptr;
10820 eventheap[0]->eventptr = (VOID *) freeevents;
10821 freeevents = eventheap[0];
10822 eventheapdelete(eventheap, heapsize, 0);
10823 heapsize--;
10824 do {
10825 if (heapsize == 0) {
10826 printf("Error: Input vertices are all identical.\n");
10827 triexit(1);
10828 }
10829 secondvertex = (vertex) eventheap[0]->eventptr;
10830 eventheap[0]->eventptr = (VOID *) freeevents;
10831 freeevents = eventheap[0];
10832 eventheapdelete(eventheap, heapsize, 0);
10833 heapsize--;
10834 if ((firstvertex[0] == secondvertex[0]) &&
10835 (firstvertex[1] == secondvertex[1])) {
10836 if (!b->quiet) {
10837 printf(
10838"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10839 secondvertex[0], secondvertex[1]);
10840 }
10841 setvertextype(secondvertex, UNDEADVERTEX);
10842 m->undeads++;
10843 }
10844 } while ((firstvertex[0] == secondvertex[0]) &&
10845 (firstvertex[1] == secondvertex[1]));
10846 setorg(lefttri, firstvertex);
10847 setdest(lefttri, secondvertex);
10848 setorg(righttri, secondvertex);
10849 setdest(righttri, firstvertex);
10850 lprev(lefttri, bottommost);
10851 lastvertex = secondvertex;
10852 while (heapsize > 0) {
10853 nextevent = eventheap[0];
10854 eventheapdelete(eventheap, heapsize, 0);
10855 heapsize--;
10856 check4events = 1;
10857 if (nextevent->xkey < m->xmin) {
10858 decode(nextevent->eventptr, fliptri);
10859 oprev(fliptri, farlefttri);
10860 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10861 onext(fliptri, farrighttri);
10862 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10863
10864 if (otriequal(farlefttri, bottommost)) {
10865 lprev(fliptri, bottommost);
10866 }
10867 flip(m, b, &fliptri);
10868 setapex(fliptri, NULL);
10869 lprev(fliptri, lefttri);
10870 lnext(fliptri, righttri);
10871 sym(lefttri, farlefttri);
10872
10873 if (randomnation(SAMPLERATE) == 0) {
10874 symself(fliptri);
10875 dest(fliptri, leftvertex);
10876 apex(fliptri, midvertex);
10877 org(fliptri, rightvertex);
10878 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10879 midvertex, rightvertex, nextevent->ykey);
10880 }
10881 } else {
10882 nextvertex = (vertex) nextevent->eventptr;
10883 if ((nextvertex[0] == lastvertex[0]) &&
10884 (nextvertex[1] == lastvertex[1])) {
10885 if (!b->quiet) {
10886 printf(
10887"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10888 nextvertex[0], nextvertex[1]);
10889 }
10890 setvertextype(nextvertex, UNDEADVERTEX);
10891 m->undeads++;
10892 check4events = 0;
10893 } else {
10894 lastvertex = nextvertex;
10895
10896 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10897 &searchtri, &farrightflag);
10898/*
10899 otricopy(bottommost, searchtri);
10900 farrightflag = 0;
10901 while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) {
10902 onextself(searchtri);
10903 farrightflag = otriequal(searchtri, bottommost);
10904 }
10905*/
10906
10907 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10908
10909 otricopy(searchtri, farrighttri);
10910 sym(searchtri, farlefttri);
10911 maketriangle(m, b, &lefttri);
10912 maketriangle(m, b, &righttri);
10913 dest(farrighttri, connectvertex);
10914 setorg(lefttri, connectvertex);
10915 setdest(lefttri, nextvertex);
10916 setorg(righttri, nextvertex);
10917 setdest(righttri, connectvertex);
10918 bond(lefttri, righttri);
10919 lnextself(lefttri);
10920 lprevself(righttri);
10921 bond(lefttri, righttri);
10922 lnextself(lefttri);
10923 lprevself(righttri);
10924 bond(lefttri, farlefttri);
10925 bond(righttri, farrighttri);
10926 if (!farrightflag && otriequal(farrighttri, bottommost)) {
10927 otricopy(lefttri, bottommost);
10928 }
10929
10930 if (randomnation(SAMPLERATE) == 0) {
10931 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
10932 } else if (randomnation(SAMPLERATE) == 0) {
10933 lnext(righttri, inserttri);
10934 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
10935 }
10936 }
10937 }
10938 nextevent->eventptr = (VOID *) freeevents;
10939 freeevents = nextevent;
10940
10941 if (check4events) {
10942 apex(farlefttri, leftvertex);
10943 dest(lefttri, midvertex);
10944 apex(lefttri, rightvertex);
10945 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10946 if (lefttest > 0.0) {
10947 newevent = freeevents;
10948 freeevents = (struct event *) freeevents->eventptr;
10949 newevent->xkey = m->xminextreme;
10950 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10951 lefttest);
10952 newevent->eventptr = (VOID *) encode(lefttri);
10953 eventheapinsert(eventheap, heapsize, newevent);
10954 heapsize++;
10955 setorg(lefttri, newevent);
10956 }
10957 apex(righttri, leftvertex);
10958 org(righttri, midvertex);
10959 apex(farrighttri, rightvertex);
10960 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10961 if (righttest > 0.0) {
10962 newevent = freeevents;
10963 freeevents = (struct event *) freeevents->eventptr;
10964 newevent->xkey = m->xminextreme;
10965 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10966 righttest);
10967 newevent->eventptr = (VOID *) encode(farrighttri);
10968 eventheapinsert(eventheap, heapsize, newevent);
10969 heapsize++;
10970 setorg(farrighttri, newevent);
10971 }
10972 }
10973 }
10974
10975 pooldeinit(&m->splaynodes);
10976 lprevself(bottommost);
10977 return removeghosts(m, b, &bottommost);
10978}
10979
10980#endif /* not REDUCED */
10981
10982/** **/
10983/** **/
10984/********* Sweepline Delaunay triangulation ends here *********/
10985
10986/********* General mesh construction routines begin here *********/
10987/** **/
10988/** **/
10989
10990/*****************************************************************************/
10991/* */
10992/* delaunay() Form a Delaunay triangulation. */
10993/* */
10994/*****************************************************************************/
10995
10996#ifdef ANSI_DECLARATORS
10997long delaunay(struct mesh *m, struct behavior *b)
10998#else /* not ANSI_DECLARATORS */
10999long delaunay(m, b)
11000struct mesh *m;
11001struct behavior *b;
11002#endif /* not ANSI_DECLARATORS */
11003
11004{
11005 long hulledges;
11006
11007 m->eextras = 0;
11009
11010#ifdef REDUCED
11011 if (!b->quiet) {
11012 printf(
11013 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11014 }
11015 hulledges = divconqdelaunay(m, b);
11016#else /* not REDUCED */
11017 if (!b->quiet) {
11018 printf("Constructing Delaunay triangulation ");
11019 if (b->incremental) {
11020 printf("by incremental method.\n");
11021 } else if (b->sweepline) {
11022 printf("by sweepline method.\n");
11023 } else {
11024 printf("by divide-and-conquer method.\n");
11025 }
11026 }
11027 if (b->incremental) {
11028 hulledges = incrementaldelaunay(m, b);
11029 } else if (b->sweepline) {
11030 hulledges = sweeplinedelaunay(m, b);
11031 } else {
11032 hulledges = divconqdelaunay(m, b);
11033 }
11034#endif /* not REDUCED */
11035
11036 if (m->triangles.items == 0) {
11037 /* The input vertices were all collinear, so there are no triangles. */
11038 return 0l;
11039 } else {
11040 return hulledges;
11041 }
11042}
11043
11044/*****************************************************************************/
11045/* */
11046/* reconstruct() Reconstruct a triangulation from its .ele (and possibly */
11047/* .poly) file. Used when the -r switch is used. */
11048/* */
11049/* Reads an .ele file and reconstructs the original mesh. If the -p switch */
11050/* is used, this procedure will also read a .poly file and reconstruct the */
11051/* subsegments of the original mesh. If the -a switch is used, this */
11052/* procedure will also read an .area file and set a maximum area constraint */
11053/* on each triangle. */
11054/* */
11055/* Vertices that are not corners of triangles, such as nodes on edges of */
11056/* subparametric elements, are discarded. */
11057/* */
11058/* This routine finds the adjacencies between triangles (and subsegments) */
11059/* by forming one stack of triangles for each vertex. Each triangle is on */
11060/* three different stacks simultaneously. Each triangle's subsegment */
11061/* pointers are used to link the items in each stack. This memory-saving */
11062/* feature makes the code harder to read. The most important thing to keep */
11063/* in mind is that each triangle is removed from a stack precisely when */
11064/* the corresponding pointer is adjusted to refer to a subsegment rather */
11065/* than the next triangle of the stack. */
11066/* */
11067/*****************************************************************************/
11068
11069#ifndef CDT_ONLY
11070
11071#ifdef TRILIBRARY
11072
11073#ifdef ANSI_DECLARATORS
11074int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11075 REAL *triangleattriblist, REAL *trianglearealist,
11076 int elements, int corners, int attribs,
11077 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11078#else /* not ANSI_DECLARATORS */
11079int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11080 elements, corners, attribs, segmentlist, segmentmarkerlist,
11081 numberofsegments)
11082struct mesh *m;
11083struct behavior *b;
11084int *trianglelist;
11085REAL *triangleattriblist;
11086REAL *trianglearealist;
11087int elements;
11088int corners;
11089int attribs;
11090int *segmentlist;
11091int *segmentmarkerlist;
11092int numberofsegments;
11093#endif /* not ANSI_DECLARATORS */
11094
11095#else /* not TRILIBRARY */
11096
11097#ifdef ANSI_DECLARATORS
11098long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11099 char *areafilename, char *polyfilename, FILE *polyfile)
11100#else /* not ANSI_DECLARATORS */
11101long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11102struct mesh *m;
11103struct behavior *b;
11104char *elefilename;
11105char *areafilename;
11106char *polyfilename;
11107FILE *polyfile;
11108#endif /* not ANSI_DECLARATORS */
11109
11110#endif /* not TRILIBRARY */
11111
11112{
11113#ifdef TRILIBRARY
11114 int vertexindex;
11115 int attribindex;
11116#else /* not TRILIBRARY */
11117 FILE *elefile;
11118 FILE *areafile;
11119 char inputline[INPUTLINESIZE];
11120 char *stringptr;
11121 int areaelements;
11122#endif /* not TRILIBRARY */
11123 struct otri triangleloop;
11124 struct otri triangleleft;
11125 struct otri checktri;
11126 struct otri checkleft;
11127 struct otri checkneighbor;
11128 struct osub subsegloop;
11129 triangle *vertexarray;
11130 triangle *prevlink;
11131 triangle nexttri;
11132 vertex tdest, tapex;
11133 vertex checkdest, checkapex;
11134 vertex shorg;
11135 vertex killvertex;
11136 vertex segmentorg, segmentdest;
11137 REAL area;
11138 int corner[3];
11139 int end[2];
11140 int killvertexindex;
11141 int incorners;
11142 int segmentmarkers;
11143 int boundmarker;
11144 int aroundvertex;
11145 long hullsize;
11146 int notfound;
11147 long elementnumber, segmentnumber;
11148 int i, j;
11149 triangle ptr; /* Temporary variable used by sym(). */
11150
11151#ifdef TRILIBRARY
11152 m->inelements = elements;
11153 incorners = corners;
11154 if (incorners < 3) {
11155 printf("Error: Triangles must have at least 3 vertices.\n");
11156 triexit(1);
11157 }
11158 m->eextras = attribs;
11159#else /* not TRILIBRARY */
11160 /* Read the triangles from an .ele file. */
11161 if (!b->quiet) {
11162 printf("Opening %s.\n", elefilename);
11163 }
11164 elefile = fopen(elefilename, "r");
11165 if (elefile == (FILE *) NULL) {
11166 printf(" Error: Cannot access file %s.\n", elefilename);
11167 triexit(1);
11168 }
11169 /* Read number of triangles, number of vertices per triangle, and */
11170 /* number of triangle attributes from .ele file. */
11171 stringptr = readline(inputline, elefile, elefilename);
11172 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11173 stringptr = findfield(stringptr);
11174 if (*stringptr == '\0') {
11175 incorners = 3;
11176 } else {
11177 incorners = (int) strtol(stringptr, &stringptr, 0);
11178 if (incorners < 3) {
11179 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11180 elefilename);
11181 triexit(1);
11182 }
11183 }
11184 stringptr = findfield(stringptr);
11185 if (*stringptr == '\0') {
11186 m->eextras = 0;
11187 } else {
11188 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11189 }
11190#endif /* not TRILIBRARY */
11191
11193
11194 /* Create the triangles. */
11195 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11196 maketriangle(m, b, &triangleloop);
11197 /* Mark the triangle as living. */
11198 triangleloop.tri[3] = (triangle) triangleloop.tri;
11199 }
11200
11201 segmentmarkers = 0;
11202 if (b->poly) {
11203#ifdef TRILIBRARY
11204 m->insegments = numberofsegments;
11205 segmentmarkers = segmentmarkerlist != (int *) NULL;
11206#else /* not TRILIBRARY */
11207 /* Read number of segments and number of segment */
11208 /* boundary markers from .poly file. */
11209 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11210 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11211 stringptr = findfield(stringptr);
11212 if (*stringptr != '\0') {
11213 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11214 }
11215#endif /* not TRILIBRARY */
11216
11217 /* Create the subsegments. */
11218 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11219 makesubseg(m, &subsegloop);
11220 /* Mark the subsegment as living. */
11221 subsegloop.ss[2] = (subseg) subsegloop.ss;
11222 }
11223 }
11224
11225#ifdef TRILIBRARY
11226 vertexindex = 0;
11227 attribindex = 0;
11228#else /* not TRILIBRARY */
11229 if (b->vararea) {
11230 /* Open an .area file, check for consistency with the .ele file. */
11231 if (!b->quiet) {
11232 printf("Opening %s.\n", areafilename);
11233 }
11234 areafile = fopen(areafilename, "r");
11235 if (areafile == (FILE *) NULL) {
11236 printf(" Error: Cannot access file %s.\n", areafilename);
11237 triexit(1);
11238 }
11239 stringptr = readline(inputline, areafile, areafilename);
11240 areaelements = (int) strtol(stringptr, &stringptr, 0);
11241 if (areaelements != m->inelements) {
11242 printf("Error: %s and %s disagree on number of triangles.\n",
11243 elefilename, areafilename);
11244 triexit(1);
11245 }
11246 }
11247#endif /* not TRILIBRARY */
11248
11249 if (!b->quiet) {
11250 printf("Reconstructing mesh.\n");
11251 }
11252 /* Allocate a temporary array that maps each vertex to some adjacent */
11253 /* triangle. I took care to allocate all the permanent memory for */
11254 /* triangles and subsegments first. */
11255 vertexarray = (triangle *) trimalloc(m->vertices.items *
11256 (int) sizeof(triangle));
11257 /* Each vertex is initially unrepresented. */
11258 for (i = 0; i < m->vertices.items; i++) {
11259 vertexarray[i] = (triangle) m->dummytri;
11260 }
11261
11262 if (b->verbose) {
11263 printf(" Assembling triangles.\n");
11264 }
11265 /* Read the triangles from the .ele file, and link */
11266 /* together those that share an edge. */
11267 traversalinit(&m->triangles);
11268 triangleloop.tri = triangletraverse(m);
11269 elementnumber = b->firstnumber;
11270 while (triangleloop.tri != (triangle *) NULL) {
11271#ifdef TRILIBRARY
11272 /* Copy the triangle's three corners. */
11273 for (j = 0; j < 3; j++) {
11274 corner[j] = trianglelist[vertexindex++];
11275 if ((corner[j] < b->firstnumber) ||
11276 (corner[j] >= b->firstnumber + m->invertices)) {
11277 printf("Error: Triangle %ld has an invalid vertex index.\n",
11278 elementnumber);
11279 triexit(1);
11280 }
11281 }
11282#else /* not TRILIBRARY */
11283 /* Read triangle number and the triangle's three corners. */
11284 stringptr = readline(inputline, elefile, elefilename);
11285 for (j = 0; j < 3; j++) {
11286 stringptr = findfield(stringptr);
11287 if (*stringptr == '\0') {
11288 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11289 elementnumber, j + 1, elefilename);
11290 triexit(1);
11291 } else {
11292 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11293 if ((corner[j] < b->firstnumber) ||
11294 (corner[j] >= b->firstnumber + m->invertices)) {
11295 printf("Error: Triangle %ld has an invalid vertex index.\n",
11296 elementnumber);
11297 triexit(1);
11298 }
11299 }
11300 }
11301#endif /* not TRILIBRARY */
11302
11303 /* Find out about (and throw away) extra nodes. */
11304 for (j = 3; j < incorners; j++) {
11305#ifdef TRILIBRARY
11306 killvertexindex = trianglelist[vertexindex++];
11307#else /* not TRILIBRARY */
11308 stringptr = findfield(stringptr);
11309 if (*stringptr != '\0') {
11310 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11311#endif /* not TRILIBRARY */
11312 if ((killvertexindex >= b->firstnumber) &&
11313 (killvertexindex < b->firstnumber + m->invertices)) {
11314 /* Delete the non-corner vertex if it's not already deleted. */
11315 killvertex = getvertex(m, b, killvertexindex);
11316 if (vertextype(killvertex) != DEADVERTEX) {
11317 vertexdealloc(m, killvertex);
11318 }
11319 }
11320#ifndef TRILIBRARY
11321 }
11322#endif /* not TRILIBRARY */
11323 }
11324
11325 /* Read the triangle's attributes. */
11326 for (j = 0; j < m->eextras; j++) {
11327#ifdef TRILIBRARY
11328 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11329#else /* not TRILIBRARY */
11330 stringptr = findfield(stringptr);
11331 if (*stringptr == '\0') {
11332 setelemattribute(triangleloop, j, 0);
11333 } else {
11334 setelemattribute(triangleloop, j,
11335 (REAL) strtod(stringptr, &stringptr));
11336 }
11337#endif /* not TRILIBRARY */
11338 }
11339
11340 if (b->vararea) {
11341#ifdef TRILIBRARY
11342 area = trianglearealist[elementnumber - b->firstnumber];
11343#else /* not TRILIBRARY */
11344 /* Read an area constraint from the .area file. */
11345 stringptr = readline(inputline, areafile, areafilename);
11346 stringptr = findfield(stringptr);
11347 if (*stringptr == '\0') {
11348 area = -1.0; /* No constraint on this triangle. */
11349 } else {
11350 area = (REAL) strtod(stringptr, &stringptr);
11351 }
11352#endif /* not TRILIBRARY */
11353 setareabound(triangleloop, area);
11354 }
11355
11356 /* Set the triangle's vertices. */
11357 triangleloop.orient = 0;
11358 setorg(triangleloop, getvertex(m, b, corner[0]));
11359 setdest(triangleloop, getvertex(m, b, corner[1]));
11360 setapex(triangleloop, getvertex(m, b, corner[2]));
11361 /* Try linking the triangle to others that share these vertices. */
11362 for (triangleloop.orient = 0; triangleloop.orient < 3;
11363 triangleloop.orient++) {
11364 /* Take the number for the origin of triangleloop. */
11365 aroundvertex = corner[triangleloop.orient];
11366 /* Look for other triangles having this vertex. */
11367 nexttri = vertexarray[aroundvertex - b->firstnumber];
11368 /* Link the current triangle to the next one in the stack. */
11369 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11370 /* Push the current triangle onto the stack. */
11371 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11372 decode(nexttri, checktri);
11373 if (checktri.tri != m->dummytri) {
11374 dest(triangleloop, tdest);
11375 apex(triangleloop, tapex);
11376 /* Look for other triangles that share an edge. */
11377 do {
11378 dest(checktri, checkdest);
11379 apex(checktri, checkapex);
11380 if (tapex == checkdest) {
11381 /* The two triangles share an edge; bond them together. */
11382 lprev(triangleloop, triangleleft);
11383 bond(triangleleft, checktri);
11384 }
11385 if (tdest == checkapex) {
11386 /* The two triangles share an edge; bond them together. */
11387 lprev(checktri, checkleft);
11388 bond(triangleloop, checkleft);
11389 }
11390 /* Find the next triangle in the stack. */
11391 nexttri = checktri.tri[6 + checktri.orient];
11392 decode(nexttri, checktri);
11393 } while (checktri.tri != m->dummytri);
11394 }
11395 }
11396 triangleloop.tri = triangletraverse(m);
11397 elementnumber++;
11398 }
11399
11400#ifdef TRILIBRARY
11401 vertexindex = 0;
11402#else /* not TRILIBRARY */
11403 fclose(elefile);
11404 if (b->vararea) {
11405 fclose(areafile);
11406 }
11407#endif /* not TRILIBRARY */
11408
11409 hullsize = 0; /* Prepare to count the boundary edges. */
11410 if (b->poly) {
11411 if (b->verbose) {
11412 printf(" Marking segments in triangulation.\n");
11413 }
11414 /* Read the segments from the .poly file, and link them */
11415 /* to their neighboring triangles. */
11416 boundmarker = 0;
11417 traversalinit(&m->subsegs);
11418 subsegloop.ss = subsegtraverse(m);
11419 segmentnumber = b->firstnumber;
11420 while (subsegloop.ss != (subseg *) NULL) {
11421#ifdef TRILIBRARY
11422 end[0] = segmentlist[vertexindex++];
11423 end[1] = segmentlist[vertexindex++];
11424 if (segmentmarkers) {
11425 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11426 }
11427#else /* not TRILIBRARY */
11428 /* Read the endpoints of each segment, and possibly a boundary marker. */
11429 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11430 /* Skip the first (segment number) field. */
11431 stringptr = findfield(stringptr);
11432 if (*stringptr == '\0') {
11433 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11434 polyfilename);
11435 triexit(1);
11436 } else {
11437 end[0] = (int) strtol(stringptr, &stringptr, 0);
11438 }
11439 stringptr = findfield(stringptr);
11440 if (*stringptr == '\0') {
11441 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11442 segmentnumber, polyfilename);
11443 triexit(1);
11444 } else {
11445 end[1] = (int) strtol(stringptr, &stringptr, 0);
11446 }
11447 if (segmentmarkers) {
11448 stringptr = findfield(stringptr);
11449 if (*stringptr == '\0') {
11450 boundmarker = 0;
11451 } else {
11452 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11453 }
11454 }
11455#endif /* not TRILIBRARY */
11456 for (j = 0; j < 2; j++) {
11457 if ((end[j] < b->firstnumber) ||
11458 (end[j] >= b->firstnumber + m->invertices)) {
11459 printf("Error: Segment %ld has an invalid vertex index.\n",
11460 segmentnumber);
11461 triexit(1);
11462 }
11463 }
11464
11465 /* set the subsegment's vertices. */
11466 subsegloop.ssorient = 0;
11467 segmentorg = getvertex(m, b, end[0]);
11468 segmentdest = getvertex(m, b, end[1]);
11469 setsorg(subsegloop, segmentorg);
11470 setsdest(subsegloop, segmentdest);
11471 setsegorg(subsegloop, segmentorg);
11472 setsegdest(subsegloop, segmentdest);
11473 setmark(subsegloop, boundmarker);
11474 /* Try linking the subsegment to triangles that share these vertices. */
11475 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11476 subsegloop.ssorient++) {
11477 /* Take the number for the destination of subsegloop. */
11478 aroundvertex = end[1 - subsegloop.ssorient];
11479 /* Look for triangles having this vertex. */
11480 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11481 nexttri = vertexarray[aroundvertex - b->firstnumber];
11482 decode(nexttri, checktri);
11483 sorg(subsegloop, shorg);
11484 notfound = 1;
11485 /* Look for triangles having this edge. Note that I'm only */
11486 /* comparing each triangle's destination with the subsegment; */
11487 /* each triangle's apex is handled through a different vertex. */
11488 /* Because each triangle appears on three vertices' lists, each */
11489 /* occurrence of a triangle on a list can (and does) represent */
11490 /* an edge. In this way, most edges are represented twice, and */
11491 /* every triangle-subsegment bond is represented once. */
11492 while (notfound && (checktri.tri != m->dummytri)) {
11493 dest(checktri, checkdest);
11494 if (shorg == checkdest) {
11495 /* We have a match. Remove this triangle from the list. */
11496 *prevlink = checktri.tri[6 + checktri.orient];
11497 /* Bond the subsegment to the triangle. */
11498 tsbond(checktri, subsegloop);
11499 /* Check if this is a boundary edge. */
11500 sym(checktri, checkneighbor);
11501 if (checkneighbor.tri == m->dummytri) {
11502 /* The next line doesn't insert a subsegment (because there's */
11503 /* already one there), but it sets the boundary markers of */
11504 /* the existing subsegment and its vertices. */
11505 insertsubseg(m, b, &checktri, 1);
11506 hullsize++;
11507 }
11508 notfound = 0;
11509 }
11510 /* Find the next triangle in the stack. */
11511 prevlink = &checktri.tri[6 + checktri.orient];
11512 nexttri = checktri.tri[6 + checktri.orient];
11513 decode(nexttri, checktri);
11514 }
11515 }
11516 subsegloop.ss = subsegtraverse(m);
11517 segmentnumber++;
11518 }
11519 }
11520
11521 /* Mark the remaining edges as not being attached to any subsegment. */
11522 /* Also, count the (yet uncounted) boundary edges. */
11523 for (i = 0; i < m->vertices.items; i++) {
11524 /* Search the stack of triangles adjacent to a vertex. */
11525 nexttri = vertexarray[i];
11526 decode(nexttri, checktri);
11527 while (checktri.tri != m->dummytri) {
11528 /* Find the next triangle in the stack before this */
11529 /* information gets overwritten. */
11530 nexttri = checktri.tri[6 + checktri.orient];
11531 /* No adjacent subsegment. (This overwrites the stack info.) */
11532 tsdissolve(checktri);
11533 sym(checktri, checkneighbor);
11534 if (checkneighbor.tri == m->dummytri) {
11535 insertsubseg(m, b, &checktri, 1);
11536 hullsize++;
11537 }
11538 decode(nexttri, checktri);
11539 }
11540 }
11541
11542 trifree((VOID *) vertexarray);
11543 return hullsize;
11544}
11545
11546#endif /* not CDT_ONLY */
11547
11548/** **/
11549/** **/
11550/********* General mesh construction routines end here *********/
11551
11552/********* Segment insertion begins here *********/
11553/** **/
11554/** **/
11555
11556/*****************************************************************************/
11557/* */
11558/* finddirection() Find the first triangle on the path from one point */
11559/* to another. */
11560/* */
11561/* Finds the triangle that intersects a line segment drawn from the */
11562/* origin of `searchtri' to the point `searchpoint', and returns the result */
11563/* in `searchtri'. The origin of `searchtri' does not change, even though */
11564/* the triangle returned may differ from the one passed in. This routine */
11565/* is used to find the direction to move in to get from one point to */
11566/* another. */
11567/* */
11568/* The return value notes whether the destination or apex of the found */
11569/* triangle is collinear with the two points in question. */
11570/* */
11571/*****************************************************************************/
11572
11573#ifdef ANSI_DECLARATORS
11574enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11575 struct otri *searchtri,
11576 vertex searchpoint)
11577#else /* not ANSI_DECLARATORS */
11578enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11579struct mesh *m;
11580struct behavior *b;
11581struct otri *searchtri;
11582vertex searchpoint;
11583#endif /* not ANSI_DECLARATORS */
11584
11585{
11586 struct otri checktri;
11587 vertex startvertex;
11588 vertex leftvertex, rightvertex;
11589 REAL leftccw, rightccw;
11590 int leftflag, rightflag;
11591 triangle ptr; /* Temporary variable used by onext() and oprev(). */
11592
11593 org(*searchtri, startvertex);
11594 dest(*searchtri, rightvertex);
11595 apex(*searchtri, leftvertex);
11596 /* Is `searchpoint' to the left? */
11597 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11598 leftflag = leftccw > 0.0;
11599 /* Is `searchpoint' to the right? */
11600 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11601 rightflag = rightccw > 0.0;
11602 if (leftflag && rightflag) {
11603 /* `searchtri' faces directly away from `searchpoint'. We could go left */
11604 /* or right. Ask whether it's a triangle or a boundary on the left. */
11605 onext(*searchtri, checktri);
11606 if (checktri.tri == m->dummytri) {
11607 leftflag = 0;
11608 } else {
11609 rightflag = 0;
11610 }
11611 }
11612 while (leftflag) {
11613 /* Turn left until satisfied. */
11614 onextself(*searchtri);
11615 if (searchtri->tri == m->dummytri) {
11616 printf("Internal error in finddirection(): Unable to find a\n");
11617 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11618 startvertex[1]);
11619 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11620 internalerror();
11621 }
11622 apex(*searchtri, leftvertex);
11623 rightccw = leftccw;
11624 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11625 leftflag = leftccw > 0.0;
11626 }
11627 while (rightflag) {
11628 /* Turn right until satisfied. */
11629 oprevself(*searchtri);
11630 if (searchtri->tri == m->dummytri) {
11631 printf("Internal error in finddirection(): Unable to find a\n");
11632 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11633 startvertex[1]);
11634 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11635 internalerror();
11636 }
11637 dest(*searchtri, rightvertex);
11638 leftccw = rightccw;
11639 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11640 rightflag = rightccw > 0.0;
11641 }
11642 if (leftccw == 0.0) {
11643 return LEFTCOLLINEAR;
11644 } else if (rightccw == 0.0) {
11645 return RIGHTCOLLINEAR;
11646 } else {
11647 return WITHIN;
11648 }
11649}
11650
11651/*****************************************************************************/
11652/* */
11653/* segmentintersection() Find the intersection of an existing segment */
11654/* and a segment that is being inserted. Insert */
11655/* a vertex at the intersection, splitting an */
11656/* existing subsegment. */
11657/* */
11658/* The segment being inserted connects the apex of splittri to endpoint2. */
11659/* splitsubseg is the subsegment being split, and MUST adjoin splittri. */
11660/* Hence, endpoints of the subsegment being split are the origin and */
11661/* destination of splittri. */
11662/* */
11663/* On completion, splittri is a handle having the newly inserted */
11664/* intersection point as its origin, and endpoint1 as its destination. */
11665/* */
11666/*****************************************************************************/
11667
11668#ifdef ANSI_DECLARATORS
11669void segmentintersection(struct mesh *m, struct behavior *b,
11670 struct otri *splittri, struct osub *splitsubseg,
11671 vertex endpoint2)
11672#else /* not ANSI_DECLARATORS */
11673void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11674struct mesh *m;
11675struct behavior *b;
11676struct otri *splittri;
11677struct osub *splitsubseg;
11678vertex endpoint2;
11679#endif /* not ANSI_DECLARATORS */
11680
11681{
11682 struct osub opposubseg;
11683 vertex endpoint1;
11684 vertex torg, tdest;
11685 vertex leftvertex, rightvertex;
11686 vertex newvertex;
11687 enum insertvertexresult success;
11688 /* enum finddirectionresult collinear; LM: remove unsed variable warning */
11689 REAL ex, ey;
11690 REAL tx, ty;
11691 REAL etx, ety;
11692 REAL split, denom;
11693 int i;
11694 triangle ptr; /* Temporary variable used by onext(). */
11695 subseg sptr; /* Temporary variable used by snext(). */
11696
11697 /* Find the other three segment endpoints. */
11698 apex(*splittri, endpoint1);
11699 org(*splittri, torg);
11700 dest(*splittri, tdest);
11701 /* Segment intersection formulae; see the Antonio reference. */
11702 tx = tdest[0] - torg[0];
11703 ty = tdest[1] - torg[1];
11704 ex = endpoint2[0] - endpoint1[0];
11705 ey = endpoint2[1] - endpoint1[1];
11706 etx = torg[0] - endpoint2[0];
11707 ety = torg[1] - endpoint2[1];
11708 denom = ty * ex - tx * ey;
11709 if (denom == 0.0) {
11710 printf("Internal error in segmentintersection():");
11711 printf(" Attempt to find intersection of parallel segments.\n");
11712 internalerror();
11713 }
11714 split = (ey * etx - ex * ety) / denom;
11715 /* Create the new vertex. */
11716 newvertex = (vertex) poolalloc(&m->vertices);
11717 /* Interpolate its coordinate and attributes. */
11718 for (i = 0; i < 2 + m->nextras; i++) {
11719 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11720 }
11721 setvertexmark(newvertex, mark(*splitsubseg));
11722 setvertextype(newvertex, INPUTVERTEX);
11723 if (b->verbose > 1) {
11724 printf(
11725 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11726 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11727 }
11728 /* Insert the intersection vertex. This should always succeed. */
11729 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11730 if (success != SUCCESSFULVERTEX) {
11731 printf("Internal error in segmentintersection():\n");
11732 printf(" Failure to split a segment.\n");
11733 internalerror();
11734 }
11735 /* Record a triangle whose origin is the new vertex. */
11736 setvertex2tri(newvertex, encode(*splittri));
11737 if (m->steinerleft > 0) {
11738 m->steinerleft--;
11739 }
11740
11741 /* Divide the segment into two, and correct the segment endpoints. */
11742 ssymself(*splitsubseg);
11743 spivot(*splitsubseg, opposubseg);
11744 sdissolve(*splitsubseg);
11745 sdissolve(opposubseg);
11746 do {
11747 setsegorg(*splitsubseg, newvertex);
11748 snextself(*splitsubseg);
11749 } while (splitsubseg->ss != m->dummysub);
11750 do {
11751 setsegorg(opposubseg, newvertex);
11752 snextself(opposubseg);
11753 } while (opposubseg.ss != m->dummysub);
11754
11755 /* Inserting the vertex may have caused edge flips. We wish to rediscover */
11756 /* the edge connecting endpoint1 to the new intersection vertex. */
11757 /* collinear = LN: remove unsed variable warning */
11758 finddirection(m, b, splittri, endpoint1);
11759 dest(*splittri, rightvertex);
11760 apex(*splittri, leftvertex);
11761 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11762 onextself(*splittri);
11763 } else if ((rightvertex[0] != endpoint1[0]) ||
11764 (rightvertex[1] != endpoint1[1])) {
11765 printf("Internal error in segmentintersection():\n");
11766 printf(" Topological inconsistency after splitting a segment.\n");
11767 internalerror();
11768 }
11769 /* `splittri' should have destination endpoint1. */
11770}
11771
11772/*****************************************************************************/
11773/* */
11774/* scoutsegment() Scout the first triangle on the path from one endpoint */
11775/* to another, and check for completion (reaching the */
11776/* second endpoint), a collinear vertex, or the */
11777/* intersection of two segments. */
11778/* */
11779/* Returns one if the entire segment is successfully inserted, and zero if */
11780/* the job must be finished by conformingedge() or constrainededge(). */
11781/* */
11782/* If the first triangle on the path has the second endpoint as its */
11783/* destination or apex, a subsegment is inserted and the job is done. */
11784/* */
11785/* If the first triangle on the path has a destination or apex that lies on */
11786/* the segment, a subsegment is inserted connecting the first endpoint to */
11787/* the collinear vertex, and the search is continued from the collinear */
11788/* vertex. */
11789/* */
11790/* If the first triangle on the path has a subsegment opposite its origin, */
11791/* then there is a segment that intersects the segment being inserted. */
11792/* Their intersection vertex is inserted, splitting the subsegment. */
11793/* */
11794/*****************************************************************************/
11795
11796#ifdef ANSI_DECLARATORS
11797int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11798 vertex endpoint2, int newmark)
11799#else /* not ANSI_DECLARATORS */
11800int scoutsegment(m, b, searchtri, endpoint2, newmark)
11801struct mesh *m;
11802struct behavior *b;
11803struct otri *searchtri;
11804vertex endpoint2;
11805int newmark;
11806#endif /* not ANSI_DECLARATORS */
11807
11808{
11809 struct otri crosstri;
11810 struct osub crosssubseg;
11811 vertex leftvertex, rightvertex;
11812 enum finddirectionresult collinear;
11813 subseg sptr; /* Temporary variable used by tspivot(). */
11814
11815 collinear = finddirection(m, b, searchtri, endpoint2);
11816 dest(*searchtri, rightvertex);
11817 apex(*searchtri, leftvertex);
11818 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11819 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11820 /* The segment is already an edge in the mesh. */
11821 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11822 lprevself(*searchtri);
11823 }
11824 /* Insert a subsegment, if there isn't already one there. */
11825 insertsubseg(m, b, searchtri, newmark);
11826 return 1;
11827 } else if (collinear == LEFTCOLLINEAR) {
11828 /* We've collided with a vertex between the segment's endpoints. */
11829 /* Make the collinear vertex be the triangle's origin. */
11830 lprevself(*searchtri);
11831 insertsubseg(m, b, searchtri, newmark);
11832 /* Insert the remainder of the segment. */
11833 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11834 } else if (collinear == RIGHTCOLLINEAR) {
11835 /* We've collided with a vertex between the segment's endpoints. */
11836 insertsubseg(m, b, searchtri, newmark);
11837 /* Make the collinear vertex be the triangle's origin. */
11838 lnextself(*searchtri);
11839 /* Insert the remainder of the segment. */
11840 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11841 } else {
11842 lnext(*searchtri, crosstri);
11843 tspivot(crosstri, crosssubseg);
11844 /* Check for a crossing segment. */
11845 if (crosssubseg.ss == m->dummysub) {
11846 return 0;
11847 } else {
11848 /* Insert a vertex at the intersection. */
11849 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11850 otricopy(crosstri, *searchtri);
11851 insertsubseg(m, b, searchtri, newmark);
11852 /* Insert the remainder of the segment. */
11853 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11854 }
11855 }
11856}
11857
11858/*****************************************************************************/
11859/* */
11860/* conformingedge() Force a segment into a conforming Delaunay */
11861/* triangulation by inserting a vertex at its midpoint, */
11862/* and recursively forcing in the two half-segments if */
11863/* necessary. */
11864/* */
11865/* Generates a sequence of subsegments connecting `endpoint1' to */
11866/* `endpoint2'. `newmark' is the boundary marker of the segment, assigned */
11867/* to each new splitting vertex and subsegment. */
11868/* */
11869/* Note that conformingedge() does not always maintain the conforming */
11870/* Delaunay property. Once inserted, segments are locked into place; */
11871/* vertices inserted later (to force other segments in) may render these */
11872/* fixed segments non-Delaunay. The conforming Delaunay property will be */
11873/* restored by enforcequality() by splitting encroached subsegments. */
11874/* */
11875/*****************************************************************************/
11876
11877#ifndef REDUCED
11878#ifndef CDT_ONLY
11879
11880#ifdef ANSI_DECLARATORS
11881void conformingedge(struct mesh *m, struct behavior *b,
11882 vertex endpoint1, vertex endpoint2, int newmark)
11883#else /* not ANSI_DECLARATORS */
11884void conformingedge(m, b, endpoint1, endpoint2, newmark)
11885struct mesh *m;
11886struct behavior *b;
11887vertex endpoint1;
11888vertex endpoint2;
11889int newmark;
11890#endif /* not ANSI_DECLARATORS */
11891
11892{
11893 struct otri searchtri1, searchtri2;
11894 struct osub brokensubseg;
11895 vertex newvertex;
11896 vertex midvertex1, midvertex2;
11897 enum insertvertexresult success;
11898 int i;
11899 subseg sptr; /* Temporary variable used by tspivot(). */
11900
11901 if (b->verbose > 2) {
11902 printf("Forcing segment into triangulation by recursive splitting:\n");
11903 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11904 endpoint2[0], endpoint2[1]);
11905 }
11906 /* Create a new vertex to insert in the middle of the segment. */
11907 newvertex = (vertex) poolalloc(&m->vertices);
11908 /* Interpolate coordinates and attributes. */
11909 for (i = 0; i < 2 + m->nextras; i++) {
11910 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11911 }
11912 setvertexmark(newvertex, newmark);
11913 setvertextype(newvertex, SEGMENTVERTEX);
11914 /* No known triangle to search from. */
11915 searchtri1.tri = m->dummytri;
11916 /* Attempt to insert the new vertex. */
11917 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11918 0, 0);
11919 if (success == DUPLICATEVERTEX) {
11920 if (b->verbose > 2) {
11921 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
11922 newvertex[0], newvertex[1]);
11923 }
11924 /* Use the vertex that's already there. */
11925 vertexdealloc(m, newvertex);
11926 org(searchtri1, newvertex);
11927 } else {
11928 if (success == VIOLATINGVERTEX) {
11929 if (b->verbose > 2) {
11930 printf(" Two segments intersect at (%.12g, %.12g).\n",
11931 newvertex[0], newvertex[1]);
11932 }
11933 /* By fluke, we've landed right on another segment. Split it. */
11934 tspivot(searchtri1, brokensubseg);
11935 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11936 0, 0);
11937 if (success != SUCCESSFULVERTEX) {
11938 printf("Internal error in conformingedge():\n");
11939 printf(" Failure to split a segment.\n");
11940 internalerror();
11941 }
11942 }
11943 /* The vertex has been inserted successfully. */
11944 if (m->steinerleft > 0) {
11945 m->steinerleft--;
11946 }
11947 }
11948 otricopy(searchtri1, searchtri2);
11949 /* `searchtri1' and `searchtri2' are fastened at their origins to */
11950 /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */
11951 /* respectively. First, we must get `searchtri2' out of the way so it */
11952 /* won't be invalidated during the insertion of the first half of the */
11953 /* segment. */
11954 finddirection(m, b, &searchtri2, endpoint2);
11955 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11956 /* The origin of searchtri1 may have changed if a collision with an */
11957 /* intervening vertex on the segment occurred. */
11958 org(searchtri1, midvertex1);
11959 conformingedge(m, b, midvertex1, endpoint1, newmark);
11960 }
11961 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11962 /* The origin of searchtri2 may have changed if a collision with an */
11963 /* intervening vertex on the segment occurred. */
11964 org(searchtri2, midvertex2);
11965 conformingedge(m, b, midvertex2, endpoint2, newmark);
11966 }
11967}
11968
11969#endif /* not CDT_ONLY */
11970#endif /* not REDUCED */
11971
11972/*****************************************************************************/
11973/* */
11974/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */
11975/* recursively from an existing vertex. Pay special */
11976/* attention to stacking inverted triangles. */
11977/* */
11978/* This is a support routine for inserting segments into a constrained */
11979/* Delaunay triangulation. */
11980/* */
11981/* The origin of fixuptri is treated as if it has just been inserted, and */
11982/* the local Delaunay condition needs to be enforced. It is only enforced */
11983/* in one sector, however, that being the angular range defined by */
11984/* fixuptri. */
11985/* */
11986/* This routine also needs to make decisions regarding the "stacking" of */
11987/* triangles. (Read the description of constrainededge() below before */
11988/* reading on here, so you understand the algorithm.) If the position of */
11989/* the new vertex (the origin of fixuptri) indicates that the vertex before */
11990/* it on the polygon is a reflex vertex, then "stack" the triangle by */
11991/* doing nothing. (fixuptri is an inverted triangle, which is how stacked */
11992/* triangles are identified.) */
11993/* */
11994/* Otherwise, check whether the vertex before that was a reflex vertex. */
11995/* If so, perform an edge flip, thereby eliminating an inverted triangle */
11996/* (popping it off the stack). The edge flip may result in the creation */
11997/* of a new inverted triangle, depending on whether or not the new vertex */
11998/* is visible to the vertex three edges behind on the polygon. */
11999/* */
12000/* If neither of the two vertices behind the new vertex are reflex */
12001/* vertices, fixuptri and fartri, the triangle opposite it, are not */
12002/* inverted; hence, ensure that the edge between them is locally Delaunay. */
12003/* */
12004/* `leftside' indicates whether or not fixuptri is to the left of the */
12005/* segment being inserted. (Imagine that the segment is pointing up from */
12006/* endpoint1 to endpoint2.) */
12007/* */
12008/*****************************************************************************/
12009
12010#ifdef ANSI_DECLARATORS
12011void delaunayfixup(struct mesh *m, struct behavior *b,
12012 struct otri *fixuptri, int leftside)
12013#else /* not ANSI_DECLARATORS */
12014void delaunayfixup(m, b, fixuptri, leftside)
12015struct mesh *m;
12016struct behavior *b;
12017struct otri *fixuptri;
12018int leftside;
12019#endif /* not ANSI_DECLARATORS */
12020
12021{
12022 struct otri neartri;
12023 struct otri fartri;
12024 struct osub faredge;
12025 vertex nearvertex, leftvertex, rightvertex, farvertex;
12026 triangle ptr; /* Temporary variable used by sym(). */
12027 subseg sptr; /* Temporary variable used by tspivot(). */
12028
12029 lnext(*fixuptri, neartri);
12030 sym(neartri, fartri);
12031 /* Check if the edge opposite the origin of fixuptri can be flipped. */
12032 if (fartri.tri == m->dummytri) {
12033 return;
12034 }
12035 tspivot(neartri, faredge);
12036 if (faredge.ss != m->dummysub) {
12037 return;
12038 }
12039 /* Find all the relevant vertices. */
12040 apex(neartri, nearvertex);
12041 org(neartri, leftvertex);
12042 dest(neartri, rightvertex);
12043 apex(fartri, farvertex);
12044 /* Check whether the previous polygon vertex is a reflex vertex. */
12045 if (leftside) {
12046 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12047 /* leftvertex is a reflex vertex too. Nothing can */
12048 /* be done until a convex section is found. */
12049 return;
12050 }
12051 } else {
12052 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12053 /* rightvertex is a reflex vertex too. Nothing can */
12054 /* be done until a convex section is found. */
12055 return;
12056 }
12057 }
12058 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12059 /* fartri is not an inverted triangle, and farvertex is not a reflex */
12060 /* vertex. As there are no reflex vertices, fixuptri isn't an */
12061 /* inverted triangle, either. Hence, test the edge between the */
12062 /* triangles to ensure it is locally Delaunay. */
12063 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12064 0.0) {
12065 return;
12066 }
12067 /* Not locally Delaunay; go on to an edge flip. */
12068 } /* else fartri is inverted; remove it from the stack by flipping. */
12069 flip(m, b, &neartri);
12070 lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */
12071 /* Recursively process the two triangles that result from the flip. */
12072 delaunayfixup(m, b, fixuptri, leftside);
12073 delaunayfixup(m, b, &fartri, leftside);
12074}
12075
12076/*****************************************************************************/
12077/* */
12078/* constrainededge() Force a segment into a constrained Delaunay */
12079/* triangulation by deleting the triangles it */
12080/* intersects, and triangulating the polygons that */
12081/* form on each side of it. */
12082/* */
12083/* Generates a single subsegment connecting `endpoint1' to `endpoint2'. */
12084/* The triangle `starttri' has `endpoint1' as its origin. `newmark' is the */
12085/* boundary marker of the segment. */
12086/* */
12087/* To insert a segment, every triangle whose interior intersects the */
12088/* segment is deleted. The union of these deleted triangles is a polygon */
12089/* (which is not necessarily monotone, but is close enough), which is */
12090/* divided into two polygons by the new segment. This routine's task is */
12091/* to generate the Delaunay triangulation of these two polygons. */
12092/* */
12093/* You might think of this routine's behavior as a two-step process. The */
12094/* first step is to walk from endpoint1 to endpoint2, flipping each edge */
12095/* encountered. This step creates a fan of edges connected to endpoint1, */
12096/* including the desired edge to endpoint2. The second step enforces the */
12097/* Delaunay condition on each side of the segment in an incremental manner: */
12098/* proceeding along the polygon from endpoint1 to endpoint2 (this is done */
12099/* independently on each side of the segment), each vertex is "enforced" */
12100/* as if it had just been inserted, but affecting only the previous */
12101/* vertices. The result is the same as if the vertices had been inserted */
12102/* in the order they appear on the polygon, so the result is Delaunay. */
12103/* */
12104/* In truth, constrainededge() interleaves these two steps. The procedure */
12105/* walks from endpoint1 to endpoint2, and each time an edge is encountered */
12106/* and flipped, the newly exposed vertex (at the far end of the flipped */
12107/* edge) is "enforced" upon the previously flipped edges, usually affecting */
12108/* only one side of the polygon (depending upon which side of the segment */
12109/* the vertex falls on). */
12110/* */
12111/* The algorithm is complicated by the need to handle polygons that are not */
12112/* convex. Although the polygon is not necessarily monotone, it can be */
12113/* triangulated in a manner similar to the stack-based algorithms for */
12114/* monotone polygons. For each reflex vertex (local concavity) of the */
12115/* polygon, there will be an inverted triangle formed by one of the edge */
12116/* flips. (An inverted triangle is one with negative area - that is, its */
12117/* vertices are arranged in clockwise order - and is best thought of as a */
12118/* wrinkle in the fabric of the mesh.) Each inverted triangle can be */
12119/* thought of as a reflex vertex pushed on the stack, waiting to be fixed */
12120/* later. */
12121/* */
12122/* A reflex vertex is popped from the stack when a vertex is inserted that */
12123/* is visible to the reflex vertex. (However, if the vertex behind the */
12124/* reflex vertex is not visible to the reflex vertex, a new inverted */
12125/* triangle will take its place on the stack.) These details are handled */
12126/* by the delaunayfixup() routine above. */
12127/* */
12128/*****************************************************************************/
12129
12130#ifdef ANSI_DECLARATORS
12131void constrainededge(struct mesh *m, struct behavior *b,
12132 struct otri *starttri, vertex endpoint2, int newmark)
12133#else /* not ANSI_DECLARATORS */
12134void constrainededge(m, b, starttri, endpoint2, newmark)
12135struct mesh *m;
12136struct behavior *b;
12137struct otri *starttri;
12138vertex endpoint2;
12139int newmark;
12140#endif /* not ANSI_DECLARATORS */
12141
12142{
12143 struct otri fixuptri, fixuptri2;
12144 struct osub crosssubseg;
12145 vertex endpoint1;
12146 vertex farvertex;
12147 REAL area;
12148 int collision;
12149 int done;
12150 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12151 subseg sptr; /* Temporary variable used by tspivot(). */
12152
12153 org(*starttri, endpoint1);
12154 lnext(*starttri, fixuptri);
12155 flip(m, b, &fixuptri);
12156 /* `collision' indicates whether we have found a vertex directly */
12157 /* between endpoint1 and endpoint2. */
12158 collision = 0;
12159 done = 0;
12160 do {
12161 org(fixuptri, farvertex);
12162 /* `farvertex' is the extreme point of the polygon we are "digging" */
12163 /* to get from endpoint1 to endpoint2. */
12164 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12165 oprev(fixuptri, fixuptri2);
12166 /* Enforce the Delaunay condition around endpoint2. */
12167 delaunayfixup(m, b, &fixuptri, 0);
12168 delaunayfixup(m, b, &fixuptri2, 1);
12169 done = 1;
12170 } else {
12171 /* Check whether farvertex is to the left or right of the segment */
12172 /* being inserted, to decide which edge of fixuptri to dig */
12173 /* through next. */
12174 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12175 if (area == 0.0) {
12176 /* We've collided with a vertex between endpoint1 and endpoint2. */
12177 collision = 1;
12178 oprev(fixuptri, fixuptri2);
12179 /* Enforce the Delaunay condition around farvertex. */
12180 delaunayfixup(m, b, &fixuptri, 0);
12181 delaunayfixup(m, b, &fixuptri2, 1);
12182 done = 1;
12183 } else {
12184 if (area > 0.0) { /* farvertex is to the left of the segment. */
12185 oprev(fixuptri, fixuptri2);
12186 /* Enforce the Delaunay condition around farvertex, on the */
12187 /* left side of the segment only. */
12188 delaunayfixup(m, b, &fixuptri2, 1);
12189 /* Flip the edge that crosses the segment. After the edge is */
12190 /* flipped, one of its endpoints is the fan vertex, and the */
12191 /* destination of fixuptri is the fan vertex. */
12192 lprevself(fixuptri);
12193 } else { /* farvertex is to the right of the segment. */
12194 delaunayfixup(m, b, &fixuptri, 0);
12195 /* Flip the edge that crosses the segment. After the edge is */
12196 /* flipped, one of its endpoints is the fan vertex, and the */
12197 /* destination of fixuptri is the fan vertex. */
12198 oprevself(fixuptri);
12199 }
12200 /* Check for two intersecting segments. */
12201 tspivot(fixuptri, crosssubseg);
12202 if (crosssubseg.ss == m->dummysub) {
12203 flip(m, b, &fixuptri); /* May create inverted triangle at left. */
12204 } else {
12205 /* We've collided with a segment between endpoint1 and endpoint2. */
12206 collision = 1;
12207 /* Insert a vertex at the intersection. */
12208 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12209 done = 1;
12210 }
12211 }
12212 }
12213 } while (!done);
12214 /* Insert a subsegment to make the segment permanent. */
12215 insertsubseg(m, b, &fixuptri, newmark);
12216 /* If there was a collision with an interceding vertex, install another */
12217 /* segment connecting that vertex with endpoint2. */
12218 if (collision) {
12219 /* Insert the remainder of the segment. */
12220 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12221 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12222 }
12223 }
12224}
12225
12226/*****************************************************************************/
12227/* */
12228/* insertsegment() Insert a PSLG segment into a triangulation. */
12229/* */
12230/*****************************************************************************/
12231
12232#ifdef ANSI_DECLARATORS
12233void insertsegment(struct mesh *m, struct behavior *b,
12234 vertex endpoint1, vertex endpoint2, int newmark)
12235#else /* not ANSI_DECLARATORS */
12236void insertsegment(m, b, endpoint1, endpoint2, newmark)
12237struct mesh *m;
12238struct behavior *b;
12239vertex endpoint1;
12240vertex endpoint2;
12241int newmark;
12242#endif /* not ANSI_DECLARATORS */
12243
12244{
12245 struct otri searchtri1, searchtri2;
12246 triangle encodedtri;
12247 vertex checkvertex;
12248 triangle ptr; /* Temporary variable used by sym(). */
12249
12250 if (b->verbose > 1) {
12251 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12252 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12253 }
12254
12255 /* Find a triangle whose origin is the segment's first endpoint. */
12256 checkvertex = (vertex) NULL;
12257 encodedtri = vertex2tri(endpoint1);
12258 if (encodedtri != (triangle) NULL) {
12259 decode(encodedtri, searchtri1);
12260 org(searchtri1, checkvertex);
12261 }
12262 if (checkvertex != endpoint1) {
12263 /* Find a boundary triangle to search from. */
12264 searchtri1.tri = m->dummytri;
12265 searchtri1.orient = 0;
12266 symself(searchtri1);
12267 /* Search for the segment's first endpoint by point location. */
12268 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12269 printf(
12270 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12271 printf(" (%.12g, %.12g) in triangulation.\n",
12272 endpoint1[0], endpoint1[1]);
12273 internalerror();
12274 }
12275 }
12276 /* Remember this triangle to improve subsequent point location. */
12277 otricopy(searchtri1, m->recenttri);
12278 /* Scout the beginnings of a path from the first endpoint */
12279 /* toward the second. */
12280 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12281 /* The segment was easily inserted. */
12282 return;
12283 }
12284 /* The first endpoint may have changed if a collision with an intervening */
12285 /* vertex on the segment occurred. */
12286 org(searchtri1, endpoint1);
12287
12288 /* Find a triangle whose origin is the segment's second endpoint. */
12289 checkvertex = (vertex) NULL;
12290 encodedtri = vertex2tri(endpoint2);
12291 if (encodedtri != (triangle) NULL) {
12292 decode(encodedtri, searchtri2);
12293 org(searchtri2, checkvertex);
12294 }
12295 if (checkvertex != endpoint2) {
12296 /* Find a boundary triangle to search from. */
12297 searchtri2.tri = m->dummytri;
12298 searchtri2.orient = 0;
12299 symself(searchtri2);
12300 /* Search for the segment's second endpoint by point location. */
12301 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12302 printf(
12303 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12304 printf(" (%.12g, %.12g) in triangulation.\n",
12305 endpoint2[0], endpoint2[1]);
12306 internalerror();
12307 }
12308 }
12309 /* Remember this triangle to improve subsequent point location. */
12310 otricopy(searchtri2, m->recenttri);
12311 /* Scout the beginnings of a path from the second endpoint */
12312 /* toward the first. */
12313 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12314 /* The segment was easily inserted. */
12315 return;
12316 }
12317 /* The second endpoint may have changed if a collision with an intervening */
12318 /* vertex on the segment occurred. */
12319 org(searchtri2, endpoint2);
12320
12321#ifndef REDUCED
12322#ifndef CDT_ONLY
12323 if (b->splitseg) {
12324 /* Insert vertices to force the segment into the triangulation. */
12325 conformingedge(m, b, endpoint1, endpoint2, newmark);
12326 } else {
12327#endif /* not CDT_ONLY */
12328#endif /* not REDUCED */
12329 /* Insert the segment directly into the triangulation. */
12330 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12331#ifndef REDUCED
12332#ifndef CDT_ONLY
12333 }
12334#endif /* not CDT_ONLY */
12335#endif /* not REDUCED */
12336}
12337
12338/*****************************************************************************/
12339/* */
12340/* markhull() Cover the convex hull of a triangulation with subsegments. */
12341/* */
12342/*****************************************************************************/
12343
12344#ifdef ANSI_DECLARATORS
12345void markhull(struct mesh *m, struct behavior *b)
12346#else /* not ANSI_DECLARATORS */
12347void markhull(m, b)
12348struct mesh *m;
12349struct behavior *b;
12350#endif /* not ANSI_DECLARATORS */
12351
12352{
12353 struct otri hulltri;
12354 struct otri nexttri;
12355 struct otri starttri;
12356 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12357
12358 /* Find a triangle handle on the hull. */
12359 hulltri.tri = m->dummytri;
12360 hulltri.orient = 0;
12361 symself(hulltri);
12362 /* Remember where we started so we know when to stop. */
12363 otricopy(hulltri, starttri);
12364 /* Go once counterclockwise around the convex hull. */
12365 do {
12366 /* Create a subsegment if there isn't already one here. */
12367 insertsubseg(m, b, &hulltri, 1);
12368 /* To find the next hull edge, go clockwise around the next vertex. */
12369 lnextself(hulltri);
12370 oprev(hulltri, nexttri);
12371 while (nexttri.tri != m->dummytri) {
12372 otricopy(nexttri, hulltri);
12373 oprev(hulltri, nexttri);
12374 }
12375 } while (!otriequal(hulltri, starttri));
12376}
12377
12378/*****************************************************************************/
12379/* */
12380/* formskeleton() Create the segments of a triangulation, including PSLG */
12381/* segments and edges on the convex hull. */
12382/* */
12383/* The PSLG segments are read from a .poly file. The return value is the */
12384/* number of segments in the file. */
12385/* */
12386/*****************************************************************************/
12387
12388#ifdef TRILIBRARY
12389
12390#ifdef ANSI_DECLARATORS
12391void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12392 int *segmentmarkerlist, int numberofsegments)
12393#else /* not ANSI_DECLARATORS */
12394void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12395struct mesh *m;
12396struct behavior *b;
12397int *segmentlist;
12398int *segmentmarkerlist;
12399int numberofsegments;
12400#endif /* not ANSI_DECLARATORS */
12401
12402#else /* not TRILIBRARY */
12403
12404#ifdef ANSI_DECLARATORS
12405void formskeleton(struct mesh *m, struct behavior *b,
12406 FILE *polyfile, char *polyfilename)
12407#else /* not ANSI_DECLARATORS */
12408void formskeleton(m, b, polyfile, polyfilename)
12409struct mesh *m;
12410struct behavior *b;
12411FILE *polyfile;
12412char *polyfilename;
12413#endif /* not ANSI_DECLARATORS */
12414
12415#endif /* not TRILIBRARY */
12416
12417{
12418#ifdef TRILIBRARY
12419 char polyfilename[6];
12420 int index;
12421#else /* not TRILIBRARY */
12422 char inputline[INPUTLINESIZE];
12423 char *stringptr;
12424#endif /* not TRILIBRARY */
12425 vertex endpoint1, endpoint2;
12426 int segmentmarkers;
12427 int end1, end2;
12428 int boundmarker;
12429 int i;
12430
12431 if (b->poly) {
12432 if (!b->quiet) {
12433 printf("Recovering segments in Delaunay triangulation.\n");
12434 }
12435#ifdef TRILIBRARY
12436 strcpy(polyfilename, "input");
12437 m->insegments = numberofsegments;
12438 segmentmarkers = segmentmarkerlist != (int *) NULL;
12439 index = 0;
12440#else /* not TRILIBRARY */
12441 /* Read the segments from a .poly file. */
12442 /* Read number of segments and number of boundary markers. */
12443 stringptr = readline(inputline, polyfile, polyfilename);
12444 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12445 stringptr = findfield(stringptr);
12446 if (*stringptr == '\0') {
12447 segmentmarkers = 0;
12448 } else {
12449 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12450 }
12451#endif /* not TRILIBRARY */
12452 /* If the input vertices are collinear, there is no triangulation, */
12453 /* so don't try to insert segments. */
12454 if (m->triangles.items == 0) {
12455 return;
12456 }
12457
12458 /* If segments are to be inserted, compute a mapping */
12459 /* from vertices to triangles. */
12460 if (m->insegments > 0) {
12461 makevertexmap(m, b);
12462 if (b->verbose) {
12463 printf(" Recovering PSLG segments.\n");
12464 }
12465 }
12466
12467 boundmarker = 0;
12468 /* Read and insert the segments. */
12469 for (i = 0; i < m->insegments; i++) {
12470#ifdef TRILIBRARY
12471 end1 = segmentlist[index++];
12472 end2 = segmentlist[index++];
12473 if (segmentmarkers) {
12474 boundmarker = segmentmarkerlist[i];
12475 }
12476#else /* not TRILIBRARY */
12477 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12478 stringptr = findfield(stringptr);
12479 if (*stringptr == '\0') {
12480 printf("Error: Segment %d has no endpoints in %s.\n",
12481 b->firstnumber + i, polyfilename);
12482 triexit(1);
12483 } else {
12484 end1 = (int) strtol(stringptr, &stringptr, 0);
12485 }
12486 stringptr = findfield(stringptr);
12487 if (*stringptr == '\0') {
12488 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12489 b->firstnumber + i, polyfilename);
12490 triexit(1);
12491 } else {
12492 end2 = (int) strtol(stringptr, &stringptr, 0);
12493 }
12494 if (segmentmarkers) {
12495 stringptr = findfield(stringptr);
12496 if (*stringptr == '\0') {
12497 boundmarker = 0;
12498 } else {
12499 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12500 }
12501 }
12502#endif /* not TRILIBRARY */
12503 if ((end1 < b->firstnumber) ||
12504 (end1 >= b->firstnumber + m->invertices)) {
12505 if (!b->quiet) {
12506 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12507 b->firstnumber + i, polyfilename);
12508 }
12509 } else if ((end2 < b->firstnumber) ||
12510 (end2 >= b->firstnumber + m->invertices)) {
12511 if (!b->quiet) {
12512 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12513 b->firstnumber + i, polyfilename);
12514 }
12515 } else {
12516 /* Find the vertices numbered `end1' and `end2'. */
12517 endpoint1 = getvertex(m, b, end1);
12518 endpoint2 = getvertex(m, b, end2);
12519 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12520 if (!b->quiet) {
12521 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12522 b->firstnumber + i, polyfilename);
12523 }
12524 } else {
12525 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12526 }
12527 }
12528 }
12529 } else {
12530 m->insegments = 0;
12531 }
12532 if (b->convex || !b->poly) {
12533 /* Enclose the convex hull with subsegments. */
12534 if (b->verbose) {
12535 printf(" Enclosing convex hull with segments.\n");
12536 }
12537 markhull(m, b);
12538 }
12539}
12540
12541/** **/
12542/** **/
12543/********* Segment insertion ends here *********/
12544
12545/********* Carving out holes and concavities begins here *********/
12546/** **/
12547/** **/
12548
12549/*****************************************************************************/
12550/* */
12551/* infecthull() Virally infect all of the triangles of the convex hull */
12552/* that are not protected by subsegments. Where there are */
12553/* subsegments, set boundary markers as appropriate. */
12554/* */
12555/*****************************************************************************/
12556
12557#ifdef ANSI_DECLARATORS
12558void infecthull(struct mesh *m, struct behavior *b)
12559#else /* not ANSI_DECLARATORS */
12560void infecthull(m, b)
12561struct mesh *m;
12562struct behavior *b;
12563#endif /* not ANSI_DECLARATORS */
12564
12565{
12566 struct otri hulltri;
12567 struct otri nexttri;
12568 struct otri starttri;
12569 struct osub hullsubseg;
12570 triangle **deadtriangle;
12571 vertex horg, hdest;
12572 triangle ptr; /* Temporary variable used by sym(). */
12573 subseg sptr; /* Temporary variable used by tspivot(). */
12574
12575 if (b->verbose) {
12576 printf(" Marking concavities (external triangles) for elimination.\n");
12577 }
12578 /* Find a triangle handle on the hull. */
12579 hulltri.tri = m->dummytri;
12580 hulltri.orient = 0;
12581 symself(hulltri);
12582 /* Remember where we started so we know when to stop. */
12583 otricopy(hulltri, starttri);
12584 /* Go once counterclockwise around the convex hull. */
12585 do {
12586 /* Ignore triangles that are already infected. */
12587 if (!infected(hulltri)) {
12588 /* Is the triangle protected by a subsegment? */
12589 tspivot(hulltri, hullsubseg);
12590 if (hullsubseg.ss == m->dummysub) {
12591 /* The triangle is not protected; infect it. */
12592 if (!infected(hulltri)) {
12593 infect(hulltri);
12594 deadtriangle = (triangle **) poolalloc(&m->viri);
12595 *deadtriangle = hulltri.tri;
12596 }
12597 } else {
12598 /* The triangle is protected; set boundary markers if appropriate. */
12599 if (mark(hullsubseg) == 0) {
12600 setmark(hullsubseg, 1);
12601 org(hulltri, horg);
12602 dest(hulltri, hdest);
12603 if (vertexmark(horg) == 0) {
12604 setvertexmark(horg, 1);
12605 }
12606 if (vertexmark(hdest) == 0) {
12607 setvertexmark(hdest, 1);
12608 }
12609 }
12610 }
12611 }
12612 /* To find the next hull edge, go clockwise around the next vertex. */
12613 lnextself(hulltri);
12614 oprev(hulltri, nexttri);
12615 while (nexttri.tri != m->dummytri) {
12616 otricopy(nexttri, hulltri);
12617 oprev(hulltri, nexttri);
12618 }
12619 } while (!otriequal(hulltri, starttri));
12620}
12621
12622/*****************************************************************************/
12623/* */
12624/* plague() Spread the virus from all infected triangles to any neighbors */
12625/* not protected by subsegments. Delete all infected triangles. */
12626/* */
12627/* This is the procedure that actually creates holes and concavities. */
12628/* */
12629/* This procedure operates in two phases. The first phase identifies all */
12630/* the triangles that will die, and marks them as infected. They are */
12631/* marked to ensure that each triangle is added to the virus pool only */
12632/* once, so the procedure will terminate. */
12633/* */
12634/* The second phase actually eliminates the infected triangles. It also */
12635/* eliminates orphaned vertices. */
12636/* */
12637/*****************************************************************************/
12638
12639#ifdef ANSI_DECLARATORS
12640void plague(struct mesh *m, struct behavior *b)
12641#else /* not ANSI_DECLARATORS */
12642void plague(m, b)
12643struct mesh *m;
12644struct behavior *b;
12645#endif /* not ANSI_DECLARATORS */
12646
12647{
12648 struct otri testtri;
12649 struct otri neighbor;
12650 triangle **virusloop;
12651 triangle **deadtriangle;
12652 struct osub neighborsubseg;
12653 vertex testvertex;
12654 vertex norg, ndest;
12655 vertex deadorg, deaddest, deadapex;
12656 int killorg;
12657 triangle ptr; /* Temporary variable used by sym() and onext(). */
12658 subseg sptr; /* Temporary variable used by tspivot(). */
12659
12660 if (b->verbose) {
12661 printf(" Marking neighbors of marked triangles.\n");
12662 }
12663 /* Loop through all the infected triangles, spreading the virus to */
12664 /* their neighbors, then to their neighbors' neighbors. */
12665 traversalinit(&m->viri);
12666 virusloop = (triangle **) traverse(&m->viri);
12667 while (virusloop != (triangle **) NULL) {
12668 testtri.tri = *virusloop;
12669 /* A triangle is marked as infected by messing with one of its pointers */
12670 /* to subsegments, setting it to an illegal value. Hence, we have to */
12671 /* temporarily uninfect this triangle so that we can examine its */
12672 /* adjacent subsegments. */
12673 uninfect(testtri);
12674 if (b->verbose > 2) {
12675 /* Assign the triangle an orientation for convenience in */
12676 /* checking its vertices. */
12677 testtri.orient = 0;
12678 org(testtri, deadorg);
12679 dest(testtri, deaddest);
12680 apex(testtri, deadapex);
12681 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12682 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12683 deadapex[0], deadapex[1]);
12684 }
12685 /* Check each of the triangle's three neighbors. */
12686 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12687 /* Find the neighbor. */
12688 sym(testtri, neighbor);
12689 /* Check for a subsegment between the triangle and its neighbor. */
12690 tspivot(testtri, neighborsubseg);
12691 /* Check if the neighbor is nonexistent or already infected. */
12692 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12693 if (neighborsubseg.ss != m->dummysub) {
12694 /* There is a subsegment separating the triangle from its */
12695 /* neighbor, but both triangles are dying, so the subsegment */
12696 /* dies too. */
12697 subsegdealloc(m, neighborsubseg.ss);
12698 if (neighbor.tri != m->dummytri) {
12699 /* Make sure the subsegment doesn't get deallocated again */
12700 /* later when the infected neighbor is visited. */
12701 uninfect(neighbor);
12702 tsdissolve(neighbor);
12703 infect(neighbor);
12704 }
12705 }
12706 } else { /* The neighbor exists and is not infected. */
12707 if (neighborsubseg.ss == m->dummysub) {
12708 /* There is no subsegment protecting the neighbor, so */
12709 /* the neighbor becomes infected. */
12710 if (b->verbose > 2) {
12711 org(neighbor, deadorg);
12712 dest(neighbor, deaddest);
12713 apex(neighbor, deadapex);
12714 printf(
12715 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12716 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12717 deadapex[0], deadapex[1]);
12718 }
12719 infect(neighbor);
12720 /* Ensure that the neighbor's neighbors will be infected. */
12721 deadtriangle = (triangle **) poolalloc(&m->viri);
12722 *deadtriangle = neighbor.tri;
12723 } else { /* The neighbor is protected by a subsegment. */
12724 /* Remove this triangle from the subsegment. */
12725 stdissolve(neighborsubseg);
12726 /* The subsegment becomes a boundary. Set markers accordingly. */
12727 if (mark(neighborsubseg) == 0) {
12728 setmark(neighborsubseg, 1);
12729 }
12730 org(neighbor, norg);
12731 dest(neighbor, ndest);
12732 if (vertexmark(norg) == 0) {
12733 setvertexmark(norg, 1);
12734 }
12735 if (vertexmark(ndest) == 0) {
12736 setvertexmark(ndest, 1);
12737 }
12738 }
12739 }
12740 }
12741 /* Remark the triangle as infected, so it doesn't get added to the */
12742 /* virus pool again. */
12743 infect(testtri);
12744 virusloop = (triangle **) traverse(&m->viri);
12745 }
12746
12747 if (b->verbose) {
12748 printf(" Deleting marked triangles.\n");
12749 }
12750
12751 traversalinit(&m->viri);
12752 virusloop = (triangle **) traverse(&m->viri);
12753 while (virusloop != (triangle **) NULL) {
12754 testtri.tri = *virusloop;
12755
12756 /* Check each of the three corners of the triangle for elimination. */
12757 /* This is done by walking around each vertex, checking if it is */
12758 /* still connected to at least one live triangle. */
12759 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12760 org(testtri, testvertex);
12761 /* Check if the vertex has already been tested. */
12762 if (testvertex != (vertex) NULL) {
12763 killorg = 1;
12764 /* Mark the corner of the triangle as having been tested. */
12765 setorg(testtri, NULL);
12766 /* Walk counterclockwise about the vertex. */
12767 onext(testtri, neighbor);
12768 /* Stop upon reaching a boundary or the starting triangle. */
12769 while ((neighbor.tri != m->dummytri) &&
12770 (!otriequal(neighbor, testtri))) {
12771 if (infected(neighbor)) {
12772 /* Mark the corner of this triangle as having been tested. */
12773 setorg(neighbor, NULL);
12774 } else {
12775 /* A live triangle. The vertex survives. */
12776 killorg = 0;
12777 }
12778 /* Walk counterclockwise about the vertex. */
12779 onextself(neighbor);
12780 }
12781 /* If we reached a boundary, we must walk clockwise as well. */
12782 if (neighbor.tri == m->dummytri) {
12783 /* Walk clockwise about the vertex. */
12784 oprev(testtri, neighbor);
12785 /* Stop upon reaching a boundary. */
12786 while (neighbor.tri != m->dummytri) {
12787 if (infected(neighbor)) {
12788 /* Mark the corner of this triangle as having been tested. */
12789 setorg(neighbor, NULL);
12790 } else {
12791 /* A live triangle. The vertex survives. */
12792 killorg = 0;
12793 }
12794 /* Walk clockwise about the vertex. */
12795 oprevself(neighbor);
12796 }
12797 }
12798 if (killorg) {
12799 if (b->verbose > 1) {
12800 printf(" Deleting vertex (%.12g, %.12g)\n",
12801 testvertex[0], testvertex[1]);
12802 }
12803 setvertextype(testvertex, UNDEADVERTEX);
12804 m->undeads++;
12805 }
12806 }
12807 }
12808
12809 /* Record changes in the number of boundary edges, and disconnect */
12810 /* dead triangles from their neighbors. */
12811 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12812 sym(testtri, neighbor);
12813 if (neighbor.tri == m->dummytri) {
12814 /* There is no neighboring triangle on this edge, so this edge */
12815 /* is a boundary edge. This triangle is being deleted, so this */
12816 /* boundary edge is deleted. */
12817 m->hullsize--;
12818 } else {
12819 /* Disconnect the triangle from its neighbor. */
12820 dissolve(neighbor);
12821 /* There is a neighboring triangle on this edge, so this edge */
12822 /* becomes a boundary edge when this triangle is deleted. */
12823 m->hullsize++;
12824 }
12825 }
12826 /* Return the dead triangle to the pool of triangles. */
12827 triangledealloc(m, testtri.tri);
12828 virusloop = (triangle **) traverse(&m->viri);
12829 }
12830 /* Empty the virus pool. */
12831 poolrestart(&m->viri);
12832}
12833
12834/*****************************************************************************/
12835/* */
12836/* regionplague() Spread regional attributes and/or area constraints */
12837/* (from a .poly file) throughout the mesh. */
12838/* */
12839/* This procedure operates in two phases. The first phase spreads an */
12840/* attribute and/or an area constraint through a (segment-bounded) region. */
12841/* The triangles are marked to ensure that each triangle is added to the */
12842/* virus pool only once, so the procedure will terminate. */
12843/* */
12844/* The second phase uninfects all infected triangles, returning them to */
12845/* normal. */
12846/* */
12847/*****************************************************************************/
12848
12849#ifdef ANSI_DECLARATORS
12850void regionplague(struct mesh *m, struct behavior *b,
12851 REAL attribute, REAL area)
12852#else /* not ANSI_DECLARATORS */
12853void regionplague(m, b, attribute, area)
12854struct mesh *m;
12855struct behavior *b;
12856REAL attribute;
12857REAL area;
12858#endif /* not ANSI_DECLARATORS */
12859
12860{
12861 struct otri testtri;
12862 struct otri neighbor;
12863 triangle **virusloop;
12864 triangle **regiontri;
12865 struct osub neighborsubseg;
12866 vertex regionorg, regiondest, regionapex;
12867 triangle ptr; /* Temporary variable used by sym() and onext(). */
12868 subseg sptr; /* Temporary variable used by tspivot(). */
12869
12870 if (b->verbose > 1) {
12871 printf(" Marking neighbors of marked triangles.\n");
12872 }
12873 /* Loop through all the infected triangles, spreading the attribute */
12874 /* and/or area constraint to their neighbors, then to their neighbors' */
12875 /* neighbors. */
12876 traversalinit(&m->viri);
12877 virusloop = (triangle **) traverse(&m->viri);
12878 while (virusloop != (triangle **) NULL) {
12879 testtri.tri = *virusloop;
12880 /* A triangle is marked as infected by messing with one of its pointers */
12881 /* to subsegments, setting it to an illegal value. Hence, we have to */
12882 /* temporarily uninfect this triangle so that we can examine its */
12883 /* adjacent subsegments. */
12884 uninfect(testtri);
12885 if (b->regionattrib) {
12886 /* Set an attribute. */
12887 setelemattribute(testtri, m->eextras, attribute);
12888 }
12889 if (b->vararea) {
12890 /* Set an area constraint. */
12891 setareabound(testtri, area);
12892 }
12893 if (b->verbose > 2) {
12894 /* Assign the triangle an orientation for convenience in */
12895 /* checking its vertices. */
12896 testtri.orient = 0;
12897 org(testtri, regionorg);
12898 dest(testtri, regiondest);
12899 apex(testtri, regionapex);
12900 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12901 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12902 regionapex[0], regionapex[1]);
12903 }
12904 /* Check each of the triangle's three neighbors. */
12905 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12906 /* Find the neighbor. */
12907 sym(testtri, neighbor);
12908 /* Check for a subsegment between the triangle and its neighbor. */
12909 tspivot(testtri, neighborsubseg);
12910 /* Make sure the neighbor exists, is not already infected, and */
12911 /* isn't protected by a subsegment. */
12912 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12913 && (neighborsubseg.ss == m->dummysub)) {
12914 if (b->verbose > 2) {
12915 org(neighbor, regionorg);
12916 dest(neighbor, regiondest);
12917 apex(neighbor, regionapex);
12918 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12919 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12920 regionapex[0], regionapex[1]);
12921 }
12922 /* Infect the neighbor. */
12923 infect(neighbor);
12924 /* Ensure that the neighbor's neighbors will be infected. */
12925 regiontri = (triangle **) poolalloc(&m->viri);
12926 *regiontri = neighbor.tri;
12927 }
12928 }
12929 /* Remark the triangle as infected, so it doesn't get added to the */
12930 /* virus pool again. */
12931 infect(testtri);
12932 virusloop = (triangle **) traverse(&m->viri);
12933 }
12934
12935 /* Uninfect all triangles. */
12936 if (b->verbose > 1) {
12937 printf(" Unmarking marked triangles.\n");
12938 }
12939 traversalinit(&m->viri);
12940 virusloop = (triangle **) traverse(&m->viri);
12941 while (virusloop != (triangle **) NULL) {
12942 testtri.tri = *virusloop;
12943 uninfect(testtri);
12944 virusloop = (triangle **) traverse(&m->viri);
12945 }
12946 /* Empty the virus pool. */
12947 poolrestart(&m->viri);
12948}
12949
12950/*****************************************************************************/
12951/* */
12952/* carveholes() Find the holes and infect them. Find the area */
12953/* constraints and infect them. Infect the convex hull. */
12954/* Spread the infection and kill triangles. Spread the */
12955/* area constraints. */
12956/* */
12957/* This routine mainly calls other routines to carry out all these */
12958/* functions. */
12959/* */
12960/*****************************************************************************/
12961
12962#ifdef ANSI_DECLARATORS
12963void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12964 REAL *regionlist, int regions)
12965#else /* not ANSI_DECLARATORS */
12966void carveholes(m, b, holelist, holes, regionlist, regions)
12967struct mesh *m;
12968struct behavior *b;
12969REAL *holelist;
12970int holes;
12971REAL *regionlist;
12972int regions;
12973#endif /* not ANSI_DECLARATORS */
12974
12975{
12976 struct otri searchtri;
12977 struct otri triangleloop;
12978 struct otri *regiontris;
12979 triangle **holetri;
12980 triangle **regiontri;
12981 vertex searchorg, searchdest;
12982 enum locateresult intersect;
12983 int i;
12984 triangle ptr; /* Temporary variable used by sym(). */
12985
12986 if (!(b->quiet || (b->noholes && b->convex))) {
12987 printf("Removing unwanted triangles.\n");
12988 if (b->verbose && (holes > 0)) {
12989 printf(" Marking holes for elimination.\n");
12990 }
12991 }
12992
12993 if (regions > 0) {
12994 /* Allocate storage for the triangles in which region points fall. */
12995 regiontris = (struct otri *) trimalloc(regions *
12996 (int) sizeof(struct otri));
12997 } else {
12998 regiontris = (struct otri *) NULL;
12999 }
13000
13001 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13002 /* Initialize a pool of viri to be used for holes, concavities, */
13003 /* regional attributes, and/or regional area constraints. */
13004 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13005 }
13006
13007 if (!b->convex) {
13008 /* Mark as infected any unprotected triangles on the boundary. */
13009 /* This is one way by which concavities are created. */
13010 infecthull(m, b);
13011 }
13012
13013 if ((holes > 0) && !b->noholes) {
13014 /* Infect each triangle in which a hole lies. */
13015 for (i = 0; i < 2 * holes; i += 2) {
13016 /* Ignore holes that aren't within the bounds of the mesh. */
13017 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13018 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13019 /* Start searching from some triangle on the outer boundary. */
13020 searchtri.tri = m->dummytri;
13021 searchtri.orient = 0;
13022 symself(searchtri);
13023 /* Ensure that the hole is to the left of this boundary edge; */
13024 /* otherwise, locate() will falsely report that the hole */
13025 /* falls within the starting triangle. */
13026 org(searchtri, searchorg);
13027 dest(searchtri, searchdest);
13028 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13029 0.0) {
13030 /* Find a triangle that contains the hole. */
13031 intersect = locate(m, b, &holelist[i], &searchtri);
13032 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13033 /* Infect the triangle. This is done by marking the triangle */
13034 /* as infected and including the triangle in the virus pool. */
13035 infect(searchtri);
13036 holetri = (triangle **) poolalloc(&m->viri);
13037 *holetri = searchtri.tri;
13038 }
13039 }
13040 }
13041 }
13042 }
13043
13044 /* Now, we have to find all the regions BEFORE we carve the holes, because */
13045 /* locate() won't work when the triangulation is no longer convex. */
13046 /* (Incidentally, this is the reason why regional attributes and area */
13047 /* constraints can't be used when refining a preexisting mesh, which */
13048 /* might not be convex; they can only be used with a freshly */
13049 /* triangulated PSLG.) */
13050 if (regions > 0) {
13051 /* Find the starting triangle for each region. */
13052 for (i = 0; i < regions; i++) {
13053 regiontris[i].tri = m->dummytri;
13054 /* Ignore region points that aren't within the bounds of the mesh. */
13055 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13056 (regionlist[4 * i + 1] >= m->ymin) &&
13057 (regionlist[4 * i + 1] <= m->ymax)) {
13058 /* Start searching from some triangle on the outer boundary. */
13059 searchtri.tri = m->dummytri;
13060 searchtri.orient = 0;
13061 symself(searchtri);
13062 /* Ensure that the region point is to the left of this boundary */
13063 /* edge; otherwise, locate() will falsely report that the */
13064 /* region point falls within the starting triangle. */
13065 org(searchtri, searchorg);
13066 dest(searchtri, searchdest);
13067 if (counterclockwise(m, b, searchorg, searchdest, &regionlist[4 * i]) >
13068 0.0) {
13069 /* Find a triangle that contains the region point. */
13070 intersect = locate(m, b, &regionlist[4 * i], &searchtri);
13071 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13072 /* Record the triangle for processing after the */
13073 /* holes have been carved. */
13074 otricopy(searchtri, regiontris[i]);
13075 }
13076 }
13077 }
13078 }
13079 }
13080
13081 if (m->viri.items > 0) {
13082 /* Carve the holes and concavities. */
13083 plague(m, b);
13084 }
13085 /* The virus pool should be empty now. */
13086
13087 if (regions > 0) {
13088 if (!b->quiet) {
13089 if (b->regionattrib) {
13090 if (b->vararea) {
13091 printf("Spreading regional attributes and area constraints.\n");
13092 } else {
13093 printf("Spreading regional attributes.\n");
13094 }
13095 } else {
13096 printf("Spreading regional area constraints.\n");
13097 }
13098 }
13099 if (b->regionattrib && !b->refine) {
13100 /* Assign every triangle a regional attribute of zero. */
13101 traversalinit(&m->triangles);
13102 triangleloop.orient = 0;
13103 triangleloop.tri = triangletraverse(m);
13104 while (triangleloop.tri != (triangle *) NULL) {
13105 setelemattribute(triangleloop, m->eextras, 0.0);
13106 triangleloop.tri = triangletraverse(m);
13107 }
13108 }
13109 for (i = 0; i < regions; i++) {
13110 if (regiontris[i].tri != m->dummytri) {
13111 /* Make sure the triangle under consideration still exists. */
13112 /* It may have been eaten by the virus. */
13113 if (!deadtri(regiontris[i].tri)) {
13114 /* Put one triangle in the virus pool. */
13115 infect(regiontris[i]);
13116 regiontri = (triangle **) poolalloc(&m->viri);
13117 *regiontri = regiontris[i].tri;
13118 /* Apply one region's attribute and/or area constraint. */
13119 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13120 /* The virus pool should be empty now. */
13121 }
13122 }
13123 }
13124 if (b->regionattrib && !b->refine) {
13125 /* Note the fact that each triangle has an additional attribute. */
13126 m->eextras++;
13127 }
13128 }
13129
13130 /* Free up memory. */
13131 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13132 pooldeinit(&m->viri);
13133 }
13134 if (regions > 0) {
13135 trifree((VOID *) regiontris);
13136 }
13137}
13138
13139/** **/
13140/** **/
13141/********* Carving out holes and concavities ends here *********/
13142
13143/********* Mesh quality maintenance begins here *********/
13144/** **/
13145/** **/
13146
13147/*****************************************************************************/
13148/* */
13149/* tallyencs() Traverse the entire list of subsegments, and check each */
13150/* to see if it is encroached. If so, add it to the list. */
13151/* */
13152/*****************************************************************************/
13153
13154#ifndef CDT_ONLY
13155
13156#ifdef ANSI_DECLARATORS
13157void tallyencs(struct mesh *m, struct behavior *b)
13158#else /* not ANSI_DECLARATORS */
13159void tallyencs(m, b)
13160struct mesh *m;
13161struct behavior *b;
13162#endif /* not ANSI_DECLARATORS */
13163
13164{
13165 struct osub subsegloop;
13166 int dummy;
13167
13168 traversalinit(&m->subsegs);
13169 subsegloop.ssorient = 0;
13170 subsegloop.ss = subsegtraverse(m);
13171 while (subsegloop.ss != (subseg *) NULL) {
13172 /* If the segment is encroached, add it to the list. */
13173 dummy = checkseg4encroach(m, b, &subsegloop);
13174 subsegloop.ss = subsegtraverse(m);
13175 }
13176}
13177
13178#endif /* not CDT_ONLY */
13179
13180/*****************************************************************************/
13181/* */
13182/* precisionerror() Print an error message for precision problems. */
13183/* */
13184/*****************************************************************************/
13185
13186#ifndef CDT_ONLY
13187
13188void precisionerror()
13189{
13190 printf("Try increasing the area criterion and/or reducing the minimum\n");
13191 printf(" allowable angle so that tiny triangles are not created.\n");
13192#ifdef SINGLE
13193 printf("Alternatively, try recompiling me with double precision\n");
13194 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13195 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13196#endif /* SINGLE */
13197}
13198
13199#endif /* not CDT_ONLY */
13200
13201/*****************************************************************************/
13202/* */
13203/* splitencsegs() Split all the encroached subsegments. */
13204/* */
13205/* Each encroached subsegment is repaired by splitting it - inserting a */
13206/* vertex at or near its midpoint. Newly inserted vertices may encroach */
13207/* upon other subsegments; these are also repaired. */
13208/* */
13209/* `triflaws' is a flag that specifies whether one should take note of new */
13210/* bad triangles that result from inserting vertices to repair encroached */
13211/* subsegments. */
13212/* */
13213/*****************************************************************************/
13214
13215#ifndef CDT_ONLY
13216
13217#ifdef ANSI_DECLARATORS
13218void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13219#else /* not ANSI_DECLARATORS */
13220void splitencsegs(m, b, triflaws)
13221struct mesh *m;
13222struct behavior *b;
13223int triflaws;
13224#endif /* not ANSI_DECLARATORS */
13225
13226{
13227 struct otri enctri;
13228 struct otri testtri;
13229 struct osub testsh;
13230 struct osub currentenc;
13231 struct badsubseg *encloop;
13232 vertex eorg, edest, eapex;
13233 vertex newvertex;
13234 enum insertvertexresult success;
13235 REAL segmentlength, nearestpoweroftwo;
13236 REAL split;
13237 REAL multiplier, divisor;
13238 int acuteorg, acuteorg2, acutedest, acutedest2;
13239 int dummy;
13240 int i;
13241 triangle ptr; /* Temporary variable used by stpivot(). */
13242 subseg sptr; /* Temporary variable used by snext(). */
13243
13244 /* Note that steinerleft == -1 if an unlimited number */
13245 /* of Steiner points is allowed. */
13246 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13247 traversalinit(&m->badsubsegs);
13248 encloop = badsubsegtraverse(m);
13249 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13250 sdecode(encloop->encsubseg, currentenc);
13251 sorg(currentenc, eorg);
13252 sdest(currentenc, edest);
13253 /* Make sure that this segment is still the same segment it was */
13254 /* when it was determined to be encroached. If the segment was */
13255 /* enqueued multiple times (because several newly inserted */
13256 /* vertices encroached it), it may have already been split. */
13257 if (!deadsubseg(currentenc.ss) &&
13258 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13259 /* To decide where to split a segment, we need to know if the */
13260 /* segment shares an endpoint with an adjacent segment. */
13261 /* The concern is that, if we simply split every encroached */
13262 /* segment in its center, two adjacent segments with a small */
13263 /* angle between them might lead to an infinite loop; each */
13264 /* vertex added to split one segment will encroach upon the */
13265 /* other segment, which must then be split with a vertex that */
13266 /* will encroach upon the first segment, and so on forever. */
13267 /* To avoid this, imagine a set of concentric circles, whose */
13268 /* radii are powers of two, about each segment endpoint. */
13269 /* These concentric circles determine where the segment is */
13270 /* split. (If both endpoints are shared with adjacent */
13271 /* segments, split the segment in the middle, and apply the */
13272 /* concentric circles for later splittings.) */
13273
13274 /* Is the origin shared with another segment? */
13275 stpivot(currentenc, enctri);
13276 lnext(enctri, testtri);
13277 tspivot(testtri, testsh);
13278 acuteorg = testsh.ss != m->dummysub;
13279 /* Is the destination shared with another segment? */
13280 lnextself(testtri);
13281 tspivot(testtri, testsh);
13282 acutedest = testsh.ss != m->dummysub;
13283
13284 /* If we're using Chew's algorithm (rather than Ruppert's) */
13285 /* to define encroachment, delete free vertices from the */
13286 /* subsegment's diametral circle. */
13287 if (!b->conformdel && !acuteorg && !acutedest) {
13288 apex(enctri, eapex);
13289 while ((vertextype(eapex) == FREEVERTEX) &&
13290 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13291 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13292 deletevertex(m, b, &testtri);
13293 stpivot(currentenc, enctri);
13294 apex(enctri, eapex);
13295 lprev(enctri, testtri);
13296 }
13297 }
13298
13299 /* Now, check the other side of the segment, if there's a triangle */
13300 /* there. */
13301 sym(enctri, testtri);
13302 if (testtri.tri != m->dummytri) {
13303 /* Is the destination shared with another segment? */
13304 lnextself(testtri);
13305 tspivot(testtri, testsh);
13306 acutedest2 = testsh.ss != m->dummysub;
13307 acutedest = acutedest || acutedest2;
13308 /* Is the origin shared with another segment? */
13309 lnextself(testtri);
13310 tspivot(testtri, testsh);
13311 acuteorg2 = testsh.ss != m->dummysub;
13312 acuteorg = acuteorg || acuteorg2;
13313
13314 /* Delete free vertices from the subsegment's diametral circle. */
13315 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13316 org(testtri, eapex);
13317 while ((vertextype(eapex) == FREEVERTEX) &&
13318 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13319 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13320 deletevertex(m, b, &testtri);
13321 sym(enctri, testtri);
13322 apex(testtri, eapex);
13323 lprevself(testtri);
13324 }
13325 }
13326 }
13327
13328 /* Use the concentric circles if exactly one endpoint is shared */
13329 /* with another adjacent segment. */
13330 if (acuteorg || acutedest) {
13331 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13332 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13333 /* Find the power of two that most evenly splits the segment. */
13334 /* The worst case is a 2:1 ratio between subsegment lengths. */
13335 nearestpoweroftwo = 1.0;
13336 while (segmentlength > 3.0 * nearestpoweroftwo) {
13337 nearestpoweroftwo *= 2.0;
13338 }
13339 while (segmentlength < 1.5 * nearestpoweroftwo) {
13340 nearestpoweroftwo *= 0.5;
13341 }
13342 /* Where do we split the segment? */
13343 split = nearestpoweroftwo / segmentlength;
13344 if (acutedest) {
13345 split = 1.0 - split;
13346 }
13347 } else {
13348 /* If we're not worried about adjacent segments, split */
13349 /* this segment in the middle. */
13350 split = 0.5;
13351 }
13352
13353 /* Create the new vertex. */
13354 newvertex = (vertex) poolalloc(&m->vertices);
13355 /* Interpolate its coordinate and attributes. */
13356 for (i = 0; i < 2 + m->nextras; i++) {
13357 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13358 }
13359
13360 if (!b->noexact) {
13361 /* Roundoff in the above calculation may yield a `newvertex' */
13362 /* that is not precisely collinear with `eorg' and `edest'. */
13363 /* Improve collinearity by one step of iterative refinement. */
13364 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13365 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13366 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13367 if ((multiplier != 0.0) && (divisor != 0.0)) {
13368 multiplier = multiplier / divisor;
13369 /* Watch out for NANs. */
13370 if (multiplier == multiplier) {
13371 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13372 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13373 }
13374 }
13375 }
13376
13377 setvertexmark(newvertex, mark(currentenc));
13378 setvertextype(newvertex, SEGMENTVERTEX);
13379 if (b->verbose > 1) {
13380 printf(
13381 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13382 eorg[0], eorg[1], edest[0], edest[1],
13383 newvertex[0], newvertex[1]);
13384 }
13385 /* Check whether the new vertex lies on an endpoint. */
13386 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13387 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13388 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13389 newvertex[0], newvertex[1]);
13390 printf("I attempted to split a segment to a smaller size than\n");
13391 printf(" can be accommodated by the finite precision of\n");
13392 printf(" floating point arithmetic.\n");
13393 precisionerror();
13394 triexit(1);
13395 }
13396 /* Insert the splitting vertex. This should always succeed. */
13397 success = insertvertex(m, b, newvertex, &enctri, &currentenc,
13398 1, triflaws);
13399 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13400 printf("Internal error in splitencsegs():\n");
13401 printf(" Failure to split a segment.\n");
13402 internalerror();
13403 }
13404 if (m->steinerleft > 0) {
13405 m->steinerleft--;
13406 }
13407 /* Check the two new subsegments to see if they're encroached. */
13408 dummy = checkseg4encroach(m, b, &currentenc);
13409 snextself(currentenc);
13410 dummy = checkseg4encroach(m, b, &currentenc);
13411 }
13412
13413 badsubsegdealloc(m, encloop);
13414 encloop = badsubsegtraverse(m);
13415 }
13416 }
13417}
13418
13419#endif /* not CDT_ONLY */
13420
13421/*****************************************************************************/
13422/* */
13423/* tallyfaces() Test every triangle in the mesh for quality measures. */
13424/* */
13425/*****************************************************************************/
13426
13427#ifndef CDT_ONLY
13428
13429#ifdef ANSI_DECLARATORS
13430void tallyfaces(struct mesh *m, struct behavior *b)
13431#else /* not ANSI_DECLARATORS */
13432void tallyfaces(m, b)
13433struct mesh *m;
13434struct behavior *b;
13435#endif /* not ANSI_DECLARATORS */
13436
13437{
13438 struct otri triangleloop;
13439
13440 if (b->verbose) {
13441 printf(" Making a list of bad triangles.\n");
13442 }
13443 traversalinit(&m->triangles);
13444 triangleloop.orient = 0;
13445 triangleloop.tri = triangletraverse(m);
13446 while (triangleloop.tri != (triangle *) NULL) {
13447 /* If the triangle is bad, enqueue it. */
13448 testtriangle(m, b, &triangleloop);
13449 triangleloop.tri = triangletraverse(m);
13450 }
13451}
13452
13453#endif /* not CDT_ONLY */
13454
13455/*****************************************************************************/
13456/* */
13457/* splittriangle() Inserts a vertex at the circumcenter of a triangle. */
13458/* Deletes the newly inserted vertex if it encroaches */
13459/* upon a segment. */
13460/* */
13461/*****************************************************************************/
13462
13463#ifndef CDT_ONLY
13464
13465#ifdef ANSI_DECLARATORS
13466void splittriangle(struct mesh *m, struct behavior *b,
13467 struct badtriang *badtri)
13468#else /* not ANSI_DECLARATORS */
13469void splittriangle(m, b, badtri)
13470struct mesh *m;
13471struct behavior *b;
13472struct badtriang *badtri;
13473#endif /* not ANSI_DECLARATORS */
13474
13475{
13476 struct otri badotri;
13477 vertex borg, bdest, bapex;
13478 vertex newvertex;
13479 REAL xi, eta;
13480 enum insertvertexresult success;
13481 int errorflag;
13482 int i;
13483
13484 decode(badtri->poortri, badotri);
13485 org(badotri, borg);
13486 dest(badotri, bdest);
13487 apex(badotri, bapex);
13488 /* Make sure that this triangle is still the same triangle it was */
13489 /* when it was tested and determined to be of bad quality. */
13490 /* Subsequent transformations may have made it a different triangle. */
13491 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13492 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13493 if (b->verbose > 1) {
13494 printf(" Splitting this triangle at its circumcenter:\n");
13495 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13496 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13497 }
13498
13499 errorflag = 0;
13500 /* Create a new vertex at the triangle's circumcenter. */
13501 newvertex = (vertex) poolalloc(&m->vertices);
13502 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13503
13504 /* Check whether the new vertex lies on a triangle vertex. */
13505 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13506 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13507 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13508 if (!b->quiet) {
13509 printf(
13510 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13511 newvertex[0], newvertex[1]);
13512 errorflag = 1;
13513 }
13514 vertexdealloc(m, newvertex);
13515 } else {
13516 for (i = 2; i < 2 + m->nextras; i++) {
13517 /* Interpolate the vertex attributes at the circumcenter. */
13518 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13519 + eta * (bapex[i] - borg[i]);
13520 }
13521 /* The new vertex must be in the interior, and therefore is a */
13522 /* free vertex with a marker of zero. */
13523 setvertexmark(newvertex, 0);
13524 setvertextype(newvertex, FREEVERTEX);
13525
13526 /* Ensure that the handle `badotri' does not represent the longest */
13527 /* edge of the triangle. This ensures that the circumcenter must */
13528 /* fall to the left of this edge, so point location will work. */
13529 /* (If the angle org-apex-dest exceeds 90 degrees, then the */
13530 /* circumcenter lies outside the org-dest edge, and eta is */
13531 /* negative. Roundoff error might prevent eta from being */
13532 /* negative when it should be, so I test eta against xi.) */
13533 if (eta < xi) {
13534 lprevself(badotri);
13535 }
13536
13537 /* Insert the circumcenter, searching from the edge of the triangle, */
13538 /* and maintain the Delaunay property of the triangulation. */
13539 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13540 1, 1);
13541 if (success == SUCCESSFULVERTEX) {
13542 if (m->steinerleft > 0) {
13543 m->steinerleft--;
13544 }
13545 } else if (success == ENCROACHINGVERTEX) {
13546 /* If the newly inserted vertex encroaches upon a subsegment, */
13547 /* delete the new vertex. */
13548 undovertex(m, b);
13549 if (b->verbose > 1) {
13550 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13551 }
13552 vertexdealloc(m, newvertex);
13553 } else if (success == VIOLATINGVERTEX) {
13554 /* Failed to insert the new vertex, but some subsegment was */
13555 /* marked as being encroached. */
13556 vertexdealloc(m, newvertex);
13557 } else { /* success == DUPLICATEVERTEX */
13558 /* Couldn't insert the new vertex because a vertex is already there. */
13559 if (!b->quiet) {
13560 printf(
13561 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13562 newvertex[0], newvertex[1]);
13563 errorflag = 1;
13564 }
13565 vertexdealloc(m, newvertex);
13566 }
13567 }
13568 if (errorflag) {
13569 if (b->verbose) {
13570 printf(" The new vertex is at the circumcenter of triangle\n");
13571 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13572 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13573 }
13574 printf("This probably means that I am trying to refine triangles\n");
13575 printf(" to a smaller size than can be accommodated by the finite\n");
13576 printf(" precision of floating point arithmetic. (You can be\n");
13577 printf(" sure of this if I fail to terminate.)\n");
13578 precisionerror();
13579 }
13580 }
13581}
13582
13583#endif /* not CDT_ONLY */
13584
13585/*****************************************************************************/
13586/* */
13587/* enforcequality() Remove all the encroached subsegments and bad */
13588/* triangles from the triangulation. */
13589/* */
13590/*****************************************************************************/
13591
13592#ifndef CDT_ONLY
13593
13594#ifdef ANSI_DECLARATORS
13595void enforcequality(struct mesh *m, struct behavior *b)
13596#else /* not ANSI_DECLARATORS */
13597void enforcequality(m, b)
13598struct mesh *m;
13599struct behavior *b;
13600#endif /* not ANSI_DECLARATORS */
13601
13602{
13603 struct badtriang *badtri;
13604 int i;
13605
13606 if (!b->quiet) {
13607 printf("Adding Steiner points to enforce quality.\n");
13608 }
13609 /* Initialize the pool of encroached subsegments. */
13610 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13612 if (b->verbose) {
13613 printf(" Looking for encroached subsegments.\n");
13614 }
13615 /* Test all segments to see if they're encroached. */
13616 tallyencs(m, b);
13617 if (b->verbose && (m->badsubsegs.items > 0)) {
13618 printf(" Splitting encroached subsegments.\n");
13619 }
13620 /* Fix encroached subsegments without noting bad triangles. */
13621 splitencsegs(m, b, 0);
13622 /* At this point, if we haven't run out of Steiner points, the */
13623 /* triangulation should be (conforming) Delaunay. */
13624
13625 /* Next, we worry about enforcing triangle quality. */
13626 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13627 /* Initialize the pool of bad triangles. */
13628 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13629 BADTRIPERBLOCK, 0);
13630 /* Initialize the queues of bad triangles. */
13631 for (i = 0; i < 4096; i++) {
13632 m->queuefront[i] = (struct badtriang *) NULL;
13633 }
13634 m->firstnonemptyq = -1;
13635 /* Test all triangles to see if they're bad. */
13636 tallyfaces(m, b);
13637 /* Initialize the pool of recently flipped triangles. */
13638 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13640 m->checkquality = 1;
13641 if (b->verbose) {
13642 printf(" Splitting bad triangles.\n");
13643 }
13644 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13645 /* Fix one bad triangle by inserting a vertex at its circumcenter. */
13646 badtri = dequeuebadtriang(m);
13647 splittriangle(m, b, badtri);
13648 if (m->badsubsegs.items > 0) {
13649 /* Put bad triangle back in queue for another try later. */
13650 enqueuebadtriang(m, b, badtri);
13651 /* Fix any encroached subsegments that resulted. */
13652 /* Record any new bad triangles that result. */
13653 splitencsegs(m, b, 1);
13654 } else {
13655 /* Return the bad triangle to the pool. */
13656 pooldealloc(&m->badtriangles, (VOID *) badtri);
13657 }
13658 }
13659 }
13660 /* At this point, if the "-D" switch was selected and we haven't run out */
13661 /* of Steiner points, the triangulation should be (conforming) Delaunay */
13662 /* and have no low-quality triangles. */
13663
13664 /* Might we have run out of Steiner points too soon? */
13665 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13666 (m->steinerleft == 0)) {
13667 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13668 if (m->badsubsegs.items == 1) {
13669 printf(" one encroached subsegment, and therefore might not be truly\n"
13670 );
13671 } else {
13672 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13673 , m->badsubsegs.items);
13674 }
13675 printf(" Delaunay. If the Delaunay property is important to you,\n");
13676 printf(" try increasing the number of Steiner points (controlled by\n");
13677 printf(" the -S switch) slightly and try again.\n\n");
13678 }
13679}
13680
13681#endif /* not CDT_ONLY */
13682
13683/** **/
13684/** **/
13685/********* Mesh quality maintenance ends here *********/
13686
13687/*****************************************************************************/
13688/* */
13689/* highorder() Create extra nodes for quadratic subparametric elements. */
13690/* */
13691/*****************************************************************************/
13692
13693#ifdef ANSI_DECLARATORS
13694void highorder(struct mesh *m, struct behavior *b)
13695#else /* not ANSI_DECLARATORS */
13696void highorder(m, b)
13697struct mesh *m;
13698struct behavior *b;
13699#endif /* not ANSI_DECLARATORS */
13700
13701{
13702 struct otri triangleloop, trisym;
13703 struct osub checkmark;
13704 vertex newvertex;
13705 vertex torg, tdest;
13706 int i;
13707 triangle ptr; /* Temporary variable used by sym(). */
13708 subseg sptr; /* Temporary variable used by tspivot(). */
13709
13710 if (!b->quiet) {
13711 printf("Adding vertices for second-order triangles.\n");
13712 }
13713 /* The following line ensures that dead items in the pool of nodes */
13714 /* cannot be allocated for the extra nodes associated with high */
13715 /* order elements. This ensures that the primary nodes (at the */
13716 /* corners of elements) will occur earlier in the output files, and */
13717 /* have lower indices, than the extra nodes. */
13718 m->vertices.deaditemstack = (VOID *) NULL;
13719
13720 traversalinit(&m->triangles);
13721 triangleloop.tri = triangletraverse(m);
13722 /* To loop over the set of edges, loop over all triangles, and look at */
13723 /* the three edges of each triangle. If there isn't another triangle */
13724 /* adjacent to the edge, operate on the edge. If there is another */
13725 /* adjacent triangle, operate on the edge only if the current triangle */
13726 /* has a smaller pointer than its neighbor. This way, each edge is */
13727 /* considered only once. */
13728 while (triangleloop.tri != (triangle *) NULL) {
13729 for (triangleloop.orient = 0; triangleloop.orient < 3;
13730 triangleloop.orient++) {
13731 sym(triangleloop, trisym);
13732 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13733 org(triangleloop, torg);
13734 dest(triangleloop, tdest);
13735 /* Create a new node in the middle of the edge. Interpolate */
13736 /* its attributes. */
13737 newvertex = (vertex) poolalloc(&m->vertices);
13738 for (i = 0; i < 2 + m->nextras; i++) {
13739 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13740 }
13741 /* Set the new node's marker to zero or one, depending on */
13742 /* whether it lies on a boundary. */
13743 setvertexmark(newvertex, trisym.tri == m->dummytri);
13744 setvertextype(newvertex,
13745 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13746 if (b->usesegments) {
13747 tspivot(triangleloop, checkmark);
13748 /* If this edge is a segment, transfer the marker to the new node. */
13749 if (checkmark.ss != m->dummysub) {
13750 setvertexmark(newvertex, mark(checkmark));
13751 setvertextype(newvertex, SEGMENTVERTEX);
13752 }
13753 }
13754 if (b->verbose > 1) {
13755 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13756 }
13757 /* Record the new node in the (one or two) adjacent elements. */
13758 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13759 (triangle) newvertex;
13760 if (trisym.tri != m->dummytri) {
13761 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13762 }
13763 }
13764 }
13765 triangleloop.tri = triangletraverse(m);
13766 }
13767}
13768
13769/********* File I/O routines begin here *********/
13770/** **/
13771/** **/
13772
13773/*****************************************************************************/
13774/* */
13775/* readline() Read a nonempty line from a file. */
13776/* */
13777/* A line is considered "nonempty" if it contains something that looks like */
13778/* a number. Comments (prefaced by `#') are ignored. */
13779/* */
13780/*****************************************************************************/
13781
13782#ifndef TRILIBRARY
13783
13784#ifdef ANSI_DECLARATORS
13785char *readline(char *string, FILE *infile, char *infilename)
13786#else /* not ANSI_DECLARATORS */
13787char *readline(string, infile, infilename)
13788char *string;
13789FILE *infile;
13790char *infilename;
13791#endif /* not ANSI_DECLARATORS */
13792
13793{
13794 char *result;
13795
13796 /* Search for something that looks like a number. */
13797 do {
13798 result = fgets(string, INPUTLINESIZE, infile);
13799 if (result == (char *) NULL) {
13800 printf(" Error: Unexpected end of file in %s.\n", infilename);
13801 triexit(1);
13802 }
13803 /* Skip anything that doesn't look like a number, a comment, */
13804 /* or the end of a line. */
13805 while ((*result != '\0') && (*result != '#')
13806 && (*result != '.') && (*result != '+') && (*result != '-')
13807 && ((*result < '0') || (*result > '9'))) {
13808 result++;
13809 }
13810 /* If it's a comment or end of line, read another line and try again. */
13811 } while ((*result == '#') || (*result == '\0'));
13812 return result;
13813}
13814
13815#endif /* not TRILIBRARY */
13816
13817/*****************************************************************************/
13818/* */
13819/* findfield() Find the next field of a string. */
13820/* */
13821/* Jumps past the current field by searching for whitespace, then jumps */
13822/* past the whitespace to find the next field. */
13823/* */
13824/*****************************************************************************/
13825
13826#ifndef TRILIBRARY
13827
13828#ifdef ANSI_DECLARATORS
13829char *findfield(char *string)
13830#else /* not ANSI_DECLARATORS */
13831char *findfield(string)
13832char *string;
13833#endif /* not ANSI_DECLARATORS */
13834
13835{
13836 char *result;
13837
13838 result = string;
13839 /* Skip the current field. Stop upon reaching whitespace. */
13840 while ((*result != '\0') && (*result != '#')
13841 && (*result != ' ') && (*result != '\t')) {
13842 result++;
13843 }
13844 /* Now skip the whitespace and anything else that doesn't look like a */
13845 /* number, a comment, or the end of a line. */
13846 while ((*result != '\0') && (*result != '#')
13847 && (*result != '.') && (*result != '+') && (*result != '-')
13848 && ((*result < '0') || (*result > '9'))) {
13849 result++;
13850 }
13851 /* Check for a comment (prefixed with `#'). */
13852 if (*result == '#') {
13853 *result = '\0';
13854 }
13855 return result;
13856}
13857
13858#endif /* not TRILIBRARY */
13859
13860/*****************************************************************************/
13861/* */
13862/* readnodes() Read the vertices from a file, which may be a .node or */
13863/* .poly file. */
13864/* */
13865/*****************************************************************************/
13866
13867#ifndef TRILIBRARY
13868
13869#ifdef ANSI_DECLARATORS
13870void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13871 char *polyfilename, FILE **polyfile)
13872#else /* not ANSI_DECLARATORS */
13873void readnodes(m, b, nodefilename, polyfilename, polyfile)
13874struct mesh *m;
13875struct behavior *b;
13876char *nodefilename;
13877char *polyfilename;
13878FILE **polyfile;
13879#endif /* not ANSI_DECLARATORS */
13880
13881{
13882 FILE *infile;
13883 vertex vertexloop;
13884 char inputline[INPUTLINESIZE];
13885 char *stringptr;
13886 char *infilename;
13887 REAL x, y;
13888 int firstnode;
13889 int nodemarkers;
13890 int currentmarker;
13891 int i, j;
13892
13893 if (b->poly) {
13894 /* Read the vertices from a .poly file. */
13895 if (!b->quiet) {
13896 printf("Opening %s.\n", polyfilename);
13897 }
13898 *polyfile = fopen(polyfilename, "r");
13899 if (*polyfile == (FILE *) NULL) {
13900 printf(" Error: Cannot access file %s.\n", polyfilename);
13901 triexit(1);
13902 }
13903 /* Read number of vertices, number of dimensions, number of vertex */
13904 /* attributes, and number of boundary markers. */
13905 stringptr = readline(inputline, *polyfile, polyfilename);
13906 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13907 stringptr = findfield(stringptr);
13908 if (*stringptr == '\0') {
13909 m->mesh_dim = 2;
13910 } else {
13911 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13912 }
13913 stringptr = findfield(stringptr);
13914 if (*stringptr == '\0') {
13915 m->nextras = 0;
13916 } else {
13917 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13918 }
13919 stringptr = findfield(stringptr);
13920 if (*stringptr == '\0') {
13921 nodemarkers = 0;
13922 } else {
13923 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13924 }
13925 if (m->invertices > 0) {
13926 infile = *polyfile;
13927 infilename = polyfilename;
13928 m->readnodefile = 0;
13929 } else {
13930 /* If the .poly file claims there are zero vertices, that means that */
13931 /* the vertices should be read from a separate .node file. */
13932 m->readnodefile = 1;
13933 infilename = nodefilename;
13934 }
13935 } else {
13936 m->readnodefile = 1;
13937 infilename = nodefilename;
13938 *polyfile = (FILE *) NULL;
13939 }
13940
13941 if (m->readnodefile) {
13942 /* Read the vertices from a .node file. */
13943 if (!b->quiet) {
13944 printf("Opening %s.\n", nodefilename);
13945 }
13946 infile = fopen(nodefilename, "r");
13947 if (infile == (FILE *) NULL) {
13948 printf(" Error: Cannot access file %s.\n", nodefilename);
13949 triexit(1);
13950 }
13951 /* Read number of vertices, number of dimensions, number of vertex */
13952 /* attributes, and number of boundary markers. */
13953 stringptr = readline(inputline, infile, nodefilename);
13954 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13955 stringptr = findfield(stringptr);
13956 if (*stringptr == '\0') {
13957 m->mesh_dim = 2;
13958 } else {
13959 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13960 }
13961 stringptr = findfield(stringptr);
13962 if (*stringptr == '\0') {
13963 m->nextras = 0;
13964 } else {
13965 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13966 }
13967 stringptr = findfield(stringptr);
13968 if (*stringptr == '\0') {
13969 nodemarkers = 0;
13970 } else {
13971 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13972 }
13973 }
13974
13975 if (m->invertices < 3) {
13976 printf("Error: Input must have at least three input vertices.\n");
13977 triexit(1);
13978 }
13979 if (m->mesh_dim != 2) {
13980 printf("Error: Triangle only works with two-dimensional meshes.\n");
13981 triexit(1);
13982 }
13983 if (m->nextras == 0) {
13984 b->weighted = 0;
13985 }
13986
13988
13989 /* Read the vertices. */
13990 for (i = 0; i < m->invertices; i++) {
13991 vertexloop = (vertex) poolalloc(&m->vertices);
13992 stringptr = readline(inputline, infile, infilename);
13993 if (i == 0) {
13994 firstnode = (int) strtol(stringptr, &stringptr, 0);
13995 if ((firstnode == 0) || (firstnode == 1)) {
13996 b->firstnumber = firstnode;
13997 }
13998 }
13999 stringptr = findfield(stringptr);
14000 if (*stringptr == '\0') {
14001 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14002 triexit(1);
14003 }
14004 x = (REAL) strtod(stringptr, &stringptr);
14005 stringptr = findfield(stringptr);
14006 if (*stringptr == '\0') {
14007 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14008 triexit(1);
14009 }
14010 y = (REAL) strtod(stringptr, &stringptr);
14011 vertexloop[0] = x;
14012 vertexloop[1] = y;
14013 /* Read the vertex attributes. */
14014 for (j = 2; j < 2 + m->nextras; j++) {
14015 stringptr = findfield(stringptr);
14016 if (*stringptr == '\0') {
14017 vertexloop[j] = 0.0;
14018 } else {
14019 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14020 }
14021 }
14022 if (nodemarkers) {
14023 /* Read a vertex marker. */
14024 stringptr = findfield(stringptr);
14025 if (*stringptr == '\0') {
14026 setvertexmark(vertexloop, 0);
14027 } else {
14028 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14029 setvertexmark(vertexloop, currentmarker);
14030 }
14031 } else {
14032 /* If no markers are specified in the file, they default to zero. */
14033 setvertexmark(vertexloop, 0);
14034 }
14035 setvertextype(vertexloop, INPUTVERTEX);
14036 /* Determine the smallest and largest x and y coordinates. */
14037 if (i == 0) {
14038 m->xmin = m->xmax = x;
14039 m->ymin = m->ymax = y;
14040 } else {
14041 m->xmin = (x < m->xmin) ? x : m->xmin;
14042 m->xmax = (x > m->xmax) ? x : m->xmax;
14043 m->ymin = (y < m->ymin) ? y : m->ymin;
14044 m->ymax = (y > m->ymax) ? y : m->ymax;
14045 }
14046 }
14047 if (m->readnodefile) {
14048 fclose(infile);
14049 }
14050
14051 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14052 /* Delaunay algorithm. */
14053 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14054}
14055
14056#endif /* not TRILIBRARY */
14057
14058/*****************************************************************************/
14059/* */
14060/* transfernodes() Read the vertices from memory. */
14061/* */
14062/*****************************************************************************/
14063
14064#ifdef TRILIBRARY
14065
14066#ifdef ANSI_DECLARATORS
14067void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14068 REAL *pointattriblist, int *pointmarkerlist,
14069 int numberofpoints, int numberofpointattribs)
14070#else /* not ANSI_DECLARATORS */
14071void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14072 numberofpoints, numberofpointattribs)
14073struct mesh *m;
14074struct behavior *b;
14075REAL *pointlist;
14076REAL *pointattriblist;
14077int *pointmarkerlist;
14078int numberofpoints;
14079int numberofpointattribs;
14080#endif /* not ANSI_DECLARATORS */
14081
14082{
14083 vertex vertexloop;
14084 REAL x, y;
14085 int i, j;
14086 int coordindex;
14087 int attribindex;
14088
14089 m->invertices = numberofpoints;
14090 m->mesh_dim = 2;
14091 m->nextras = numberofpointattribs;
14092 m->readnodefile = 0;
14093 if (m->invertices < 3) {
14094 printf("Error: Input must have at least three input vertices.\n");
14095 triexit(1);
14096 }
14097 if (m->nextras == 0) {
14098 b->weighted = 0;
14099 }
14100
14102
14103 /* Read the vertices. */
14104 coordindex = 0;
14105 attribindex = 0;
14106 for (i = 0; i < m->invertices; i++) {
14107 vertexloop = (vertex) poolalloc(&m->vertices);
14108 /* Read the vertex coordinates. */
14109 x = vertexloop[0] = pointlist[coordindex++];
14110 y = vertexloop[1] = pointlist[coordindex++];
14111 /* Read the vertex attributes. */
14112 for (j = 0; j < numberofpointattribs; j++) {
14113 vertexloop[2 + j] = pointattriblist[attribindex++];
14114 }
14115 if (pointmarkerlist != (int *) NULL) {
14116 /* Read a vertex marker. */
14117 setvertexmark(vertexloop, pointmarkerlist[i]);
14118 } else {
14119 /* If no markers are specified, they default to zero. */
14120 setvertexmark(vertexloop, 0);
14121 }
14122 setvertextype(vertexloop, INPUTVERTEX);
14123 /* Determine the smallest and largest x and y coordinates. */
14124 if (i == 0) {
14125 m->xmin = m->xmax = x;
14126 m->ymin = m->ymax = y;
14127 } else {
14128 m->xmin = (x < m->xmin) ? x : m->xmin;
14129 m->xmax = (x > m->xmax) ? x : m->xmax;
14130 m->ymin = (y < m->ymin) ? y : m->ymin;
14131 m->ymax = (y > m->ymax) ? y : m->ymax;
14132 }
14133 }
14134
14135 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14136 /* Delaunay algorithm. */
14137 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14138}
14139
14140#endif /* TRILIBRARY */
14141
14142/*****************************************************************************/
14143/* */
14144/* readholes() Read the holes, and possibly regional attributes and area */
14145/* constraints, from a .poly file. */
14146/* */
14147/*****************************************************************************/
14148
14149#ifndef TRILIBRARY
14150
14151#ifdef ANSI_DECLARATORS
14152void readholes(struct mesh *m, struct behavior *b,
14153 FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14154 REAL **rlist, int *regions)
14155#else /* not ANSI_DECLARATORS */
14156void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14157struct mesh *m;
14158struct behavior *b;
14159FILE *polyfile;
14160char *polyfilename;
14161REAL **hlist;
14162int *holes;
14163REAL **rlist;
14164int *regions;
14165#endif /* not ANSI_DECLARATORS */
14166
14167{
14168 REAL *holelist;
14169 REAL *regionlist;
14170 char inputline[INPUTLINESIZE];
14171 char *stringptr;
14172 int index;
14173 int i;
14174
14175 /* Read the holes. */
14176 stringptr = readline(inputline, polyfile, polyfilename);
14177 *holes = (int) strtol(stringptr, &stringptr, 0);
14178 if (*holes > 0) {
14179 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14180 *hlist = holelist;
14181 for (i = 0; i < 2 * *holes; i += 2) {
14182 stringptr = readline(inputline, polyfile, polyfilename);
14183 stringptr = findfield(stringptr);
14184 if (*stringptr == '\0') {
14185 printf("Error: Hole %d has no x coordinate.\n",
14186 b->firstnumber + (i >> 1));
14187 triexit(1);
14188 } else {
14189 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14190 }
14191 stringptr = findfield(stringptr);
14192 if (*stringptr == '\0') {
14193 printf("Error: Hole %d has no y coordinate.\n",
14194 b->firstnumber + (i >> 1));
14195 triexit(1);
14196 } else {
14197 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14198 }
14199 }
14200 } else {
14201 *hlist = (REAL *) NULL;
14202 }
14203
14204#ifndef CDT_ONLY
14205 if ((b->regionattrib || b->vararea) && !b->refine) {
14206 /* Read the area constraints. */
14207 stringptr = readline(inputline, polyfile, polyfilename);
14208 *regions = (int) strtol(stringptr, &stringptr, 0);
14209 if (*regions > 0) {
14210 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14211 *rlist = regionlist;
14212 index = 0;
14213 for (i = 0; i < *regions; i++) {
14214 stringptr = readline(inputline, polyfile, polyfilename);
14215 stringptr = findfield(stringptr);
14216 if (*stringptr == '\0') {
14217 printf("Error: Region %d has no x coordinate.\n",
14218 b->firstnumber + i);
14219 triexit(1);
14220 } else {
14221 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14222 }
14223 stringptr = findfield(stringptr);
14224 if (*stringptr == '\0') {
14225 printf("Error: Region %d has no y coordinate.\n",
14226 b->firstnumber + i);
14227 triexit(1);
14228 } else {
14229 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14230 }
14231 stringptr = findfield(stringptr);
14232 if (*stringptr == '\0') {
14233 printf(
14234 "Error: Region %d has no region attribute or area constraint.\n",
14235 b->firstnumber + i);
14236 triexit(1);
14237 } else {
14238 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14239 }
14240 stringptr = findfield(stringptr);
14241 if (*stringptr == '\0') {
14242 regionlist[index] = regionlist[index - 1];
14243 } else {
14244 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14245 }
14246 index++;
14247 }
14248 }
14249 } else {
14250 /* Set `*regions' to zero to avoid an accidental free() later. */
14251 *regions = 0;
14252 *rlist = (REAL *) NULL;
14253 }
14254#endif /* not CDT_ONLY */
14255
14256 fclose(polyfile);
14257}
14258
14259#endif /* not TRILIBRARY */
14260
14261/*****************************************************************************/
14262/* */
14263/* finishfile() Write the command line to the output file so the user */
14264/* can remember how the file was generated. Close the file. */
14265/* */
14266/*****************************************************************************/
14267
14268#ifndef TRILIBRARY
14269
14270#ifdef ANSI_DECLARATORS
14271void finishfile(FILE *outfile, int argc, char **argv)
14272#else /* not ANSI_DECLARATORS */
14273void finishfile(outfile, argc, argv)
14274FILE *outfile;
14275int argc;
14276char **argv;
14277#endif /* not ANSI_DECLARATORS */
14278
14279{
14280 int i;
14281
14282 fprintf(outfile, "# Generated by");
14283 for (i = 0; i < argc; i++) {
14284 fprintf(outfile, " ");
14285 fputs(argv[i], outfile);
14286 }
14287 fprintf(outfile, "\n");
14288 fclose(outfile);
14289}
14290
14291#endif /* not TRILIBRARY */
14292
14293/*****************************************************************************/
14294/* */
14295/* writenodes() Number the vertices and write them to a .node file. */
14296/* */
14297/* To save memory, the vertex numbers are written over the boundary markers */
14298/* after the vertices are written to a file. */
14299/* */
14300/*****************************************************************************/
14301
14302#ifdef TRILIBRARY
14303
14304#ifdef ANSI_DECLARATORS
14305void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14306 REAL **pointattriblist, int **pointmarkerlist)
14307#else /* not ANSI_DECLARATORS */
14308void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14309struct mesh *m;
14310struct behavior *b;
14311REAL **pointlist;
14312REAL **pointattriblist;
14313int **pointmarkerlist;
14314#endif /* not ANSI_DECLARATORS */
14315
14316#else /* not TRILIBRARY */
14317
14318#ifdef ANSI_DECLARATORS
14319void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14320 int argc, char **argv)
14321#else /* not ANSI_DECLARATORS */
14322void writenodes(m, b, nodefilename, argc, argv)
14323struct mesh *m;
14324struct behavior *b;
14325char *nodefilename;
14326int argc;
14327char **argv;
14328#endif /* not ANSI_DECLARATORS */
14329
14330#endif /* not TRILIBRARY */
14331
14332{
14333#ifdef TRILIBRARY
14334 REAL *plist;
14335 REAL *palist;
14336 int *pmlist;
14337 int coordindex;
14338 int attribindex;
14339#else /* not TRILIBRARY */
14340 FILE *outfile;
14341#endif /* not TRILIBRARY */
14342 vertex vertexloop;
14343 long outvertices;
14344 int vertexnumber;
14345 int i;
14346
14347 if (b->jettison) {
14348 outvertices = m->vertices.items - m->undeads;
14349 } else {
14350 outvertices = m->vertices.items;
14351 }
14352
14353#ifdef TRILIBRARY
14354 if (!b->quiet) {
14355 printf("Writing vertices.\n");
14356 }
14357 /* Allocate memory for output vertices if necessary. */
14358 if (*pointlist == (REAL *) NULL) {
14359 *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14360 }
14361 /* Allocate memory for output vertex attributes if necessary. */
14362 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14363 *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14364 sizeof(REAL)));
14365 }
14366 /* Allocate memory for output vertex markers if necessary. */
14367 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14368 *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14369 }
14370 plist = *pointlist;
14371 palist = *pointattriblist;
14372 pmlist = *pointmarkerlist;
14373 coordindex = 0;
14374 attribindex = 0;
14375#else /* not TRILIBRARY */
14376 if (!b->quiet) {
14377 printf("Writing %s.\n", nodefilename);
14378 }
14379 outfile = fopen(nodefilename, "w");
14380 if (outfile == (FILE *) NULL) {
14381 printf(" Error: Cannot create file %s.\n", nodefilename);
14382 triexit(1);
14383 }
14384 /* Number of vertices, number of dimensions, number of vertex attributes, */
14385 /* and number of boundary markers (zero or one). */
14386 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14387 m->nextras, 1 - b->nobound);
14388#endif /* not TRILIBRARY */
14389
14390 traversalinit(&m->vertices);
14391 vertexnumber = b->firstnumber;
14392 vertexloop = vertextraverse(m);
14393 while (vertexloop != (vertex) NULL) {
14394 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14395#ifdef TRILIBRARY
14396 /* X and y coordinates. */
14397 plist[coordindex++] = vertexloop[0];
14398 plist[coordindex++] = vertexloop[1];
14399 /* Vertex attributes. */
14400 for (i = 0; i < m->nextras; i++) {
14401 palist[attribindex++] = vertexloop[2 + i];
14402 }
14403 if (!b->nobound) {
14404 /* Copy the boundary marker. */
14405 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14406 }
14407#else /* not TRILIBRARY */
14408 /* Vertex number, x and y coordinates. */
14409 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14410 vertexloop[1]);
14411 for (i = 0; i < m->nextras; i++) {
14412 /* Write an attribute. */
14413 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14414 }
14415 if (b->nobound) {
14416 fprintf(outfile, "\n");
14417 } else {
14418 /* Write the boundary marker. */
14419 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14420 }
14421#endif /* not TRILIBRARY */
14422
14423 setvertexmark(vertexloop, vertexnumber);
14424 vertexnumber++;
14425 }
14426 vertexloop = vertextraverse(m);
14427 }
14428
14429#ifndef TRILIBRARY
14430 finishfile(outfile, argc, argv);
14431#endif /* not TRILIBRARY */
14432}
14433
14434/*****************************************************************************/
14435/* */
14436/* numbernodes() Number the vertices. */
14437/* */
14438/* Each vertex is assigned a marker equal to its number. */
14439/* */
14440/* Used when writenodes() is not called because no .node file is written. */
14441/* */
14442/*****************************************************************************/
14443
14444#ifdef ANSI_DECLARATORS
14445void numbernodes(struct mesh *m, struct behavior *b)
14446#else /* not ANSI_DECLARATORS */
14447void numbernodes(m, b)
14448struct mesh *m;
14449struct behavior *b;
14450#endif /* not ANSI_DECLARATORS */
14451
14452{
14453 vertex vertexloop;
14454 int vertexnumber;
14455
14456 traversalinit(&m->vertices);
14457 vertexnumber = b->firstnumber;
14458 vertexloop = vertextraverse(m);
14459 while (vertexloop != (vertex) NULL) {
14460 setvertexmark(vertexloop, vertexnumber);
14461 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14462 vertexnumber++;
14463 }
14464 vertexloop = vertextraverse(m);
14465 }
14466}
14467
14468/*****************************************************************************/
14469/* */
14470/* writeelements() Write the triangles to an .ele file. */
14471/* */
14472/*****************************************************************************/
14473
14474#ifdef TRILIBRARY
14475
14476#ifdef ANSI_DECLARATORS
14477void writeelements(struct mesh *m, struct behavior *b,
14478 int **trianglelist, REAL **triangleattriblist)
14479#else /* not ANSI_DECLARATORS */
14480void writeelements(m, b, trianglelist, triangleattriblist)
14481struct mesh *m;
14482struct behavior *b;
14483int **trianglelist;
14484REAL **triangleattriblist;
14485#endif /* not ANSI_DECLARATORS */
14486
14487#else /* not TRILIBRARY */
14488
14489#ifdef ANSI_DECLARATORS
14490void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14491 int argc, char **argv)
14492#else /* not ANSI_DECLARATORS */
14493void writeelements(m, b, elefilename, argc, argv)
14494struct mesh *m;
14495struct behavior *b;
14496char *elefilename;
14497int argc;
14498char **argv;
14499#endif /* not ANSI_DECLARATORS */
14500
14501#endif /* not TRILIBRARY */
14502
14503{
14504#ifdef TRILIBRARY
14505 int *tlist;
14506 REAL *talist;
14507 int vertexindex;
14508 int attribindex;
14509#else /* not TRILIBRARY */
14510 FILE *outfile;
14511#endif /* not TRILIBRARY */
14512 struct otri triangleloop;
14513 vertex p1, p2, p3;
14514 vertex mid1, mid2, mid3;
14515 long elementnumber;
14516 int i;
14517
14518#ifdef TRILIBRARY
14519 if (!b->quiet) {
14520 printf("Writing triangles.\n");
14521 }
14522 /* Allocate memory for output triangles if necessary. */
14523 if (*trianglelist == (int *) NULL) {
14524 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14525 ((b->order + 1) * (b->order + 2) /
14526 2) * sizeof(int)));
14527 }
14528 /* Allocate memory for output triangle attributes if necessary. */
14529 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14530 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14531 m->eextras *
14532 sizeof(REAL)));
14533 }
14534 tlist = *trianglelist;
14535 talist = *triangleattriblist;
14536 vertexindex = 0;
14537 attribindex = 0;
14538#else /* not TRILIBRARY */
14539 if (!b->quiet) {
14540 printf("Writing %s.\n", elefilename);
14541 }
14542 outfile = fopen(elefilename, "w");
14543 if (outfile == (FILE *) NULL) {
14544 printf(" Error: Cannot create file %s.\n", elefilename);
14545 triexit(1);
14546 }
14547 /* Number of triangles, vertices per triangle, attributes per triangle. */
14548 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14549 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14550#endif /* not TRILIBRARY */
14551
14552 traversalinit(&m->triangles);
14553 triangleloop.tri = triangletraverse(m);
14554 triangleloop.orient = 0;
14555 elementnumber = b->firstnumber;
14556 while (triangleloop.tri != (triangle *) NULL) {
14557 org(triangleloop, p1);
14558 dest(triangleloop, p2);
14559 apex(triangleloop, p3);
14560 if (b->order == 1) {
14561#ifdef TRILIBRARY
14562 tlist[vertexindex++] = vertexmark(p1);
14563 tlist[vertexindex++] = vertexmark(p2);
14564 tlist[vertexindex++] = vertexmark(p3);
14565#else /* not TRILIBRARY */
14566 /* Triangle number, indices for three vertices. */
14567 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14569#endif /* not TRILIBRARY */
14570 } else {
14571 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14572 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14573 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14574#ifdef TRILIBRARY
14575 tlist[vertexindex++] = vertexmark(p1);
14576 tlist[vertexindex++] = vertexmark(p2);
14577 tlist[vertexindex++] = vertexmark(p3);
14578 tlist[vertexindex++] = vertexmark(mid1);
14579 tlist[vertexindex++] = vertexmark(mid2);
14580 tlist[vertexindex++] = vertexmark(mid3);
14581#else /* not TRILIBRARY */
14582 /* Triangle number, indices for six vertices. */
14583 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14585 vertexmark(mid2), vertexmark(mid3));
14586#endif /* not TRILIBRARY */
14587 }
14588
14589#ifdef TRILIBRARY
14590 for (i = 0; i < m->eextras; i++) {
14591 talist[attribindex++] = elemattribute(triangleloop, i);
14592 }
14593#else /* not TRILIBRARY */
14594 for (i = 0; i < m->eextras; i++) {
14595 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14596 }
14597 fprintf(outfile, "\n");
14598#endif /* not TRILIBRARY */
14599
14600 triangleloop.tri = triangletraverse(m);
14601 elementnumber++;
14602 }
14603
14604#ifndef TRILIBRARY
14605 finishfile(outfile, argc, argv);
14606#endif /* not TRILIBRARY */
14607}
14608
14609/*****************************************************************************/
14610/* */
14611/* writepoly() Write the segments and holes to a .poly file. */
14612/* */
14613/*****************************************************************************/
14614
14615#ifdef TRILIBRARY
14616
14617#ifdef ANSI_DECLARATORS
14618void writepoly(struct mesh *m, struct behavior *b,
14619 int **segmentlist, int **segmentmarkerlist)
14620#else /* not ANSI_DECLARATORS */
14621void writepoly(m, b, segmentlist, segmentmarkerlist)
14622struct mesh *m;
14623struct behavior *b;
14624int **segmentlist;
14625int **segmentmarkerlist;
14626#endif /* not ANSI_DECLARATORS */
14627
14628#else /* not TRILIBRARY */
14629
14630#ifdef ANSI_DECLARATORS
14631void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14632 REAL *holelist, int holes, REAL *regionlist, int regions,
14633 int argc, char **argv)
14634#else /* not ANSI_DECLARATORS */
14635void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14636 argc, argv)
14637struct mesh *m;
14638struct behavior *b;
14639char *polyfilename;
14640REAL *holelist;
14641int holes;
14642REAL *regionlist;
14643int regions;
14644int argc;
14645char **argv;
14646#endif /* not ANSI_DECLARATORS */
14647
14648#endif /* not TRILIBRARY */
14649
14650{
14651#ifdef TRILIBRARY
14652 int *slist;
14653 int *smlist;
14654 int index;
14655#else /* not TRILIBRARY */
14656 FILE *outfile;
14657 long holenumber, regionnumber;
14658#endif /* not TRILIBRARY */
14659 struct osub subsegloop;
14660 vertex endpoint1, endpoint2;
14661 long subsegnumber;
14662
14663#ifdef TRILIBRARY
14664 if (!b->quiet) {
14665 printf("Writing segments.\n");
14666 }
14667 /* Allocate memory for output segments if necessary. */
14668 if (*segmentlist == (int *) NULL) {
14669 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14670 sizeof(int)));
14671 }
14672 /* Allocate memory for output segment markers if necessary. */
14673 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14674 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14675 sizeof(int)));
14676 }
14677 slist = *segmentlist;
14678 smlist = *segmentmarkerlist;
14679 index = 0;
14680#else /* not TRILIBRARY */
14681 if (!b->quiet) {
14682 printf("Writing %s.\n", polyfilename);
14683 }
14684 outfile = fopen(polyfilename, "w");
14685 if (outfile == (FILE *) NULL) {
14686 printf(" Error: Cannot create file %s.\n", polyfilename);
14687 triexit(1);
14688 }
14689 /* The zero indicates that the vertices are in a separate .node file. */
14690 /* Followed by number of dimensions, number of vertex attributes, */
14691 /* and number of boundary markers (zero or one). */
14692 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14693 1 - b->nobound);
14694 /* Number of segments, number of boundary markers (zero or one). */
14695 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14696#endif /* not TRILIBRARY */
14697
14698 traversalinit(&m->subsegs);
14699 subsegloop.ss = subsegtraverse(m);
14700 subsegloop.ssorient = 0;
14701 subsegnumber = b->firstnumber;
14702 while (subsegloop.ss != (subseg *) NULL) {
14703 sorg(subsegloop, endpoint1);
14704 sdest(subsegloop, endpoint2);
14705#ifdef TRILIBRARY
14706 /* Copy indices of the segment's two endpoints. */
14707 slist[index++] = vertexmark(endpoint1);
14708 slist[index++] = vertexmark(endpoint2);
14709 if (!b->nobound) {
14710 /* Copy the boundary marker. */
14711 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14712 }
14713#else /* not TRILIBRARY */
14714 /* Segment number, indices of its two endpoints, and possibly a marker. */
14715 if (b->nobound) {
14716 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14717 vertexmark(endpoint1), vertexmark(endpoint2));
14718 } else {
14719 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14720 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14721 }
14722#endif /* not TRILIBRARY */
14723
14724 subsegloop.ss = subsegtraverse(m);
14725 subsegnumber++;
14726 }
14727
14728#ifndef TRILIBRARY
14729#ifndef CDT_ONLY
14730 fprintf(outfile, "%d\n", holes);
14731 if (holes > 0) {
14732 for (holenumber = 0; holenumber < holes; holenumber++) {
14733 /* Hole number, x and y coordinates. */
14734 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14735 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14736 }
14737 }
14738 if (regions > 0) {
14739 fprintf(outfile, "%d\n", regions);
14740 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14741 /* Region number, x and y coordinates, attribute, maximum area. */
14742 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14743 b->firstnumber + regionnumber,
14744 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14745 regionlist[4 * regionnumber + 2],
14746 regionlist[4 * regionnumber + 3]);
14747 }
14748 }
14749#endif /* not CDT_ONLY */
14750
14751 finishfile(outfile, argc, argv);
14752#endif /* not TRILIBRARY */
14753}
14754
14755/*****************************************************************************/
14756/* */
14757/* writeedges() Write the edges to an .edge file. */
14758/* */
14759/*****************************************************************************/
14760
14761#ifdef TRILIBRARY
14762
14763#ifdef ANSI_DECLARATORS
14764void writeedges(struct mesh *m, struct behavior *b,
14765 int **edgelist, int **edgemarkerlist)
14766#else /* not ANSI_DECLARATORS */
14767void writeedges(m, b, edgelist, edgemarkerlist)
14768struct mesh *m;
14769struct behavior *b;
14770int **edgelist;
14771int **edgemarkerlist;
14772#endif /* not ANSI_DECLARATORS */
14773
14774#else /* not TRILIBRARY */
14775
14776#ifdef ANSI_DECLARATORS
14777void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14778 int argc, char **argv)
14779#else /* not ANSI_DECLARATORS */
14780void writeedges(m, b, edgefilename, argc, argv)
14781struct mesh *m;
14782struct behavior *b;
14783char *edgefilename;
14784int argc;
14785char **argv;
14786#endif /* not ANSI_DECLARATORS */
14787
14788#endif /* not TRILIBRARY */
14789
14790{
14791#ifdef TRILIBRARY
14792 int *elist;
14793 int *emlist;
14794 int index;
14795#else /* not TRILIBRARY */
14796 FILE *outfile;
14797#endif /* not TRILIBRARY */
14798 struct otri triangleloop, trisym;
14799 struct osub checkmark;
14800 vertex p1, p2;
14801 long edgenumber;
14802 triangle ptr; /* Temporary variable used by sym(). */
14803 subseg sptr; /* Temporary variable used by tspivot(). */
14804
14805#ifdef TRILIBRARY
14806 if (!b->quiet) {
14807 printf("Writing edges.\n");
14808 }
14809 /* Allocate memory for edges if necessary. */
14810 if (*edgelist == (int *) NULL) {
14811 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14812 }
14813 /* Allocate memory for edge markers if necessary. */
14814 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14815 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14816 }
14817 elist = *edgelist;
14818 emlist = *edgemarkerlist;
14819 index = 0;
14820#else /* not TRILIBRARY */
14821 if (!b->quiet) {
14822 printf("Writing %s.\n", edgefilename);
14823 }
14824 outfile = fopen(edgefilename, "w");
14825 if (outfile == (FILE *) NULL) {
14826 printf(" Error: Cannot create file %s.\n", edgefilename);
14827 triexit(1);
14828 }
14829 /* Number of edges, number of boundary markers (zero or one). */
14830 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14831#endif /* not TRILIBRARY */
14832
14833 traversalinit(&m->triangles);
14834 triangleloop.tri = triangletraverse(m);
14835 edgenumber = b->firstnumber;
14836 /* To loop over the set of edges, loop over all triangles, and look at */
14837 /* the three edges of each triangle. If there isn't another triangle */
14838 /* adjacent to the edge, operate on the edge. If there is another */
14839 /* adjacent triangle, operate on the edge only if the current triangle */
14840 /* has a smaller pointer than its neighbor. This way, each edge is */
14841 /* considered only once. */
14842 while (triangleloop.tri != (triangle *) NULL) {
14843 for (triangleloop.orient = 0; triangleloop.orient < 3;
14844 triangleloop.orient++) {
14845 sym(triangleloop, trisym);
14846 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14847 org(triangleloop, p1);
14848 dest(triangleloop, p2);
14849#ifdef TRILIBRARY
14850 elist[index++] = vertexmark(p1);
14851 elist[index++] = vertexmark(p2);
14852#endif /* TRILIBRARY */
14853 if (b->nobound) {
14854#ifndef TRILIBRARY
14855 /* Edge number, indices of two endpoints. */
14856 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14858#endif /* not TRILIBRARY */
14859 } else {
14860 /* Edge number, indices of two endpoints, and a boundary marker. */
14861 /* If there's no subsegment, the boundary marker is zero. */
14862 if (b->usesegments) {
14863 tspivot(triangleloop, checkmark);
14864 if (checkmark.ss == m->dummysub) {
14865#ifdef TRILIBRARY
14866 emlist[edgenumber - b->firstnumber] = 0;
14867#else /* not TRILIBRARY */
14868 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14869 vertexmark(p1), vertexmark(p2), 0);
14870#endif /* not TRILIBRARY */
14871 } else {
14872#ifdef TRILIBRARY
14873 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14874#else /* not TRILIBRARY */
14875 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14876 vertexmark(p1), vertexmark(p2), mark(checkmark));
14877#endif /* not TRILIBRARY */
14878 }
14879 } else {
14880#ifdef TRILIBRARY
14881 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14882#else /* not TRILIBRARY */
14883 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14884 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14885#endif /* not TRILIBRARY */
14886 }
14887 }
14888 edgenumber++;
14889 }
14890 }
14891 triangleloop.tri = triangletraverse(m);
14892 }
14893
14894#ifndef TRILIBRARY
14895 finishfile(outfile, argc, argv);
14896#endif /* not TRILIBRARY */
14897}
14898
14899/*****************************************************************************/
14900/* */
14901/* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */
14902/* file. */
14903/* */
14904/* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
14905/* Hence, the Voronoi vertices are listed by traversing the Delaunay */
14906/* triangles, and the Voronoi edges are listed by traversing the Delaunay */
14907/* edges. */
14908/* */
14909/* WARNING: In order to assign numbers to the Voronoi vertices, this */
14910/* procedure messes up the subsegments or the extra nodes of every */
14911/* element. Hence, you should call this procedure last. */
14912/* */
14913/*****************************************************************************/
14914
14915#ifdef TRILIBRARY
14916
14917#ifdef ANSI_DECLARATORS
14918void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14919 REAL **vpointattriblist, int **vpointmarkerlist,
14920 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14921#else /* not ANSI_DECLARATORS */
14922void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
14923 vedgelist, vedgemarkerlist, vnormlist)
14924struct mesh *m;
14925struct behavior *b;
14926REAL **vpointlist;
14927REAL **vpointattriblist;
14928int **vpointmarkerlist;
14929int **vedgelist;
14930int **vedgemarkerlist;
14931REAL **vnormlist;
14932#endif /* not ANSI_DECLARATORS */
14933
14934#else /* not TRILIBRARY */
14935
14936#ifdef ANSI_DECLARATORS
14937void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14938 char *vedgefilename, int argc, char **argv)
14939#else /* not ANSI_DECLARATORS */
14940void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
14941struct mesh *m;
14942struct behavior *b;
14943char *vnodefilename;
14944char *vedgefilename;
14945int argc;
14946char **argv;
14947#endif /* not ANSI_DECLARATORS */
14948
14949#endif /* not TRILIBRARY */
14950
14951{
14952#ifdef TRILIBRARY
14953 REAL *plist;
14954 REAL *palist;
14955 int *elist;
14956 REAL *normlist;
14957 int coordindex;
14958 int attribindex;
14959#else /* not TRILIBRARY */
14960 FILE *outfile;
14961#endif /* not TRILIBRARY */
14962 struct otri triangleloop, trisym;
14963 vertex torg, tdest, tapex;
14964 REAL circumcenter[2];
14965 REAL xi, eta;
14966 long vnodenumber, vedgenumber;
14967 int p1, p2;
14968 int i;
14969 triangle ptr; /* Temporary variable used by sym(). */
14970
14971#ifdef TRILIBRARY
14972 if (!b->quiet) {
14973 printf("Writing Voronoi vertices.\n");
14974 }
14975 /* Allocate memory for Voronoi vertices if necessary. */
14976 if (*vpointlist == (REAL *) NULL) {
14977 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
14978 sizeof(REAL)));
14979 }
14980 /* Allocate memory for Voronoi vertex attributes if necessary. */
14981 if (*vpointattriblist == (REAL *) NULL) {
14982 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14983 m->nextras * sizeof(REAL)));
14984 }
14985 *vpointmarkerlist = (int *) NULL;
14986 plist = *vpointlist;
14987 palist = *vpointattriblist;
14988 coordindex = 0;
14989 attribindex = 0;
14990#else /* not TRILIBRARY */
14991 if (!b->quiet) {
14992 printf("Writing %s.\n", vnodefilename);
14993 }
14994 outfile = fopen(vnodefilename, "w");
14995 if (outfile == (FILE *) NULL) {
14996 printf(" Error: Cannot create file %s.\n", vnodefilename);
14997 triexit(1);
14998 }
14999 /* Number of triangles, two dimensions, number of vertex attributes, */
15000 /* no markers. */
15001 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15002#endif /* not TRILIBRARY */
15003
15004 traversalinit(&m->triangles);
15005 triangleloop.tri = triangletraverse(m);
15006 triangleloop.orient = 0;
15007 vnodenumber = b->firstnumber;
15008 while (triangleloop.tri != (triangle *) NULL) {
15009 org(triangleloop, torg);
15010 dest(triangleloop, tdest);
15011 apex(triangleloop, tapex);
15012 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15013#ifdef TRILIBRARY
15014 /* X and y coordinates. */
15015 plist[coordindex++] = circumcenter[0];
15016 plist[coordindex++] = circumcenter[1];
15017 for (i = 2; i < 2 + m->nextras; i++) {
15018 /* Interpolate the vertex attributes at the circumcenter. */
15019 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15020 + eta * (tapex[i] - torg[i]);
15021 }
15022#else /* not TRILIBRARY */
15023 /* Voronoi vertex number, x and y coordinates. */
15024 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15025 circumcenter[1]);
15026 for (i = 2; i < 2 + m->nextras; i++) {
15027 /* Interpolate the vertex attributes at the circumcenter. */
15028 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15029 + eta * (tapex[i] - torg[i]));
15030 }
15031 fprintf(outfile, "\n");
15032#endif /* not TRILIBRARY */
15033
15034 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15035 triangleloop.tri = triangletraverse(m);
15036 vnodenumber++;
15037 }
15038
15039#ifndef TRILIBRARY
15040 finishfile(outfile, argc, argv);
15041#endif /* not TRILIBRARY */
15042
15043#ifdef TRILIBRARY
15044 if (!b->quiet) {
15045 printf("Writing Voronoi edges.\n");
15046 }
15047 /* Allocate memory for output Voronoi edges if necessary. */
15048 if (*vedgelist == (int *) NULL) {
15049 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15050 }
15051 *vedgemarkerlist = (int *) NULL;
15052 /* Allocate memory for output Voronoi norms if necessary. */
15053 if (*vnormlist == (REAL *) NULL) {
15054 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15055 }
15056 elist = *vedgelist;
15057 normlist = *vnormlist;
15058 coordindex = 0;
15059#else /* not TRILIBRARY */
15060 if (!b->quiet) {
15061 printf("Writing %s.\n", vedgefilename);
15062 }
15063 outfile = fopen(vedgefilename, "w");
15064 if (outfile == (FILE *) NULL) {
15065 printf(" Error: Cannot create file %s.\n", vedgefilename);
15066 triexit(1);
15067 }
15068 /* Number of edges, zero boundary markers. */
15069 fprintf(outfile, "%ld %d\n", m->edges, 0);
15070#endif /* not TRILIBRARY */
15071
15072 traversalinit(&m->triangles);
15073 triangleloop.tri = triangletraverse(m);
15074 vedgenumber = b->firstnumber;
15075 /* To loop over the set of edges, loop over all triangles, and look at */
15076 /* the three edges of each triangle. If there isn't another triangle */
15077 /* adjacent to the edge, operate on the edge. If there is another */
15078 /* adjacent triangle, operate on the edge only if the current triangle */
15079 /* has a smaller pointer than its neighbor. This way, each edge is */
15080 /* considered only once. */
15081 while (triangleloop.tri != (triangle *) NULL) {
15082 for (triangleloop.orient = 0; triangleloop.orient < 3;
15083 triangleloop.orient++) {
15084 sym(triangleloop, trisym);
15085 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15086 /* Find the number of this triangle (and Voronoi vertex). */
15087 p1 = * (int *) (triangleloop.tri + 6);
15088 if (trisym.tri == m->dummytri) {
15089 org(triangleloop, torg);
15090 dest(triangleloop, tdest);
15091#ifdef TRILIBRARY
15092 /* Copy an infinite ray. Index of one endpoint, and -1. */
15093 elist[coordindex] = p1;
15094 normlist[coordindex++] = tdest[1] - torg[1];
15095 elist[coordindex] = -1;
15096 normlist[coordindex++] = torg[0] - tdest[0];
15097#else /* not TRILIBRARY */
15098 /* Write an infinite ray. Edge number, index of one endpoint, -1, */
15099 /* and x and y coordinates of a vector representing the */
15100 /* direction of the ray. */
15101 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15102 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15103#endif /* not TRILIBRARY */
15104 } else {
15105 /* Find the number of the adjacent triangle (and Voronoi vertex). */
15106 p2 = * (int *) (trisym.tri + 6);
15107 /* Finite edge. Write indices of two endpoints. */
15108#ifdef TRILIBRARY
15109 elist[coordindex] = p1;
15110 normlist[coordindex++] = 0.0;
15111 elist[coordindex] = p2;
15112 normlist[coordindex++] = 0.0;
15113#else /* not TRILIBRARY */
15114 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15115#endif /* not TRILIBRARY */
15116 }
15117 vedgenumber++;
15118 }
15119 }
15120 triangleloop.tri = triangletraverse(m);
15121 }
15122
15123#ifndef TRILIBRARY
15124 finishfile(outfile, argc, argv);
15125#endif /* not TRILIBRARY */
15126}
15127
15128#ifdef TRILIBRARY
15129
15130#ifdef ANSI_DECLARATORS
15131void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15132#else /* not ANSI_DECLARATORS */
15133void writeneighbors(m, b, neighborlist)
15134struct mesh *m;
15135struct behavior *b;
15136int **neighborlist;
15137#endif /* not ANSI_DECLARATORS */
15138
15139#else /* not TRILIBRARY */
15140
15141#ifdef ANSI_DECLARATORS
15142void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15143 int argc, char **argv)
15144#else /* not ANSI_DECLARATORS */
15145void writeneighbors(m, b, neighborfilename, argc, argv)
15146struct mesh *m;
15147struct behavior *b;
15148char *neighborfilename;
15149int argc;
15150char **argv;
15151#endif /* not ANSI_DECLARATORS */
15152
15153#endif /* not TRILIBRARY */
15154
15155{
15156#ifdef TRILIBRARY
15157 int *nlist;
15158 int index;
15159#else /* not TRILIBRARY */
15160 FILE *outfile;
15161#endif /* not TRILIBRARY */
15162 struct otri triangleloop, trisym;
15163 long elementnumber;
15164 int neighbor1, neighbor2, neighbor3;
15165 triangle ptr; /* Temporary variable used by sym(). */
15166
15167#ifdef TRILIBRARY
15168 if (!b->quiet) {
15169 printf("Writing neighbors.\n");
15170 }
15171 /* Allocate memory for neighbors if necessary. */
15172 if (*neighborlist == (int *) NULL) {
15173 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15174 sizeof(int)));
15175 }
15176 nlist = *neighborlist;
15177 index = 0;
15178#else /* not TRILIBRARY */
15179 if (!b->quiet) {
15180 printf("Writing %s.\n", neighborfilename);
15181 }
15182 outfile = fopen(neighborfilename, "w");
15183 if (outfile == (FILE *) NULL) {
15184 printf(" Error: Cannot create file %s.\n", neighborfilename);
15185 triexit(1);
15186 }
15187 /* Number of triangles, three neighbors per triangle. */
15188 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15189#endif /* not TRILIBRARY */
15190
15191 traversalinit(&m->triangles);
15192 triangleloop.tri = triangletraverse(m);
15193 triangleloop.orient = 0;
15194 elementnumber = b->firstnumber;
15195 while (triangleloop.tri != (triangle *) NULL) {
15196 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15197 triangleloop.tri = triangletraverse(m);
15198 elementnumber++;
15199 }
15200 * (int *) (m->dummytri + 6) = -1;
15201
15202 traversalinit(&m->triangles);
15203 triangleloop.tri = triangletraverse(m);
15204 elementnumber = b->firstnumber;
15205 while (triangleloop.tri != (triangle *) NULL) {
15206 triangleloop.orient = 1;
15207 sym(triangleloop, trisym);
15208 neighbor1 = * (int *) (trisym.tri + 6);
15209 triangleloop.orient = 2;
15210 sym(triangleloop, trisym);
15211 neighbor2 = * (int *) (trisym.tri + 6);
15212 triangleloop.orient = 0;
15213 sym(triangleloop, trisym);
15214 neighbor3 = * (int *) (trisym.tri + 6);
15215#ifdef TRILIBRARY
15216 nlist[index++] = neighbor1;
15217 nlist[index++] = neighbor2;
15218 nlist[index++] = neighbor3;
15219#else /* not TRILIBRARY */
15220 /* Triangle number, neighboring triangle numbers. */
15221 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15222 neighbor1, neighbor2, neighbor3);
15223#endif /* not TRILIBRARY */
15224
15225 triangleloop.tri = triangletraverse(m);
15226 elementnumber++;
15227 }
15228
15229#ifndef TRILIBRARY
15230 finishfile(outfile, argc, argv);
15231#endif /* not TRILIBRARY */
15232}
15233
15234/*****************************************************************************/
15235/* */
15236/* writeoff() Write the triangulation to an .off file. */
15237/* */
15238/* OFF stands for the Object File Format, a format used by the Geometry */
15239/* Center's Geomview package. */
15240/* */
15241/*****************************************************************************/
15242
15243#ifndef TRILIBRARY
15244
15245#ifdef ANSI_DECLARATORS
15246void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15247 int argc, char **argv)
15248#else /* not ANSI_DECLARATORS */
15249void writeoff(m, b, offfilename, argc, argv)
15250struct mesh *m;
15251struct behavior *b;
15252char *offfilename;
15253int argc;
15254char **argv;
15255#endif /* not ANSI_DECLARATORS */
15256
15257{
15258 FILE *outfile;
15259 struct otri triangleloop;
15260 vertex vertexloop;
15261 vertex p1, p2, p3;
15262 long outvertices;
15263
15264 if (!b->quiet) {
15265 printf("Writing %s.\n", offfilename);
15266 }
15267
15268 if (b->jettison) {
15269 outvertices = m->vertices.items - m->undeads;
15270 } else {
15271 outvertices = m->vertices.items;
15272 }
15273
15274 outfile = fopen(offfilename, "w");
15275 if (outfile == (FILE *) NULL) {
15276 printf(" Error: Cannot create file %s.\n", offfilename);
15277 triexit(1);
15278 }
15279 /* Number of vertices, triangles, and edges. */
15280 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15281 m->edges);
15282
15283 /* Write the vertices. */
15284 traversalinit(&m->vertices);
15285 vertexloop = vertextraverse(m);
15286 while (vertexloop != (vertex) NULL) {
15287 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15288 /* The "0.0" is here because the OFF format uses 3D coordinates. */
15289 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15290 0.0);
15291 }
15292 vertexloop = vertextraverse(m);
15293 }
15294
15295 /* Write the triangles. */
15296 traversalinit(&m->triangles);
15297 triangleloop.tri = triangletraverse(m);
15298 triangleloop.orient = 0;
15299 while (triangleloop.tri != (triangle *) NULL) {
15300 org(triangleloop, p1);
15301 dest(triangleloop, p2);
15302 apex(triangleloop, p3);
15303 /* The "3" means a three-vertex polygon. */
15304 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15305 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15306 triangleloop.tri = triangletraverse(m);
15307 }
15308 finishfile(outfile, argc, argv);
15309}
15310
15311#endif /* not TRILIBRARY */
15312
15313/** **/
15314/** **/
15315/********* File I/O routines end here *********/
15316
15317/*****************************************************************************/
15318/* */
15319/* quality_statistics() Print statistics about the quality of the mesh. */
15320/* */
15321/*****************************************************************************/
15322
15323#ifdef ANSI_DECLARATORS
15324void quality_statistics(struct mesh *m, struct behavior *b)
15325#else /* not ANSI_DECLARATORS */
15326void quality_statistics(m, b)
15327struct mesh *m;
15328struct behavior *b;
15329#endif /* not ANSI_DECLARATORS */
15330
15331{
15332 struct otri triangleloop;
15333 vertex p[3];
15334 REAL cossquaretable[8];
15335 REAL ratiotable[16];
15336 REAL dx[3], dy[3];
15337 REAL edgelength[3];
15338 REAL dotproduct;
15339 REAL cossquare;
15340 REAL triarea;
15341 REAL shortest, longest;
15342 REAL trilongest2;
15343 REAL smallestarea, biggestarea;
15344 REAL triminaltitude2;
15345 REAL minaltitude;
15346 REAL triaspect2;
15347 REAL worstaspect;
15348 REAL smallestangle, biggestangle;
15349 REAL radconst, degconst;
15350 int angletable[18];
15351 int aspecttable[16];
15352 int aspectindex;
15353 int tendegree;
15354 int acutebiggest;
15355 int i, ii, j, k;
15356
15357 printf("Mesh quality statistics:\n\n");
15358 radconst = PI / 18.0;
15359 degconst = 180.0 / PI;
15360 for (i = 0; i < 8; i++) {
15361 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15362 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15363 }
15364 for (i = 0; i < 18; i++) {
15365 angletable[i] = 0;
15366 }
15367
15368 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15369 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15370 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15371 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15372 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15373 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15374 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15375 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15376 for (i = 0; i < 16; i++) {
15377 aspecttable[i] = 0;
15378 }
15379
15380 worstaspect = 0.0;
15381 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15382 minaltitude = minaltitude * minaltitude;
15383 shortest = minaltitude;
15384 longest = 0.0;
15385 smallestarea = minaltitude;
15386 biggestarea = 0.0;
15387 worstaspect = 0.0;
15388 smallestangle = 0.0;
15389 biggestangle = 2.0;
15390 acutebiggest = 1;
15391
15392 traversalinit(&m->triangles);
15393 triangleloop.tri = triangletraverse(m);
15394 triangleloop.orient = 0;
15395 while (triangleloop.tri != (triangle *) NULL) {
15396 org(triangleloop, p[0]);
15397 dest(triangleloop, p[1]);
15398 apex(triangleloop, p[2]);
15399 trilongest2 = 0.0;
15400
15401 for (i = 0; i < 3; i++) {
15402 j = plus1mod3[i];
15403 k = minus1mod3[i];
15404 dx[i] = p[j][0] - p[k][0];
15405 dy[i] = p[j][1] - p[k][1];
15406 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15407 if (edgelength[i] > trilongest2) {
15408 trilongest2 = edgelength[i];
15409 }
15410 if (edgelength[i] > longest) {
15411 longest = edgelength[i];
15412 }
15413 if (edgelength[i] < shortest) {
15414 shortest = edgelength[i];
15415 }
15416 }
15417
15418 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15419 if (triarea < smallestarea) {
15420 smallestarea = triarea;
15421 }
15422 if (triarea > biggestarea) {
15423 biggestarea = triarea;
15424 }
15425 triminaltitude2 = triarea * triarea / trilongest2;
15426 if (triminaltitude2 < minaltitude) {
15427 minaltitude = triminaltitude2;
15428 }
15429 triaspect2 = trilongest2 / triminaltitude2;
15430 if (triaspect2 > worstaspect) {
15431 worstaspect = triaspect2;
15432 }
15433 aspectindex = 0;
15434 while ((aspectindex < 15) &&
15435 (triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15436 ) {
15437 aspectindex++;
15438 }
15439 aspecttable[aspectindex]++;
15440
15441 for (i = 0; i < 3; i++) {
15442 j = plus1mod3[i];
15443 k = minus1mod3[i];
15444 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15445 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15446 tendegree = 8;
15447 for (ii = 7; ii >= 0; ii--) {
15448 if (cossquare > cossquaretable[ii]) {
15449 tendegree = ii;
15450 }
15451 }
15452 if (dotproduct <= 0.0) {
15453 angletable[tendegree]++;
15454 if (cossquare > smallestangle) {
15455 smallestangle = cossquare;
15456 }
15457 if (acutebiggest && (cossquare < biggestangle)) {
15458 biggestangle = cossquare;
15459 }
15460 } else {
15461 angletable[17 - tendegree]++;
15462 if (acutebiggest || (cossquare > biggestangle)) {
15463 biggestangle = cossquare;
15464 acutebiggest = 0;
15465 }
15466 }
15467 }
15468 triangleloop.tri = triangletraverse(m);
15469 }
15470
15471 shortest = sqrt(shortest);
15472 longest = sqrt(longest);
15473 minaltitude = sqrt(minaltitude);
15474 worstaspect = sqrt(worstaspect);
15475 smallestarea *= 0.5;
15476 biggestarea *= 0.5;
15477 if (smallestangle >= 1.0) {
15478 smallestangle = 0.0;
15479 } else {
15480 smallestangle = degconst * acos(sqrt(smallestangle));
15481 }
15482 if (biggestangle >= 1.0) {
15483 biggestangle = 180.0;
15484 } else {
15485 if (acutebiggest) {
15486 biggestangle = degconst * acos(sqrt(biggestangle));
15487 } else {
15488 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15489 }
15490 }
15491
15492 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15493 smallestarea, biggestarea);
15494 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15495 shortest, longest);
15496 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15497 minaltitude, worstaspect);
15498
15499 printf(" Triangle aspect ratio histogram:\n");
15500 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15501 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15502 aspecttable[8]);
15503 for (i = 1; i < 7; i++) {
15504 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15505 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15506 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15507 }
15508 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15509 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15510 aspecttable[15]);
15511 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15512
15513 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15514 smallestangle, biggestangle);
15515
15516 printf(" Angle histogram:\n");
15517 for (i = 0; i < 9; i++) {
15518 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15519 i * 10, i * 10 + 10, angletable[i],
15520 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15521 }
15522 printf("\n");
15523}
15524
15525/*****************************************************************************/
15526/* */
15527/* statistics() Print all sorts of cool facts. */
15528/* */
15529/*****************************************************************************/
15530
15531#ifdef ANSI_DECLARATORS
15532void statistics(struct mesh *m, struct behavior *b)
15533#else /* not ANSI_DECLARATORS */
15534void statistics(m, b)
15535struct mesh *m;
15536struct behavior *b;
15537#endif /* not ANSI_DECLARATORS */
15538
15539{
15540 printf("\nStatistics:\n\n");
15541 printf(" Input vertices: %d\n", m->invertices);
15542 if (b->refine) {
15543 printf(" Input triangles: %d\n", m->inelements);
15544 }
15545 if (b->poly) {
15546 printf(" Input segments: %d\n", m->insegments);
15547 if (!b->refine) {
15548 printf(" Input holes: %d\n", m->holes);
15549 }
15550 }
15551
15552 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15553 printf(" Mesh triangles: %ld\n", m->triangles.items);
15554 printf(" Mesh edges: %ld\n", m->edges);
15555 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15556 if (b->poly || b->refine) {
15557 printf(" Mesh interior boundary edges: %ld\n",
15558 m->subsegs.items - m->hullsize);
15559 printf(" Mesh subsegments (constrained edges): %ld\n",
15560 m->subsegs.items);
15561 }
15562 printf("\n");
15563
15564 if (b->verbose) {
15566 printf("Memory allocation statistics:\n\n");
15567 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15568 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15569 if (m->subsegs.maxitems > 0) {
15570 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15571 }
15572 if (m->viri.maxitems > 0) {
15573 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15574 }
15575 if (m->badsubsegs.maxitems > 0) {
15576 printf(" Maximum number of encroached subsegments: %ld\n",
15577 m->badsubsegs.maxitems);
15578 }
15579 if (m->badtriangles.maxitems > 0) {
15580 printf(" Maximum number of bad triangles: %ld\n",
15581 m->badtriangles.maxitems);
15582 }
15583 if (m->flipstackers.maxitems > 0) {
15584 printf(" Maximum number of stacked triangle flips: %ld\n",
15585 m->flipstackers.maxitems);
15586 }
15587 if (m->splaynodes.maxitems > 0) {
15588 printf(" Maximum number of splay tree nodes: %ld\n",
15589 m->splaynodes.maxitems);
15590 }
15591 printf(" Approximate heap memory use (bytes): %ld\n\n",
15592 m->vertices.maxitems * m->vertices.itembytes +
15593 m->triangles.maxitems * m->triangles.itembytes +
15594 m->subsegs.maxitems * m->subsegs.itembytes +
15595 m->viri.maxitems * m->viri.itembytes +
15596 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15597 m->badtriangles.maxitems * m->badtriangles.itembytes +
15598 m->flipstackers.maxitems * m->flipstackers.itembytes +
15599 m->splaynodes.maxitems * m->splaynodes.itembytes);
15600
15601 printf("Algorithmic statistics:\n\n");
15602 if (!b->weighted) {
15603 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15604 } else {
15605 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15606 }
15607 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15608 if (m->hyperbolacount > 0) {
15609 printf(" Number of right-of-hyperbola tests: %ld\n",
15610 m->hyperbolacount);
15611 }
15612 if (m->circletopcount > 0) {
15613 printf(" Number of circle top computations: %ld\n",
15614 m->circletopcount);
15615 }
15616 if (m->circumcentercount > 0) {
15617 printf(" Number of triangle circumcenter computations: %ld\n",
15618 m->circumcentercount);
15619 }
15620 printf("\n");
15621 }
15622}
15623
15624/*****************************************************************************/
15625/* */
15626/* main() or triangulate() Gosh, do everything. */
15627/* */
15628/* The sequence is roughly as follows. Many of these steps can be skipped, */
15629/* depending on the command line switches. */
15630/* */
15631/* - Initialize constants and parse the command line. */
15632/* - Read the vertices from a file and either */
15633/* - triangulate them (no -r), or */
15634/* - read an old mesh from files and reconstruct it (-r). */
15635/* - Insert the PSLG segments (-p), and possibly segments on the convex */
15636/* hull (-c). */
15637/* - Read the holes (-p), regional attributes (-pA), and regional area */
15638/* constraints (-pa). Carve the holes and concavities, and spread the */
15639/* regional attributes and area constraints. */
15640/* - Enforce the constraints on minimum angle (-q) and maximum area (-a). */
15641/* Also enforce the conforming Delaunay property (-q and -a). */
15642/* - Compute the number of edges in the resulting mesh. */
15643/* - Promote the mesh's linear triangles to higher order elements (-o). */
15644/* - Write the output files and print the statistics. */
15645/* - Check the consistency and Delaunay property of the mesh (-C). */
15646/* */
15647/*****************************************************************************/
15648
15649#ifdef TRILIBRARY
15650
15651#ifdef ANSI_DECLARATORS
15652void triangulate(char *triswitches, struct triangulateio *in,
15653 struct triangulateio *out, struct triangulateio *vorout)
15654#else /* not ANSI_DECLARATORS */
15655void triangulate(triswitches, in, out, vorout)
15656char *triswitches;
15657struct triangulateio *in;
15658struct triangulateio *out;
15659struct triangulateio *vorout;
15660#endif /* not ANSI_DECLARATORS */
15661
15662#else /* not TRILIBRARY */
15663
15664#ifdef ANSI_DECLARATORS
15665int main(int argc, char **argv)
15666#else /* not ANSI_DECLARATORS */
15667int main(argc, argv)
15668int argc;
15669char **argv;
15670#endif /* not ANSI_DECLARATORS */
15671
15672#endif /* not TRILIBRARY */
15673
15674{
15675 struct mesh m;
15676 struct behavior b;
15677 REAL *holearray; /* Array of holes. */
15678 REAL *regionarray; /* Array of regional attributes and area constraints. */
15679#ifndef TRILIBRARY
15680 FILE *polyfile;
15681#endif /* not TRILIBRARY */
15682#ifndef NO_TIMER
15683 /* Variables for timing the performance of Triangle. The types are */
15684 /* defined in sys/time.h. */
15685 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15686 struct timezone tz;
15687#endif /* not NO_TIMER */
15688
15689#ifndef NO_TIMER
15690 gettimeofday(&tv0, &tz);
15691#endif /* not NO_TIMER */
15692
15693 triangleinit(&m);
15694#ifdef TRILIBRARY
15695 parsecommandline(1, &triswitches, &b);
15696#else /* not TRILIBRARY */
15697 parsecommandline(argc, argv, &b);
15698#endif /* not TRILIBRARY */
15699 m.steinerleft = b.steiner;
15700
15701#ifdef TRILIBRARY
15705#else /* not TRILIBRARY */
15706 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15707#endif /* not TRILIBRARY */
15708
15709#ifndef NO_TIMER
15710 if (!b.quiet) {
15711 gettimeofday(&tv1, &tz);
15712 }
15713#endif /* not NO_TIMER */
15714
15715#ifdef CDT_ONLY
15716 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15717#else /* not CDT_ONLY */
15718 if (b.refine) {
15719 /* Read and reconstruct a mesh. */
15720#ifdef TRILIBRARY
15721 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15726 in->numberofsegments);
15727#else /* not TRILIBRARY */
15728 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15729 b.inpolyfilename, polyfile);
15730#endif /* not TRILIBRARY */
15731 } else {
15732 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15733 }
15734#endif /* not CDT_ONLY */
15735
15736#ifndef NO_TIMER
15737 if (!b.quiet) {
15738 gettimeofday(&tv2, &tz);
15739 if (b.refine) {
15740 printf("Mesh reconstruction");
15741 } else {
15742 printf("Delaunay");
15743 }
15744 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15745 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15746 }
15747#endif /* not NO_TIMER */
15748
15749 /* Ensure that no vertex can be mistaken for a triangular bounding */
15750 /* box vertex in insertvertex(). */
15751 m.infvertex1 = (vertex) NULL;
15752 m.infvertex2 = (vertex) NULL;
15753 m.infvertex3 = (vertex) NULL;
15754
15755 if (b.usesegments) {
15756 m.checksegments = 1; /* Segments will be introduced next. */
15757 if (!b.refine) {
15758 /* Insert PSLG segments and/or convex hull segments. */
15759#ifdef TRILIBRARY
15760 formskeleton(&m, &b, in->segmentlist,
15762#else /* not TRILIBRARY */
15763 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15764#endif /* not TRILIBRARY */
15765 }
15766 }
15767
15768#ifndef NO_TIMER
15769 if (!b.quiet) {
15770 gettimeofday(&tv3, &tz);
15771 if (b.usesegments && !b.refine) {
15772 printf("Segment milliseconds: %ld\n",
15773 1000l * (tv3.tv_sec - tv2.tv_sec) +
15774 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15775 }
15776 }
15777#endif /* not NO_TIMER */
15778
15779 if (b.poly && (m.triangles.items > 0)) {
15780#ifdef TRILIBRARY
15781 holearray = in->holelist;
15782 m.holes = in->numberofholes;
15783 regionarray = in->regionlist;
15784 m.regions = in->numberofregions;
15785#else /* not TRILIBRARY */
15786 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15787 &regionarray, &m.regions);
15788#endif /* not TRILIBRARY */
15789 if (!b.refine) {
15790 /* Carve out holes and concavities. */
15791 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15792 }
15793 } else {
15794 /* Without a PSLG, there can be no holes or regional attributes */
15795 /* or area constraints. The following are set to zero to avoid */
15796 /* an accidental free() later. */
15797 m.holes = 0;
15798 m.regions = 0;
15799 }
15800
15801#ifndef NO_TIMER
15802 if (!b.quiet) {
15803 gettimeofday(&tv4, &tz);
15804 if (b.poly && !b.refine) {
15805 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15806 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15807 }
15808 }
15809#endif /* not NO_TIMER */
15810
15811#ifndef CDT_ONLY
15812 if (b.quality && (m.triangles.items > 0)) {
15813 enforcequality(&m, &b); /* Enforce angle and area constraints. */
15814 }
15815#endif /* not CDT_ONLY */
15816
15817#ifndef NO_TIMER
15818 if (!b.quiet) {
15819 gettimeofday(&tv5, &tz);
15820#ifndef CDT_ONLY
15821 if (b.quality) {
15822 printf("Quality milliseconds: %ld\n",
15823 1000l * (tv5.tv_sec - tv4.tv_sec) +
15824 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15825 }
15826#endif /* not CDT_ONLY */
15827 }
15828#endif /* not NO_TIMER */
15829
15830 /* Calculate the number of edges. */
15831 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15832
15833 if (b.order > 1) {
15834 highorder(&m, &b); /* Promote elements to higher polynomial order. */
15835 }
15836 if (!b.quiet) {
15837 printf("\n");
15838 }
15839
15840#ifdef TRILIBRARY
15841 if (b.jettison) {
15842 out->numberofpoints = m.vertices.items - m.undeads;
15843 } else {
15844 out->numberofpoints = m.vertices.items;
15845 }
15846 out->numberofpointattributes = m.nextras;
15847 out->numberoftriangles = m.triangles.items;
15848 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15849 out->numberoftriangleattributes = m.eextras;
15850 out->numberofedges = m.edges;
15851 if (b.usesegments) {
15852 out->numberofsegments = m.subsegs.items;
15853 } else {
15854 out->numberofsegments = m.hullsize;
15855 }
15856 if (vorout != (struct triangulateio *) NULL) {
15857 vorout->numberofpoints = m.triangles.items;
15858 vorout->numberofpointattributes = m.nextras;
15859 vorout->numberofedges = m.edges;
15860 }
15861#endif /* TRILIBRARY */
15862 /* If not using iteration numbers, don't write a .node file if one was */
15863 /* read, because the original one would be overwritten! */
15864 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15865 if (!b.quiet) {
15866#ifdef TRILIBRARY
15867 printf("NOT writing vertices.\n");
15868#else /* not TRILIBRARY */
15869 printf("NOT writing a .node file.\n");
15870#endif /* not TRILIBRARY */
15871 }
15872 numbernodes(&m, &b); /* We must remember to number the vertices. */
15873 } else {
15874 /* writenodes() numbers the vertices too. */
15875#ifdef TRILIBRARY
15876 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15877 &out->pointmarkerlist);
15878#else /* not TRILIBRARY */
15879 writenodes(&m, &b, b.outnodefilename, argc, argv);
15880#endif /* TRILIBRARY */
15881 }
15882 if (b.noelewritten) {
15883 if (!b.quiet) {
15884#ifdef TRILIBRARY
15885 printf("NOT writing triangles.\n");
15886#else /* not TRILIBRARY */
15887 printf("NOT writing an .ele file.\n");
15888#endif /* not TRILIBRARY */
15889 }
15890 } else {
15891#ifdef TRILIBRARY
15893#else /* not TRILIBRARY */
15894 writeelements(&m, &b, b.outelefilename, argc, argv);
15895#endif /* not TRILIBRARY */
15896 }
15897 /* The -c switch (convex switch) causes a PSLG to be written */
15898 /* even if none was read. */
15899 if (b.poly || b.convex) {
15900 /* If not using iteration numbers, don't overwrite the .poly file. */
15901 if (b.nopolywritten || b.noiterationnum) {
15902 if (!b.quiet) {
15903#ifdef TRILIBRARY
15904 printf("NOT writing segments.\n");
15905#else /* not TRILIBRARY */
15906 printf("NOT writing a .poly file.\n");
15907#endif /* not TRILIBRARY */
15908 }
15909 } else {
15910#ifdef TRILIBRARY
15911 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15912 out->numberofholes = m.holes;
15913 out->numberofregions = m.regions;
15914 if (b.poly) {
15915 out->holelist = in->holelist;
15916 out->regionlist = in->regionlist;
15917 } else {
15918 out->holelist = (REAL *) NULL;
15919 out->regionlist = (REAL *) NULL;
15920 }
15921#else /* not TRILIBRARY */
15922 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15923 m.regions, argc, argv);
15924#endif /* not TRILIBRARY */
15925 }
15926 }
15927#ifndef TRILIBRARY
15928#ifndef CDT_ONLY
15929 if (m.regions > 0) {
15930 trifree((VOID *) regionarray);
15931 }
15932#endif /* not CDT_ONLY */
15933 if (m.holes > 0) {
15934 trifree((VOID *) holearray);
15935 }
15936 if (b.geomview) {
15937 writeoff(&m, &b, b.offfilename, argc, argv);
15938 }
15939#endif /* not TRILIBRARY */
15940 if (b.edgesout) {
15941#ifdef TRILIBRARY
15942 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15943#else /* not TRILIBRARY */
15944 writeedges(&m, &b, b.edgefilename, argc, argv);
15945#endif /* not TRILIBRARY */
15946 }
15947 if (b.voronoi) {
15948#ifdef TRILIBRARY
15949 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15950 &vorout->pointmarkerlist, &vorout->edgelist,
15951 &vorout->edgemarkerlist, &vorout->normlist);
15952#else /* not TRILIBRARY */
15953 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15954#endif /* not TRILIBRARY */
15955 }
15956 if (b.neighbors) {
15957#ifdef TRILIBRARY
15958 writeneighbors(&m, &b, &out->neighborlist);
15959#else /* not TRILIBRARY */
15960 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15961#endif /* not TRILIBRARY */
15962 }
15963
15964 if (!b.quiet) {
15965#ifndef NO_TIMER
15966 gettimeofday(&tv6, &tz);
15967 printf("\nOutput milliseconds: %ld\n",
15968 1000l * (tv6.tv_sec - tv5.tv_sec) +
15969 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15970 printf("Total running milliseconds: %ld\n",
15971 1000l * (tv6.tv_sec - tv0.tv_sec) +
15972 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15973#endif /* not NO_TIMER */
15974
15975 statistics(&m, &b);
15976 }
15977
15978#ifndef REDUCED
15979 if (b.docheck) {
15980 checkmesh(&m, &b);
15981 checkdelaunay(&m, &b);
15982 }
15983#endif /* not REDUCED */
15984
15985 triangledeinit(&m, &b);
15986#ifndef TRILIBRARY
15987 return 0;
15988#endif /* not TRILIBRARY */
15989}
SVector< double, 2 > v
Definition: Dict.h:5
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define s0(x)
Definition: RSha256.hxx:90
#define s1(x)
Definition: RSha256.hxx:91
#define h(i)
Definition: RSha256.hxx:106
#define e(i)
Definition: RSha256.hxx:103
static double p3(double t, double a, double b, double c, double d)
static double p1(double t, double a, double b)
static double p2(double t, double a, double b, double c)
static RooMathCoreReg dummy
include TDocParser_001 C image html pict1_TDocParser_001 png width
Definition: TDocParser.cxx:121
float xmin
Definition: THbookFile.cxx:93
float ymin
Definition: THbookFile.cxx:93
float xmax
Definition: THbookFile.cxx:93
float ymax
Definition: THbookFile.cxx:93
double acos(double)
double cos(double)
double sqrt(double)
typedef void((*Func_t)())
TCanvas * alignment()
Definition: alignment.C:1
#define free
Definition: civetweb.c:1539
#define malloc
Definition: civetweb.c:1536
int main(int argc, char **argv)
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
Double_t ey[n]
Definition: legend1.C:17
Double_t ex[n]
Definition: legend1.C:17
static double B[]
static double Q[]
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
static constexpr double s
static constexpr double pc
Definition: first.py:1
REAL * pointattributelist
Definition: triangle.h:290
int * neighborlist
Definition: triangle.h:298
int numberoftriangleattributes
Definition: triangle.h:301
int numberofpoints
Definition: triangle.h:292
int * edgemarkerlist
Definition: triangle.h:314
int numberofsegments
Definition: triangle.h:305
REAL * normlist
Definition: triangle.h:315
int numberoftriangles
Definition: triangle.h:299
REAL * trianglearealist
Definition: triangle.h:297
int * trianglelist
Definition: triangle.h:295
REAL * pointlist
Definition: triangle.h:289
int * segmentmarkerlist
Definition: triangle.h:304
int numberofholes
Definition: triangle.h:308
REAL * regionlist
Definition: triangle.h:310
int numberofpointattributes
Definition: triangle.h:293
int numberofcorners
Definition: triangle.h:300
int numberofregions
Definition: triangle.h:311
int numberofedges
Definition: triangle.h:316
int * pointmarkerlist
Definition: triangle.h:291
int * segmentlist
Definition: triangle.h:303
REAL * triangleattributelist
Definition: triangle.h:296
REAL * holelist
Definition: triangle.h:307
int * edgelist
Definition: triangle.h:313
auto * tv3
Definition: textalign.C:34
auto * tv1
Definition: textalign.C:26
auto * tv2
Definition: textalign.C:30
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4
auto * t1
Definition: textangle.C:20
static long int sum(long int i)
Definition: Factory.cxx:2258
#define SEGMENTVERTEX
Definition: triangle.c:284
#define sdest(osub, vertexptr)
Definition: triangle.c:1181
#define sorg(osub, vertexptr)
Definition: triangle.c:1178
#define VIRUSPERBLOCK
Definition: triangle.c:269
REAL splitter
Definition: triangle.c:616
VOID * traverse(struct memorypool *pool)
Definition: triangle.c:4101
void highorder(struct mesh *m, struct behavior *b)
Definition: triangle.c:13694
#define apex(otri, vertexptr)
Definition: triangle.c:1043
void makevertexmap(struct mesh *m, struct behavior *b)
Definition: triangle.c:7375
#define Square(a, x, y)
Definition: triangle.c:4812
#define dnext(otri1, otri2)
Definition: triangle.c:986
void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, REAL **pointattriblist, int **pointmarkerlist)
Definition: triangle.c:14305
finddirectionresult
Definition: triangle.c:359
@ LEFTCOLLINEAR
Definition: triangle.c:359
@ RIGHTCOLLINEAR
Definition: triangle.c:359
@ WITHIN
Definition: triangle.c:359
void numbernodes(struct mesh *m, struct behavior *b)
Definition: triangle.c:14445
#define vertextype(vx)
Definition: triangle.c:1288
void writepoly(struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist)
Definition: triangle.c:14618
vertex getvertex(struct mesh *m, struct behavior *b, int number)
Definition: triangle.c:4555
#define setelemattribute(otri, attnum, value)
Definition: triangle.c:1102
#define setsorg(osub, vertexptr)
Definition: triangle.c:1184
#define segdest(osub, vertexptr)
Definition: triangle.c:1193
void poolrestart(struct memorypool *pool)
Definition: triangle.c:3864
#define segorg(osub, vertexptr)
Definition: triangle.c:1190
#define Two_Product(a, b, x, y)
Definition: triangle.c:4789
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
Definition: triangle.c:9257
#define sdecode(sptr, osub)
Definition: triangle.c:1132
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
Definition: triangle.c:8173
#define setorg(otri, vertexptr)
Definition: triangle.c:1046
void exactinit()
Definition: triangle.c:4863
REAL estimate(int elen, REAL *e)
Definition: triangle.c:5087
#define SUBSEGPERBLOCK
Definition: triangle.c:267
enum locateresult preciselocate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment)
Definition: triangle.c:7470
#define elemattribute(otri, attnum)
Definition: triangle.c:1099
#define FILENAMESIZE
Definition: triangle.c:255
int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
Definition: triangle.c:4937
void makesubseg(struct mesh *m, struct osub *newsubseg)
Definition: triangle.c:4681
#define vertexmark(vx)
Definition: triangle.c:1283
#define bond(otri1, otri2)
Definition: triangle.c:1057
#define snextself(osub)
Definition: triangle.c:1171
#define onextself(otri)
Definition: triangle.c:966
#define encode(otri)
Definition: triangle.c:921
void trifree(VOID *memptr)
Definition: triangle.c:1414
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
Definition: triangle.c:4356
unsigned long randomseed
Definition: triangle.c:625
void pooldealloc(struct memorypool *pool, VOID *dyingitem)
Definition: triangle.c:4042
#define infect(otri)
Definition: triangle.c:1084
#define INPUTLINESIZE
Definition: triangle.c:260
#define tsdissolve(otri)
Definition: triangle.c:1271
#define setsegorg(osub, vertexptr)
Definition: triangle.c:1196
void alternateaxes(vertex *sortarray, int arraysize, int axis)
Definition: triangle.c:9335
#define lnext(otri1, otri2)
Definition: triangle.c:942
int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
Definition: triangle.c:1336
void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
Definition: triangle.c:15131
REAL ** triangle
Definition: triangle.c:478
REAL iccerrboundB
Definition: triangle.c:620
#define dissolve(otri)
Definition: triangle.c:1066
#define mark(osub)
Definition: triangle.c:1206
REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight, REAL permanent)
Definition: triangle.c:5945
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
Definition: triangle.c:11669
long divconqdelaunay(struct mesh *m, struct behavior *b)
Definition: triangle.c:9953
#define Two_Product_Presplit(a, b, bhi, blo, x, y)
Definition: triangle.c:4796
void regionplague(struct mesh *m, struct behavior *b, REAL attribute, REAL area)
Definition: triangle.c:12850
REAL ccwerrboundB
Definition: triangle.c:619
#define onext(otri1, otri2)
Definition: triangle.c:962
#define TRIPERBLOCK
Definition: triangle.c:266
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
Definition: triangle.c:12011
void triangledeinit(struct mesh *m, struct behavior *b)
Definition: triangle.c:4596
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
Definition: triangle.c:3910
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
Definition: triangle.c:7614
vertex vertextraverse(struct mesh *m)
Definition: triangle.c:4469
#define oprevself(otri)
Definition: triangle.c:978
#define SAMPLERATE
Definition: triangle.c:301
#define lprev(otri1, otri2)
Definition: triangle.c:951
#define killsubseg(sub)
Definition: triangle.c:1242
#define FREEVERTEX
Definition: triangle.c:285
triangle * triangletraverse(struct mesh *m)
Definition: triangle.c:4377
#define tspivot(otri, osub)
Definition: triangle.c:1252
#define STARTINDEX
#define ssymself(osub)
Definition: triangle.c:1150
#define PI
Definition: triangle.c:305
VOID * poolalloc(struct memorypool *pool)
Definition: triangle.c:3979
REAL o3derrboundC
Definition: triangle.c:621
int plus1mod3[3]
Definition: triangle.c:902
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
Definition: triangle.c:4637
void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
Definition: triangle.c:3640
#define Two_Diff_Tail(a, b, x, y)
Definition: triangle.c:4764
void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, REAL **vpointattriblist, int **vpointmarkerlist, int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
Definition: triangle.c:14918
insertvertexresult
Definition: triangle.c:351
@ SUCCESSFULVERTEX
Definition: triangle.c:351
@ ENCROACHINGVERTEX
Definition: triangle.c:351
@ VIOLATINGVERTEX
Definition: triangle.c:351
@ DUPLICATEVERTEX
Definition: triangle.c:352
void triexit(int status)
Definition: triangle.c:1385
void poolzero(struct memorypool *pool)
Definition: triangle.c:3830
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
Definition: triangle.c:7785
#define dprev(otri1, otri2)
Definition: triangle.c:998
#define vertex2tri(vx)
Definition: triangle.c:1293
REAL ccwerrboundC
Definition: triangle.c:619
#define lnextself(otri)
Definition: triangle.c:946
#define areabound(otri)
Definition: triangle.c:1107
#define DEADVERTEX
Definition: triangle.c:286
void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments)
Definition: triangle.c:12391
locateresult
Definition: triangle.c:343
@ OUTSIDE
Definition: triangle.c:343
@ INTRIANGLE
Definition: triangle.c:343
@ ONVERTEX
Definition: triangle.c:343
@ ONEDGE
Definition: triangle.c:343
#define TRILIBRARY
Definition: triangle.c:214
#define deadtri(tria)
Definition: triangle.c:1117
#define setvertexmark(vx, value)
Definition: triangle.c:1285
REAL o3derrboundB
Definition: triangle.c:621
#define SPLAYNODEPERBLOCK
Definition: triangle.c:277
void triangulate(char *triswitches, struct triangulateio *in, struct triangulateio *out, struct triangulateio *vorout)
Definition: triangle.c:15652
#define setvertex2tri(vx, value)
Definition: triangle.c:1295
#define deadsubseg(sub)
Definition: triangle.c:1240
void initializevertexpool(struct mesh *m, struct behavior *b)
Definition: triangle.c:4246
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
Definition: triangle.c:8834
#define SQUAREROOTTWO
Definition: triangle.c:309
void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, struct otri *innerleft, struct otri *innerright, struct otri *farright, int axis)
Definition: triangle.c:9399
void parsecommandline(int argc, char **argv, struct behavior *b)
Definition: triangle.c:3257
VOID * trimalloc(int size)
Definition: triangle.c:1396
#define oprev(otri1, otri2)
Definition: triangle.c:974
#define killtri(tria)
Definition: triangle.c:1119
REAL epsilon
Definition: triangle.c:617
#define BADSUBSEGPERBLOCK
Definition: triangle.c:271
void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
Definition: triangle.c:4402
#define INPUTVERTEX
Definition: triangle.c:283
long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
Definition: triangle.c:9890
void vertexdealloc(struct mesh *m, vertex dyingvertex)
Definition: triangle.c:4448
void infecthull(struct mesh *m, struct behavior *b)
Definition: triangle.c:12558
void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, REAL *regionlist, int regions)
Definition: triangle.c:12963
#define setapex(otri, vertexptr)
Definition: triangle.c:1052
#define UNDEADVERTEX
Definition: triangle.c:287
#define dest(otri, vertexptr)
Definition: triangle.c:1040
void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist, REAL *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs)
Definition: triangle.c:14067
#define otricopy(otri1, otri2)
Definition: triangle.c:1071
#define Two_Sum(a, b, x, y)
Definition: triangle.c:4760
#define tsbond(otri, osub)
Definition: triangle.c:1265
#define setmark(osub, value)
Definition: triangle.c:1208
#define stdissolve(osub)
Definition: triangle.c:1276
void initializetrisubpools(struct mesh *m, struct behavior *b)
Definition: triangle.c:4289
#define BADTRIPERBLOCK
Definition: triangle.c:273
int minus1mod3[3]
Definition: triangle.c:903
void writeedges(struct mesh *m, struct behavior *b, int **edgelist, int **edgemarkerlist)
Definition: triangle.c:14764
REAL ** subseg
Definition: triangle.c:495
#define Two_One_Product(a1, a0, b, x3, x2, x1, x0)
Definition: triangle.c:4837
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
Definition: triangle.c:4831
long delaunay(struct mesh *m, struct behavior *b)
Definition: triangle.c:10997
#define setdest(otri, vertexptr)
Definition: triangle.c:1049
void markhull(struct mesh *m, struct behavior *b)
Definition: triangle.c:12345
void vertexsort(vertex *sortarray, int arraysize)
Definition: triangle.c:9183
unsigned long randomnation(unsigned int choices)
Definition: triangle.c:6647
REAL o3derrboundA
Definition: triangle.c:621
REAL incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
Definition: triangle.c:5863
#define dnextself(otri)
Definition: triangle.c:990
#define stpivot(osub, otri)
Definition: triangle.c:1259
#define VERTEXPERBLOCK
Definition: triangle.c:268
REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
Definition: triangle.c:5126
int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
Definition: triangle.c:5031
#define decode(ptr, otri)
Definition: triangle.c:912
#define otriequal(otri1, otri2)
Definition: triangle.c:1077
#define org(otri, vertexptr)
Definition: triangle.c:1037
#define sdissolve(osub)
Definition: triangle.c:1220
void traversalinit(struct memorypool *pool)
Definition: triangle.c:4065
#define symself(otri)
Definition: triangle.c:936
#define SAMPLEFACTOR
Definition: triangle.c:295
REAL nonregular(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
Definition: triangle.c:6453
void plague(struct mesh *m, struct behavior *b)
Definition: triangle.c:12640
#define setsegdest(osub, vertexptr)
Definition: triangle.c:1199
#define uninfect(otri)
Definition: triangle.c:1088
#define lprevself(otri)
Definition: triangle.c:955
REAL resulterrbound
Definition: triangle.c:618
void internalerror()
Definition: triangle.c:3241
#define FLIPSTACKERPERBLOCK
Definition: triangle.c:275
REAL * vertex
Definition: triangle.c:512
void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition: triangle.c:8024
#define setvertextype(vx, value)
Definition: triangle.c:1290
#define INEXACT
Definition: triangle.c:250
void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes)
Definition: triangle.c:4166
#define sym(otri1, otri2)
Definition: triangle.c:932
void quality_statistics(struct mesh *m, struct behavior *b)
Definition: triangle.c:15324
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition: triangle.c:7889
#define sencode(osub)
Definition: triangle.c:1141
REAL counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
Definition: triangle.c:5215
void pooldeinit(struct memorypool *pool)
Definition: triangle.c:3958
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
Definition: triangle.c:11574
REAL ccwerrboundA
Definition: triangle.c:619
REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
Definition: triangle.c:5284
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
Definition: triangle.c:12131
#define setsdest(osub, vertexptr)
Definition: triangle.c:1187
REAL iccerrboundA
Definition: triangle.c:620
#define spivot(osub1, osub2)
Definition: triangle.c:1156
#define infected(otri)
Definition: triangle.c:1094
#define ssym(osub1, osub2)
Definition: triangle.c:1146
void writeelements(struct mesh *m, struct behavior *b, int **trianglelist, REAL **triangleattriblist)
Definition: triangle.c:14477
void insertsegment(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
Definition: triangle.c:12233
#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0)
Definition: triangle.c:4827
void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
Definition: triangle.c:3734
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
Definition: triangle.c:9726
#define Fast_Two_Sum(a, b, x, y)
Definition: triangle.c:4749
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
Definition: triangle.c:11797
void findcircumcenter(struct mesh *m, struct behavior *b, vertex torg, vertex tdest, vertex tapex, vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
Definition: triangle.c:6494
#define Split(a, ahi, alo)
Definition: triangle.c:4775
#define Absolute(a)
Definition: triangle.c:4729
subseg * subsegtraverse(struct mesh *m)
Definition: triangle.c:4423
REAL orient3d(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight)
Definition: triangle.c:6370
void statistics(struct mesh *m, struct behavior *b)
Definition: triangle.c:15532
REAL iccerrboundC
Definition: triangle.c:620
#define sbond(osub1, osub2)
Definition: triangle.c:1213
#define setareabound(otri, value)
Definition: triangle.c:1109
void triangleinit(struct mesh *m)
Definition: triangle.c:6608
#define REAL
Definition: triangle.h:277
#define VOID
Definition: triangle.h:286