Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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#include <stdint.h>
320#ifndef NO_TIMER
321#include <sys/time.h>
322#endif /* not NO_TIMER */
323#ifdef CPU86
324#include <float.h>
325#endif /* CPU86 */
326#ifdef LINUX
327#include <fenv.h>
328#endif /* LINUX */
329#ifdef TRILIBRARY
330#include "triangle.h"
331#endif /* TRILIBRARY */
332
333/* A few forward declarations. */
334
335#ifndef TRILIBRARY
336char *readline();
337char *findfield();
338#endif /* not TRILIBRARY */
339
340/* Labels that signify the result of point location. The result of a */
341/* search indicates that the point falls in the interior of a triangle, on */
342/* an edge, on a vertex, or outside the mesh. */
343
345
346/* Labels that signify the result of vertex insertion. The result indicates */
347/* that the vertex was inserted with complete success, was inserted but */
348/* encroaches upon a subsegment, was not inserted because it lies on a */
349/* segment, or was not inserted because another vertex occupies the same */
350/* location. */
351
354
355/* Labels that signify the result of direction finding. The result */
356/* indicates that a segment connecting the two query points falls within */
357/* the direction triangle, along the left edge of the direction triangle, */
358/* or along the right edge of the direction triangle. */
359
361
362/*****************************************************************************/
363/* */
364/* The basic mesh data structures */
365/* */
366/* There are three: vertices, triangles, and subsegments (abbreviated */
367/* `subseg'). These three data structures, linked by pointers, comprise */
368/* the mesh. A vertex simply represents a mesh vertex and its properties. */
369/* A triangle is a triangle. A subsegment is a special data structure used */
370/* to represent an impenetrable edge of the mesh (perhaps on the outer */
371/* boundary, on the boundary of a hole, or part of an internal boundary */
372/* separating two triangulated regions). Subsegments represent boundaries, */
373/* defined by the user, that triangles may not lie across. */
374/* */
375/* A triangle consists of a list of three vertices, a list of three */
376/* adjoining triangles, a list of three adjoining subsegments (when */
377/* segments exist), an arbitrary number of optional user-defined */
378/* floating-point attributes, and an optional area constraint. The latter */
379/* is an upper bound on the permissible area of each triangle in a region, */
380/* used for mesh refinement. */
381/* */
382/* For a triangle on a boundary of the mesh, some or all of the neighboring */
383/* triangles may not be present. For a triangle in the interior of the */
384/* mesh, often no neighboring subsegments are present. Such absent */
385/* triangles and subsegments are never represented by NULL pointers; they */
386/* are represented by two special records: `dummytri', the triangle that */
387/* fills "outer space", and `dummysub', the omnipresent subsegment. */
388/* `dummytri' and `dummysub' are used for several reasons; for instance, */
389/* they can be dereferenced and their contents examined without violating */
390/* protected memory. */
391/* */
392/* However, it is important to understand that a triangle includes other */
393/* information as well. The pointers to adjoining vertices, triangles, and */
394/* subsegments are ordered in a way that indicates their geometric relation */
395/* to each other. Furthermore, each of these pointers contains orientation */
396/* information. Each pointer to an adjoining triangle indicates which face */
397/* of that triangle is contacted. Similarly, each pointer to an adjoining */
398/* subsegment indicates which side of that subsegment is contacted, and how */
399/* the subsegment is oriented relative to the triangle. */
400/* */
401/* The data structure representing a subsegment may be thought to be */
402/* abutting the edge of one or two triangle data structures: either */
403/* sandwiched between two triangles, or resting against one triangle on an */
404/* exterior boundary or hole boundary. */
405/* */
406/* A subsegment consists of a list of four vertices--the vertices of the */
407/* subsegment, and the vertices of the segment it is a part of--a list of */
408/* two adjoining subsegments, and a list of two adjoining triangles. One */
409/* of the two adjoining triangles may not be present (though there should */
410/* always be one), and neighboring subsegments might not be present. */
411/* Subsegments also store a user-defined integer "boundary marker". */
412/* Typically, this integer is used to indicate what boundary conditions are */
413/* to be applied at that location in a finite element simulation. */
414/* */
415/* Like triangles, subsegments maintain information about the relative */
416/* orientation of neighboring objects. */
417/* */
418/* Vertices are relatively simple. A vertex is a list of floating-point */
419/* numbers, starting with the x, and y coordinates, followed by an */
420/* arbitrary number of optional user-defined floating-point attributes, */
421/* followed by an integer boundary marker. During the segment insertion */
422/* phase, there is also a pointer from each vertex to a triangle that may */
423/* contain it. Each pointer is not always correct, but when one is, it */
424/* speeds up segment insertion. These pointers are assigned values once */
425/* at the beginning of the segment insertion phase, and are not used or */
426/* updated except during this phase. Edge flipping during segment */
427/* insertion will render some of them incorrect. Hence, don't rely upon */
428/* them for anything. */
429/* */
430/* Other than the exception mentioned above, vertices have no information */
431/* about what triangles, subfacets, or subsegments they are linked to. */
432/* */
433/*****************************************************************************/
434
435/*****************************************************************************/
436/* */
437/* Handles */
438/* */
439/* The oriented triangle (`otri') and oriented subsegment (`osub') data */
440/* structures defined below do not themselves store any part of the mesh. */
441/* The mesh itself is made of `triangle's, `subseg's, and `vertex's. */
442/* */
443/* Oriented triangles and oriented subsegments will usually be referred to */
444/* as "handles." A handle is essentially a pointer into the mesh; it */
445/* allows you to "hold" one particular part of the mesh. Handles are used */
446/* to specify the regions in which one is traversing and modifying the mesh.*/
447/* A single `triangle' may be held by many handles, or none at all. (The */
448/* latter case is not a memory leak, because the triangle is still */
449/* connected to other triangles in the mesh.) */
450/* */
451/* An `otri' is a handle that holds a triangle. It holds a specific edge */
452/* of the triangle. An `osub' is a handle that holds a subsegment. It */
453/* holds either the left or right side of the subsegment. */
454/* */
455/* Navigation about the mesh is accomplished through a set of mesh */
456/* manipulation primitives, further below. Many of these primitives take */
457/* a handle and produce a new handle that holds the mesh near the first */
458/* handle. Other primitives take two handles and glue the corresponding */
459/* parts of the mesh together. The orientation of the handles is */
460/* important. For instance, when two triangles are glued together by the */
461/* bond() primitive, they are glued at the edges on which the handles lie. */
462/* */
463/* Because vertices have no information about which triangles they are */
464/* attached to, I commonly represent a vertex by use of a handle whose */
465/* origin is the vertex. A single handle can simultaneously represent a */
466/* triangle, an edge, and a vertex. */
467/* */
468/*****************************************************************************/
469
470/* The triangle data structure. Each triangle contains three pointers to */
471/* adjoining triangles, plus three pointers to vertices, plus three */
472/* pointers to subsegments (declared below; these pointers are usually */
473/* `dummysub'). It may or may not also contain user-defined attributes */
474/* and/or a floating-point "area constraint." It may also contain extra */
475/* pointers for nodes, when the user asks for high-order elements. */
476/* Because the size and structure of a `triangle' is not decided until */
477/* runtime, I haven't simply declared the type `triangle' as a struct. */
478
479typedef REAL **triangle; /* Really: typedef triangle *triangle */
480
481/* An oriented triangle: includes a pointer to a triangle and orientation. */
482/* The orientation denotes an edge of the triangle. Hence, there are */
483/* three possible orientations. By convention, each edge always points */
484/* counterclockwise about the corresponding triangle. */
485
486struct otri {
488 int orient; /* Ranges from 0 to 2. */
489};
490
491/* The subsegment data structure. Each subsegment contains two pointers to */
492/* adjoining subsegments, plus four pointers to vertices, plus two */
493/* pointers to adjoining triangles, plus one boundary marker, plus one */
494/* segment number. */
495
496typedef REAL **subseg; /* Really: typedef subseg *subseg */
497
498/* An oriented subsegment: includes a pointer to a subsegment and an */
499/* orientation. The orientation denotes a side of the edge. Hence, there */
500/* are two possible orientations. By convention, the edge is always */
501/* directed so that the "side" denoted is the right side of the edge. */
502
503struct osub {
505 int ssorient; /* Ranges from 0 to 1. */
506};
507
508/* The vertex data structure. Each vertex is actually an array of REALs. */
509/* The number of REALs is unknown until runtime. An integer boundary */
510/* marker, and sometimes a pointer to a triangle, is appended after the */
511/* REALs. */
512
513typedef REAL *vertex;
514
515/* A queue used to store encroached subsegments. Each subsegment's vertices */
516/* are stored so that we can check whether a subsegment is still the same. */
517
518struct badsubseg {
519 subseg encsubseg; /* An encroached subsegment. */
520 vertex subsegorg, subsegdest; /* Its two vertices. */
521};
522
523/* A queue used to store bad triangles. The key is the square of the cosine */
524/* of the smallest angle of the triangle. Each triangle's vertices are */
525/* stored so that one can check whether a triangle is still the same. */
526
527struct badtriang {
528 triangle poortri; /* A skinny or too-large triangle. */
529 REAL key; /* cos^2 of smallest (apical) angle. */
530 vertex triangorg, triangdest, triangapex; /* Its three vertices. */
531 struct badtriang *nexttriang; /* Pointer to next bad triangle. */
532};
533
534/* A stack of triangles flipped during the most recent vertex insertion. */
535/* The stack is used to undo the vertex insertion if the vertex encroaches */
536/* upon a subsegment. */
537
539 triangle flippedtri; /* A recently flipped triangle. */
540 struct flipstacker *prevflip; /* Previous flip in the stack. */
541};
542
543/* A node in a heap used to store events for the sweepline Delaunay */
544/* algorithm. Nodes do not point directly to their parents or children in */
545/* the heap. Instead, each node knows its position in the heap, and can */
546/* look up its parent and children in a separate array. The `eventptr' */
547/* points either to a `vertex' or to a triangle (in encoded format, so */
548/* that an orientation is included). In the latter case, the origin of */
549/* the oriented triangle is the apex of a "circle event" of the sweepline */
550/* algorithm. To distinguish site events from circle events, all circle */
551/* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */
552
553struct event {
554 REAL xkey, ykey; /* Coordinates of the event. */
555 VOID *eventptr; /* Can be a vertex or the location of a circle event. */
556 int heapposition; /* Marks this event's position in the heap. */
557};
558
559/* A node in the splay tree. Each node holds an oriented ghost triangle */
560/* that represents a boundary edge of the growing triangulation. When a */
561/* circle event covers two boundary edges with a triangle, so that they */
562/* are no longer boundary edges, those edges are not immediately deleted */
563/* from the tree; rather, they are lazily deleted when they are next */
564/* encountered. (Since only a random sample of boundary edges are kept */
565/* in the tree, lazy deletion is faster.) `keydest' is used to verify */
566/* that a triangle is still the same as when it entered the splay tree; if */
567/* it has been rotated (due to a circle event), it no longer represents a */
568/* boundary edge and should be deleted. */
569
570struct splaynode {
571 struct otri keyedge; /* Lprev of an edge on the front. */
572 vertex keydest; /* Used to verify that splay node is still live. */
573 struct splaynode *lchild, *rchild; /* Children in splay tree. */
574};
575
576/* A type used to allocate memory. firstblock is the first block of items. */
577/* nowblock is the block from which items are currently being allocated. */
578/* nextitem points to the next slab of free memory for an item. */
579/* deaditemstack is the head of a linked list (stack) of deallocated items */
580/* that can be recycled. unallocateditems is the number of items that */
581/* remain to be allocated from nowblock. */
582/* */
583/* Traversal is the process of walking through the entire list of items, and */
584/* is separate from allocation. Note that a traversal will visit items on */
585/* the "deaditemstack" stack as well as live items. pathblock points to */
586/* the block currently being traversed. pathitem points to the next item */
587/* to be traversed. pathitemsleft is the number of items that remain to */
588/* be traversed in pathblock. */
589/* */
590/* alignbytes determines how new records should be aligned in memory. */
591/* itembytes is the length of a record in bytes (after rounding up). */
592/* itemsperblock is the number of items allocated at once in a single */
593/* block. itemsfirstblock is the number of items in the first block, */
594/* which can vary from the others. items is the number of currently */
595/* allocated items. maxitems is the maximum number of items that have */
596/* been allocated at once; it is the current number of items plus the */
597/* number of records kept on deaditemstack. */
598
612};
613
614
615/* Global constants. */
616
617REAL splitter; /* Used to split REAL factors for exact multiplication. */
618REAL epsilon; /* Floating-point machine epsilon. */
623
624/* Random number seed is not constant, but I've made it global anyway. */
625
626uintptr_t randomseed; /* Current random number seed. */
627
628
629/* Mesh data structure. Triangle operates on only one mesh, but the mesh */
630/* structure is used (instead of global variables) to allow reentrancy. */
631
632struct mesh {
633
634/* Variables used to allocate memory for triangles, subsegments, vertices, */
635/* viri (triangles being eaten), encroached segments, bad (skinny or too */
636/* large) triangles, and splay tree nodes. */
637
646
647/* Variables that maintain the bad triangle queues. The queues are */
648/* ordered from 4095 (highest priority) to 0 (lowest priority). */
649
650 struct badtriang *queuefront[4096];
651 struct badtriang *queuetail[4096];
652 int nextnonemptyq[4096];
654
655/* Variable that maintains the stack of recently flipped triangles. */
656
658
659/* Other variables. */
660
661 REAL xmin, xmax, ymin, ymax; /* x and y bounds. */
662 REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */
663 int invertices; /* Number of input vertices. */
664 int inelements; /* Number of input triangles. */
665 int insegments; /* Number of input segments. */
666 int holes; /* Number of input holes. */
667 int regions; /* Number of input regions. */
668 int undeads; /* Number of input vertices that don't appear in the mesh. */
669 long edges; /* Number of output edges. */
670 int mesh_dim; /* Dimension (ought to be 2). */
671 int nextras; /* Number of attributes per vertex. */
672 int eextras; /* Number of attributes per triangle. */
673 long hullsize; /* Number of edges in convex hull. */
674 int steinerleft; /* Number of Steiner points not yet used. */
675 int vertexmarkindex; /* Index to find boundary marker of a vertex. */
676 int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */
677 int highorderindex; /* Index to find extra nodes for high-order elements. */
678 int elemattribindex; /* Index to find attributes of a triangle. */
679 int areaboundindex; /* Index to find area bound of a triangle. */
680 int checksegments; /* Are there segments in the triangulation yet? */
681 int checkquality; /* Has quality triangulation begun yet? */
682 int readnodefile; /* Has a .node file been read? */
683 long samples; /* Number of random samples for point location. */
684
685 long incirclecount; /* Number of incircle tests performed. */
686 long counterclockcount; /* Number of counterclockwise tests performed. */
687 long orient3dcount; /* Number of 3D orientation tests performed. */
688 long hyperbolacount; /* Number of right-of-hyperbola tests performed. */
689 long circumcentercount; /* Number of circumcenter calculations performed. */
690 long circletopcount; /* Number of circle top calculations performed. */
691
692/* Triangular bounding box vertices. */
693
695
696/* Pointer to the `triangle' that occupies all of "outer space." */
697
699 triangle *dummytribase; /* Keep base address so we can free() it later. */
700
701/* Pointer to the omnipresent subsegment. Referenced by any triangle or */
702/* subsegment that isn't really connected to a subsegment at that */
703/* location. */
704
706 subseg *dummysubbase; /* Keep base address so we can free() it later. */
707
708/* Pointer to a recently visited triangle. Improves point location if */
709/* proximate vertices are inserted sequentially. */
710
712
713}; /* End of `struct mesh'. */
714
715
716/* Data structure for command line switches and file names. This structure */
717/* is used (instead of global variables) to allow reentrancy. */
718
719struct behavior {
720
721/* Switches for the triangulator. */
722/* poly: -p switch. refine: -r switch. */
723/* quality: -q switch. */
724/* minangle: minimum angle bound, specified after -q switch. */
725/* goodangle: cosine squared of minangle. */
726/* offconstant: constant used to place off-center Steiner points. */
727/* vararea: -a switch without number. */
728/* fixedarea: -a switch with number. */
729/* maxarea: maximum area bound, specified after -a switch. */
730/* usertest: -u switch. */
731/* regionattrib: -A switch. convex: -c switch. */
732/* weighted: 1 for -w switch, 2 for -W switch. jettison: -j switch */
733/* firstnumber: inverse of -z switch. All items are numbered starting */
734/* from `firstnumber'. */
735/* edgesout: -e switch. voronoi: -v switch. */
736/* neighbors: -n switch. geomview: -g switch. */
737/* nobound: -B switch. nopolywritten: -P switch. */
738/* nonodewritten: -N switch. noelewritten: -E switch. */
739/* noiterationnum: -I switch. noholes: -O switch. */
740/* noexact: -X switch. */
741/* order: element order, specified after -o switch. */
742/* nobisect: count of how often -Y switch is selected. */
743/* steiner: maximum number of Steiner points, specified after -S switch. */
744/* incremental: -i switch. sweepline: -F switch. */
745/* dwyer: inverse of -l switch. */
746/* splitseg: -s switch. */
747/* conformdel: -D switch. docheck: -C switch. */
748/* quiet: -Q switch. verbose: count of how often -V switch is selected. */
749/* usesegments: -p, -r, -q, or -c switch; determines whether segments are */
750/* used at all. */
751/* */
752/* Read the instructions to find out the meaning of these switches. */
753
765 int order;
770
771/* Variables for file names. */
772
773#ifndef TRILIBRARY
774 char innodefilename[FILENAMESIZE];
775 char inelefilename[FILENAMESIZE];
776 char inpolyfilename[FILENAMESIZE];
777 char areafilename[FILENAMESIZE];
778 char outnodefilename[FILENAMESIZE];
779 char outelefilename[FILENAMESIZE];
780 char outpolyfilename[FILENAMESIZE];
781 char edgefilename[FILENAMESIZE];
782 char vnodefilename[FILENAMESIZE];
783 char vedgefilename[FILENAMESIZE];
784 char neighborfilename[FILENAMESIZE];
785 char offfilename[FILENAMESIZE];
786#endif /* not TRILIBRARY */
787
788}; /* End of `struct behavior'. */
789
790
791/*****************************************************************************/
792/* */
793/* Mesh manipulation primitives. Each triangle contains three pointers to */
794/* other triangles, with orientations. Each pointer points not to the */
795/* first byte of a triangle, but to one of the first three bytes of a */
796/* triangle. It is necessary to extract both the triangle itself and the */
797/* orientation. To save memory, I keep both pieces of information in one */
798/* pointer. To make this possible, I assume that all triangles are aligned */
799/* to four-byte boundaries. The decode() routine below decodes a pointer, */
800/* extracting an orientation (in the range 0 to 2) and a pointer to the */
801/* beginning of a triangle. The encode() routine compresses a pointer to a */
802/* triangle and an orientation into a single pointer. My assumptions that */
803/* triangles are four-byte-aligned and that the `uintptr_t' type is */
804/* long enough to hold a pointer are two of the few kludges in this program.*/
805/* */
806/* Subsegments are manipulated similarly. A pointer to a subsegment */
807/* carries both an address and an orientation in the range 0 to 1. */
808/* */
809/* The other primitives take an oriented triangle or oriented subsegment, */
810/* and return an oriented triangle or oriented subsegment or vertex; or */
811/* they change the connections in the data structure. */
812/* */
813/* Below, triangles and subsegments are denoted by their vertices. The */
814/* triangle abc has origin (org) a, destination (dest) b, and apex (apex) */
815/* c. These vertices occur in counterclockwise order about the triangle. */
816/* The handle abc may simultaneously denote vertex a, edge ab, and triangle */
817/* abc. */
818/* */
819/* Similarly, the subsegment ab has origin (sorg) a and destination (sdest) */
820/* b. If ab is thought to be directed upward (with b directly above a), */
821/* then the handle ab is thought to grasp the right side of ab, and may */
822/* simultaneously denote vertex a and edge ab. */
823/* */
824/* An asterisk (*) denotes a vertex whose identity is unknown. */
825/* */
826/* Given this notation, a partial list of mesh manipulation primitives */
827/* follows. */
828/* */
829/* */
830/* For triangles: */
831/* */
832/* sym: Find the abutting triangle; same edge. */
833/* sym(abc) -> ba* */
834/* */
835/* lnext: Find the next edge (counterclockwise) of a triangle. */
836/* lnext(abc) -> bca */
837/* */
838/* lprev: Find the previous edge (clockwise) of a triangle. */
839/* lprev(abc) -> cab */
840/* */
841/* onext: Find the next edge counterclockwise with the same origin. */
842/* onext(abc) -> ac* */
843/* */
844/* oprev: Find the next edge clockwise with the same origin. */
845/* oprev(abc) -> a*b */
846/* */
847/* dnext: Find the next edge counterclockwise with the same destination. */
848/* dnext(abc) -> *ba */
849/* */
850/* dprev: Find the next edge clockwise with the same destination. */
851/* dprev(abc) -> cb* */
852/* */
853/* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */
854/* rnext(abc) -> *a* */
855/* */
856/* rprev: Find the previous edge (clockwise) of the adjacent triangle. */
857/* rprev(abc) -> b** */
858/* */
859/* org: Origin dest: Destination apex: Apex */
860/* org(abc) -> a dest(abc) -> b apex(abc) -> c */
861/* */
862/* bond: Bond two triangles together at the resepective handles. */
863/* bond(abc, bad) */
864/* */
865/* */
866/* For subsegments: */
867/* */
868/* ssym: Reverse the orientation of a subsegment. */
869/* ssym(ab) -> ba */
870/* */
871/* spivot: Find adjoining subsegment with the same origin. */
872/* spivot(ab) -> a* */
873/* */
874/* snext: Find next subsegment in sequence. */
875/* snext(ab) -> b* */
876/* */
877/* sorg: Origin sdest: Destination */
878/* sorg(ab) -> a sdest(ab) -> b */
879/* */
880/* sbond: Bond two subsegments together at the respective origins. */
881/* sbond(ab, ac) */
882/* */
883/* */
884/* For interacting tetrahedra and subfacets: */
885/* */
886/* tspivot: Find a subsegment abutting a triangle. */
887/* tspivot(abc) -> ba */
888/* */
889/* stpivot: Find a triangle abutting a subsegment. */
890/* stpivot(ab) -> ba* */
891/* */
892/* tsbond: Bond a triangle to a subsegment. */
893/* tsbond(abc, ba) */
894/* */
895/*****************************************************************************/
896
897/********* Mesh manipulation primitives begin here *********/
898/** **/
899/** **/
900
901/* Fast lookup arrays to speed some of the mesh manipulation primitives. */
902
903int plus1mod3[3] = {1, 2, 0};
904int minus1mod3[3] = {2, 0, 1};
905
906/********* Primitives for triangles *********/
907/* */
908/* */
909
910/* decode() converts a pointer to an oriented triangle. The orientation is */
911/* extracted from the two least significant bits of the pointer. */
912
913#define decode(ptr, otri) \
914 (otri).orient = (int) ((uintptr_t) (ptr) & (uintptr_t) 3l); \
915 (otri).tri = (triangle *) \
916 ((uintptr_t) (ptr) ^ (uintptr_t) (otri).orient)
917
918/* encode() compresses an oriented triangle into a single pointer. It */
919/* relies on the assumption that all triangles are aligned to four-byte */
920/* boundaries, so the two least significant bits of (otri).tri are zero. */
921
922#define encode(otri) \
923 (triangle) ((uintptr_t) (otri).tri | (uintptr_t) (otri).orient)
924
925/* The following handle manipulation primitives are all described by Guibas */
926/* and Stolfi. However, Guibas and Stolfi use an edge-based data */
927/* structure, whereas I use a triangle-based data structure. */
928
929/* sym() finds the abutting triangle, on the same edge. Note that the edge */
930/* direction is necessarily reversed, because the handle specified by an */
931/* oriented triangle is directed counterclockwise around the triangle. */
932
933#define sym(otri1, otri2) \
934 ptr = (otri1).tri[(otri1).orient]; \
935 decode(ptr, otri2);
936
937#define symself(otri) \
938 ptr = (otri).tri[(otri).orient]; \
939 decode(ptr, otri);
940
941/* lnext() finds the next edge (counterclockwise) of a triangle. */
942
943#define lnext(otri1, otri2) \
944 (otri2).tri = (otri1).tri; \
945 (otri2).orient = plus1mod3[(otri1).orient]
946
947#define lnextself(otri) \
948 (otri).orient = plus1mod3[(otri).orient]
949
950/* lprev() finds the previous edge (clockwise) of a triangle. */
951
952#define lprev(otri1, otri2) \
953 (otri2).tri = (otri1).tri; \
954 (otri2).orient = minus1mod3[(otri1).orient]
955
956#define lprevself(otri) \
957 (otri).orient = minus1mod3[(otri).orient]
958
959/* onext() spins counterclockwise around a vertex; that is, it finds the */
960/* next edge with the same origin in the counterclockwise direction. This */
961/* edge is part of a different triangle. */
962
963#define onext(otri1, otri2) \
964 lprev(otri1, otri2); \
965 symself(otri2);
966
967#define onextself(otri) \
968 lprevself(otri); \
969 symself(otri);
970
971/* oprev() spins clockwise around a vertex; that is, it finds the next edge */
972/* with the same origin in the clockwise direction. This edge is part of */
973/* a different triangle. */
974
975#define oprev(otri1, otri2) \
976 sym(otri1, otri2); \
977 lnextself(otri2);
978
979#define oprevself(otri) \
980 symself(otri); \
981 lnextself(otri);
982
983/* dnext() spins counterclockwise around a vertex; that is, it finds the */
984/* next edge with the same destination in the counterclockwise direction. */
985/* This edge is part of a different triangle. */
986
987#define dnext(otri1, otri2) \
988 sym(otri1, otri2); \
989 lprevself(otri2);
990
991#define dnextself(otri) \
992 symself(otri); \
993 lprevself(otri);
994
995/* dprev() spins clockwise around a vertex; that is, it finds the next edge */
996/* with the same destination in the clockwise direction. This edge is */
997/* part of a different triangle. */
998
999#define dprev(otri1, otri2) \
1000 lnext(otri1, otri2); \
1001 symself(otri2);
1002
1003#define dprevself(otri) \
1004 lnextself(otri); \
1005 symself(otri);
1006
1007/* rnext() moves one edge counterclockwise about the adjacent triangle. */
1008/* (It's best understood by reading Guibas and Stolfi. It involves */
1009/* changing triangles twice.) */
1010
1011#define rnext(otri1, otri2) \
1012 sym(otri1, otri2); \
1013 lnextself(otri2); \
1014 symself(otri2);
1015
1016#define rnextself(otri) \
1017 symself(otri); \
1018 lnextself(otri); \
1019 symself(otri);
1020
1021/* rprev() moves one edge clockwise about the adjacent triangle. */
1022/* (It's best understood by reading Guibas and Stolfi. It involves */
1023/* changing triangles twice.) */
1024
1025#define rprev(otri1, otri2) \
1026 sym(otri1, otri2); \
1027 lprevself(otri2); \
1028 symself(otri2);
1029
1030#define rprevself(otri) \
1031 symself(otri); \
1032 lprevself(otri); \
1033 symself(otri);
1034
1035/* These primitives determine or set the origin, destination, or apex of a */
1036/* triangle. */
1037
1038#define org(otri, vertexptr) \
1039 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
1040
1041#define dest(otri, vertexptr) \
1042 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
1043
1044#define apex(otri, vertexptr) \
1045 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
1046
1047#define setorg(otri, vertexptr) \
1048 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1049
1050#define setdest(otri, vertexptr) \
1051 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1052
1053#define setapex(otri, vertexptr) \
1054 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
1055
1056/* Bond two triangles together. */
1057
1058#define bond(otri1, otri2) \
1059 (otri1).tri[(otri1).orient] = encode(otri2); \
1060 (otri2).tri[(otri2).orient] = encode(otri1)
1061
1062/* Dissolve a bond (from one side). Note that the other triangle will still */
1063/* think it's connected to this triangle. Usually, however, the other */
1064/* triangle is being deleted entirely, or bonded to another triangle, so */
1065/* it doesn't matter. */
1066
1067#define dissolve(otri) \
1068 (otri).tri[(otri).orient] = (triangle) m->dummytri
1069
1070/* Copy an oriented triangle. */
1071
1072#define otricopy(otri1, otri2) \
1073 (otri2).tri = (otri1).tri; \
1074 (otri2).orient = (otri1).orient
1075
1076/* Test for equality of oriented triangles. */
1077
1078#define otriequal(otri1, otri2) \
1079 (((otri1).tri == (otri2).tri) && \
1080 ((otri1).orient == (otri2).orient))
1081
1082/* Primitives to infect or cure a triangle with the virus. These rely on */
1083/* the assumption that all subsegments are aligned to four-byte boundaries.*/
1084
1085#define infect(otri) \
1086 (otri).tri[6] = (triangle) \
1087 ((uintptr_t) (otri).tri[6] | (uintptr_t) 2l)
1088
1089#define uninfect(otri) \
1090 (otri).tri[6] = (triangle) \
1091 ((uintptr_t) (otri).tri[6] & ~ (uintptr_t) 2l)
1092
1093/* Test a triangle for viral infection. */
1094
1095#define infected(otri) \
1096 (((uintptr_t) (otri).tri[6] & (uintptr_t) 2l) != 0l)
1097
1098/* Check or set a triangle's attributes. */
1099
1100#define elemattribute(otri, attnum) \
1101 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
1102
1103#define setelemattribute(otri, attnum, value) \
1104 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
1105
1106/* Check or set a triangle's maximum area bound. */
1107
1108#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
1109
1110#define setareabound(otri, value) \
1111 ((REAL *) (otri).tri)[m->areaboundindex] = value
1112
1113/* Check or set a triangle's deallocation. Its second pointer is set to */
1114/* NULL to indicate that it is not allocated. (Its first pointer is used */
1115/* for the stack of dead items.) Its fourth pointer (its first vertex) */
1116/* is set to NULL in case a `badtriang' structure points to it. */
1117
1118#define deadtri(tria) ((tria)[1] == (triangle) NULL)
1119
1120#define killtri(tria) \
1121 (tria)[1] = (triangle) NULL; \
1122 (tria)[3] = (triangle) NULL
1123
1124/********* Primitives for subsegments *********/
1125/* */
1126/* */
1127
1128/* sdecode() converts a pointer to an oriented subsegment. The orientation */
1129/* is extracted from the least significant bit of the pointer. The two */
1130/* least significant bits (one for orientation, one for viral infection) */
1131/* are masked out to produce the real pointer. */
1132
1133#define sdecode(sptr, osub) \
1134 (osub).ssorient = (int) ((uintptr_t) (sptr) & (uintptr_t) 1l); \
1135 (osub).ss = (subseg *) \
1136 ((uintptr_t) (sptr) & ~ (uintptr_t) 3l)
1137
1138/* sencode() compresses an oriented subsegment into a single pointer. It */
1139/* relies on the assumption that all subsegments are aligned to two-byte */
1140/* boundaries, so the least significant bit of (osub).ss is zero. */
1141
1142#define sencode(osub) \
1143 (subseg) ((uintptr_t) (osub).ss | (uintptr_t) (osub).ssorient)
1144
1145/* ssym() toggles the orientation of a subsegment. */
1146
1147#define ssym(osub1, osub2) \
1148 (osub2).ss = (osub1).ss; \
1149 (osub2).ssorient = 1 - (osub1).ssorient
1150
1151#define ssymself(osub) \
1152 (osub).ssorient = 1 - (osub).ssorient
1153
1154/* spivot() finds the other subsegment (from the same segment) that shares */
1155/* the same origin. */
1156
1157#define spivot(osub1, osub2) \
1158 sptr = (osub1).ss[(osub1).ssorient]; \
1159 sdecode(sptr, osub2)
1160
1161#define spivotself(osub) \
1162 sptr = (osub).ss[(osub).ssorient]; \
1163 sdecode(sptr, osub)
1164
1165/* snext() finds the next subsegment (from the same segment) in sequence; */
1166/* one whose origin is the input subsegment's destination. */
1167
1168#define snext(osub1, osub2) \
1169 sptr = (osub1).ss[1 - (osub1).ssorient]; \
1170 sdecode(sptr, osub2)
1171
1172#define snextself(osub) \
1173 sptr = (osub).ss[1 - (osub).ssorient]; \
1174 sdecode(sptr, osub)
1175
1176/* These primitives determine or set the origin or destination of a */
1177/* subsegment or the segment that includes it. */
1178
1179#define sorg(osub, vertexptr) \
1180 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
1181
1182#define sdest(osub, vertexptr) \
1183 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
1184
1185#define setsorg(osub, vertexptr) \
1186 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
1187
1188#define setsdest(osub, vertexptr) \
1189 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
1190
1191#define segorg(osub, vertexptr) \
1192 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
1193
1194#define segdest(osub, vertexptr) \
1195 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
1196
1197#define setsegorg(osub, vertexptr) \
1198 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
1199
1200#define setsegdest(osub, vertexptr) \
1201 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
1202
1203/* These primitives read or set a boundary marker. Boundary markers are */
1204/* used to hold user-defined tags for setting boundary conditions in */
1205/* finite element solvers. */
1206
1207#define mark(osub) (* (int *) ((osub).ss + 8))
1208
1209#define setmark(osub, value) \
1210 * (int *) ((osub).ss + 8) = value
1211
1212/* Bond two subsegments together. */
1213
1214#define sbond(osub1, osub2) \
1215 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
1216 (osub2).ss[(osub2).ssorient] = sencode(osub1)
1217
1218/* Dissolve a subsegment bond (from one side). Note that the other */
1219/* subsegment will still think it's connected to this subsegment. */
1220
1221#define sdissolve(osub) \
1222 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
1223
1224/* Copy a subsegment. */
1225
1226#define subsegcopy(osub1, osub2) \
1227 (osub2).ss = (osub1).ss; \
1228 (osub2).ssorient = (osub1).ssorient
1229
1230/* Test for equality of subsegments. */
1231
1232#define subsegequal(osub1, osub2) \
1233 (((osub1).ss == (osub2).ss) && \
1234 ((osub1).ssorient == (osub2).ssorient))
1235
1236/* Check or set a subsegment's deallocation. Its second pointer is set to */
1237/* NULL to indicate that it is not allocated. (Its first pointer is used */
1238/* for the stack of dead items.) Its third pointer (its first vertex) */
1239/* is set to NULL in case a `badsubseg' structure points to it. */
1240
1241#define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
1242
1243#define killsubseg(sub) \
1244 (sub)[1] = (subseg) NULL; \
1245 (sub)[2] = (subseg) NULL
1246
1247/********* Primitives for interacting triangles and subsegments *********/
1248/* */
1249/* */
1250
1251/* tspivot() finds a subsegment abutting a triangle. */
1252
1253#define tspivot(otri, osub) \
1254 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
1255 sdecode(sptr, osub)
1256
1257/* stpivot() finds a triangle abutting a subsegment. It requires that the */
1258/* variable `ptr' of type `triangle' be defined. */
1259
1260#define stpivot(osub, otri) \
1261 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
1262 decode(ptr, otri)
1263
1264/* Bond a triangle to a subsegment. */
1265
1266#define tsbond(otri, osub) \
1267 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
1268 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
1269
1270/* Dissolve a bond (from the triangle side). */
1271
1272#define tsdissolve(otri) \
1273 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
1274
1275/* Dissolve a bond (from the subsegment side). */
1276
1277#define stdissolve(osub) \
1278 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
1279
1280/********* Primitives for vertices *********/
1281/* */
1282/* */
1283
1284#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
1285
1286#define setvertexmark(vx, value) \
1287 ((int *) (vx))[m->vertexmarkindex] = value
1288
1289#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
1290
1291#define setvertextype(vx, value) \
1292 ((int *) (vx))[m->vertexmarkindex + 1] = value
1293
1294#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
1295
1296#define setvertex2tri(vx, value) \
1297 ((triangle *) (vx))[m->vertex2triindex] = value
1298
1299/** **/
1300/** **/
1301/********* Mesh manipulation primitives end here *********/
1302
1303/********* User-defined triangle evaluation routine begins here *********/
1304/** **/
1305/** **/
1306
1307/*****************************************************************************/
1308/* */
1309/* triunsuitable() Determine if a triangle is unsuitable, and thus must */
1310/* be further refined. */
1311/* */
1312/* You may write your own procedure that decides whether or not a selected */
1313/* triangle is too big (and needs to be refined). There are two ways to do */
1314/* this. */
1315/* */
1316/* (1) Modify the procedure `triunsuitable' below, then recompile */
1317/* Triangle. */
1318/* */
1319/* (2) Define the symbol EXTERNAL_TEST (either by adding the definition */
1320/* to this file, or by using the appropriate compiler switch). This way, */
1321/* you can compile triangle.c separately from your test. Write your own */
1322/* `triunsuitable' procedure in a separate C file (using the same prototype */
1323/* as below). Compile it and link the object code with triangle.o. */
1324/* */
1325/* This procedure returns 1 if the triangle is too large and should be */
1326/* refined; 0 otherwise. */
1327/* */
1328/*****************************************************************************/
1329
1330#ifdef EXTERNAL_TEST
1331
1332int triunsuitable();
1333
1334#else /* not EXTERNAL_TEST */
1335
1336#ifdef ANSI_DECLARATORS
1337int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area )
1338#else /* not ANSI_DECLARATORS */
1339int triunsuitable(triorg, tridest, triapex, area)
1340vertex triorg; /* The triangle's origin vertex. */
1341vertex tridest; /* The triangle's destination vertex. */
1342vertex triapex; /* The triangle's apex vertex. */
1343REAL area; /* The area of the triangle. */
1344#endif /* not ANSI_DECLARATORS */
1345
1346{
1347 REAL dxoa, dxda, dxod;
1348 REAL dyoa, dyda, dyod;
1349 REAL oalen, dalen, odlen;
1350 REAL maxlen;
1351
1352 (void)area; /*LM: added to suppress warning */
1353
1354 dxoa = triorg[0] - triapex[0];
1355 dyoa = triorg[1] - triapex[1];
1356 dxda = tridest[0] - triapex[0];
1357 dyda = tridest[1] - triapex[1];
1358 dxod = triorg[0] - tridest[0];
1359 dyod = triorg[1] - tridest[1];
1360 /* Find the squares of the lengths of the triangle's three edges. */
1361 oalen = dxoa * dxoa + dyoa * dyoa;
1362 dalen = dxda * dxda + dyda * dyda;
1363 odlen = dxod * dxod + dyod * dyod;
1364 /* Find the square of the length of the longest edge. */
1365 maxlen = (dalen > oalen) ? dalen : oalen;
1366 maxlen = (odlen > maxlen) ? odlen : maxlen;
1367
1368 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
1369 return 1;
1370 } else {
1371 return 0;
1372 }
1373}
1374
1375#endif /* not EXTERNAL_TEST */
1376
1377/** **/
1378/** **/
1379/********* User-defined triangle evaluation routine ends here *********/
1380
1381/********* Memory allocation and program exit wrappers begin here *********/
1382/** **/
1383/** **/
1384
1385#ifdef ANSI_DECLARATORS
1386void triexit(int status)
1387#else /* not ANSI_DECLARATORS */
1388void triexit(status)
1389int status;
1390#endif /* not ANSI_DECLARATORS */
1391
1392{
1393 exit(status);
1394}
1395
1396#ifdef ANSI_DECLARATORS
1398#else /* not ANSI_DECLARATORS */
1400int size;
1401#endif /* not ANSI_DECLARATORS */
1402
1403{
1404 VOID *memptr;
1405
1406 memptr = (VOID *) malloc((unsigned int) size);
1407 if (memptr == (VOID *) NULL) {
1408 printf("Error: Out of memory.\n");
1409 triexit(1);
1410 }
1411 return(memptr);
1412}
1413
1414#ifdef ANSI_DECLARATORS
1415void trifree(VOID *memptr)
1416#else /* not ANSI_DECLARATORS */
1417void trifree(memptr)
1418VOID *memptr;
1419#endif /* not ANSI_DECLARATORS */
1420
1421{
1422 free(memptr);
1423}
1424
1425/** **/
1426/** **/
1427/********* Memory allocation and program exit wrappers end here *********/
1428
1429/********* User interaction routines begin here *********/
1430/** **/
1431/** **/
1432
1433/*****************************************************************************/
1434/* */
1435/* syntax() Print list of command line switches. */
1436/* */
1437/*****************************************************************************/
1438
1439#ifndef TRILIBRARY
1440
1441void syntax()
1442{
1443#ifdef CDT_ONLY
1444#ifdef REDUCED
1445 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
1446#else /* not REDUCED */
1447 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
1448#endif /* not REDUCED */
1449#else /* not CDT_ONLY */
1450#ifdef REDUCED
1451 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
1452#else /* not REDUCED */
1453 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
1454#endif /* not REDUCED */
1455#endif /* not CDT_ONLY */
1456
1457 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
1458#ifndef CDT_ONLY
1459 printf(" -r Refines a previously generated mesh.\n");
1460 printf(
1461 " -q Quality mesh generation. A minimum angle may be specified.\n");
1462 printf(" -a Applies a maximum triangle area constraint.\n");
1463 printf(" -u Applies a user-defined triangle constraint.\n");
1464#endif /* not CDT_ONLY */
1465 printf(
1466 " -A Applies attributes to identify triangles in certain regions.\n");
1467 printf(" -c Encloses the convex hull with segments.\n");
1468#ifndef CDT_ONLY
1469 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
1470#endif /* not CDT_ONLY */
1471/*
1472 printf(" -w Weighted Delaunay triangulation.\n");
1473 printf(" -W Regular triangulation (lower hull of a height field).\n");
1474*/
1475 printf(" -j Jettison unused vertices from output .node file.\n");
1476 printf(" -e Generates an edge list.\n");
1477 printf(" -v Generates a Voronoi diagram.\n");
1478 printf(" -n Generates a list of triangle neighbors.\n");
1479 printf(" -g Generates an .off file for Geomview.\n");
1480 printf(" -B Suppresses output of boundary information.\n");
1481 printf(" -P Suppresses output of .poly file.\n");
1482 printf(" -N Suppresses output of .node file.\n");
1483 printf(" -E Suppresses output of .ele file.\n");
1484 printf(" -I Suppresses mesh iteration numbers.\n");
1485 printf(" -O Ignores holes in .poly file.\n");
1486 printf(" -X Suppresses use of exact arithmetic.\n");
1487 printf(" -z Numbers all items starting from zero (rather than one).\n");
1488 printf(" -o2 Generates second-order subparametric elements.\n");
1489#ifndef CDT_ONLY
1490 printf(" -Y Suppresses boundary segment splitting.\n");
1491 printf(" -S Specifies maximum number of added Steiner points.\n");
1492#endif /* not CDT_ONLY */
1493#ifndef REDUCED
1494 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
1495 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
1496#endif /* not REDUCED */
1497 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
1498#ifndef REDUCED
1499#ifndef CDT_ONLY
1500 printf(
1501 " -s Force segments into mesh by splitting (instead of using CDT).\n");
1502#endif /* not CDT_ONLY */
1503 printf(" -C Check consistency of final mesh.\n");
1504#endif /* not REDUCED */
1505 printf(" -Q Quiet: No terminal output except errors.\n");
1506 printf(" -V Verbose: Detailed information on what I'm doing.\n");
1507 printf(" -h Help: Detailed instructions for Triangle.\n");
1508 triexit(0);
1509}
1510
1511#endif /* not TRILIBRARY */
1512
1513/*****************************************************************************/
1514/* */
1515/* info() Print out complete instructions. */
1516/* */
1517/*****************************************************************************/
1518
1519#ifndef TRILIBRARY
1520
1521void info()
1522{
1523 printf("Triangle\n");
1524 printf(
1525"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
1526 printf("Version 1.6\n\n");
1527 printf(
1528"Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
1529 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
1530 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
1531 printf(
1532"Created as part of the Quake project (tools for earthquake simulation).\n");
1533 printf(
1534"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
1535 printf("There is no warranty whatsoever. Use at your own risk.\n");
1536#ifdef SINGLE
1537 printf("This executable is compiled for single precision arithmetic.\n\n\n");
1538#else /* not SINGLE */
1539 printf("This executable is compiled for double precision arithmetic.\n\n\n");
1540#endif /* not SINGLE */
1541 printf(
1542"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
1543 printf(
1544"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
1545 printf(
1546"high-quality triangular meshes. The latter can be generated with no small\n"
1547);
1548 printf(
1549"or large angles, and are thus suitable for finite element analysis. If no\n"
1550);
1551 printf(
1552"command line switch is specified, your .node input file is read, and the\n");
1553 printf(
1554"Delaunay triangulation is returned in .node and .ele output files. The\n");
1555 printf("command syntax is:\n\n");
1556 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
1557 printf(
1558"Underscores indicate that numbers may optionally follow certain switches.\n");
1559 printf(
1560"Do not leave any space between a switch and its numeric parameter.\n");
1561 printf(
1562"input_file must be a file with extension .node, or extension .poly if the\n");
1563 printf(
1564"-p switch is used. If -r is used, you must supply .node and .ele files,\n");
1565 printf(
1566"and possibly a .poly file and an .area file as well. The formats of these\n"
1567);
1568 printf("files are described below.\n\n");
1569 printf("Command Line Switches:\n\n");
1570 printf(
1571" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
1572);
1573 printf(
1574" vertices, segments, holes, regional attributes, and regional area\n");
1575 printf(
1576" constraints. Generates a constrained Delaunay triangulation (CDT)\n"
1577);
1578 printf(
1579" fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
1580 printf(
1581" constrained Delaunay triangulation (CCDT). If you want a truly\n");
1582 printf(
1583" Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
1584 printf(
1585" well. When -p is not used, Triangle reads a .node file by default.\n"
1586);
1587 printf(
1588" -r Refines a previously generated mesh. The mesh is read from a .node\n"
1589);
1590 printf(
1591" file and an .ele file. If -p is also used, a .poly file is read\n");
1592 printf(
1593" and used to constrain segments in the mesh. If -a is also used\n");
1594 printf(
1595" (with no number following), an .area file is read and used to\n");
1596 printf(
1597" impose area constraints on the mesh. Further details on refinement\n"
1598);
1599 printf(" appear below.\n");
1600 printf(
1601" -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
1602 printf(
1603" Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
1604);
1605 printf(
1606" ensure that all angles are between 20 and 140 degrees. An\n");
1607 printf(
1608" alternative bound on the minimum angle, replacing 20 degrees, may\n");
1609 printf(
1610" be specified after the `q'. The specified angle may include a\n");
1611 printf(
1612" decimal point, but not exponential notation. Note that a bound of\n"
1613);
1614 printf(
1615" theta degrees on the smallest angle also implies a bound of\n");
1616 printf(
1617" (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
1618);
1619 printf(
1620" degrees or smaller, Triangle is mathematically guaranteed to\n");
1621 printf(
1622" terminate (assuming infinite precision arithmetic--Triangle may\n");
1623 printf(
1624" fail to terminate if you run out of precision). In practice,\n");
1625 printf(
1626" Triangle often succeeds for minimum angles up to 34 degrees. For\n");
1627 printf(
1628" some meshes, however, you might need to reduce the minimum angle to\n"
1629);
1630 printf(
1631" avoid problems associated with insufficient floating-point\n");
1632 printf(" precision.\n");
1633 printf(
1634" -a Imposes a maximum triangle area. If a number follows the `a', no\n");
1635 printf(
1636" triangle is generated whose area is larger than that number. If no\n"
1637);
1638 printf(
1639" number is specified, an .area file (if -r is used) or .poly file\n");
1640 printf(
1641" (if -r is not used) specifies a set of maximum area constraints.\n");
1642 printf(
1643" An .area file contains a separate area constraint for each\n");
1644 printf(
1645" triangle, and is useful for refining a finite element mesh based on\n"
1646);
1647 printf(
1648" a posteriori error estimates. A .poly file can optionally contain\n"
1649);
1650 printf(
1651" an area constraint for each segment-bounded region, thereby\n");
1652 printf(
1653" controlling triangle densities in a first triangulation of a PSLG.\n"
1654);
1655 printf(
1656" You can impose both a fixed area constraint and a varying area\n");
1657 printf(
1658" constraint by invoking the -a switch twice, once with and once\n");
1659 printf(
1660" without a number following. Each area specified may include a\n");
1661 printf(" decimal point.\n");
1662 printf(
1663" -u Imposes a user-defined constraint on triangle size. There are two\n"
1664);
1665 printf(
1666" ways to use this feature. One is to edit the triunsuitable()\n");
1667 printf(
1668" procedure in triangle.c to encode any constraint you like, then\n");
1669 printf(
1670" recompile Triangle. The other is to compile triangle.c with the\n");
1671 printf(
1672" EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
1673 printf(
1674" link Triangle with a separate object file that implements\n");
1675 printf(
1676" triunsuitable(). In either case, the -u switch causes the user-\n");
1677 printf(" defined test to be applied to every triangle.\n");
1678 printf(
1679" -A Assigns an additional floating-point attribute to each triangle\n");
1680 printf(
1681" that identifies what segment-bounded region each triangle belongs\n");
1682 printf(
1683" to. Attributes are assigned to regions by the .poly file. If a\n");
1684 printf(
1685" region is not explicitly marked by the .poly file, triangles in\n");
1686 printf(
1687" that region are assigned an attribute of zero. The -A switch has\n");
1688 printf(
1689" an effect only when the -p switch is used and the -r switch is not.\n"
1690);
1691 printf(
1692" -c Creates segments on the convex hull of the triangulation. If you\n");
1693 printf(
1694" are triangulating a vertex set, this switch causes a .poly file to\n"
1695);
1696 printf(
1697" be written, containing all edges of the convex hull. If you are\n");
1698 printf(
1699" triangulating a PSLG, this switch specifies that the whole convex\n");
1700 printf(
1701" hull of the PSLG should be triangulated, regardless of what\n");
1702 printf(
1703" segments the PSLG has. If you do not use this switch when\n");
1704 printf(
1705" triangulating a PSLG, Triangle assumes that you have identified the\n"
1706);
1707 printf(
1708" region to be triangulated by surrounding it with segments of the\n");
1709 printf(
1710" input PSLG. Beware: if you are not careful, this switch can cause\n"
1711);
1712 printf(
1713" the introduction of an extremely thin angle between a PSLG segment\n"
1714);
1715 printf(
1716" and a convex hull segment, which can cause overrefinement (and\n");
1717 printf(
1718" possibly failure if Triangle runs out of precision). If you are\n");
1719 printf(
1720" refining a mesh, the -c switch works differently: it causes a\n");
1721 printf(
1722" .poly file to be written containing the boundary edges of the mesh\n"
1723);
1724 printf(" (useful if no .poly file was read).\n");
1725 printf(
1726" -D Conforming Delaunay triangulation: use this switch if you want to\n"
1727);
1728 printf(
1729" ensure that all the triangles in the mesh are Delaunay, and not\n");
1730 printf(
1731" merely constrained Delaunay; or if you want to ensure that all the\n"
1732);
1733 printf(
1734" Voronoi vertices lie within the triangulation. (Some finite volume\n"
1735);
1736 printf(
1737" methods have this requirement.) This switch invokes Ruppert's\n");
1738 printf(
1739" original algorithm, which splits every subsegment whose diametral\n");
1740 printf(
1741" circle is encroached. It usually increases the number of vertices\n"
1742);
1743 printf(" and triangles.\n");
1744 printf(
1745" -j Jettisons vertices that are not part of the final triangulation\n");
1746 printf(
1747" from the output .node file. By default, Triangle copies all\n");
1748 printf(
1749" vertices in the input .node file to the output .node file, in the\n");
1750 printf(
1751" same order, so their indices do not change. The -j switch prevents\n"
1752);
1753 printf(
1754" duplicated input vertices, or vertices `eaten' by holes, from\n");
1755 printf(
1756" appearing in the output .node file. Thus, if two input vertices\n");
1757 printf(
1758" have exactly the same coordinates, only the first appears in the\n");
1759 printf(
1760" output. If any vertices are jettisoned, the vertex numbering in\n");
1761 printf(
1762" the output .node file differs from that of the input .node file.\n");
1763 printf(
1764" -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
1765 printf(
1766" -v Outputs the Voronoi diagram associated with the triangulation.\n");
1767 printf(
1768" Does not attempt to detect degeneracies, so some Voronoi vertices\n");
1769 printf(
1770" may be duplicated. See the discussion of Voronoi diagrams below.\n");
1771 printf(
1772" -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
1773 printf(" triangle.\n");
1774 printf(
1775" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
1776);
1777 printf(" viewing with the Geometry Center's Geomview package.\n");
1778 printf(
1779" -B No boundary markers in the output .node, .poly, and .edge output\n");
1780 printf(
1781" files. See the detailed discussion of boundary markers below.\n");
1782 printf(
1783" -P No output .poly file. Saves disk space, but you lose the ability\n");
1784 printf(
1785" to maintain constraining segments on later refinements of the mesh.\n"
1786);
1787 printf(" -N No output .node file.\n");
1788 printf(" -E No output .ele file.\n");
1789 printf(
1790" -I No iteration numbers. Suppresses the output of .node and .poly\n");
1791 printf(
1792" files, so your input files won't be overwritten. (If your input is\n"
1793);
1794 printf(
1795" a .poly file only, a .node file is written.) Cannot be used with\n");
1796 printf(
1797" the -r switch, because that would overwrite your input .ele file.\n");
1798 printf(
1799" Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
1800 printf(
1801" using a .node file for input, because no .node file is written, so\n"
1802);
1803 printf(" there is no record of any added Steiner points.\n");
1804 printf(" -O No holes. Ignores the holes in the .poly file.\n");
1805 printf(
1806" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
1807);
1808 printf(
1809" arithmetic for certain tests if it thinks the inexact tests are not\n"
1810);
1811 printf(
1812" accurate enough. Exact arithmetic ensures the robustness of the\n");
1813 printf(
1814" triangulation algorithms, despite floating-point roundoff error.\n");
1815 printf(
1816" Disabling exact arithmetic with the -X switch causes a small\n");
1817 printf(
1818" improvement in speed and creates the possibility that Triangle will\n"
1819);
1820 printf(" fail to produce a valid mesh. Not recommended.\n");
1821 printf(
1822" -z Numbers all items starting from zero (rather than one). Note that\n"
1823);
1824 printf(
1825" this switch is normally overridden by the value used to number the\n"
1826);
1827 printf(
1828" first vertex of the input .node or .poly file. However, this\n");
1829 printf(
1830" switch is useful when calling Triangle from another program.\n");
1831 printf(
1832" -o2 Generates second-order subparametric elements with six nodes each.\n"
1833);
1834 printf(
1835" -Y No new vertices on the boundary. This switch is useful when the\n");
1836 printf(
1837" mesh boundary must be preserved so that it conforms to some\n");
1838 printf(
1839" adjacent mesh. Be forewarned that you will probably sacrifice much\n"
1840);
1841 printf(
1842" of the quality of the mesh; Triangle will try, but the resulting\n");
1843 printf(
1844" mesh may contain poorly shaped triangles. Works well if all the\n");
1845 printf(
1846" boundary vertices are closely spaced. Specify this switch twice\n");
1847 printf(
1848" (`-YY') to prevent all segment splitting, including internal\n");
1849 printf(" boundaries.\n");
1850 printf(
1851" -S Specifies the maximum number of Steiner points (vertices that are\n");
1852 printf(
1853" not in the input, but are added to meet the constraints on minimum\n"
1854);
1855 printf(
1856" angle and maximum area). The default is to allow an unlimited\n");
1857 printf(
1858" number. If you specify this switch with no number after it,\n");
1859 printf(
1860" the limit is set to zero. Triangle always adds vertices at segment\n"
1861);
1862 printf(
1863" intersections, even if it needs to use more vertices than the limit\n"
1864);
1865 printf(
1866" you set. When Triangle inserts segments by splitting (-s), it\n");
1867 printf(
1868" always adds enough vertices to ensure that all the segments of the\n"
1869);
1870 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
1871 printf(
1872" -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
1873 printf(
1874" construct a Delaunay triangulation. Try it if the divide-and-\n");
1875 printf(" conquer algorithm fails.\n");
1876 printf(
1877" -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
1878 printf(
1879" triangulation. Warning: does not use exact arithmetic for all\n");
1880 printf(" calculations. An exact result is not guaranteed.\n");
1881 printf(
1882" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
1883 printf(
1884" default, Triangle alternates between vertical and horizontal cuts,\n"
1885);
1886 printf(
1887" which usually improve the speed except with vertex sets that are\n");
1888 printf(
1889" small or short and wide. This switch is primarily of theoretical\n");
1890 printf(" interest.\n");
1891 printf(
1892" -s Specifies that segments should be forced into the triangulation by\n"
1893);
1894 printf(
1895" recursively splitting them at their midpoints, rather than by\n");
1896 printf(
1897" generating a constrained Delaunay triangulation. Segment splitting\n"
1898);
1899 printf(
1900" is true to Ruppert's original algorithm, but can create needlessly\n"
1901);
1902 printf(
1903" small triangles. This switch is primarily of theoretical interest.\n"
1904);
1905 printf(
1906" -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
1907);
1908 printf(
1909" checking, even if the -X switch is used. Useful if you suspect\n");
1910 printf(" Triangle is buggy.\n");
1911 printf(
1912" -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
1913 printf(" unless an error occurs.\n");
1914 printf(
1915" -V Verbose: Gives detailed information about what Triangle is doing.\n"
1916);
1917 printf(
1918" Add more `V's for increasing amount of detail. `-V' is most\n");
1919 printf(
1920" useful; itgives information on algorithmic progress and much more\n");
1921 printf(
1922" detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
1923 printf(
1924" prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
1925);
1926 printf(" information only a debugger could love.\n");
1927 printf(" -h Help: Displays these instructions.\n");
1928 printf("\n");
1929 printf("Definitions:\n");
1930 printf("\n");
1931 printf(
1932" A Delaunay triangulation of a vertex set is a triangulation whose\n");
1933 printf(
1934" vertices are the vertex set, that covers the convex hull of the vertex\n");
1935 printf(
1936" set. A Delaunay triangulation has the property that no vertex lies\n");
1937 printf(
1938" inside the circumscribing circle (circle that passes through all three\n");
1939 printf(" vertices) of any triangle in the triangulation.\n\n");
1940 printf(
1941" A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
1942 printf(
1943" polygonal cells (some of which may be unbounded, meaning infinitely\n");
1944 printf(
1945" large), where each cell is the set of points in the plane that are closer\n"
1946);
1947 printf(
1948" to some input vertex than to any other input vertex. The Voronoi diagram\n"
1949);
1950 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
1951 printf(
1952" A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
1953 printf(
1954" Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
1955);
1956 printf(
1957" Segments may intersect each other only at their endpoints. The file\n");
1958 printf(" format for PSLGs (.poly files) is described below.\n\n");
1959 printf(
1960" A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
1961 printf(
1962" Delaunay triangulation, but each PSLG segment is present as a single edge\n"
1963);
1964 printf(
1965" of the CDT. (A constrained Delaunay triangulation is not truly a\n");
1966 printf(
1967" Delaunay triangulation, because some of its triangles might not be\n");
1968 printf(
1969" Delaunay.) By definition, a CDT does not have any vertices other than\n");
1970 printf(
1971" those specified in the input PSLG. Depending on context, a CDT might\n");
1972 printf(
1973" cover the convex hull of the PSLG, or it might cover only a segment-\n");
1974 printf(" bounded region (e.g. a polygon).\n\n");
1975 printf(
1976" A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
1977);
1978 printf(
1979" each triangle is truly Delaunay, and each PSLG segment is represented by\n"
1980);
1981 printf(
1982" a linear contiguous sequence of edges of the triangulation. New vertices\n"
1983);
1984 printf(
1985" (not part of the PSLG) may appear, and each input segment may have been\n");
1986 printf(
1987" subdivided into shorter edges (subsegments) by these additional vertices.\n"
1988);
1989 printf(
1990" The new vertices are frequently necessary to maintain the Delaunay\n");
1991 printf(" property while ensuring that every segment is represented.\n\n");
1992 printf(
1993" A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
1994 printf(
1995" triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
1996 printf(" vertices may appear, and input segments may be subdivided into\n");
1997 printf(
1998" subsegments, but not to guarantee that segments are respected; rather, to\n"
1999);
2000 printf(
2001" improve the quality of the triangles. The high-quality meshes produced\n");
2002 printf(
2003" by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
2004 printf(" with the -D switch.\n\n");
2005 printf("File Formats:\n\n");
2006 printf(
2007" All files may contain comments prefixed by the character '#'. Vertices,\n"
2008);
2009 printf(
2010" triangles, edges, holes, and maximum area constraints must be numbered\n");
2011 printf(
2012" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
2013 printf(
2014" input files must be consistent; if the vertices are numbered from 1, so\n");
2015 printf(
2016" must be all other objects. Triangle automatically detects your choice\n");
2017 printf(
2018" while reading the .node (or .poly) file. (When calling Triangle from\n");
2019 printf(
2020" another program, use the -z switch if you wish to number objects from\n");
2021 printf(" zero.) Examples of these file formats are given below.\n\n");
2022 printf(" .node files:\n");
2023 printf(
2024" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2025);
2026 printf(
2027" <# of boundary markers (0 or 1)>\n"
2028);
2029 printf(
2030" Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2031 printf("\n");
2032 printf(
2033" The attributes, which are typically floating-point values of physical\n");
2034 printf(
2035" quantities (such as mass or conductivity) associated with the nodes of\n"
2036);
2037 printf(
2038" a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
2039);
2040 printf(
2041" -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
2042);
2043 printf(" has attributes assigned to it by linear interpolation.\n\n");
2044 printf(
2045" If the fourth entry of the first line is `1', the last column of the\n");
2046 printf(
2047" remainder of the file is assumed to contain boundary markers. Boundary\n"
2048);
2049 printf(
2050" markers are used to identify boundary vertices and vertices resting on\n"
2051);
2052 printf(
2053" PSLG segments; a complete description appears in a section below. The\n"
2054);
2055 printf(
2056" .node file produced by Triangle contains boundary markers in the last\n");
2057 printf(" column unless they are suppressed by the -B switch.\n\n");
2058 printf(" .ele files:\n");
2059 printf(
2060" First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
2061 printf(
2062" Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
2063 printf("\n");
2064 printf(
2065" Nodes are indices into the corresponding .node file. The first three\n");
2066 printf(
2067" nodes are the corner vertices, and are listed in counterclockwise order\n"
2068);
2069 printf(
2070" around each triangle. (The remaining nodes, if any, depend on the type\n"
2071);
2072 printf(" of finite element used.)\n\n");
2073 printf(
2074" The attributes are just like those of .node files. Because there is no\n"
2075);
2076 printf(
2077" simple mapping from input to output triangles, Triangle attempts to\n");
2078 printf(
2079" interpolate attributes, and may cause a lot of diffusion of attributes\n"
2080);
2081 printf(
2082" among nearby triangles as the triangulation is refined. Attributes do\n"
2083);
2084 printf(" not diffuse across segments, so attributes used to identify\n");
2085 printf(" segment-bounded regions remain intact.\n\n");
2086 printf(
2087" In .ele files produced by Triangle, each triangular element has three\n");
2088 printf(
2089" nodes (vertices) unless the -o2 switch is used, in which case\n");
2090 printf(
2091" subparametric quadratic elements with six nodes each are generated.\n");
2092 printf(
2093" The first three nodes are the corners in counterclockwise order, and\n");
2094 printf(
2095" the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
2096 printf(
2097" opposite the first, second, and third vertices, respectively.\n");
2098 printf("\n");
2099 printf(" .poly files:\n");
2100 printf(
2101" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2102);
2103 printf(
2104" <# of boundary markers (0 or 1)>\n"
2105);
2106 printf(
2107" Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2108 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
2109 printf(
2110" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
2111 printf(" One line: <# of holes>\n");
2112 printf(" Following lines: <hole #> <x> <y>\n");
2113 printf(
2114" Optional line: <# of regional attributes and/or area constraints>\n");
2115 printf(
2116" Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
2117 printf("\n");
2118 printf(
2119" A .poly file represents a PSLG, as well as some additional information.\n"
2120);
2121 printf(
2122" The first section lists all the vertices, and is identical to the\n");
2123 printf(
2124" format of .node files. <# of vertices> may be set to zero to indicate\n"
2125);
2126 printf(
2127" that the vertices are listed in a separate .node file; .poly files\n");
2128 printf(
2129" produced by Triangle always have this format. A vertex set represented\n"
2130);
2131 printf(
2132" this way has the advantage that it may easily be triangulated with or\n");
2133 printf(
2134" without segments (depending on whether the -p switch is invoked).\n");
2135 printf("\n");
2136 printf(
2137" The second section lists the segments. Segments are edges whose\n");
2138 printf(
2139" presence in the triangulation is enforced. (Depending on the choice of\n"
2140);
2141 printf(
2142" switches, segment might be subdivided into smaller edges). Each\n");
2143 printf(
2144" segment is specified by listing the indices of its two endpoints. This\n"
2145);
2146 printf(
2147" means that you must include its endpoints in the vertex list. Each\n");
2148 printf(" segment, like each point, may have a boundary marker.\n\n");
2149 printf(
2150" If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
2151);
2152 printf(
2153" Delaunay triangulation (CDT), in which each segment appears as a single\n"
2154);
2155 printf(
2156" edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
2157);
2158 printf(
2159" produces a conforming constrained Delaunay triangulation (CCDT), in\n");
2160 printf(
2161" which segments may be subdivided into smaller edges. If -D is\n");
2162 printf(
2163" selected, Triangle produces a conforming Delaunay triangulation, so\n");
2164 printf(
2165" that every triangle is Delaunay, and not just constrained Delaunay.\n");
2166 printf("\n");
2167 printf(
2168" The third section lists holes (and concavities, if -c is selected) in\n");
2169 printf(
2170" the triangulation. Holes are specified by identifying a point inside\n");
2171 printf(
2172" each hole. After the triangulation is formed, Triangle creates holes\n");
2173 printf(
2174" by eating triangles, spreading out from each hole point until its\n");
2175 printf(
2176" progress is blocked by segments in the PSLG. You must be careful to\n");
2177 printf(
2178" enclose each hole in segments, or your whole triangulation might be\n");
2179 printf(
2180" eaten away. If the two triangles abutting a segment are eaten, the\n");
2181 printf(
2182" segment itself is also eaten. Do not place a hole directly on a\n");
2183 printf(" segment; if you do, Triangle chooses one side of the segment\n");
2184 printf(" arbitrarily.\n\n");
2185 printf(
2186" The optional fourth section lists regional attributes (to be assigned\n");
2187 printf(
2188" to all triangles in a region) and regional constraints on the maximum\n");
2189 printf(
2190" triangle area. Triangle reads this section only if the -A switch is\n");
2191 printf(
2192" used or the -a switch is used without a number following it, and the -r\n"
2193);
2194 printf(
2195" switch is not used. Regional attributes and area constraints are\n");
2196 printf(
2197" propagated in the same manner as holes: you specify a point for each\n");
2198 printf(
2199" attribute and/or constraint, and the attribute and/or constraint\n");
2200 printf(
2201" affects the whole region (bounded by segments) containing the point.\n");
2202 printf(
2203" If two values are written on a line after the x and y coordinate, the\n");
2204 printf(
2205" first such value is assumed to be a regional attribute (but is only\n");
2206 printf(
2207" applied if the -A switch is selected), and the second value is assumed\n"
2208);
2209 printf(
2210" to be a regional area constraint (but is only applied if the -a switch\n"
2211);
2212 printf(
2213" is selected). You may specify just one value after the coordinates,\n");
2214 printf(
2215" which can serve as both an attribute and an area constraint, depending\n"
2216);
2217 printf(
2218" on the choice of switches. If you are using the -A and -a switches\n");
2219 printf(
2220" simultaneously and wish to assign an attribute to some region without\n");
2221 printf(" imposing an area constraint, use a negative maximum area.\n\n");
2222 printf(
2223" When a triangulation is created from a .poly file, you must either\n");
2224 printf(
2225" enclose the entire region to be triangulated in PSLG segments, or\n");
2226 printf(
2227" use the -c switch, which automatically creates extra segments that\n");
2228 printf(
2229" enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
2230);
2231 printf(
2232" Triangle eats all triangles that are not enclosed by segments; if you\n");
2233 printf(
2234" are not careful, your whole triangulation may be eaten away. If you do\n"
2235);
2236 printf(
2237" use the -c switch, you can still produce concavities by the appropriate\n"
2238);
2239 printf(
2240" placement of holes just inside the boundary of the convex hull.\n");
2241 printf("\n");
2242 printf(
2243" An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
2244 printf(
2245" upon segments (except, of course, the endpoints of each segment). You\n"
2246);
2247 printf(
2248" aren't required to make your .poly files ideal, but you should be aware\n"
2249);
2250 printf(
2251" of what can go wrong. Segment intersections are relatively safe--\n");
2252 printf(
2253" Triangle calculates the intersection points for you and adds them to\n");
2254 printf(
2255" the triangulation--as long as your machine's floating-point precision\n");
2256 printf(
2257" doesn't become a problem. You are tempting the fates if you have three\n"
2258);
2259 printf(
2260" segments that cross at the same location, and expect Triangle to figure\n"
2261);
2262 printf(
2263" out where the intersection point is. Thanks to floating-point roundoff\n"
2264);
2265 printf(
2266" error, Triangle will probably decide that the three segments intersect\n"
2267);
2268 printf(
2269" at three different points, and you will find a minuscule triangle in\n");
2270 printf(
2271" your output--unless Triangle tries to refine the tiny triangle, uses\n");
2272 printf(
2273" up the last bit of machine precision, and fails to terminate at all.\n");
2274 printf(
2275" You're better off putting the intersection point in the input files,\n");
2276 printf(
2277" and manually breaking up each segment into two. Similarly, if you\n");
2278 printf(
2279" place a vertex at the middle of a segment, and hope that Triangle will\n"
2280);
2281 printf(
2282" break up the segment at that vertex, you might get lucky. On the other\n"
2283);
2284 printf(
2285" hand, Triangle might decide that the vertex doesn't lie precisely on\n");
2286 printf(
2287" the segment, and you'll have a needle-sharp triangle in your output--or\n"
2288);
2289 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
2290 printf("\n");
2291 printf(
2292" When Triangle reads a .poly file, it also writes a .poly file, which\n");
2293 printf(
2294" includes all the subsegments--the edges that are parts of input\n");
2295 printf(
2296" segments. If the -c switch is used, the output .poly file also\n");
2297 printf(
2298" includes all of the edges on the convex hull. Hence, the output .poly\n"
2299);
2300 printf(
2301" file is useful for finding edges associated with input segments and for\n"
2302);
2303 printf(
2304" setting boundary conditions in finite element simulations. Moreover,\n");
2305 printf(
2306" you will need the output .poly file if you plan to refine the output\n");
2307 printf(
2308" mesh, and don't want segments to be missing in later triangulations.\n");
2309 printf("\n");
2310 printf(" .area files:\n");
2311 printf(" First line: <# of triangles>\n");
2312 printf(" Following lines: <triangle #> <maximum area>\n");
2313 printf("\n");
2314 printf(
2315" An .area file associates with each triangle a maximum area that is used\n"
2316);
2317 printf(
2318" for mesh refinement. As with other file formats, every triangle must\n");
2319 printf(
2320" be represented, and the triangles must be numbered consecutively. A\n");
2321 printf(
2322" triangle may be left unconstrained by assigning it a negative maximum\n");
2323 printf(" area.\n\n");
2324 printf(" .edge files:\n");
2325 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
2326 printf(
2327" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
2328 printf("\n");
2329 printf(
2330" Endpoints are indices into the corresponding .node file. Triangle can\n"
2331);
2332 printf(
2333" produce .edge files (use the -e switch), but cannot read them. The\n");
2334 printf(
2335" optional column of boundary markers is suppressed by the -B switch.\n");
2336 printf("\n");
2337 printf(
2338" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
2339 printf(
2340" infinite ray with only one endpoint. For these edges, a different\n");
2341 printf(" format is used:\n\n");
2342 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
2343 printf(
2344" The `direction' is a floating-point vector that indicates the direction\n"
2345);
2346 printf(" of the infinite ray.\n\n");
2347 printf(" .neigh files:\n");
2348 printf(
2349" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
2350);
2351 printf(
2352" Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
2353 printf("\n");
2354 printf(
2355" Neighbors are indices into the corresponding .ele file. An index of -1\n"
2356);
2357 printf(
2358" indicates no neighbor (because the triangle is on an exterior\n");
2359 printf(
2360" boundary). The first neighbor of triangle i is opposite the first\n");
2361 printf(" corner of triangle i, and so on.\n\n");
2362 printf(
2363" Triangle can produce .neigh files (use the -n switch), but cannot read\n"
2364);
2365 printf(" them.\n\n");
2366 printf("Boundary Markers:\n\n");
2367 printf(
2368" Boundary markers are tags used mainly to identify which output vertices\n");
2369 printf(
2370" and edges are associated with which PSLG segment, and to identify which\n");
2371 printf(
2372" vertices and edges occur on a boundary of the triangulation. A common\n");
2373 printf(
2374" use is to determine where boundary conditions should be applied to a\n");
2375 printf(
2376" finite element mesh. You can prevent boundary markers from being written\n"
2377);
2378 printf(" into files produced by Triangle by using the -B switch.\n\n");
2379 printf(
2380" The boundary marker associated with each segment in an output .poly file\n"
2381);
2382 printf(" and each edge in an output .edge file is chosen as follows:\n");
2383 printf(
2384" - If an output edge is part or all of a PSLG segment with a nonzero\n");
2385 printf(
2386" boundary marker, then the edge is assigned the same marker.\n");
2387 printf(
2388" - Otherwise, if the edge lies on a boundary of the triangulation\n");
2389 printf(
2390" (even the boundary of a hole), then the edge is assigned the marker\n");
2391 printf(" one (1).\n");
2392 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
2393 printf(
2394" The boundary marker associated with each vertex in an output .node file\n");
2395 printf(" is chosen as follows:\n");
2396 printf(
2397" - If a vertex is assigned a nonzero boundary marker in the input file,\n"
2398);
2399 printf(
2400" then it is assigned the same marker in the output .node file.\n");
2401 printf(
2402" - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
2403 printf(
2404" endpoint of the segment) with a nonzero boundary marker, then the\n");
2405 printf(
2406" vertex is assigned the same marker. If the vertex lies on several\n");
2407 printf(" such segments, one of the markers is chosen arbitrarily.\n");
2408 printf(
2409" - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
2410 printf(" then the vertex is assigned the marker one (1).\n");
2411 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
2412 printf("\n");
2413 printf(
2414" If you want Triangle to determine for you which vertices and edges are on\n"
2415);
2416 printf(
2417" the boundary, assign them the boundary marker zero (or use no markers at\n"
2418);
2419 printf(
2420" all) in your input files. In the output files, all boundary vertices,\n");
2421 printf(" edges, and segments will be assigned the value one.\n\n");
2422 printf("Triangulation Iteration Numbers:\n\n");
2423 printf(
2424" Because Triangle can read and refine its own triangulations, input\n");
2425 printf(
2426" and output files have iteration numbers. For instance, Triangle might\n");
2427 printf(
2428" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
2429 printf(
2430" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
2431 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
2432 printf(
2433" their iteration number is zero; hence, Triangle might read the file\n");
2434 printf(
2435" points.node, triangulate it, and produce the files points.1.node and\n");
2436 printf(" points.1.ele.\n\n");
2437 printf(
2438" Iteration numbers allow you to create a sequence of successively finer\n");
2439 printf(
2440" meshes suitable for multigrid methods. They also allow you to produce a\n"
2441);
2442 printf(
2443" sequence of meshes using error estimate-driven mesh refinement.\n");
2444 printf("\n");
2445 printf(
2446" If you're not using refinement or quality meshing, and you don't like\n");
2447 printf(
2448" iteration numbers, use the -I switch to disable them. This switch also\n");
2449 printf(
2450" disables output of .node and .poly files to prevent your input files from\n"
2451);
2452 printf(
2453" being overwritten. (If the input is a .poly file that contains its own\n");
2454 printf(
2455" points, a .node file is written. This can be quite convenient for\n");
2456 printf(" computing CDTs or quality meshes.)\n\n");
2457 printf("Examples of How to Use Triangle:\n\n");
2458 printf(
2459" `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
2460);
2461 printf(
2462" triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
2463 printf(
2464" to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
2465 printf(
2466" instead. (No additional .node file is needed, so none is written.)\n");
2467 printf("\n");
2468 printf(
2469" `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
2470 printf(
2471" object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
2472);
2473 printf(
2474" its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
2475);
2476 printf(
2477" The segments are copied to object.2.poly, and all edges are written to\n");
2478 printf(" object.2.edge.\n\n");
2479 printf(
2480" `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
2481);
2482 printf(
2483" object.node), generates a mesh whose angles are all between 31.5 and 117\n"
2484);
2485 printf(
2486" degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
2487);
2488 printf(
2489" mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
2490 printf(" into multiple subsegments; these are written to object.1.poly.\n");
2491 printf("\n");
2492 printf(
2493" Here is a sample file `box.poly' describing a square with a square hole:\n"
2494);
2495 printf("\n");
2496 printf(
2497" # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
2498);
2499 printf(" 8 2 0 1\n");
2500 printf(" # Outer box has these vertices:\n");
2501 printf(" 1 0 0 0\n");
2502 printf(" 2 0 3 0\n");
2503 printf(" 3 3 0 0\n");
2504 printf(" 4 3 3 33 # A special marker for this vertex.\n");
2505 printf(" # Inner square has these vertices:\n");
2506 printf(" 5 1 1 0\n");
2507 printf(" 6 1 2 0\n");
2508 printf(" 7 2 1 0\n");
2509 printf(" 8 2 2 0\n");
2510 printf(" # Five segments with boundary markers.\n");
2511 printf(" 5 1\n");
2512 printf(" 1 1 2 5 # Left side of outer box.\n");
2513 printf(" # Square hole has these segments:\n");
2514 printf(" 2 5 7 0\n");
2515 printf(" 3 7 8 0\n");
2516 printf(" 4 8 6 10\n");
2517 printf(" 5 6 5 0\n");
2518 printf(" # One hole in the middle of the inner square.\n");
2519 printf(" 1\n");
2520 printf(" 1 1.5 1.5\n");
2521 printf("\n");
2522 printf(
2523" Note that some segments are missing from the outer square, so you must\n");
2524 printf(
2525" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
2526);
2527 printf(
2528" file `box.1.node', with twelve vertices. The last four vertices were\n");
2529 printf(
2530" added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
2531 printf(
2532" from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
2533 printf(
2534" other vertices but 4 have been marked to indicate that they lie on a\n");
2535 printf(" boundary.\n\n");
2536 printf(" 12 2 0 1\n");
2537 printf(" 1 0 0 5\n");
2538 printf(" 2 0 3 5\n");
2539 printf(" 3 3 0 1\n");
2540 printf(" 4 3 3 33\n");
2541 printf(" 5 1 1 1\n");
2542 printf(" 6 1 2 10\n");
2543 printf(" 7 2 1 1\n");
2544 printf(" 8 2 2 10\n");
2545 printf(" 9 0 1.5 5\n");
2546 printf(" 10 1.5 0 1\n");
2547 printf(" 11 3 1.5 1\n");
2548 printf(" 12 1.5 3 1\n");
2549 printf(" # Generated by triangle -pqc box.poly\n");
2550 printf("\n");
2551 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
2552 printf("\n");
2553 printf(" 12 3 0\n");
2554 printf(" 1 5 6 9\n");
2555 printf(" 2 10 3 7\n");
2556 printf(" 3 6 8 12\n");
2557 printf(" 4 9 1 5\n");
2558 printf(" 5 6 2 9\n");
2559 printf(" 6 7 3 11\n");
2560 printf(" 7 11 4 8\n");
2561 printf(" 8 7 5 10\n");
2562 printf(" 9 12 2 6\n");
2563 printf(" 10 8 7 11\n");
2564 printf(" 11 5 1 10\n");
2565 printf(" 12 8 4 12\n");
2566 printf(" # Generated by triangle -pqc box.poly\n\n");
2567 printf(
2568" Here is the output file `box.1.poly'. Note that segments have been added\n"
2569);
2570 printf(
2571" to represent the convex hull, and some segments have been subdivided by\n");
2572 printf(
2573" newly added vertices. Note also that <# of vertices> is set to zero to\n");
2574 printf(" indicate that the vertices should be read from the .node file.\n");
2575 printf("\n");
2576 printf(" 0 2 0 1\n");
2577 printf(" 12 1\n");
2578 printf(" 1 1 9 5\n");
2579 printf(" 2 5 7 1\n");
2580 printf(" 3 8 7 1\n");
2581 printf(" 4 6 8 10\n");
2582 printf(" 5 5 6 1\n");
2583 printf(" 6 3 10 1\n");
2584 printf(" 7 4 11 1\n");
2585 printf(" 8 2 12 1\n");
2586 printf(" 9 9 2 5\n");
2587 printf(" 10 10 1 1\n");
2588 printf(" 11 11 3 1\n");
2589 printf(" 12 12 4 1\n");
2590 printf(" 1\n");
2591 printf(" 1 1.5 1.5\n");
2592 printf(" # Generated by triangle -pqc box.poly\n");
2593 printf("\n");
2594 printf("Refinement and Area Constraints:\n");
2595 printf("\n");
2596 printf(
2597" The -r switch causes a mesh (.node and .ele files) to be read and\n");
2598 printf(
2599" refined. If the -p switch is also used, a .poly file is read and used to\n"
2600);
2601 printf(
2602" specify edges that are constrained and cannot be eliminated (although\n");
2603 printf(
2604" they can be subdivided into smaller edges) by the refinement process.\n");
2605 printf("\n");
2606 printf(
2607" When you refine a mesh, you generally want to impose tighter constraints.\n"
2608);
2609 printf(
2610" One way to accomplish this is to use -q with a larger angle, or -a\n");
2611 printf(
2612" followed by a smaller area than you used to generate the mesh you are\n");
2613 printf(
2614" refining. Another way to do this is to create an .area file, which\n");
2615 printf(
2616" specifies a maximum area for each triangle, and use the -a switch\n");
2617 printf(
2618" (without a number following). Each triangle's area constraint is applied\n"
2619);
2620 printf(
2621" to that triangle. Area constraints tend to diffuse as the mesh is\n");
2622 printf(
2623" refined, so if there are large variations in area constraint between\n");
2624 printf(
2625" adjacent triangles, you may not get the results you want. In that case,\n"
2626);
2627 printf(
2628" consider instead using the -u switch and writing a C procedure that\n");
2629 printf(" determines which triangles are too large.\n\n");
2630 printf(
2631" If you are refining a mesh composed of linear (three-node) elements, the\n"
2632);
2633 printf(
2634" output mesh contains all the nodes present in the input mesh, in the same\n"
2635);
2636 printf(
2637" order, with new nodes added at the end of the .node file. However, the\n");
2638 printf(
2639" refinement is not hierarchical: there is no guarantee that each output\n");
2640 printf(
2641" element is contained in a single input element. Often, an output element\n"
2642);
2643 printf(
2644" can overlap two or three input elements, and some input edges are not\n");
2645 printf(
2646" present in the output mesh. Hence, a sequence of refined meshes forms a\n"
2647);
2648 printf(
2649" hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
2650 printf(
2651" mesh of higher-order elements, the hierarchical property applies only to\n"
2652);
2653 printf(
2654" the nodes at the corners of an element; the midpoint nodes on each edge\n");
2655 printf(" are discarded before the mesh is refined.\n\n");
2656 printf(
2657" Maximum area constraints in .poly files operate differently from those in\n"
2658);
2659 printf(
2660" .area files. A maximum area in a .poly file applies to the whole\n");
2661 printf(
2662" (segment-bounded) region in which a point falls, whereas a maximum area\n");
2663 printf(
2664" in an .area file applies to only one triangle. Area constraints in .poly\n"
2665);
2666 printf(
2667" files are used only when a mesh is first generated, whereas area\n");
2668 printf(
2669" constraints in .area files are used only to refine an existing mesh, and\n"
2670);
2671 printf(
2672" are typically based on a posteriori error estimates resulting from a\n");
2673 printf(" finite element simulation on that mesh.\n\n");
2674 printf(
2675" `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
2676 printf(
2677" refines the triangulation to enforce a 25 degree minimum angle, and then\n"
2678);
2679 printf(
2680" writes the refined triangulation to object.2.node and object.2.ele.\n");
2681 printf("\n");
2682 printf(
2683" `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
2684);
2685 printf(
2686" After reconstructing the mesh and its subsegments, Triangle refines the\n");
2687 printf(
2688" mesh so that no triangle has area greater than 6.2, and furthermore the\n");
2689 printf(
2690" triangles satisfy the maximum area constraints in z.3.area. No angle\n");
2691 printf(
2692" bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
2693);
2694 printf(" z.4.poly.\n\n");
2695 printf(
2696" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
2697 printf(
2698" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
2699 printf(" suitable for multigrid.\n\n");
2700 printf("Convex Hulls and Mesh Boundaries:\n\n");
2701 printf(
2702" If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
2703 printf(
2704" hull as a by-product in the output .poly file if you use the -c switch.\n");
2705 printf(
2706" There are faster algorithms for finding a two-dimensional convex hull\n");
2707 printf(" than triangulation, of course, but this one comes for free.\n\n");
2708 printf(
2709" If the input is an unconstrained mesh (you are using the -r switch but\n");
2710 printf(
2711" not the -p switch), Triangle produces a list of its boundary edges\n");
2712 printf(
2713" (including hole boundaries) as a by-product when you use the -c switch.\n");
2714 printf(
2715" If you also use the -p switch, the output .poly file contains all the\n");
2716 printf(" segments from the input .poly file as well.\n\n");
2717 printf("Voronoi Diagrams:\n\n");
2718 printf(
2719" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
2720 printf(
2721" .v.edge. For example, `triangle -v points' reads points.node, produces\n");
2722 printf(
2723" its Delaunay triangulation in points.1.node and points.1.ele, and\n");
2724 printf(
2725" produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
2726);
2727 printf(
2728" .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
2729 printf(
2730" file contains a list of all Voronoi edges, some of which may be infinite\n"
2731);
2732 printf(
2733" rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
2734 printf(" vertices through Triangle, if so desired.)\n\n");
2735 printf(
2736" This implementation does not use exact arithmetic to compute the Voronoi\n"
2737);
2738 printf(
2739" vertices, and does not check whether neighboring vertices are identical.\n"
2740);
2741 printf(
2742" Be forewarned that if the Delaunay triangulation is degenerate or\n");
2743 printf(
2744" near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
2745 printf(" crossing edges.\n\n");
2746 printf(
2747" The result is a valid Voronoi diagram only if Triangle's output is a true\n"
2748);
2749 printf(
2750" Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
2751 printf(
2752" may contain crossing edges and other pathology) if the output is a CDT or\n"
2753);
2754 printf(
2755" CCDT, or if it has holes or concavities. If the triangulated domain is\n");
2756 printf(
2757" convex and has no holes, you can use -D switch to force Triangle to\n");
2758 printf(
2759" construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
2760 printf(" Voronoi diagram will be valid.\n\n");
2761 printf("Mesh Topology:\n\n");
2762 printf(
2763" You may wish to know which triangles are adjacent to a certain Delaunay\n");
2764 printf(
2765" edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
2766 printf(
2767" Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
2768 printf(
2769" each other. All of this information can be found by cross-referencing\n");
2770 printf(
2771" output files with the recollection that the Delaunay triangulation and\n");
2772 printf(" the Voronoi diagram are planar duals.\n\n");
2773 printf(
2774" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
2775 printf(
2776" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
2777 printf(
2778" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
2779 printf(
2780" vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
2781 printf(" of vertex k of the corresponding .node file.\n\n");
2782 printf(
2783" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
2784 printf(
2785" vertices of the corresponding Voronoi edge. If the endpoints of a\n");
2786 printf(
2787" Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
2788);
2789 printf(
2790" and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
2791);
2792 printf(
2793" respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
2794);
2795 printf(
2796" at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
2797);
2798 printf(
2799" a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
2800);
2801 printf(
2802" adjoin the right and left sides of the corresponding Voronoi edge,\n");
2803 printf(
2804" respectively. To find which Voronoi cells are adjacent to each other,\n");
2805 printf(" just read the list of Delaunay edges.\n\n");
2806 printf(
2807" Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
2808);
2809 printf(
2810" but you can reconstructed it straightforwardly. For instance, to find\n");
2811 printf(
2812" all the edges of Voronoi cell 1, search the output .edge file for every\n");
2813 printf(
2814" edge that has input vertex 1 as an endpoint. The corresponding dual\n");
2815 printf(
2816" edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
2817 printf("\n");
2818 printf(
2819" For each Voronoi vertex, the .neigh file gives a list of the three\n");
2820 printf(
2821" Voronoi vertices attached to it. You might find this more convenient\n");
2822 printf(" than the .v.edge file.\n\n");
2823 printf("Quadratic Elements:\n\n");
2824 printf(
2825" Triangle generates meshes with subparametric quadratic elements if the\n");
2826 printf(
2827" -o2 switch is specified. Quadratic elements have six nodes per element,\n"
2828);
2829 printf(
2830" rather than three. `Subparametric' means that the edges of the triangles\n"
2831);
2832 printf(
2833" are always straight, so that subparametric quadratic elements are\n");
2834 printf(
2835" geometrically identical to linear elements, even though they can be used\n"
2836);
2837 printf(
2838" with quadratic interpolating functions. The three extra nodes of an\n");
2839 printf(
2840" element fall at the midpoints of the three edges, with the fourth, fifth,\n"
2841);
2842 printf(
2843" and sixth nodes appearing opposite the first, second, and third corners\n");
2844 printf(" respectively.\n\n");
2845 printf("Domains with Small Angles:\n\n");
2846 printf(
2847" If two input segments adjoin each other at a small angle, clearly the -q\n"
2848);
2849 printf(
2850" switch cannot remove the small angle. Moreover, Triangle may have no\n");
2851 printf(
2852" choice but to generate additional triangles whose smallest angles are\n");
2853 printf(
2854" smaller than the specified bound. However, these triangles only appear\n");
2855 printf(
2856" between input segments separated by small angles. Moreover, if you\n");
2857 printf(
2858" request a minimum angle of theta degrees, Triangle will generally produce\n"
2859);
2860 printf(
2861" no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
2862);
2863 printf(" the minimum angle.\n\n");
2864 printf("Statistics:\n\n");
2865 printf(
2866" After generating a mesh, Triangle prints a count of entities in the\n");
2867 printf(
2868" output mesh, including the number of vertices, triangles, edges, exterior\n"
2869);
2870 printf(
2871" boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
2872 printf(
2873" including hole boundaries), interior boundary edges (i.e. subsegments of\n"
2874);
2875 printf(
2876" input segments not on the boundary), and total subsegments. If you've\n");
2877 printf(
2878" forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
2879);
2880 printf(
2881" with the -rNEP switches to read the mesh and print the statistics without\n"
2882);
2883 printf(
2884" writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
2885 printf("\n");
2886 printf(
2887" The -V switch produces extended statistics, including a rough estimate\n");
2888 printf(
2889" of memory use, the number of calls to geometric predicates, and\n");
2890 printf(
2891" histograms of the angles and the aspect ratios of the triangles in the\n");
2892 printf(" mesh.\n\n");
2893 printf("Exact Arithmetic:\n\n");
2894 printf(
2895" Triangle uses adaptive exact arithmetic to perform what computational\n");
2896 printf(
2897" geometers call the `orientation' and `incircle' tests. If the floating-\n"
2898);
2899 printf(
2900" point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
2901 printf(
2902" most workstations do), and does not use extended precision internal\n");
2903 printf(
2904" floating-point registers, then your output is guaranteed to be an\n");
2905 printf(
2906" absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
2907);
2908 printf(
2909" error notwithstanding. The word `adaptive' implies that these arithmetic\n"
2910);
2911 printf(
2912" routines compute the result only to the precision necessary to guarantee\n"
2913);
2914 printf(
2915" correctness, so they are usually nearly as fast as their approximate\n");
2916 printf(" counterparts.\n\n");
2917 printf(
2918" May CPUs, including Intel x86 processors, have extended precision\n");
2919 printf(
2920" floating-point registers. These must be reconfigured so their precision\n"
2921);
2922 printf(
2923" is reduced to memory precision. Triangle does this if it is compiled\n");
2924 printf(" correctly. See the makefile for details.\n\n");
2925 printf(
2926" The exact tests can be disabled with the -X switch. On most inputs, this\n"
2927);
2928 printf(
2929" switch reduces the computation time by about eight percent--it's not\n");
2930 printf(
2931" worth the risk. There are rare difficult inputs (having many collinear\n");
2932 printf(
2933" and cocircular vertices), however, for which the difference in speed\n");
2934 printf(
2935" could be a factor of two. Be forewarned that these are precisely the\n");
2936 printf(
2937" inputs most likely to cause errors if you use the -X switch. Hence, the\n"
2938);
2939 printf(" -X switch is not recommended.\n\n");
2940 printf(
2941" Unfortunately, the exact tests don't solve every numerical problem.\n");
2942 printf(
2943" Exact arithmetic is not used to compute the positions of new vertices,\n");
2944 printf(
2945" because the bit complexity of vertex coordinates would grow without\n");
2946 printf(
2947" bound. Hence, segment intersections aren't computed exactly; in very\n");
2948 printf(
2949" unusual cases, roundoff error in computing an intersection point might\n");
2950 printf(
2951" actually lead to an inverted triangle and an invalid triangulation.\n");
2952 printf(
2953" (This is one reason to specify your own intersection points in your .poly\n"
2954);
2955 printf(
2956" files.) Similarly, exact arithmetic is not used to compute the vertices\n"
2957);
2958 printf(" of the Voronoi diagram.\n\n");
2959 printf(
2960" Another pair of problems not solved by the exact arithmetic routines is\n");
2961 printf(
2962" underflow and overflow. If Triangle is compiled for double precision\n");
2963 printf(
2964" arithmetic, I believe that Triangle's geometric predicates work correctly\n"
2965);
2966 printf(
2967" if the exponent of every input coordinate falls in the range [-148, 201].\n"
2968);
2969 printf(
2970" Underflow can silently prevent the orientation and incircle tests from\n");
2971 printf(
2972" being performed exactly, while overflow typically causes a floating\n");
2973 printf(" exception.\n\n");
2974 printf("Calling Triangle from Another Program:\n\n");
2975 printf(" Read the file triangle.h for details.\n\n");
2976 printf("Troubleshooting:\n\n");
2977 printf(" Please read this section before mailing me bugs.\n\n");
2978 printf(" `My output mesh has no triangles!'\n\n");
2979 printf(
2980" If you're using a PSLG, you've probably failed to specify a proper set\n"
2981);
2982 printf(
2983" of bounding segments, or forgotten to use the -c switch. Or you may\n");
2984 printf(
2985" have placed a hole badly, thereby eating all your triangles. To test\n");
2986 printf(" these possibilities, try again with the -c and -O switches.\n");
2987 printf(
2988" Alternatively, all your input vertices may be collinear, in which case\n"
2989);
2990 printf(" you can hardly expect to triangulate them.\n\n");
2991 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
2992 printf(
2993" Bad things can happen when triangles get so small that the distance\n");
2994 printf(
2995" between their vertices isn't much larger than the precision of your\n");
2996 printf(
2997" machine's arithmetic. If you've compiled Triangle for single-precision\n"
2998);
2999 printf(
3000" arithmetic, you might do better by recompiling it for double-precision.\n"
3001);
3002 printf(
3003" Then again, you might just have to settle for more lenient constraints\n"
3004);
3005 printf(
3006" on the minimum angle and the maximum area than you had planned.\n");
3007 printf("\n");
3008 printf(
3009" You can minimize precision problems by ensuring that the origin lies\n");
3010 printf(
3011" inside your vertex set, or even inside the densest part of your\n");
3012 printf(
3013" mesh. If you're triangulating an object whose x-coordinates all fall\n");
3014 printf(
3015" between 6247133 and 6247134, you're not leaving much floating-point\n");
3016 printf(" precision for Triangle to work with.\n\n");
3017 printf(
3018" Precision problems can occur covertly if the input PSLG contains two\n");
3019 printf(
3020" segments that meet (or intersect) at an extremely small angle, or if\n");
3021 printf(
3022" such an angle is introduced by the -c switch. If you don't realize\n");
3023 printf(
3024" that a tiny angle is being formed, you might never discover why\n");
3025 printf(
3026" Triangle is crashing. To check for this possibility, use the -S switch\n"
3027);
3028 printf(
3029" (with an appropriate limit on the number of Steiner points, found by\n");
3030 printf(
3031" trial-and-error) to stop Triangle early, and view the output .poly file\n"
3032);
3033 printf(
3034" with Show Me (described below). Look carefully for regions where dense\n"
3035);
3036 printf(
3037" clusters of vertices are forming and for small angles between segments.\n"
3038);
3039 printf(
3040" Zoom in closely, as such segments might look like a single segment from\n"
3041);
3042 printf(" a distance.\n\n");
3043 printf(
3044" If some of the input values are too large, Triangle may suffer a\n");
3045 printf(
3046" floating exception due to overflow when attempting to perform an\n");
3047 printf(
3048" orientation or incircle test. (Read the section on exact arithmetic\n");
3049 printf(
3050" above.) Again, I recommend compiling Triangle for double (rather\n");
3051 printf(" than single) precision arithmetic.\n\n");
3052 printf(
3053" Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
3054 printf(
3055" -u) with an input that is not segment-bounded--that is, if your input\n");
3056 printf(
3057" is a vertex set, or you're using the -c switch. If the convex hull of\n"
3058);
3059 printf(
3060" your input vertices has collinear vertices on its boundary, an input\n");
3061 printf(
3062" vertex that you think lies on the convex hull might actually lie just\n");
3063 printf(
3064" inside the convex hull. If so, the vertex and the nearby convex hull\n");
3065 printf(
3066" edge form an extremely thin triangle. When Triangle tries to refine\n");
3067 printf(
3068" the mesh to enforce angle and area constraints, Triangle might generate\n"
3069);
3070 printf(
3071" extremely tiny triangles, or it might fail because of insufficient\n");
3072 printf(" floating-point precision.\n\n");
3073 printf(
3074" `The numbering of the output vertices doesn't match the input vertices.'\n"
3075);
3076 printf("\n");
3077 printf(
3078" You may have had duplicate input vertices, or you may have eaten some\n");
3079 printf(
3080" of your input vertices with a hole, or by placing them outside the area\n"
3081);
3082 printf(
3083" enclosed by segments. In any case, you can solve the problem by not\n");
3084 printf(" using the -j switch.\n\n");
3085 printf(
3086" `Triangle executes without incident, but when I look at the resulting\n");
3087 printf(
3088" mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
3089 printf("\n");
3090 printf(
3091" If you select the -X switch, Triangle occasionally makes mistakes due\n");
3092 printf(
3093" to floating-point roundoff error. Although these errors are rare,\n");
3094 printf(
3095" don't use the -X switch. If you still have problems, please report the\n"
3096);
3097 printf(" bug.\n\n");
3098 printf(
3099" `Triangle executes without incident, but when I look at the resulting\n");
3100 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
3101 printf(" inconsistencies.'\n");
3102 printf("\n");
3103 printf(
3104" If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
3105);
3106 printf(
3107" diagram if the domain you are triangulating is convex and free of\n");
3108 printf(
3109" holes, and you use the -D switch to construct a conforming Delaunay\n");
3110 printf(" triangulation (instead of a CDT or CCDT).\n\n");
3111 printf(
3112" Strange things can happen if you've taken liberties with your PSLG. Do\n");
3113 printf(
3114" you have a vertex lying in the middle of a segment? Triangle sometimes\n");
3115 printf(
3116" copes poorly with that sort of thing. Do you want to lay out a collinear\n"
3117);
3118 printf(
3119" row of evenly spaced, segment-connected vertices? Have you simply\n");
3120 printf(
3121" defined one long segment connecting the leftmost vertex to the rightmost\n"
3122);
3123 printf(
3124" vertex, and a bunch of vertices lying along it? This method occasionally\n"
3125);
3126 printf(
3127" works, especially with horizontal and vertical lines, but often it\n");
3128 printf(
3129" doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
3130);
3131 printf(" separate segment. If you don't like it, tough.\n\n");
3132 printf(
3133" Furthermore, if you have segments that intersect other than at their\n");
3134 printf(
3135" endpoints, try not to let the intersections fall extremely close to PSLG\n"
3136);
3137 printf(" vertices or each other.\n\n");
3138 printf(
3139" If you have problems refining a triangulation not produced by Triangle:\n");
3140 printf(
3141" Are you sure the triangulation is geometrically valid? Is it formatted\n");
3142 printf(
3143" correctly for Triangle? Are the triangles all listed so the first three\n"
3144);
3145 printf(
3146" vertices are their corners in counterclockwise order? Are all of the\n");
3147 printf(
3148" triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
3149);
3150 printf(" assumes that it starts with a CDT.\n\n");
3151 printf("Show Me:\n\n");
3152 printf(
3153" Triangle comes with a separate program named `Show Me', whose primary\n");
3154 printf(
3155" purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
3156);
3157 printf(
3158" purpose is to check the validity of your input files, and do so more\n");
3159 printf(
3160" thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
3161 printf(
3162" you have the X Windows system. Sorry, Microsoft Windows users.\n");
3163 printf("\n");
3164 printf("Triangle on the Web:\n");
3165 printf("\n");
3166 printf(" To see an illustrated version of these instructions, check out\n");
3167 printf("\n");
3168 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
3169 printf("\n");
3170 printf("A Brief Plea:\n");
3171 printf("\n");
3172 printf(
3173" If you use Triangle, and especially if you use it to accomplish real\n");
3174 printf(
3175" work, I would like very much to hear from you. A short letter or email\n");
3176 printf(
3177" (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
3178);
3179 printf(
3180" to me. The more people I know are using this program, the more easily I\n"
3181);
3182 printf(
3183" can justify spending time on improvements, which in turn will benefit\n");
3184 printf(
3185" you. Also, I can put you on a list to receive email whenever a new\n");
3186 printf(" version of Triangle is available.\n\n");
3187 printf(
3188" If you use a mesh generated by Triangle in a publication, please include\n"
3189);
3190 printf(
3191" an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
3192);
3193 printf(
3194" If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
3195 printf(
3196" ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
3197 printf(
3198" Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
3199 printf(
3200" Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
3201 printf(
3202" Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
3203 printf(
3204" Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
3205);
3206 printf(" Geometry.)'\n\n");
3207 printf("Research credit:\n\n");
3208 printf(
3209" Of course, I can take credit for only a fraction of the ideas that made\n");
3210 printf(
3211" this mesh generator possible. Triangle owes its existence to the efforts\n"
3212);
3213 printf(
3214" of many fine computational geometers and other researchers, including\n");
3215 printf(
3216" Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
3217);
3218 printf(
3219" Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
3220 printf(
3221" Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
3222 printf(
3223" Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
3224 printf(
3225" Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
3226);
3227 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
3228 printf(
3229" Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
3230 printf(" source code for references.\n\n");
3231 triexit(0);
3232}
3233
3234#endif /* not TRILIBRARY */
3235
3236/*****************************************************************************/
3237/* */
3238/* internalerror() Ask the user to send me the defective product. Exit. */
3239/* */
3240/*****************************************************************************/
3241
3243{
3244 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
3245 printf(" Include the message above, your input data set, and the exact\n");
3246 printf(" command line you used to run Triangle.\n");
3247 triexit(1);
3248}
3249
3250/*****************************************************************************/
3251/* */
3252/* parsecommandline() Read the command line, identify switches, and set */
3253/* up options and file names. */
3254/* */
3255/*****************************************************************************/
3256
3257#ifdef ANSI_DECLARATORS
3258void parsecommandline(int argc, char **argv, struct behavior *b)
3259#else /* not ANSI_DECLARATORS */
3260void parsecommandline(argc, argv, b)
3261int argc;
3262char **argv;
3263struct behavior *b;
3264#endif /* not ANSI_DECLARATORS */
3265
3266{
3267#ifdef TRILIBRARY
3268#define STARTINDEX 0
3269#else /* not TRILIBRARY */
3270#define STARTINDEX 1
3271 int increment;
3272 int meshnumber;
3273#endif /* not TRILIBRARY */
3274 /* int i, j, k; */
3275 int i, j;
3276 /* char workstring[FILENAMESIZE]; */
3277
3278 b->poly = b->refine = b->quality = 0;
3279 b->vararea = b->fixedarea = b->usertest = 0;
3280 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
3281 b->firstnumber = 1;
3282 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
3283 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
3284 b->noiterationnum = 0;
3285 b->noholes = b->noexact = 0;
3286 b->incremental = b->sweepline = 0;
3287 b->dwyer = 1;
3288 b->splitseg = 0;
3289 b->docheck = 0;
3290 b->nobisect = 0;
3291 b->conformdel = 0;
3292 b->steiner = -1;
3293 b->order = 1;
3294 b->minangle = 0.0;
3295 b->maxarea = -1.0;
3296 b->quiet = b->verbose = 0;
3297#ifndef TRILIBRARY
3298 b->innodefilename[0] = '\0';
3299#endif /* not TRILIBRARY */
3300
3301 for (i = STARTINDEX; i < argc; i++) {
3302#ifndef TRILIBRARY
3303 if (argv[i][0] == '-') {
3304#endif /* not TRILIBRARY */
3305 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
3306 if (argv[i][j] == 'p') {
3307 b->poly = 1;
3308 }
3309#ifndef CDT_ONLY
3310 if (argv[i][j] == 'r') {
3311 b->refine = 1;
3312 }
3313 if (argv[i][j] == 'q') {
3314 b->quality = 1;
3315 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3316 (argv[i][j + 1] == '.')) {
3317 k = 0;
3318 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3319 (argv[i][j + 1] == '.')) {
3320 j++;
3321 workstring[k] = argv[i][j];
3322 k++;
3323 }
3324 workstring[k] = '\0';
3325 b->minangle = (REAL) strtod(workstring, (char **) NULL);
3326 } else {
3327 b->minangle = 20.0;
3328 }
3329 }
3330 if (argv[i][j] == 'a') {
3331 b->quality = 1;
3332 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3333 (argv[i][j + 1] == '.')) {
3334 b->fixedarea = 1;
3335 k = 0;
3336 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3337 (argv[i][j + 1] == '.')) {
3338 j++;
3339 workstring[k] = argv[i][j];
3340 k++;
3341 }
3342 workstring[k] = '\0';
3343 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
3344 if (b->maxarea <= 0.0) {
3345 printf("Error: Maximum area must be greater than zero.\n");
3346 triexit(1);
3347 }
3348 } else {
3349 b->vararea = 1;
3350 }
3351 }
3352 if (argv[i][j] == 'u') {
3353 b->quality = 1;
3354 b->usertest = 1;
3355 }
3356#endif /* not CDT_ONLY */
3357 if (argv[i][j] == 'A') {
3358 b->regionattrib = 1;
3359 }
3360 if (argv[i][j] == 'c') {
3361 b->convex = 1;
3362 }
3363 if (argv[i][j] == 'w') {
3364 b->weighted = 1;
3365 }
3366 if (argv[i][j] == 'W') {
3367 b->weighted = 2;
3368 }
3369 if (argv[i][j] == 'j') {
3370 b->jettison = 1;
3371 }
3372 if (argv[i][j] == 'z') {
3373 b->firstnumber = 0;
3374 }
3375 if (argv[i][j] == 'e') {
3376 b->edgesout = 1;
3377 }
3378 if (argv[i][j] == 'v') {
3379 b->voronoi = 1;
3380 }
3381 if (argv[i][j] == 'n') {
3382 b->neighbors = 1;
3383 }
3384 if (argv[i][j] == 'g') {
3385 b->geomview = 1;
3386 }
3387 if (argv[i][j] == 'B') {
3388 b->nobound = 1;
3389 }
3390 if (argv[i][j] == 'P') {
3391 b->nopolywritten = 1;
3392 }
3393 if (argv[i][j] == 'N') {
3394 b->nonodewritten = 1;
3395 }
3396 if (argv[i][j] == 'E') {
3397 b->noelewritten = 1;
3398 }
3399#ifndef TRILIBRARY
3400 if (argv[i][j] == 'I') {
3401 b->noiterationnum = 1;
3402 }
3403#endif /* not TRILIBRARY */
3404 if (argv[i][j] == 'O') {
3405 b->noholes = 1;
3406 }
3407 if (argv[i][j] == 'X') {
3408 b->noexact = 1;
3409 }
3410 if (argv[i][j] == 'o') {
3411 if (argv[i][j + 1] == '2') {
3412 j++;
3413 b->order = 2;
3414 }
3415 }
3416#ifndef CDT_ONLY
3417 if (argv[i][j] == 'Y') {
3418 b->nobisect++;
3419 }
3420 if (argv[i][j] == 'S') {
3421 b->steiner = 0;
3422 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
3423 j++;
3424 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
3425 }
3426 }
3427#endif /* not CDT_ONLY */
3428#ifndef REDUCED
3429 if (argv[i][j] == 'i') {
3430 b->incremental = 1;
3431 }
3432 if (argv[i][j] == 'F') {
3433 b->sweepline = 1;
3434 }
3435#endif /* not REDUCED */
3436 if (argv[i][j] == 'l') {
3437 b->dwyer = 0;
3438 }
3439#ifndef REDUCED
3440#ifndef CDT_ONLY
3441 if (argv[i][j] == 's') {
3442 b->splitseg = 1;
3443 }
3444 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
3445 b->quality = 1;
3446 b->conformdel = 1;
3447 }
3448#endif /* not CDT_ONLY */
3449 if (argv[i][j] == 'C') {
3450 b->docheck = 1;
3451 }
3452#endif /* not REDUCED */
3453 if (argv[i][j] == 'Q') {
3454 b->quiet = 1;
3455 }
3456 if (argv[i][j] == 'V') {
3457 b->verbose++;
3458 }
3459#ifndef TRILIBRARY
3460 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
3461 (argv[i][j] == '?')) {
3462 info();
3463 }
3464#endif /* not TRILIBRARY */
3465 }
3466#ifndef TRILIBRARY
3467 } else {
3468 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
3469 b->innodefilename[FILENAMESIZE - 1] = '\0';
3470 }
3471#endif /* not TRILIBRARY */
3472 }
3473#ifndef TRILIBRARY
3474 if (b->innodefilename[0] == '\0') {
3475 syntax();
3476 }
3477 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
3478 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3479 }
3480 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
3481 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3482 b->poly = 1;
3483 }
3484#ifndef CDT_ONLY
3485 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
3486 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
3487 b->refine = 1;
3488 }
3489 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
3490 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3491 b->refine = 1;
3492 b->quality = 1;
3493 b->vararea = 1;
3494 }
3495#endif /* not CDT_ONLY */
3496#endif /* not TRILIBRARY */
3497 b->usesegments = b->poly || b->refine || b->quality || b->convex;
3498 b->goodangle = cos(b->minangle * PI / 180.0);
3499 if (b->goodangle == 1.0) {
3500 b->offconstant = 0.0;
3501 } else {
3502 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
3503 }
3504 b->goodangle *= b->goodangle;
3505 if (b->refine && b->noiterationnum) {
3506 printf(
3507 "Error: You cannot use the -I switch when refining a triangulation.\n");
3508 triexit(1);
3509 }
3510 /* Be careful not to allocate space for element area constraints that */
3511 /* will never be assigned any value (other than the default -1.0). */
3512 if (!b->refine && !b->poly) {
3513 b->vararea = 0;
3514 }
3515 /* Be careful not to add an extra attribute to each element unless the */
3516 /* input supports it (PSLG in, but not refining a preexisting mesh). */
3517 if (b->refine || !b->poly) {
3518 b->regionattrib = 0;
3519 }
3520 /* Regular/weighted triangulations are incompatible with PSLGs */
3521 /* and meshing. */
3522 if (b->weighted && (b->poly || b->quality)) {
3523 b->weighted = 0;
3524 if (!b->quiet) {
3525 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
3526 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
3527 );
3528 }
3529 }
3530 if (b->jettison && b->nonodewritten && !b->quiet) {
3531 printf("Warning: -j and -N switches are somewhat incompatible.\n");
3532 printf(" If any vertices are jettisoned, you will need the output\n");
3533 printf(" .node file to reconstruct the new node indices.");
3534 }
3535
3536#ifndef TRILIBRARY
3537 strcpy(b->inpolyfilename, b->innodefilename);
3538 strcpy(b->inelefilename, b->innodefilename);
3539 strcpy(b->areafilename, b->innodefilename);
3540 increment = 0;
3541 strcpy(workstring, b->innodefilename);
3542 j = 1;
3543 while (workstring[j] != '\0') {
3544 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
3545 increment = j + 1;
3546 }
3547 j++;
3548 }
3549 meshnumber = 0;
3550 if (increment > 0) {
3551 j = increment;
3552 do {
3553 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
3554 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
3555 } else {
3556 increment = 0;
3557 }
3558 j++;
3559 } while (workstring[j] != '\0');
3560 }
3561 if (b->noiterationnum) {
3562 strcpy(b->outnodefilename, b->innodefilename);
3563 strcpy(b->outelefilename, b->innodefilename);
3564 strcpy(b->edgefilename, b->innodefilename);
3565 strcpy(b->vnodefilename, b->innodefilename);
3566 strcpy(b->vedgefilename, b->innodefilename);
3567 strcpy(b->neighborfilename, b->innodefilename);
3568 strcpy(b->offfilename, b->innodefilename);
3569 strcat(b->outnodefilename, ".node");
3570 strcat(b->outelefilename, ".ele");
3571 strcat(b->edgefilename, ".edge");
3572 strcat(b->vnodefilename, ".v.node");
3573 strcat(b->vedgefilename, ".v.edge");
3574 strcat(b->neighborfilename, ".neigh");
3575 strcat(b->offfilename, ".off");
3576 } else if (increment == 0) {
3577 strcpy(b->outnodefilename, b->innodefilename);
3578 strcpy(b->outpolyfilename, b->innodefilename);
3579 strcpy(b->outelefilename, b->innodefilename);
3580 strcpy(b->edgefilename, b->innodefilename);
3581 strcpy(b->vnodefilename, b->innodefilename);
3582 strcpy(b->vedgefilename, b->innodefilename);
3583 strcpy(b->neighborfilename, b->innodefilename);
3584 strcpy(b->offfilename, b->innodefilename);
3585 strcat(b->outnodefilename, ".1.node");
3586 strcat(b->outpolyfilename, ".1.poly");
3587 strcat(b->outelefilename, ".1.ele");
3588 strcat(b->edgefilename, ".1.edge");
3589 strcat(b->vnodefilename, ".1.v.node");
3590 strcat(b->vedgefilename, ".1.v.edge");
3591 strcat(b->neighborfilename, ".1.neigh");
3592 strcat(b->offfilename, ".1.off");
3593 } else {
3594 workstring[increment] = '%';
3595 workstring[increment + 1] = 'd';
3596 workstring[increment + 2] = '\0';
3597 sprintf(b->outnodefilename, workstring, meshnumber + 1);
3598 strcpy(b->outpolyfilename, b->outnodefilename);
3599 strcpy(b->outelefilename, b->outnodefilename);
3600 strcpy(b->edgefilename, b->outnodefilename);
3601 strcpy(b->vnodefilename, b->outnodefilename);
3602 strcpy(b->vedgefilename, b->outnodefilename);
3603 strcpy(b->neighborfilename, b->outnodefilename);
3604 strcpy(b->offfilename, b->outnodefilename);
3605 strcat(b->outnodefilename, ".node");
3606 strcat(b->outpolyfilename, ".poly");
3607 strcat(b->outelefilename, ".ele");
3608 strcat(b->edgefilename, ".edge");
3609 strcat(b->vnodefilename, ".v.node");
3610 strcat(b->vedgefilename, ".v.edge");
3611 strcat(b->neighborfilename, ".neigh");
3612 strcat(b->offfilename, ".off");
3613 }
3614 strcat(b->innodefilename, ".node");
3615 strcat(b->inpolyfilename, ".poly");
3616 strcat(b->inelefilename, ".ele");
3617 strcat(b->areafilename, ".area");
3618#endif /* not TRILIBRARY */
3619}
3620
3621/** **/
3622/** **/
3623/********* User interaction routines begin here *********/
3624
3625/********* Debugging routines begin here *********/
3626/** **/
3627/** **/
3628
3629/*****************************************************************************/
3630/* */
3631/* printtriangle() Print out the details of an oriented triangle. */
3632/* */
3633/* I originally wrote this procedure to simplify debugging; it can be */
3634/* called directly from the debugger, and presents information about an */
3635/* oriented triangle in digestible form. It's also used when the */
3636/* highest level of verbosity (`-VVV') is specified. */
3637/* */
3638/*****************************************************************************/
3639
3640#ifdef ANSI_DECLARATORS
3641void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
3642#else /* not ANSI_DECLARATORS */
3643void printtriangle(m, b, t)
3644struct mesh *m;
3645struct behavior *b;
3646struct otri *t;
3647#endif /* not ANSI_DECLARATORS */
3648
3649{
3650 struct otri printtri;
3651 struct osub printsh;
3652 vertex printvertex;
3653
3654 printf("triangle x%zx with orientation %d:\n", (size_t) t->tri,
3655 t->orient);
3656 decode(t->tri[0], printtri);
3657 if (printtri.tri == m->dummytri) {
3658 printf(" [0] = Outer space\n");
3659 } else {
3660 printf(" [0] = x%zx %d\n", (size_t) printtri.tri,
3661 printtri.orient);
3662 }
3663 decode(t->tri[1], printtri);
3664 if (printtri.tri == m->dummytri) {
3665 printf(" [1] = Outer space\n");
3666 } else {
3667 printf(" [1] = x%zx %d\n", (size_t) printtri.tri,
3668 printtri.orient);
3669 }
3670 decode(t->tri[2], printtri);
3671 if (printtri.tri == m->dummytri) {
3672 printf(" [2] = Outer space\n");
3673 } else {
3674 printf(" [2] = x%zx %d\n", (size_t) printtri.tri,
3675 printtri.orient);
3676 }
3677
3678 org(*t, printvertex);
3679 if (printvertex == (vertex) NULL)
3680 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
3681 else
3682 printf(" Origin[%d] = x%zx (%.12g, %.12g)\n",
3683 (t->orient + 1) % 3 + 3, (size_t) printvertex,
3684 printvertex[0], printvertex[1]);
3685 dest(*t, printvertex);
3686 if (printvertex == (vertex) NULL)
3687 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
3688 else
3689 printf(" Dest [%d] = x%zx (%.12g, %.12g)\n",
3690 (t->orient + 2) % 3 + 3, (size_t) printvertex,
3691 printvertex[0], printvertex[1]);
3692 apex(*t, printvertex);
3693 if (printvertex == (vertex) NULL)
3694 printf(" Apex [%d] = NULL\n", t->orient + 3);
3695 else
3696 printf(" Apex [%d] = x%zx (%.12g, %.12g)\n",
3697 t->orient + 3, (size_t) printvertex,
3698 printvertex[0], printvertex[1]);
3699
3700 if (b->usesegments) {
3701 sdecode(t->tri[6], printsh);
3702 if (printsh.ss != m->dummysub) {
3703 printf(" [6] = x%zx %d\n", (size_t) printsh.ss,
3704 printsh.ssorient);
3705 }
3706 sdecode(t->tri[7], printsh);
3707 if (printsh.ss != m->dummysub) {
3708 printf(" [7] = x%zx %d\n", (size_t) printsh.ss,
3709 printsh.ssorient);
3710 }
3711 sdecode(t->tri[8], printsh);
3712 if (printsh.ss != m->dummysub) {
3713 printf(" [8] = x%zx %d\n", (size_t) printsh.ss,
3714 printsh.ssorient);
3715 }
3716 }
3717
3718 if (b->vararea) {
3719 printf(" Area constraint: %.4g\n", areabound(*t));
3720 }
3721}
3722
3723/*****************************************************************************/
3724/* */
3725/* printsubseg() Print out the details of an oriented subsegment. */
3726/* */
3727/* I originally wrote this procedure to simplify debugging; it can be */
3728/* called directly from the debugger, and presents information about an */
3729/* oriented subsegment in digestible form. It's also used when the highest */
3730/* level of verbosity (`-VVV') is specified. */
3731/* */
3732/*****************************************************************************/
3733
3734#ifdef ANSI_DECLARATORS
3735void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
3736#else /* not ANSI_DECLARATORS */
3737void printsubseg(m, b, s)
3738struct mesh *m;
3739struct behavior *b;
3740struct osub *s;
3741#endif /* not ANSI_DECLARATORS */
3742
3743{
3744 struct osub printsh;
3745 struct otri printtri;
3746 vertex printvertex;
3747
3748 (void)b; /*LM: added to suppress warning */
3749
3750 printf("subsegment x%zx with orientation %d and mark %d:\n",
3751 (size_t) s->ss, s->ssorient, mark(*s));
3752 sdecode(s->ss[0], printsh);
3753 if (printsh.ss == m->dummysub) {
3754 printf(" [0] = No subsegment\n");
3755 } else {
3756 printf(" [0] = x%zx %d\n", (size_t) printsh.ss,
3757 printsh.ssorient);
3758 }
3759 sdecode(s->ss[1], printsh);
3760 if (printsh.ss == m->dummysub) {
3761 printf(" [1] = No subsegment\n");
3762 } else {
3763 printf(" [1] = x%zx %d\n", (size_t) printsh.ss,
3764 printsh.ssorient);
3765 }
3766
3767 sorg(*s, printvertex);
3768 if (printvertex == (vertex) NULL)
3769 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
3770 else
3771 printf(" Origin[%d] = x%zx (%.12g, %.12g)\n",
3772 2 + s->ssorient, (size_t) printvertex,
3773 printvertex[0], printvertex[1]);
3774 sdest(*s, printvertex);
3775 if (printvertex == (vertex) NULL)
3776 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
3777 else
3778 printf(" Dest [%d] = x%zx (%.12g, %.12g)\n",
3779 3 - s->ssorient, (size_t) printvertex,
3780 printvertex[0], printvertex[1]);
3781
3782 decode(s->ss[6], printtri);
3783 if (printtri.tri == m->dummytri) {
3784 printf(" [6] = Outer space\n");
3785 } else {
3786 printf(" [6] = x%zx %d\n", (size_t) printtri.tri,
3787 printtri.orient);
3788 }
3789 decode(s->ss[7], printtri);
3790 if (printtri.tri == m->dummytri) {
3791 printf(" [7] = Outer space\n");
3792 } else {
3793 printf(" [7] = x%zx %d\n", (size_t) printtri.tri,
3794 printtri.orient);
3795 }
3796
3797 segorg(*s, printvertex);
3798 if (printvertex == (vertex) NULL)
3799 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
3800 else
3801 printf(" Segment origin[%d] = x%zx (%.12g, %.12g)\n",
3802 4 + s->ssorient, (size_t) printvertex,
3803 printvertex[0], printvertex[1]);
3804 segdest(*s, printvertex);
3805 if (printvertex == (vertex) NULL)
3806 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
3807 else
3808 printf(" Segment dest [%d] = x%zx (%.12g, %.12g)\n",
3809 5 - s->ssorient, (size_t) printvertex,
3810 printvertex[0], printvertex[1]);
3811}
3812
3813/** **/
3814/** **/
3815/********* Debugging routines end here *********/
3816
3817/********* Memory management routines begin here *********/
3818/** **/
3819/** **/
3820
3821/*****************************************************************************/
3822/* */
3823/* poolzero() Set all of a pool's fields to zero. */
3824/* */
3825/* This procedure should never be called on a pool that has any memory */
3826/* allocated to it, as that memory would leak. */
3827/* */
3828/*****************************************************************************/
3829
3830#ifdef ANSI_DECLARATORS
3831void poolzero(struct memorypool *pool)
3832#else /* not ANSI_DECLARATORS */
3833void poolzero(pool)
3834struct memorypool *pool;
3835#endif /* not ANSI_DECLARATORS */
3836
3837{
3838 pool->firstblock = (VOID **) NULL;
3839 pool->nowblock = (VOID **) NULL;
3840 pool->nextitem = (VOID *) NULL;
3841 pool->deaditemstack = (VOID *) NULL;
3842 pool->pathblock = (VOID **) NULL;
3843 pool->pathitem = (VOID *) NULL;
3844 pool->alignbytes = 0;
3845 pool->itembytes = 0;
3846 pool->itemsperblock = 0;
3847 pool->itemsfirstblock = 0;
3848 pool->items = 0;
3849 pool->maxitems = 0;
3850 pool->unallocateditems = 0;
3851 pool->pathitemsleft = 0;
3852}
3853
3854/*****************************************************************************/
3855/* */
3856/* poolrestart() Deallocate all items in a pool. */
3857/* */
3858/* The pool is returned to its starting state, except that no memory is */
3859/* freed to the operating system. Rather, the previously allocated blocks */
3860/* are ready to be reused. */
3861/* */
3862/*****************************************************************************/
3863
3864#ifdef ANSI_DECLARATORS
3865void poolrestart(struct memorypool *pool)
3866#else /* not ANSI_DECLARATORS */
3867void poolrestart(pool)
3868struct memorypool *pool;
3869#endif /* not ANSI_DECLARATORS */
3870
3871{
3872 uintptr_t alignptr;
3873
3874 pool->items = 0;
3875 pool->maxitems = 0;
3876
3877 /* Set the currently active block. */
3878 pool->nowblock = pool->firstblock;
3879 /* Find the first item in the pool. Increment by the size of (VOID *). */
3880 alignptr = (uintptr_t) (pool->nowblock + 1);
3881 /* Align the item on an `alignbytes'-byte boundary. */
3882 pool->nextitem = (VOID *)
3883 (alignptr + (uintptr_t) pool->alignbytes -
3884 (alignptr % (uintptr_t) pool->alignbytes));
3885 /* There are lots of unallocated items left in this block. */
3886 pool->unallocateditems = pool->itemsfirstblock;
3887 /* The stack of deallocated items is empty. */
3888 pool->deaditemstack = (VOID *) NULL;
3889}
3890
3891/*****************************************************************************/
3892/* */
3893/* poolinit() Initialize a pool of memory for allocation of items. */
3894/* */
3895/* This routine initializes the machinery for allocating items. A `pool' */
3896/* is created whose records have size at least `bytecount'. Items will be */
3897/* allocated in `itemcount'-item blocks. Each item is assumed to be a */
3898/* collection of words, and either pointers or floating-point values are */
3899/* assumed to be the "primary" word type. (The "primary" word type is used */
3900/* to determine alignment of items.) If `alignment' isn't zero, all items */
3901/* will be `alignment'-byte aligned in memory. `alignment' must be either */
3902/* a multiple or a factor of the primary word size; powers of two are safe. */
3903/* `alignment' is normally used to create a few unused bits at the bottom */
3904/* of each item's pointer, in which information may be stored. */
3905/* */
3906/* Don't change this routine unless you understand it. */
3907/* */
3908/*****************************************************************************/
3909
3910#ifdef ANSI_DECLARATORS
3911void poolinit(struct memorypool *pool, int bytecount, int itemcount,
3912 int firstitemcount, int alignment)
3913#else /* not ANSI_DECLARATORS */
3914void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
3915struct memorypool *pool;
3916int bytecount;
3917int itemcount;
3918int firstitemcount;
3919int alignment;
3920#endif /* not ANSI_DECLARATORS */
3921
3922{
3923 /* Find the proper alignment, which must be at least as large as: */
3924 /* - The parameter `alignment'. */
3925 /* - sizeof(VOID *), so the stack of dead items can be maintained */
3926 /* without unaligned accesses. */
3927 if (alignment > (int) sizeof(VOID *)) {
3928 pool->alignbytes = alignment;
3929 } else {
3930 pool->alignbytes = sizeof(VOID *);
3931 }
3932 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
3933 pool->alignbytes;
3934 pool->itemsperblock = itemcount;
3935 if (firstitemcount == 0) {
3936 pool->itemsfirstblock = itemcount;
3937 } else {
3938 pool->itemsfirstblock = firstitemcount;
3939 }
3940
3941 /* Allocate a block of items. Space for `itemsfirstblock' items and one */
3942 /* pointer (to point to the next block) are allocated, as well as space */
3943 /* to ensure alignment of the items. */
3944 pool->firstblock = (VOID **)
3945 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
3946 pool->alignbytes);
3947 /* Set the next block pointer to NULL. */
3948 *(pool->firstblock) = (VOID *) NULL;
3949 poolrestart(pool);
3950}
3951
3952/*****************************************************************************/
3953/* */
3954/* pooldeinit() Free to the operating system all memory taken by a pool. */
3955/* */
3956/*****************************************************************************/
3957
3958#ifdef ANSI_DECLARATORS
3959void pooldeinit(struct memorypool *pool)
3960#else /* not ANSI_DECLARATORS */
3961void pooldeinit(pool)
3962struct memorypool *pool;
3963#endif /* not ANSI_DECLARATORS */
3964
3965{
3966 while (pool->firstblock != (VOID **) NULL) {
3967 pool->nowblock = (VOID **) *(pool->firstblock);
3968 trifree((VOID *) pool->firstblock);
3969 pool->firstblock = pool->nowblock;
3970 }
3971}
3972
3973/*****************************************************************************/
3974/* */
3975/* poolalloc() Allocate space for an item. */
3976/* */
3977/*****************************************************************************/
3978
3979#ifdef ANSI_DECLARATORS
3981#else /* not ANSI_DECLARATORS */
3982VOID *poolalloc(pool)
3983struct memorypool *pool;
3984#endif /* not ANSI_DECLARATORS */
3985
3986{
3987 VOID *newitem;
3988 VOID **newblock;
3989 uintptr_t alignptr;
3990
3991 /* First check the linked list of dead items. If the list is not */
3992 /* empty, allocate an item from the list rather than a fresh one. */
3993 if (pool->deaditemstack != (VOID *) NULL) {
3994 newitem = pool->deaditemstack; /* Take first item in list. */
3995 pool->deaditemstack = * (VOID **) pool->deaditemstack;
3996 } else {
3997 /* Check if there are any free items left in the current block. */
3998 if (pool->unallocateditems == 0) {
3999 /* Check if another block must be allocated. */
4000 if (*(pool->nowblock) == (VOID *) NULL) {
4001 /* Allocate a new block of items, pointed to by the previous block. */
4002 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
4003 (int) sizeof(VOID *) +
4004 pool->alignbytes);
4005 *(pool->nowblock) = (VOID *) newblock;
4006 /* The next block pointer is NULL. */
4007 *newblock = (VOID *) NULL;
4008 }
4009
4010 /* Move to the new block. */
4011 pool->nowblock = (VOID **) *(pool->nowblock);
4012 /* Find the first item in the block. */
4013 /* Increment by the size of (VOID *). */
4014 alignptr = (uintptr_t) (pool->nowblock + 1);
4015 /* Align the item on an `alignbytes'-byte boundary. */
4016 pool->nextitem = (VOID *)
4017 (alignptr + (uintptr_t) pool->alignbytes -
4018 (alignptr % (uintptr_t) pool->alignbytes));
4019 /* There are lots of unallocated items left in this block. */
4020 pool->unallocateditems = pool->itemsperblock;
4021 }
4022
4023 /* Allocate a new item. */
4024 newitem = pool->nextitem;
4025 /* Advance `nextitem' pointer to next free item in block. */
4026 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
4027 pool->unallocateditems--;
4028 pool->maxitems++;
4029 }
4030 pool->items++;
4031 return newitem;
4032}
4033
4034/*****************************************************************************/
4035/* */
4036/* pooldealloc() Deallocate space for an item. */
4037/* */
4038/* The deallocated space is stored in a queue for later reuse. */
4039/* */
4040/*****************************************************************************/
4041
4042#ifdef ANSI_DECLARATORS
4043void pooldealloc(struct memorypool *pool, VOID *dyingitem)
4044#else /* not ANSI_DECLARATORS */
4045void pooldealloc(pool, dyingitem)
4046struct memorypool *pool;
4047VOID *dyingitem;
4048#endif /* not ANSI_DECLARATORS */
4049
4050{
4051 /* Push freshly killed item onto stack. */
4052 *((VOID **) dyingitem) = pool->deaditemstack;
4053 pool->deaditemstack = dyingitem;
4054 pool->items--;
4055}
4056
4057/*****************************************************************************/
4058/* */
4059/* traversalinit() Prepare to traverse the entire list of items. */
4060/* */
4061/* This routine is used in conjunction with traverse(). */
4062/* */
4063/*****************************************************************************/
4064
4065#ifdef ANSI_DECLARATORS
4066void traversalinit(struct memorypool *pool)
4067#else /* not ANSI_DECLARATORS */
4068void traversalinit(pool)
4069struct memorypool *pool;
4070#endif /* not ANSI_DECLARATORS */
4071
4072{
4073 uintptr_t alignptr;
4074
4075 /* Begin the traversal in the first block. */
4076 pool->pathblock = pool->firstblock;
4077 /* Find the first item in the block. Increment by the size of (VOID *). */
4078 alignptr = (uintptr_t) (pool->pathblock + 1);
4079 /* Align with item on an `alignbytes'-byte boundary. */
4080 pool->pathitem = (VOID *)
4081 (alignptr + (uintptr_t) pool->alignbytes -
4082 (alignptr % (uintptr_t) pool->alignbytes));
4083 /* Set the number of items left in the current block. */
4084 pool->pathitemsleft = pool->itemsfirstblock;
4085}
4086
4087/*****************************************************************************/
4088/* */
4089/* traverse() Find the next item in the list. */
4090/* */
4091/* This routine is used in conjunction with traversalinit(). Be forewarned */
4092/* that this routine successively returns all items in the list, including */
4093/* deallocated ones on the deaditemqueue. It's up to you to figure out */
4094/* which ones are actually dead. Why? I don't want to allocate extra */
4095/* space just to demarcate dead items. It can usually be done more */
4096/* space-efficiently by a routine that knows something about the structure */
4097/* of the item. */
4098/* */
4099/*****************************************************************************/
4100
4101#ifdef ANSI_DECLARATORS
4103#else /* not ANSI_DECLARATORS */
4104VOID *traverse(pool)
4105struct memorypool *pool;
4106#endif /* not ANSI_DECLARATORS */
4107
4108{
4109 VOID *newitem;
4110 uintptr_t alignptr;
4111
4112 /* Stop upon exhausting the list of items. */
4113 if (pool->pathitem == pool->nextitem) {
4114 return (VOID *) NULL;
4115 }
4116
4117 /* Check whether any untraversed items remain in the current block. */
4118 if (pool->pathitemsleft == 0) {
4119 /* Find the next block. */
4120 pool->pathblock = (VOID **) *(pool->pathblock);
4121 /* Find the first item in the block. Increment by the size of (VOID *). */
4122 alignptr = (uintptr_t) (pool->pathblock + 1);
4123 /* Align with item on an `alignbytes'-byte boundary. */
4124 pool->pathitem = (VOID *)
4125 (alignptr + (uintptr_t) pool->alignbytes -
4126 (alignptr % (uintptr_t) pool->alignbytes));
4127 /* Set the number of items left in the current block. */
4128 pool->pathitemsleft = pool->itemsperblock;
4129 }
4130
4131 newitem = pool->pathitem;
4132 /* Find the next item in the block. */
4133 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
4134 pool->pathitemsleft--;
4135 return newitem;
4136}
4137
4138/*****************************************************************************/
4139/* */
4140/* dummyinit() Initialize the triangle that fills "outer space" and the */
4141/* omnipresent subsegment. */
4142/* */
4143/* The triangle that fills "outer space," called `dummytri', is pointed to */
4144/* by every triangle and subsegment on a boundary (be it outer or inner) of */
4145/* the triangulation. Also, `dummytri' points to one of the triangles on */
4146/* the convex hull (until the holes and concavities are carved), making it */
4147/* possible to find a starting triangle for point location. */
4148/* */
4149/* The omnipresent subsegment, `dummysub', is pointed to by every triangle */
4150/* or subsegment that doesn't have a full complement of real subsegments */
4151/* to point to. */
4152/* */
4153/* `dummytri' and `dummysub' are generally required to fulfill only a few */
4154/* invariants: their vertices must remain NULL and `dummytri' must always */
4155/* be bonded (at offset zero) to some triangle on the convex hull of the */
4156/* mesh, via a boundary edge. Otherwise, the connections of `dummytri' and */
4157/* `dummysub' may change willy-nilly. This makes it possible to avoid */
4158/* writing a good deal of special-case code (in the edge flip, for example) */
4159/* for dealing with the boundary of the mesh, places where no subsegment is */
4160/* present, and so forth. Other entities are frequently bonded to */
4161/* `dummytri' and `dummysub' as if they were real mesh entities, with no */
4162/* harm done. */
4163/* */
4164/*****************************************************************************/
4165
4166#ifdef ANSI_DECLARATORS
4167void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
4168 int subsegbytes)
4169#else /* not ANSI_DECLARATORS */
4170void dummyinit(m, b, trianglebytes, subsegbytes)
4171struct mesh *m;
4172struct behavior *b;
4173int trianglebytes;
4174int subsegbytes;
4175#endif /* not ANSI_DECLARATORS */
4176
4177{
4178 uintptr_t alignptr;
4179
4180 /* Set up `dummytri', the `triangle' that occupies "outer space." */
4181 m->dummytribase = (triangle *) trimalloc(trianglebytes +
4182 m->triangles.alignbytes);
4183 /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
4184 alignptr = (uintptr_t) m->dummytribase;
4185 m->dummytri = (triangle *)
4186 (alignptr + (uintptr_t) m->triangles.alignbytes -
4187 (alignptr % (uintptr_t) m->triangles.alignbytes));
4188 /* Initialize the three adjoining triangles to be "outer space." These */
4189 /* will eventually be changed by various bonding operations, but their */
4190 /* values don't really matter, as long as they can legally be */
4191 /* dereferenced. */
4192 m->dummytri[0] = (triangle) m->dummytri;
4193 m->dummytri[1] = (triangle) m->dummytri;
4194 m->dummytri[2] = (triangle) m->dummytri;
4195 /* Three NULL vertices. */
4196 m->dummytri[3] = (triangle) NULL;
4197 m->dummytri[4] = (triangle) NULL;
4198 m->dummytri[5] = (triangle) NULL;
4199
4200 if (b->usesegments) {
4201 /* Set up `dummysub', the omnipresent subsegment pointed to by any */
4202 /* triangle side or subsegment end that isn't attached to a real */
4203 /* subsegment. */
4204 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
4205 m->subsegs.alignbytes);
4206 /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
4207 alignptr = (uintptr_t) m->dummysubbase;
4208 m->dummysub = (subseg *)
4209 (alignptr + (uintptr_t) m->subsegs.alignbytes -
4210 (alignptr % (uintptr_t) m->subsegs.alignbytes));
4211 /* Initialize the two adjoining subsegments to be the omnipresent */
4212 /* subsegment. These will eventually be changed by various bonding */
4213 /* operations, but their values don't really matter, as long as they */
4214 /* can legally be dereferenced. */
4215 m->dummysub[0] = (subseg) m->dummysub;
4216 m->dummysub[1] = (subseg) m->dummysub;
4217 /* Four NULL vertices. */
4218 m->dummysub[2] = (subseg) NULL;
4219 m->dummysub[3] = (subseg) NULL;
4220 m->dummysub[4] = (subseg) NULL;
4221 m->dummysub[5] = (subseg) NULL;
4222 /* Initialize the two adjoining triangles to be "outer space." */
4223 m->dummysub[6] = (subseg) m->dummytri;
4224 m->dummysub[7] = (subseg) m->dummytri;
4225 /* Set the boundary marker to zero. */
4226 * (int *) (m->dummysub + 8) = 0;
4227
4228 /* Initialize the three adjoining subsegments of `dummytri' to be */
4229 /* the omnipresent subsegment. */
4230 m->dummytri[6] = (triangle) m->dummysub;
4231 m->dummytri[7] = (triangle) m->dummysub;
4232 m->dummytri[8] = (triangle) m->dummysub;
4233 }
4234}
4235
4236/*****************************************************************************/
4237/* */
4238/* initializevertexpool() Calculate the size of the vertex data structure */
4239/* and initialize its memory pool. */
4240/* */
4241/* This routine also computes the `vertexmarkindex' and `vertex2triindex' */
4242/* indices used to find values within each vertex. */
4243/* */
4244/*****************************************************************************/
4245
4246#ifdef ANSI_DECLARATORS
4247void initializevertexpool(struct mesh *m, struct behavior *b)
4248#else /* not ANSI_DECLARATORS */
4250struct mesh *m;
4251struct behavior *b;
4252#endif /* not ANSI_DECLARATORS */
4253
4254{
4255 int vertexsize;
4256
4257 /* The index within each vertex at which the boundary marker is found, */
4258 /* followed by the vertex type. Ensure the vertex marker is aligned to */
4259 /* a sizeof(int)-byte address. */
4260 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
4261 sizeof(int) - 1) /
4262 sizeof(int);
4263 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
4264 if (b->poly) {
4265 /* The index within each vertex at which a triangle pointer is found. */
4266 /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
4267 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
4268 sizeof(triangle);
4269 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
4270 }
4271
4272 /* Initialize the pool of vertices. */
4273 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
4274 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
4275 sizeof(REAL));
4276}
4277
4278/*****************************************************************************/
4279/* */
4280/* initializetrisubpools() Calculate the sizes of the triangle and */
4281/* subsegment data structures and initialize */
4282/* their memory pools. */
4283/* */
4284/* This routine also computes the `highorderindex', `elemattribindex', and */
4285/* `areaboundindex' indices used to find values within each triangle. */
4286/* */
4287/*****************************************************************************/
4288
4289#ifdef ANSI_DECLARATORS
4290void initializetrisubpools(struct mesh *m, struct behavior *b)
4291#else /* not ANSI_DECLARATORS */
4293struct mesh *m;
4294struct behavior *b;
4295#endif /* not ANSI_DECLARATORS */
4296
4297{
4298 int trisize;
4299
4300 /* The index within each triangle at which the extra nodes (above three) */
4301 /* associated with high order elements are found. There are three */
4302 /* pointers to other triangles, three pointers to corners, and possibly */
4303 /* three pointers to subsegments before the extra nodes. */
4304 m->highorderindex = 6 + (b->usesegments * 3);
4305 /* The number of bytes occupied by a triangle. */
4306 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
4307 sizeof(triangle);
4308 /* The index within each triangle at which its attributes are found, */
4309 /* where the index is measured in REALs. */
4310 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
4311 /* The index within each triangle at which the maximum area constraint */
4312 /* is found, where the index is measured in REALs. Note that if the */
4313 /* `regionattrib' flag is set, an additional attribute will be added. */
4314 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
4315 /* If triangle attributes or an area bound are needed, increase the number */
4316 /* of bytes occupied by a triangle. */
4317 if (b->vararea) {
4318 trisize = (m->areaboundindex + 1) * sizeof(REAL);
4319 } else if (m->eextras + b->regionattrib > 0) {
4320 trisize = m->areaboundindex * sizeof(REAL);
4321 }
4322 /* If a Voronoi diagram or triangle neighbor graph is requested, make */
4323 /* sure there's room to store an integer index in each triangle. This */
4324 /* integer index can occupy the same space as the subsegment pointers */
4325 /* or attributes or area constraint or extra nodes. */
4326 if ((b->voronoi || b->neighbors) &&
4327 (trisize < (int) ( 6 * sizeof(triangle) + sizeof(int)))) {
4328 trisize = 6 * sizeof(triangle) + sizeof(int);
4329 }
4330
4331 /* Having determined the memory size of a triangle, initialize the pool. */
4332 poolinit(&m->triangles, trisize, TRIPERBLOCK,
4333 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
4334 TRIPERBLOCK, 4);
4335
4336 if (b->usesegments) {
4337 /* Initialize the pool of subsegments. Take into account all eight */
4338 /* pointers and one boundary marker. */
4339 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
4341
4342 /* Initialize the "outer space" triangle and omnipresent subsegment. */
4343 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
4344 } else {
4345 /* Initialize the "outer space" triangle. */
4346 dummyinit(m, b, m->triangles.itembytes, 0);
4347 }
4348}
4349
4350/*****************************************************************************/
4351/* */
4352/* triangledealloc() Deallocate space for a triangle, marking it dead. */
4353/* */
4354/*****************************************************************************/
4355
4356#ifdef ANSI_DECLARATORS
4357void triangledealloc(struct mesh *m, triangle *dyingtriangle)
4358#else /* not ANSI_DECLARATORS */
4359void triangledealloc(m, dyingtriangle)
4360struct mesh *m;
4361triangle *dyingtriangle;
4362#endif /* not ANSI_DECLARATORS */
4363
4364{
4365 /* Mark the triangle as dead. This makes it possible to detect dead */
4366 /* triangles when traversing the list of all triangles. */
4367 killtri(dyingtriangle);
4368 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
4369}
4370
4371/*****************************************************************************/
4372/* */
4373/* triangletraverse() Traverse the triangles, skipping dead ones. */
4374/* */
4375/*****************************************************************************/
4376
4377#ifdef ANSI_DECLARATORS
4379#else /* not ANSI_DECLARATORS */
4381struct mesh *m;
4382#endif /* not ANSI_DECLARATORS */
4383
4384{
4385 triangle *newtriangle;
4386
4387 do {
4388 newtriangle = (triangle *) traverse(&m->triangles);
4389 if (newtriangle == (triangle *) NULL) {
4390 return (triangle *) NULL;
4391 }
4392 } while (deadtri(newtriangle)); /* Skip dead ones. */
4393 return newtriangle;
4394}
4395
4396/*****************************************************************************/
4397/* */
4398/* subsegdealloc() Deallocate space for a subsegment, marking it dead. */
4399/* */
4400/*****************************************************************************/
4401
4402#ifdef ANSI_DECLARATORS
4403void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
4404#else /* not ANSI_DECLARATORS */
4405void subsegdealloc(m, dyingsubseg)
4406struct mesh *m;
4407subseg *dyingsubseg;
4408#endif /* not ANSI_DECLARATORS */
4409
4410{
4411 /* Mark the subsegment as dead. This makes it possible to detect dead */
4412 /* subsegments when traversing the list of all subsegments. */
4413 killsubseg(dyingsubseg);
4414 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
4415}
4416
4417/*****************************************************************************/
4418/* */
4419/* subsegtraverse() Traverse the subsegments, skipping dead ones. */
4420/* */
4421/*****************************************************************************/
4422
4423#ifdef ANSI_DECLARATORS
4425#else /* not ANSI_DECLARATORS */
4427struct mesh *m;
4428#endif /* not ANSI_DECLARATORS */
4429
4430{
4431 subseg *newsubseg;
4432
4433 do {
4434 newsubseg = (subseg *) traverse(&m->subsegs);
4435 if (newsubseg == (subseg *) NULL) {
4436 return (subseg *) NULL;
4437 }
4438 } while (deadsubseg(newsubseg)); /* Skip dead ones. */
4439 return newsubseg;
4440}
4441
4442/*****************************************************************************/
4443/* */
4444/* vertexdealloc() Deallocate space for a vertex, marking it dead. */
4445/* */
4446/*****************************************************************************/
4447
4448#ifdef ANSI_DECLARATORS
4449void vertexdealloc(struct mesh *m, vertex dyingvertex)
4450#else /* not ANSI_DECLARATORS */
4451void vertexdealloc(m, dyingvertex)
4452struct mesh *m;
4453vertex dyingvertex;
4454#endif /* not ANSI_DECLARATORS */
4455
4456{
4457 /* Mark the vertex as dead. This makes it possible to detect dead */
4458 /* vertices when traversing the list of all vertices. */
4459 setvertextype(dyingvertex, DEADVERTEX);
4460 pooldealloc(&m->vertices, (VOID *) dyingvertex);
4461}
4462
4463/*****************************************************************************/
4464/* */
4465/* vertextraverse() Traverse the vertices, skipping dead ones. */
4466/* */
4467/*****************************************************************************/
4468
4469#ifdef ANSI_DECLARATORS
4471#else /* not ANSI_DECLARATORS */
4473struct mesh *m;
4474#endif /* not ANSI_DECLARATORS */
4475
4476{
4477 vertex newvertex;
4478
4479 do {
4480 newvertex = (vertex) traverse(&m->vertices);
4481 if (newvertex == (vertex) NULL) {
4482 return (vertex) NULL;
4483 }
4484 } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */
4485 return newvertex;
4486}
4487
4488/*****************************************************************************/
4489/* */
4490/* badsubsegdealloc() Deallocate space for a bad subsegment, marking it */
4491/* dead. */
4492/* */
4493/*****************************************************************************/
4494
4495#ifndef CDT_ONLY
4496
4497#ifdef ANSI_DECLARATORS
4498void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
4499#else /* not ANSI_DECLARATORS */
4500void badsubsegdealloc(m, dyingseg)
4501struct mesh *m;
4502struct badsubseg *dyingseg;
4503#endif /* not ANSI_DECLARATORS */
4504
4505{
4506 /* Set subsegment's origin to NULL. This makes it possible to detect dead */
4507 /* badsubsegs when traversing the list of all badsubsegs . */
4508 dyingseg->subsegorg = (vertex) NULL;
4509 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
4510}
4511
4512#endif /* not CDT_ONLY */
4513
4514/*****************************************************************************/
4515/* */
4516/* badsubsegtraverse() Traverse the bad subsegments, skipping dead ones. */
4517/* */
4518/*****************************************************************************/
4519
4520#ifndef CDT_ONLY
4521
4522#ifdef ANSI_DECLARATORS
4523struct badsubseg *badsubsegtraverse(struct mesh *m)
4524#else /* not ANSI_DECLARATORS */
4525struct badsubseg *badsubsegtraverse(m)
4526struct mesh *m;
4527#endif /* not ANSI_DECLARATORS */
4528
4529{
4530 struct badsubseg *newseg;
4531
4532 do {
4533 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
4534 if (newseg == (struct badsubseg *) NULL) {
4535 return (struct badsubseg *) NULL;
4536 }
4537 } while (newseg->subsegorg == (vertex) NULL); /* Skip dead ones. */
4538 return newseg;
4539}
4540
4541#endif /* not CDT_ONLY */
4542
4543/*****************************************************************************/
4544/* */
4545/* getvertex() Get a specific vertex, by number, from the list. */
4546/* */
4547/* The first vertex is number 'firstnumber'. */
4548/* */
4549/* Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */
4550/* is large). I don't care to take the trouble to make it work in constant */
4551/* time. */
4552/* */
4553/*****************************************************************************/
4554
4555#ifdef ANSI_DECLARATORS
4556vertex getvertex(struct mesh *m, struct behavior *b, int number)
4557#else /* not ANSI_DECLARATORS */
4558vertex getvertex(m, b, number)
4559struct mesh *m;
4560struct behavior *b;
4561int number;
4562#endif /* not ANSI_DECLARATORS */
4563
4564{
4565 VOID **getblock;
4566 char *foundvertex;
4567 uintptr_t alignptr;
4568 int current;
4569
4570 getblock = m->vertices.firstblock;
4571 current = b->firstnumber;
4572
4573 /* Find the right block. */
4574 if (current + m->vertices.itemsfirstblock <= number) {
4575 getblock = (VOID **) *getblock;
4576 current += m->vertices.itemsfirstblock;
4577 while (current + m->vertices.itemsperblock <= number) {
4578 getblock = (VOID **) *getblock;
4579 current += m->vertices.itemsperblock;
4580 }
4581 }
4582
4583 /* Now find the right vertex. */
4584 alignptr = (uintptr_t) (getblock + 1);
4585 foundvertex = (char *) (alignptr + (uintptr_t) m->vertices.alignbytes -
4586 (alignptr % (uintptr_t) m->vertices.alignbytes));
4587 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
4588}
4589
4590/*****************************************************************************/
4591/* */
4592/* triangledeinit() Free all remaining allocated memory. */
4593/* */
4594/*****************************************************************************/
4595
4596#ifdef ANSI_DECLARATORS
4597void triangledeinit(struct mesh *m, struct behavior *b)
4598#else /* not ANSI_DECLARATORS */
4599void triangledeinit(m, b)
4600struct mesh *m;
4601struct behavior *b;
4602#endif /* not ANSI_DECLARATORS */
4603
4604{
4605 pooldeinit(&m->triangles);
4606 trifree((VOID *) m->dummytribase);
4607 if (b->usesegments) {
4608 pooldeinit(&m->subsegs);
4609 trifree((VOID *) m->dummysubbase);
4610 }
4611 pooldeinit(&m->vertices);
4612#ifndef CDT_ONLY
4613 if (b->quality) {
4614 pooldeinit(&m->badsubsegs);
4615 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
4616 pooldeinit(&m->badtriangles);
4617 pooldeinit(&m->flipstackers);
4618 }
4619 }
4620#endif /* not CDT_ONLY */
4621}
4622
4623/** **/
4624/** **/
4625/********* Memory management routines end here *********/
4626
4627/********* Constructors begin here *********/
4628/** **/
4629/** **/
4630
4631/*****************************************************************************/
4632/* */
4633/* maketriangle() Create a new triangle with orientation zero. */
4634/* */
4635/*****************************************************************************/
4636
4637#ifdef ANSI_DECLARATORS
4638void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
4639#else /* not ANSI_DECLARATORS */
4640void maketriangle(m, b, newotri)
4641struct mesh *m;
4642struct behavior *b;
4643struct otri *newotri;
4644#endif /* not ANSI_DECLARATORS */
4645
4646{
4647 int i;
4648
4649 newotri->tri = (triangle *) poolalloc(&m->triangles);
4650 /* Initialize the three adjoining triangles to be "outer space". */
4651 newotri->tri[0] = (triangle) m->dummytri;
4652 newotri->tri[1] = (triangle) m->dummytri;
4653 newotri->tri[2] = (triangle) m->dummytri;
4654 /* Three NULL vertices. */
4655 newotri->tri[3] = (triangle) NULL;
4656 newotri->tri[4] = (triangle) NULL;
4657 newotri->tri[5] = (triangle) NULL;
4658 if (b->usesegments) {
4659 /* Initialize the three adjoining subsegments to be the omnipresent */
4660 /* subsegment. */
4661 newotri->tri[6] = (triangle) m->dummysub;
4662 newotri->tri[7] = (triangle) m->dummysub;
4663 newotri->tri[8] = (triangle) m->dummysub;
4664 }
4665 for (i = 0; i < m->eextras; i++) {
4666 setelemattribute(*newotri, i, 0.0);
4667 }
4668 if (b->vararea) {
4669 setareabound(*newotri, -1.0);
4670 }
4671
4672 newotri->orient = 0;
4673}
4674
4675/*****************************************************************************/
4676/* */
4677/* makesubseg() Create a new subsegment with orientation zero. */
4678/* */
4679/*****************************************************************************/
4680
4681#ifdef ANSI_DECLARATORS
4682void makesubseg(struct mesh *m, struct osub *newsubseg)
4683#else /* not ANSI_DECLARATORS */
4684void makesubseg(m, newsubseg)
4685struct mesh *m;
4686struct osub *newsubseg;
4687#endif /* not ANSI_DECLARATORS */
4688
4689{
4690 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
4691 /* Initialize the two adjoining subsegments to be the omnipresent */
4692 /* subsegment. */
4693 newsubseg->ss[0] = (subseg) m->dummysub;
4694 newsubseg->ss[1] = (subseg) m->dummysub;
4695 /* Four NULL vertices. */
4696 newsubseg->ss[2] = (subseg) NULL;
4697 newsubseg->ss[3] = (subseg) NULL;
4698 newsubseg->ss[4] = (subseg) NULL;
4699 newsubseg->ss[5] = (subseg) NULL;
4700 /* Initialize the two adjoining triangles to be "outer space." */
4701 newsubseg->ss[6] = (subseg) m->dummytri;
4702 newsubseg->ss[7] = (subseg) m->dummytri;
4703 /* Set the boundary marker to zero. */
4704 setmark(*newsubseg, 0);
4705
4706 newsubseg->ssorient = 0;
4707}
4708
4709/** **/
4710/** **/
4711/********* Constructors end here *********/
4712
4713/********* Geometric primitives begin here *********/
4714/** **/
4715/** **/
4716
4717/* The adaptive exact arithmetic geometric predicates implemented herein are */
4718/* described in detail in my paper, "Adaptive Precision Floating-Point */
4719/* Arithmetic and Fast Robust Geometric Predicates." See the header for a */
4720/* full citation. */
4721
4722/* Which of the following two methods of finding the absolute values is */
4723/* fastest is compiler-dependent. A few compilers can inline and optimize */
4724/* the fabs() call; but most will incur the overhead of a function call, */
4725/* which is disastrously slow. A faster way on IEEE machines might be to */
4726/* mask the appropriate bit, but that's difficult to do in C without */
4727/* forcing the value to be stored to memory (rather than be kept in the */
4728/* register to which the optimizer assigned it). */
4729
4730#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
4731/* #define Absolute(a) fabs(a) */
4732
4733/* Many of the operations are broken up into two pieces, a main part that */
4734/* performs an approximate operation, and a "tail" that computes the */
4735/* roundoff error of that operation. */
4736/* */
4737/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */
4738/* Split(), and Two_Product() are all implemented as described in the */
4739/* reference. Each of these macros requires certain variables to be */
4740/* defined in the calling routine. The variables `bvirt', `c', `abig', */
4741/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */
4742/* they store the result of an operation that may incur roundoff error. */
4743/* The input parameter `x' (or the highest numbered `x_' parameter) must */
4744/* also be declared `INEXACT'. */
4745
4746#define Fast_Two_Sum_Tail(a, b, x, y) \
4747 bvirt = x - a; \
4748 y = b - bvirt
4749
4750#define Fast_Two_Sum(a, b, x, y) \
4751 x = (REAL) (a + b); \
4752 Fast_Two_Sum_Tail(a, b, x, y)
4753
4754#define Two_Sum_Tail(a, b, x, y) \
4755 bvirt = (REAL) (x - a); \
4756 avirt = x - bvirt; \
4757 bround = b - bvirt; \
4758 around = a - avirt; \
4759 y = around + bround
4760
4761#define Two_Sum(a, b, x, y) \
4762 x = (REAL) (a + b); \
4763 Two_Sum_Tail(a, b, x, y)
4764
4765#define Two_Diff_Tail(a, b, x, y) \
4766 bvirt = (REAL) (a - x); \
4767 avirt = x + bvirt; \
4768 bround = bvirt - b; \
4769 around = a - avirt; \
4770 y = around + bround
4771
4772#define Two_Diff(a, b, x, y) \
4773 x = (REAL) (a - b); \
4774 Two_Diff_Tail(a, b, x, y)
4775
4776#define Split(a, ahi, alo) \
4777 c = (REAL) (splitter * a); \
4778 abig = (REAL) (c - a); \
4779 ahi = c - abig; \
4780 alo = a - ahi
4781
4782#define Two_Product_Tail(a, b, x, y) \
4783 Split(a, ahi, alo); \
4784 Split(b, bhi, blo); \
4785 err1 = x - (ahi * bhi); \
4786 err2 = err1 - (alo * bhi); \
4787 err3 = err2 - (ahi * blo); \
4788 y = (alo * blo) - err3
4789
4790#define Two_Product(a, b, x, y) \
4791 x = (REAL) (a * b); \
4792 Two_Product_Tail(a, b, x, y)
4793
4794/* Two_Product_Presplit() is Two_Product() where one of the inputs has */
4795/* already been split. Avoids redundant splitting. */
4796
4797#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
4798 x = (REAL) (a * b); \
4799 Split(a, ahi, alo); \
4800 err1 = x - (ahi * bhi); \
4801 err2 = err1 - (alo * bhi); \
4802 err3 = err2 - (ahi * blo); \
4803 y = (alo * blo) - err3
4804
4805/* Square() can be done more quickly than Two_Product(). */
4806
4807#define Square_Tail(a, x, y) \
4808 Split(a, ahi, alo); \
4809 err1 = x - (ahi * ahi); \
4810 err3 = err1 - ((ahi + ahi) * alo); \
4811 y = (alo * alo) - err3
4812
4813#define Square(a, x, y) \
4814 x = (REAL) (a * a); \
4815 Square_Tail(a, x, y)
4816
4817/* Macros for summing expansions of various fixed lengths. These are all */
4818/* unrolled versions of Expansion_Sum(). */
4819
4820#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
4821 Two_Sum(a0, b , _i, x0); \
4822 Two_Sum(a1, _i, x2, x1)
4823
4824#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
4825 Two_Diff(a0, b , _i, x0); \
4826 Two_Sum( a1, _i, x2, x1)
4827
4828#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
4829 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
4830 Two_One_Sum(_j, _0, b1, x3, x2, x1)
4831
4832#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
4833 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
4834 Two_One_Diff(_j, _0, b1, x3, x2, x1)
4835
4836/* Macro for multiplying a two-component expansion by a single component. */
4837
4838#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
4839 Split(b, bhi, blo); \
4840 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
4841 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
4842 Two_Sum(_i, _0, _k, x1); \
4843 Fast_Two_Sum(_j, _k, x3, x2)
4844
4845/*****************************************************************************/
4846/* */
4847/* exactinit() Initialize the variables used for exact arithmetic. */
4848/* */
4849/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
4850/* floating-point arithmetic. `epsilon' bounds the relative roundoff */
4851/* error. It is used for floating-point error analysis. */
4852/* */
4853/* `splitter' is used to split floating-point numbers into two half- */
4854/* length significands for exact multiplication. */
4855/* */
4856/* I imagine that a highly optimizing compiler might be too smart for its */
4857/* own good, and somehow cause this routine to fail, if it pretends that */
4858/* floating-point arithmetic is too much like real arithmetic. */
4859/* */
4860/* Don't change this routine unless you fully understand it. */
4861/* */
4862/*****************************************************************************/
4863
4865{
4866 REAL half;
4867 REAL check, lastcheck;
4868 int every_other;
4869#ifdef LINUX
4870 fenv_t fenv;
4871#endif /* LINUX */
4872
4873#ifdef CPU86
4874#ifdef SINGLE
4875 _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */
4876#else /* not SINGLE */
4877 _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */
4878#endif /* not SINGLE */
4879#endif /* CPU86 */
4880#ifdef LINUX
4881#ifdef SINGLE
4882 /* fenv.__control_word = 4223; */
4883 fenv.__control_word = 4210; /* set FPU control word for single precision */
4884#else /* not SINGLE */
4885 /* fenv.__control_word = 4735; */
4886 fenv.__control_word = 4722; /* set FPU control word for double precision */
4887#endif /* not SINGLE */
4888 fesetenv(&fenv);
4889#endif /* LINUX */
4890
4891 every_other = 1;
4892 half = 0.5;
4893 epsilon = 1.0;
4894 splitter = 1.0;
4895 check = 1.0;
4896 /* Repeatedly divide `epsilon' by two until it is too small to add to */
4897 /* one without causing roundoff. (Also check if the sum is equal to */
4898 /* the previous sum, for machines that round up instead of using exact */
4899 /* rounding. Not that these routines will work on such machines.) */
4900 do {
4901 lastcheck = check;
4902 epsilon *= half;
4903 if (every_other) {
4904 splitter *= 2.0;
4905 }
4906 every_other = !every_other;
4907 check = 1.0 + epsilon;
4908 } while ((check != 1.0) && (check != lastcheck));
4909 splitter += 1.0;
4910 /* Error bounds for orientation and incircle tests. */
4911 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
4912 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
4913 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
4914 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
4915 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
4916 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
4917 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
4918 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
4919 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
4920 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
4921}
4922
4923/*****************************************************************************/
4924/* */
4925/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
4926/* components from the output expansion. */
4927/* */
4928/* Sets h = e + f. See my Robust Predicates paper for details. */
4929/* */
4930/* If round-to-even is used (as with IEEE 754), maintains the strongly */
4931/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
4932/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
4933/* properties. */
4934/* */
4935/*****************************************************************************/
4936
4937#ifdef ANSI_DECLARATORS
4938int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
4939#else /* not ANSI_DECLARATORS */
4940int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */
4941int elen;
4942REAL *e;
4943int flen;
4944REAL *f;
4945REAL *h;
4946#endif /* not ANSI_DECLARATORS */
4947
4948{
4949 REAL Q;
4950 INEXACT REAL Qnew;
4951 INEXACT REAL hh;
4952 INEXACT REAL bvirt;
4953 REAL avirt, bround, around;
4954 int eindex, findex, hindex;
4955 REAL enow, fnow;
4956
4957 enow = e[0];
4958 fnow = f[0];
4959 eindex = findex = 0;
4960 if ((fnow > enow) == (fnow > -enow)) {
4961 Q = enow;
4962 enow = e[++eindex];
4963 } else {
4964 Q = fnow;
4965 fnow = f[++findex];
4966 }
4967 hindex = 0;
4968 if ((eindex < elen) && (findex < flen)) {
4969 if ((fnow > enow) == (fnow > -enow)) {
4970 Fast_Two_Sum(enow, Q, Qnew, hh);
4971 enow = e[++eindex];
4972 } else {
4973 Fast_Two_Sum(fnow, Q, Qnew, hh);
4974 fnow = f[++findex];
4975 }
4976 Q = Qnew;
4977 if (hh != 0.0) {
4978 h[hindex++] = hh;
4979 }
4980 while ((eindex < elen) && (findex < flen)) {
4981 if ((fnow > enow) == (fnow > -enow)) {
4982 Two_Sum(Q, enow, Qnew, hh);
4983 enow = e[++eindex];
4984 } else {
4985 Two_Sum(Q, fnow, Qnew, hh);
4986 fnow = f[++findex];
4987 }
4988 Q = Qnew;
4989 if (hh != 0.0) {
4990 h[hindex++] = hh;
4991 }
4992 }
4993 }
4994 while (eindex < elen) {
4995 Two_Sum(Q, enow, Qnew, hh);
4996 enow = e[++eindex];
4997 Q = Qnew;
4998 if (hh != 0.0) {
4999 h[hindex++] = hh;
5000 }
5001 }
5002 while (findex < flen) {
5003 Two_Sum(Q, fnow, Qnew, hh);
5004 fnow = f[++findex];
5005 Q = Qnew;
5006 if (hh != 0.0) {
5007 h[hindex++] = hh;
5008 }
5009 }
5010 if ((Q != 0.0) || (hindex == 0)) {
5011 h[hindex++] = Q;
5012 }
5013 return hindex;
5014}
5015
5016/*****************************************************************************/
5017/* */
5018/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */
5019/* eliminating zero components from the */
5020/* output expansion. */
5021/* */
5022/* Sets h = be. See my Robust Predicates paper for details. */
5023/* */
5024/* Maintains the nonoverlapping property. If round-to-even is used (as */
5025/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
5026/* properties as well. (That is, if e has one of these properties, so */
5027/* will h.) */
5028/* */
5029/*****************************************************************************/
5030
5031#ifdef ANSI_DECLARATORS
5033#else /* not ANSI_DECLARATORS */
5034int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */
5035int elen;
5036REAL *e;
5037REAL b;
5038REAL *h;
5039#endif /* not ANSI_DECLARATORS */
5040
5041{
5042 INEXACT REAL Q, sum;
5043 REAL hh;
5044 INEXACT REAL product1;
5045 REAL product0;
5046 int eindex, hindex;
5047 REAL enow;
5048 INEXACT REAL bvirt;
5049 REAL avirt, bround, around;
5050 INEXACT REAL c;
5051 INEXACT REAL abig;
5052 REAL ahi, alo, bhi, blo;
5053 REAL err1, err2, err3;
5054
5055 Split(b, bhi, blo);
5056 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
5057 hindex = 0;
5058 if (hh != 0) {
5059 h[hindex++] = hh;
5060 }
5061 for (eindex = 1; eindex < elen; eindex++) {
5062 enow = e[eindex];
5063 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
5064 Two_Sum(Q, product0, sum, hh);
5065 if (hh != 0) {
5066 h[hindex++] = hh;
5067 }
5068 Fast_Two_Sum(product1, sum, Q, hh);
5069 if (hh != 0) {
5070 h[hindex++] = hh;
5071 }
5072 }
5073 if ((Q != 0.0) || (hindex == 0)) {
5074 h[hindex++] = Q;
5075 }
5076 return hindex;
5077}
5078
5079/*****************************************************************************/
5080/* */
5081/* estimate() Produce a one-word estimate of an expansion's value. */
5082/* */
5083/* See my Robust Predicates paper for details. */
5084/* */
5085/*****************************************************************************/
5086
5087#ifdef ANSI_DECLARATORS
5088REAL estimate(int elen, REAL *e)
5089#else /* not ANSI_DECLARATORS */
5090REAL estimate(elen, e)
5091int elen;
5092REAL *e;
5093#endif /* not ANSI_DECLARATORS */
5094
5095{
5096 REAL Q;
5097 int eindex;
5098
5099 Q = e[0];
5100 for (eindex = 1; eindex < elen; eindex++) {
5101 Q += e[eindex];
5102 }
5103 return Q;
5104}
5105
5106/*****************************************************************************/
5107/* */
5108/* counterclockwise() Return a positive value if the points pa, pb, and */
5109/* pc occur in counterclockwise order; a negative */
5110/* value if they occur in clockwise order; and zero */
5111/* if they are collinear. The result is also a rough */
5112/* approximation of twice the signed area of the */
5113/* triangle defined by the three points. */
5114/* */
5115/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5116/* result returned is the determinant of a matrix. This determinant is */
5117/* computed adaptively, in the sense that exact arithmetic is used only to */
5118/* the degree it is needed to ensure that the returned value has the */
5119/* correct sign. Hence, this function is usually quite fast, but will run */
5120/* more slowly when the input points are collinear or nearly so. */
5121/* */
5122/* See my Robust Predicates paper for details. */
5123/* */
5124/*****************************************************************************/
5125
5126#ifdef ANSI_DECLARATORS
5128#else /* not ANSI_DECLARATORS */
5129REAL counterclockwiseadapt(pa, pb, pc, detsum)
5130vertex pa;
5131vertex pb;
5132vertex pc;
5133REAL detsum;
5134#endif /* not ANSI_DECLARATORS */
5135
5136{
5137 INEXACT REAL acx, acy, bcx, bcy;
5138 REAL acxtail, acytail, bcxtail, bcytail;
5139 INEXACT REAL detleft, detright;
5140 REAL detlefttail, detrighttail;
5141 REAL det, errbound;
5142 REAL B[4], C1[8], C2[12], D[16];
5143 INEXACT REAL B3;
5144 int C1length, C2length, Dlength;
5145 REAL u[4];
5146 INEXACT REAL u3;
5147 INEXACT REAL s1, t1;
5148 REAL s0, t0;
5149
5150 INEXACT REAL bvirt;
5151 REAL avirt, bround, around;
5152 INEXACT REAL c;
5153 INEXACT REAL abig;
5154 REAL ahi, alo, bhi, blo;
5155 REAL err1, err2, err3;
5156 INEXACT REAL _i, _j;
5157 REAL _0;
5158
5159 acx = (REAL) (pa[0] - pc[0]);
5160 bcx = (REAL) (pb[0] - pc[0]);
5161 acy = (REAL) (pa[1] - pc[1]);
5162 bcy = (REAL) (pb[1] - pc[1]);
5163
5164 Two_Product(acx, bcy, detleft, detlefttail);
5165 Two_Product(acy, bcx, detright, detrighttail);
5166
5167 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
5168 B3, B[2], B[1], B[0]);
5169 B[3] = B3;
5170
5171 det = estimate(4, B);
5172 errbound = ccwerrboundB * detsum;
5173 if ((det >= errbound) || (-det >= errbound)) {
5174 return det;
5175 }
5176
5177 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
5178 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
5179 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
5180 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
5181
5182 if ((acxtail == 0.0) && (acytail == 0.0)
5183 && (bcxtail == 0.0) && (bcytail == 0.0)) {
5184 return det;
5185 }
5186
5187 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
5188 det += (acx * bcytail + bcy * acxtail)
5189 - (acy * bcxtail + bcx * acytail);
5190 if ((det >= errbound) || (-det >= errbound)) {
5191 return det;
5192 }
5193
5194 Two_Product(acxtail, bcy, s1, s0);
5195 Two_Product(acytail, bcx, t1, t0);
5196 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5197 u[3] = u3;
5198 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
5199
5200 Two_Product(acx, bcytail, s1, s0);
5201 Two_Product(acy, bcxtail, t1, t0);
5202 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5203 u[3] = u3;
5204 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
5205
5206 Two_Product(acxtail, bcytail, s1, s0);
5207 Two_Product(acytail, bcxtail, t1, t0);
5208 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5209 u[3] = u3;
5210 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
5211
5212 return(D[Dlength - 1]);
5213}
5214
5215#ifdef ANSI_DECLARATORS
5217 vertex pa, vertex pb, vertex pc)
5218#else /* not ANSI_DECLARATORS */
5219REAL counterclockwise(m, b, pa, pb, pc)
5220struct mesh *m;
5221struct behavior *b;
5222vertex pa;
5223vertex pb;
5224vertex pc;
5225#endif /* not ANSI_DECLARATORS */
5226
5227{
5228 REAL detleft, detright, det;
5229 REAL detsum, errbound;
5230
5231 m->counterclockcount++;
5232
5233 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
5234 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
5235 det = detleft - detright;
5236
5237 if (b->noexact) {
5238 return det;
5239 }
5240
5241 if (detleft > 0.0) {
5242 if (detright <= 0.0) {
5243 return det;
5244 } else {
5245 detsum = detleft + detright;
5246 }
5247 } else if (detleft < 0.0) {
5248 if (detright >= 0.0) {
5249 return det;
5250 } else {
5251 detsum = -detleft - detright;
5252 }
5253 } else {
5254 return det;
5255 }
5256
5257 errbound = ccwerrboundA * detsum;
5258 if ((det >= errbound) || (-det >= errbound)) {
5259 return det;
5260 }
5261
5262 return counterclockwiseadapt(pa, pb, pc, detsum);
5263}
5264
5265/*****************************************************************************/
5266/* */
5267/* incircle() Return a positive value if the point pd lies inside the */
5268/* circle passing through pa, pb, and pc; a negative value if */
5269/* it lies outside; and zero if the four points are cocircular.*/
5270/* The points pa, pb, and pc must be in counterclockwise */
5271/* order, or the sign of the result will be reversed. */
5272/* */
5273/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5274/* result returned is the determinant of a matrix. This determinant is */
5275/* computed adaptively, in the sense that exact arithmetic is used only to */
5276/* the degree it is needed to ensure that the returned value has the */
5277/* correct sign. Hence, this function is usually quite fast, but will run */
5278/* more slowly when the input points are cocircular or nearly so. */
5279/* */
5280/* See my Robust Predicates paper for details. */
5281/* */
5282/*****************************************************************************/
5283
5284#ifdef ANSI_DECLARATORS
5286#else /* not ANSI_DECLARATORS */
5287REAL incircleadapt(pa, pb, pc, pd, permanent)
5288vertex pa;
5289vertex pb;
5290vertex pc;
5291vertex pd;
5292REAL permanent;
5293#endif /* not ANSI_DECLARATORS */
5294
5295{
5296 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
5297 REAL det, errbound;
5298
5299 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5300 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5301 REAL bc[4], ca[4], ab[4];
5302 INEXACT REAL bc3, ca3, ab3;
5303 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
5304 int axbclen, axxbclen, aybclen, ayybclen, alen;
5305 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
5306 int bxcalen, bxxcalen, bycalen, byycalen, blen;
5307 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
5308 int cxablen, cxxablen, cyablen, cyyablen, clen;
5309 REAL abdet[64];
5310 int ablen;
5311 REAL fin1[1152], fin2[1152];
5312 REAL *finnow, *finother, *finswap;
5313 int finlength;
5314
5315 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
5316 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
5317 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
5318 REAL aa[4], bb[4], cc[4];
5319 INEXACT REAL aa3, bb3, cc3;
5320 INEXACT REAL ti1, tj1;
5321 REAL ti0, tj0;
5322 REAL u[4], v[4];
5323 INEXACT REAL u3, v3;
5324 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
5325 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
5326 int temp8len, temp16alen, temp16blen, temp16clen;
5327 int temp32alen, temp32blen, temp48len, temp64len;
5328 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
5329 int axtbblen, axtcclen, aytbblen, aytcclen;
5330 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
5331 int bxtaalen, bxtcclen, bytaalen, bytcclen;
5332 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
5333 int cxtaalen, cxtbblen, cytaalen, cytbblen;
5334 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
5335 int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
5336 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
5337 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
5338 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
5339 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
5340 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
5341 REAL abt[8], bct[8], cat[8];
5342 int abtlen, bctlen, catlen;
5343 REAL abtt[4], bctt[4], catt[4];
5344 int abttlen, bcttlen, cattlen;
5345 INEXACT REAL abtt3, bctt3, catt3;
5346 REAL negate;
5347
5348 INEXACT REAL bvirt;
5349 REAL avirt, bround, around;
5350 INEXACT REAL c;
5351 INEXACT REAL abig;
5352 REAL ahi, alo, bhi, blo;
5353 REAL err1, err2, err3;
5354 INEXACT REAL _i, _j;
5355 REAL _0;
5356
5357 adx = (REAL) (pa[0] - pd[0]);
5358 bdx = (REAL) (pb[0] - pd[0]);
5359 cdx = (REAL) (pc[0] - pd[0]);
5360 ady = (REAL) (pa[1] - pd[1]);
5361 bdy = (REAL) (pb[1] - pd[1]);
5362 cdy = (REAL) (pc[1] - pd[1]);
5363
5364 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
5365 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
5366 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
5367 bc[3] = bc3;
5368 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
5369 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
5370 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
5371 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
5372 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
5373
5374 Two_Product(cdx, ady, cdxady1, cdxady0);
5375 Two_Product(adx, cdy, adxcdy1, adxcdy0);
5376 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
5377 ca[3] = ca3;
5378 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
5379 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
5380 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
5381 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
5382 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
5383
5384 Two_Product(adx, bdy, adxbdy1, adxbdy0);
5385 Two_Product(bdx, ady, bdxady1, bdxady0);
5386 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
5387 ab[3] = ab3;
5388 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
5389 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
5390 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
5391 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
5392 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
5393
5394 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
5395 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
5396
5397 det = estimate(finlength, fin1);
5398 errbound = iccerrboundB * permanent;
5399 if ((det >= errbound) || (-det >= errbound)) {
5400 return det;
5401 }
5402
5403 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
5404 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
5405 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
5406 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
5407 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
5408 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
5409 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
5410 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
5411 return det;
5412 }
5413
5414 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
5415 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
5416 - (bdy * cdxtail + cdx * bdytail))
5417 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
5418 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
5419 - (cdy * adxtail + adx * cdytail))
5420 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
5421 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
5422 - (ady * bdxtail + bdx * adytail))
5423 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
5424 if ((det >= errbound) || (-det >= errbound)) {
5425 return det;
5426 }
5427
5428 finnow = fin1;
5429 finother = fin2;
5430
5431 if ((bdxtail != 0.0) || (bdytail != 0.0)
5432 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5433 Square(adx, adxadx1, adxadx0);
5434 Square(ady, adyady1, adyady0);
5435 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
5436 aa[3] = aa3;
5437 }
5438 if ((cdxtail != 0.0) || (cdytail != 0.0)
5439 || (adxtail != 0.0) || (adytail != 0.0)) {
5440 Square(bdx, bdxbdx1, bdxbdx0);
5441 Square(bdy, bdybdy1, bdybdy0);
5442 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
5443 bb[3] = bb3;
5444 }
5445 if ((adxtail != 0.0) || (adytail != 0.0)
5446 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5447 Square(cdx, cdxcdx1, cdxcdx0);
5448 Square(cdy, cdycdy1, cdycdy0);
5449 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
5450 cc[3] = cc3;
5451 }
5452
5453 if (adxtail != 0.0) {
5454 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
5455 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
5456 temp16a);
5457
5458 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
5459 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
5460
5461 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
5462 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
5463
5464 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5465 temp16blen, temp16b, temp32a);
5466 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5467 temp32alen, temp32a, temp48);
5468 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5469 temp48, finother);
5470 finswap = finnow; finnow = finother; finother = finswap;
5471 }
5472 if (adytail != 0.0) {
5473 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
5474 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
5475 temp16a);
5476
5477 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
5478 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
5479
5480 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
5481 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
5482
5483 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5484 temp16blen, temp16b, temp32a);
5485 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5486 temp32alen, temp32a, temp48);
5487 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5488 temp48, finother);
5489 finswap = finnow; finnow = finother; finother = finswap;
5490 }
5491 if (bdxtail != 0.0) {
5492 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
5493 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
5494 temp16a);
5495
5496 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
5497 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
5498
5499 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
5500 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
5501
5502 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5503 temp16blen, temp16b, temp32a);
5504 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5505 temp32alen, temp32a, temp48);
5506 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5507 temp48, finother);
5508 finswap = finnow; finnow = finother; finother = finswap;
5509 }
5510 if (bdytail != 0.0) {
5511 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
5512 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
5513 temp16a);
5514
5515 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
5516 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
5517
5518 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
5519 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
5520
5521 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5522 temp16blen, temp16b, temp32a);
5523 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5524 temp32alen, temp32a, temp48);
5525 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5526 temp48, finother);
5527 finswap = finnow; finnow = finother; finother = finswap;
5528 }
5529 if (cdxtail != 0.0) {
5530 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
5531 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
5532 temp16a);
5533
5534 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
5535 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
5536
5537 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
5538 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
5539
5540 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5541 temp16blen, temp16b, temp32a);
5542 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5543 temp32alen, temp32a, temp48);
5544 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5545 temp48, finother);
5546 finswap = finnow; finnow = finother; finother = finswap;
5547 }
5548 if (cdytail != 0.0) {
5549 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
5550 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
5551 temp16a);
5552
5553 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
5554 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
5555
5556 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
5557 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
5558
5559 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5560 temp16blen, temp16b, temp32a);
5561 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5562 temp32alen, temp32a, temp48);
5563 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5564 temp48, finother);
5565 finswap = finnow; finnow = finother; finother = finswap;
5566 }
5567
5568 if ((adxtail != 0.0) || (adytail != 0.0)) {
5569 if ((bdxtail != 0.0) || (bdytail != 0.0)
5570 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5571 Two_Product(bdxtail, cdy, ti1, ti0);
5572 Two_Product(bdx, cdytail, tj1, tj0);
5573 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5574 u[3] = u3;
5575 negate = -bdy;
5576 Two_Product(cdxtail, negate, ti1, ti0);
5577 negate = -bdytail;
5578 Two_Product(cdx, negate, tj1, tj0);
5579 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5580 v[3] = v3;
5581 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
5582
5583 Two_Product(bdxtail, cdytail, ti1, ti0);
5584 Two_Product(cdxtail, bdytail, tj1, tj0);
5585 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
5586 bctt[3] = bctt3;
5587 bcttlen = 4;
5588 } else {
5589 bct[0] = 0.0;
5590 bctlen = 1;
5591 bctt[0] = 0.0;
5592 bcttlen = 1;
5593 }
5594
5595 if (adxtail != 0.0) {
5596 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
5597 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
5598 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
5599 temp32a);
5600 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5601 temp32alen, temp32a, temp48);
5602 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5603 temp48, finother);
5604 finswap = finnow; finnow = finother; finother = finswap;
5605 if (bdytail != 0.0) {
5606 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
5607 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
5608 temp16a);
5609 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5610 temp16a, finother);
5611 finswap = finnow; finnow = finother; finother = finswap;
5612 }
5613 if (cdytail != 0.0) {
5614 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
5615 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
5616 temp16a);
5617 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5618 temp16a, finother);
5619 finswap = finnow; finnow = finother; finother = finswap;
5620 }
5621
5622 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
5623 temp32a);
5624 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
5625 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
5626 temp16a);
5627 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
5628 temp16b);
5629 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5630 temp16blen, temp16b, temp32b);
5631 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5632 temp32blen, temp32b, temp64);
5633 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5634 temp64, finother);
5635 finswap = finnow; finnow = finother; finother = finswap;
5636 }
5637 if (adytail != 0.0) {
5638 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
5639 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
5640 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
5641 temp32a);
5642 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5643 temp32alen, temp32a, temp48);
5644 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5645 temp48, finother);
5646 finswap = finnow; finnow = finother; finother = finswap;
5647
5648
5649 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
5650 temp32a);
5651 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
5652 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
5653 temp16a);
5654 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
5655 temp16b);
5656 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5657 temp16blen, temp16b, temp32b);
5658 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5659 temp32blen, temp32b, temp64);
5660 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5661 temp64, finother);
5662 finswap = finnow; finnow = finother; finother = finswap;
5663 }
5664 }
5665 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
5666 if ((cdxtail != 0.0) || (cdytail != 0.0)
5667 || (adxtail != 0.0) || (adytail != 0.0)) {
5668 Two_Product(cdxtail, ady, ti1, ti0);
5669 Two_Product(cdx, adytail, tj1, tj0);
5670 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5671 u[3] = u3;
5672 negate = -cdy;
5673 Two_Product(adxtail, negate, ti1, ti0);
5674 negate = -cdytail;
5675 Two_Product(adx, negate, tj1, tj0);
5676 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5677 v[3] = v3;
5678 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
5679
5680 Two_Product(cdxtail, adytail, ti1, ti0);
5681 Two_Product(adxtail, cdytail, tj1, tj0);
5682 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
5683 catt[3] = catt3;
5684 cattlen = 4;
5685 } else {
5686 cat[0] = 0.0;
5687 catlen = 1;
5688 catt[0] = 0.0;
5689 cattlen = 1;
5690 }
5691
5692 if (bdxtail != 0.0) {
5693 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
5694 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
5695 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
5696 temp32a);
5697 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5698 temp32alen, temp32a, temp48);
5699 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5700 temp48, finother);
5701 finswap = finnow; finnow = finother; finother = finswap;
5702 if (cdytail != 0.0) {
5703 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
5704 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
5705 temp16a);
5706 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5707 temp16a, finother);
5708 finswap = finnow; finnow = finother; finother = finswap;
5709 }
5710 if (adytail != 0.0) {
5711 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
5712 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
5713 temp16a);
5714 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5715 temp16a, finother);
5716 finswap = finnow; finnow = finother; finother = finswap;
5717 }
5718
5719 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
5720 temp32a);
5721 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
5722 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
5723 temp16a);
5724 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
5725 temp16b);
5726 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5727 temp16blen, temp16b, temp32b);
5728 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5729 temp32blen, temp32b, temp64);
5730 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5731 temp64, finother);
5732 finswap = finnow; finnow = finother; finother = finswap;
5733 }
5734 if (bdytail != 0.0) {
5735 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
5736 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
5737 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
5738 temp32a);
5739 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5740 temp32alen, temp32a, temp48);
5741 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5742 temp48, finother);
5743 finswap = finnow; finnow = finother; finother = finswap;
5744
5745
5746 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
5747 temp32a);
5748 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
5749 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
5750 temp16a);
5751 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
5752 temp16b);
5753 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5754 temp16blen, temp16b, temp32b);
5755 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5756 temp32blen, temp32b, temp64);
5757 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5758 temp64, finother);
5759 finswap = finnow; finnow = finother; finother = finswap;
5760 }
5761 }
5762 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
5763 if ((adxtail != 0.0) || (adytail != 0.0)
5764 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5765 Two_Product(adxtail, bdy, ti1, ti0);
5766 Two_Product(adx, bdytail, tj1, tj0);
5767 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5768 u[3] = u3;
5769 negate = -ady;
5770 Two_Product(bdxtail, negate, ti1, ti0);
5771 negate = -adytail;
5772 Two_Product(bdx, negate, tj1, tj0);
5773 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5774 v[3] = v3;
5775 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
5776
5777 Two_Product(adxtail, bdytail, ti1, ti0);
5778 Two_Product(bdxtail, adytail, tj1, tj0);
5779 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
5780 abtt[3] = abtt3;
5781 abttlen = 4;
5782 } else {
5783 abt[0] = 0.0;
5784 abtlen = 1;
5785 abtt[0] = 0.0;
5786 abttlen = 1;
5787 }
5788
5789 if (cdxtail != 0.0) {
5790 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
5791 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
5792 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
5793 temp32a);
5794 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5795 temp32alen, temp32a, temp48);
5796 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5797 temp48, finother);
5798 finswap = finnow; finnow = finother; finother = finswap;
5799 if (adytail != 0.0) {
5800 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
5801 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
5802 temp16a);
5803 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5804 temp16a, finother);
5805 finswap = finnow; finnow = finother; finother = finswap;
5806 }
5807 if (bdytail != 0.0) {
5808 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
5809 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
5810 temp16a);
5811 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5812 temp16a, finother);
5813 finswap = finnow; finnow = finother; finother = finswap;
5814 }
5815
5816 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
5817 temp32a);
5818 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
5819 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
5820 temp16a);
5821 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
5822 temp16b);
5823 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5824 temp16blen, temp16b, temp32b);
5825 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5826 temp32blen, temp32b, temp64);
5827 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5828 temp64, finother);
5829 finswap = finnow; finnow = finother; finother = finswap;
5830 }
5831 if (cdytail != 0.0) {
5832 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
5833 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
5834 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
5835 temp32a);
5836 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5837 temp32alen, temp32a, temp48);
5838 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5839 temp48, finother);
5840 finswap = finnow; finnow = finother; finother = finswap;
5841
5842
5843 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
5844 temp32a);
5845 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
5846 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
5847 temp16a);
5848 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
5849 temp16b);
5850 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5851 temp16blen, temp16b, temp32b);
5852 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5853 temp32blen, temp32b, temp64);
5854 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5855 temp64, finother);
5856 finswap = finnow; finnow = finother; finother = finswap;
5857 }
5858 }
5859
5860 return finnow[finlength - 1];
5861}
5862
5863#ifdef ANSI_DECLARATORS
5864REAL incircle(struct mesh *m, struct behavior *b,
5865 vertex pa, vertex pb, vertex pc, vertex pd)
5866#else /* not ANSI_DECLARATORS */
5867REAL incircle(m, b, pa, pb, pc, pd)
5868struct mesh *m;
5869struct behavior *b;
5870vertex pa;
5871vertex pb;
5872vertex pc;
5873vertex pd;
5874#endif /* not ANSI_DECLARATORS */
5875
5876{
5877 REAL adx, bdx, cdx, ady, bdy, cdy;
5878 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
5879 REAL alift, blift, clift;
5880 REAL det;
5881 REAL permanent, errbound;
5882
5883 m->incirclecount++;
5884
5885 adx = pa[0] - pd[0];
5886 bdx = pb[0] - pd[0];
5887 cdx = pc[0] - pd[0];
5888 ady = pa[1] - pd[1];
5889 bdy = pb[1] - pd[1];
5890 cdy = pc[1] - pd[1];
5891
5892 bdxcdy = bdx * cdy;
5893 cdxbdy = cdx * bdy;
5894 alift = adx * adx + ady * ady;
5895
5896 cdxady = cdx * ady;
5897 adxcdy = adx * cdy;
5898 blift = bdx * bdx + bdy * bdy;
5899
5900 adxbdy = adx * bdy;
5901 bdxady = bdx * ady;
5902 clift = cdx * cdx + cdy * cdy;
5903
5904 det = alift * (bdxcdy - cdxbdy)
5905 + blift * (cdxady - adxcdy)
5906 + clift * (adxbdy - bdxady);
5907
5908 if (b->noexact) {
5909 return det;
5910 }
5911
5912 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
5913 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
5914 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
5915 errbound = iccerrboundA * permanent;
5916 if ((det > errbound) || (-det > errbound)) {
5917 return det;
5918 }
5919
5920 return incircleadapt(pa, pb, pc, pd, permanent);
5921}
5922
5923/*****************************************************************************/
5924/* */
5925/* orient3d() Return a positive value if the point pd lies below the */
5926/* plane passing through pa, pb, and pc; "below" is defined so */
5927/* that pa, pb, and pc appear in counterclockwise order when */
5928/* viewed from above the plane. Returns a negative value if */
5929/* pd lies above the plane. Returns zero if the points are */
5930/* coplanar. The result is also a rough approximation of six */
5931/* times the signed volume of the tetrahedron defined by the */
5932/* four points. */
5933/* */
5934/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5935/* result returned is the determinant of a matrix. This determinant is */
5936/* computed adaptively, in the sense that exact arithmetic is used only to */
5937/* the degree it is needed to ensure that the returned value has the */
5938/* correct sign. Hence, this function is usually quite fast, but will run */
5939/* more slowly when the input points are coplanar or nearly so. */
5940/* */
5941/* See my Robust Predicates paper for details. */
5942/* */
5943/*****************************************************************************/
5944
5945#ifdef ANSI_DECLARATORS
5947 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
5948 REAL permanent)
5949#else /* not ANSI_DECLARATORS */
5950REAL orient3dadapt(pa, pb, pc, pd,
5951 aheight, bheight, cheight, dheight, permanent)
5952vertex pa;
5953vertex pb;
5954vertex pc;
5955vertex pd;
5956REAL aheight;
5957REAL bheight;
5958REAL cheight;
5959REAL dheight;
5960REAL permanent;
5961#endif /* not ANSI_DECLARATORS */
5962
5963{
5964 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
5965 REAL det, errbound;
5966
5967 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5968 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5969 REAL bc[4], ca[4], ab[4];
5970 INEXACT REAL bc3, ca3, ab3;
5971 REAL adet[8], bdet[8], cdet[8];
5972 int alen, blen, clen;
5973 REAL abdet[16];
5974 int ablen;
5975 REAL *finnow, *finother, *finswap;
5976 REAL fin1[192], fin2[192];
5977 int finlength;
5978
5979 REAL adxtail, bdxtail, cdxtail;
5980 REAL adytail, bdytail, cdytail;
5981 REAL adheighttail, bdheighttail, cdheighttail;
5982 INEXACT REAL at_blarge, at_clarge;
5983 INEXACT REAL bt_clarge, bt_alarge;
5984 INEXACT REAL ct_alarge, ct_blarge;
5985 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
5986 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
5987 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
5988 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
5989 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
5990 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
5991 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
5992 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
5993 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
5994 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
5995 REAL bct[8], cat[8], abt[8];
5996 int bctlen, catlen, abtlen;
5997 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
5998 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
5999 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
6000 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
6001 REAL u[4], v[12], w[16];
6002 INEXACT REAL u3;
6003 int vlength, wlength;
6004 REAL negate;
6005
6006 INEXACT REAL bvirt;
6007 REAL avirt, bround, around;
6008 INEXACT REAL c;
6009 INEXACT REAL abig;
6010 REAL ahi, alo, bhi, blo;
6011 REAL err1, err2, err3;
6012 INEXACT REAL _i, _j, _k;
6013 REAL _0;
6014
6015 adx = (REAL) (pa[0] - pd[0]);
6016 bdx = (REAL) (pb[0] - pd[0]);
6017 cdx = (REAL) (pc[0] - pd[0]);
6018 ady = (REAL) (pa[1] - pd[1]);
6019 bdy = (REAL) (pb[1] - pd[1]);
6020 cdy = (REAL) (pc[1] - pd[1]);
6021 adheight = (REAL) (aheight - dheight);
6022 bdheight = (REAL) (bheight - dheight);
6023 cdheight = (REAL) (cheight - dheight);
6024
6025 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
6026 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
6027 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
6028 bc[3] = bc3;
6029 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
6030
6031 Two_Product(cdx, ady, cdxady1, cdxady0);
6032 Two_Product(adx, cdy, adxcdy1, adxcdy0);
6033 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
6034 ca[3] = ca3;
6035 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
6036
6037 Two_Product(adx, bdy, adxbdy1, adxbdy0);
6038 Two_Product(bdx, ady, bdxady1, bdxady0);
6039 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
6040 ab[3] = ab3;
6041 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
6042
6043 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
6044 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
6045
6046 det = estimate(finlength, fin1);
6047 errbound = o3derrboundB * permanent;
6048 if ((det >= errbound) || (-det >= errbound)) {
6049 return det;
6050 }
6051
6052 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
6053 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
6054 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
6055 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
6056 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
6057 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
6058 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
6059 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
6060 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
6061
6062 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
6063 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
6064 (adheighttail == 0.0) &&
6065 (bdheighttail == 0.0) &&
6066 (cdheighttail == 0.0)) {
6067 return det;
6068 }
6069
6070 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
6071 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
6072 (bdy * cdxtail + cdx * bdytail)) +
6073 adheighttail * (bdx * cdy - bdy * cdx)) +
6074 (bdheight * ((cdx * adytail + ady * cdxtail) -
6075 (cdy * adxtail + adx * cdytail)) +
6076 bdheighttail * (cdx * ady - cdy * adx)) +
6077 (cdheight * ((adx * bdytail + bdy * adxtail) -
6078 (ady * bdxtail + bdx * adytail)) +
6079 cdheighttail * (adx * bdy - ady * bdx));
6080 if ((det >= errbound) || (-det >= errbound)) {
6081 return det;
6082 }
6083
6084 finnow = fin1;
6085 finother = fin2;
6086
6087 if (adxtail == 0.0) {
6088 if (adytail == 0.0) {
6089 at_b[0] = 0.0;
6090 at_blen = 1;
6091 at_c[0] = 0.0;
6092 at_clen = 1;
6093 } else {
6094 negate = -adytail;
6095 Two_Product(negate, bdx, at_blarge, at_b[0]);
6096 at_b[1] = at_blarge;
6097 at_blen = 2;
6098 Two_Product(adytail, cdx, at_clarge, at_c[0]);
6099 at_c[1] = at_clarge;
6100 at_clen = 2;
6101 }
6102 } else {
6103 if (adytail == 0.0) {
6104 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
6105 at_b[1] = at_blarge;
6106 at_blen = 2;
6107 negate = -adxtail;
6108 Two_Product(negate, cdy, at_clarge, at_c[0]);
6109 at_c[1] = at_clarge;
6110 at_clen = 2;
6111 } else {
6112 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
6113 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
6114 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
6115 at_blarge, at_b[2], at_b[1], at_b[0]);
6116 at_b[3] = at_blarge;
6117 at_blen = 4;
6118 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
6119 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
6120 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
6121 at_clarge, at_c[2], at_c[1], at_c[0]);
6122 at_c[3] = at_clarge;
6123 at_clen = 4;
6124 }
6125 }
6126 if (bdxtail == 0.0) {
6127 if (bdytail == 0.0) {
6128 bt_c[0] = 0.0;
6129 bt_clen = 1;
6130 bt_a[0] = 0.0;
6131 bt_alen = 1;
6132 } else {
6133 negate = -bdytail;
6134 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
6135 bt_c[1] = bt_clarge;
6136 bt_clen = 2;
6137 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
6138 bt_a[1] = bt_alarge;
6139 bt_alen = 2;
6140 }
6141 } else {
6142 if (bdytail == 0.0) {
6143 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
6144 bt_c[1] = bt_clarge;
6145 bt_clen = 2;
6146 negate = -bdxtail;
6147 Two_Product(negate, ady, bt_alarge, bt_a[0]);
6148 bt_a[1] = bt_alarge;
6149 bt_alen = 2;
6150 } else {
6151 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
6152 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
6153 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
6154 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
6155 bt_c[3] = bt_clarge;
6156 bt_clen = 4;
6157 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
6158 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
6159 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
6160 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
6161 bt_a[3] = bt_alarge;
6162 bt_alen = 4;
6163 }
6164 }
6165 if (cdxtail == 0.0) {
6166 if (cdytail == 0.0) {
6167 ct_a[0] = 0.0;
6168 ct_alen = 1;
6169 ct_b[0] = 0.0;
6170 ct_blen = 1;
6171 } else {
6172 negate = -cdytail;
6173 Two_Product(negate, adx, ct_alarge, ct_a[0]);
6174 ct_a[1] = ct_alarge;
6175 ct_alen = 2;
6176 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
6177 ct_b[1] = ct_blarge;
6178 ct_blen = 2;
6179 }
6180 } else {
6181 if (cdytail == 0.0) {
6182 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
6183 ct_a[1] = ct_alarge;
6184 ct_alen = 2;
6185 negate = -cdxtail;
6186 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
6187 ct_b[1] = ct_blarge;
6188 ct_blen = 2;
6189 } else {
6190 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
6191 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
6192 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
6193 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
6194 ct_a[3] = ct_alarge;
6195 ct_alen = 4;
6196 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
6197 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
6198 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
6199 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
6200 ct_b[3] = ct_blarge;
6201 ct_blen = 4;
6202 }
6203 }
6204
6205 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
6206 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
6207 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6208 finother);
6209 finswap = finnow; finnow = finother; finother = finswap;
6210
6211 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
6212 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
6213 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6214 finother);
6215 finswap = finnow; finnow = finother; finother = finswap;
6216
6217 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
6218 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
6219 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6220 finother);
6221 finswap = finnow; finnow = finother; finother = finswap;
6222
6223 if (adheighttail != 0.0) {
6224 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
6225 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6226 finother);
6227 finswap = finnow; finnow = finother; finother = finswap;
6228 }
6229 if (bdheighttail != 0.0) {
6230 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
6231 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6232 finother);
6233 finswap = finnow; finnow = finother; finother = finswap;
6234 }
6235 if (cdheighttail != 0.0) {
6236 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
6237 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6238 finother);
6239 finswap = finnow; finnow = finother; finother = finswap;
6240 }
6241
6242 if (adxtail != 0.0) {
6243 if (bdytail != 0.0) {
6244 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
6245 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
6246 u[3] = u3;
6247 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6248 finother);
6249 finswap = finnow; finnow = finother; finother = finswap;
6250 if (cdheighttail != 0.0) {
6251 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
6252 u3, u[2], u[1], u[0]);
6253 u[3] = u3;
6254 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6255 finother);
6256 finswap = finnow; finnow = finother; finother = finswap;
6257 }
6258 }
6259 if (cdytail != 0.0) {
6260 negate = -adxtail;
6261 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
6262 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
6263 u[3] = u3;
6264 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6265 finother);
6266 finswap = finnow; finnow = finother; finother = finswap;
6267 if (bdheighttail != 0.0) {
6268 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
6269 u3, u[2], u[1], u[0]);
6270 u[3] = u3;
6271 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6272 finother);
6273 finswap = finnow; finnow = finother; finother = finswap;
6274 }
6275 }
6276 }
6277 if (bdxtail != 0.0) {
6278 if (cdytail != 0.0) {
6279 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
6280 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
6281 u[3] = u3;
6282 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6283 finother);
6284 finswap = finnow; finnow = finother; finother = finswap;
6285 if (adheighttail != 0.0) {
6286 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
6287 u3, u[2], u[1], u[0]);
6288 u[3] = u3;
6289 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6290 finother);
6291 finswap = finnow; finnow = finother; finother = finswap;
6292 }
6293 }
6294 if (adytail != 0.0) {
6295 negate = -bdxtail;
6296 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
6297 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
6298 u[3] = u3;
6299 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6300 finother);
6301 finswap = finnow; finnow = finother; finother = finswap;
6302 if (cdheighttail != 0.0) {
6303 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
6304 u3, u[2], u[1], u[0]);
6305 u[3] = u3;
6306 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6307 finother);
6308 finswap = finnow; finnow = finother; finother = finswap;
6309 }
6310 }
6311 }
6312 if (cdxtail != 0.0) {
6313 if (adytail != 0.0) {
6314 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
6315 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
6316 u[3] = u3;
6317 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6318 finother);
6319 finswap = finnow; finnow = finother; finother = finswap;
6320 if (bdheighttail != 0.0) {
6321 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
6322 u3, u[2], u[1], u[0]);
6323 u[3] = u3;
6324 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6325 finother);
6326 finswap = finnow; finnow = finother; finother = finswap;
6327 }
6328 }
6329 if (bdytail != 0.0) {
6330 negate = -cdxtail;
6331 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
6332 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
6333 u[3] = u3;
6334 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6335 finother);
6336 finswap = finnow; finnow = finother; finother = finswap;
6337 if (adheighttail != 0.0) {
6338 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
6339 u3, u[2], u[1], u[0]);
6340 u[3] = u3;
6341 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6342 finother);
6343 finswap = finnow; finnow = finother; finother = finswap;
6344 }
6345 }
6346 }
6347
6348 if (adheighttail != 0.0) {
6349 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
6350 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6351 finother);
6352 finswap = finnow; finnow = finother; finother = finswap;
6353 }
6354 if (bdheighttail != 0.0) {
6355 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
6356 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6357 finother);
6358 finswap = finnow; finnow = finother; finother = finswap;
6359 }
6360 if (cdheighttail != 0.0) {
6361 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
6362 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6363 finother);
6364 finswap = finnow; finnow = finother; finother = finswap;
6365 }
6366
6367 return finnow[finlength - 1];
6368}
6369
6370#ifdef ANSI_DECLARATORS
6371REAL orient3d(struct mesh *m, struct behavior *b,
6372 vertex pa, vertex pb, vertex pc, vertex pd,
6373 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
6374#else /* not ANSI_DECLARATORS */
6375REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
6376struct mesh *m;
6377struct behavior *b;
6378vertex pa;
6379vertex pb;
6380vertex pc;
6381vertex pd;
6382REAL aheight;
6383REAL bheight;
6384REAL cheight;
6385REAL dheight;
6386#endif /* not ANSI_DECLARATORS */
6387
6388{
6389 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6390 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
6391 REAL det;
6392 REAL permanent, errbound;
6393
6394 m->orient3dcount++;
6395
6396 adx = pa[0] - pd[0];
6397 bdx = pb[0] - pd[0];
6398 cdx = pc[0] - pd[0];
6399 ady = pa[1] - pd[1];
6400 bdy = pb[1] - pd[1];
6401 cdy = pc[1] - pd[1];
6402 adheight = aheight - dheight;
6403 bdheight = bheight - dheight;
6404 cdheight = cheight - dheight;
6405
6406 bdxcdy = bdx * cdy;
6407 cdxbdy = cdx * bdy;
6408
6409 cdxady = cdx * ady;
6410 adxcdy = adx * cdy;
6411
6412 adxbdy = adx * bdy;
6413 bdxady = bdx * ady;
6414
6415 det = adheight * (bdxcdy - cdxbdy)
6416 + bdheight * (cdxady - adxcdy)
6417 + cdheight * (adxbdy - bdxady);
6418
6419 if (b->noexact) {
6420 return det;
6421 }
6422
6423 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
6424 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
6425 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
6426 errbound = o3derrboundA * permanent;
6427 if ((det > errbound) || (-det > errbound)) {
6428 return det;
6429 }
6430
6431 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
6432 permanent);
6433}
6434
6435/*****************************************************************************/
6436/* */
6437/* nonregular() Return a positive value if the point pd is incompatible */
6438/* with the circle or plane passing through pa, pb, and pc */
6439/* (meaning that pd is inside the circle or below the */
6440/* plane); a negative value if it is compatible; and zero if */
6441/* the four points are cocircular/coplanar. The points pa, */
6442/* pb, and pc must be in counterclockwise order, or the sign */
6443/* of the result will be reversed. */
6444/* */
6445/* If the -w switch is used, the points are lifted onto the parabolic */
6446/* lifting map, then they are dropped according to their weights, then the */
6447/* 3D orientation test is applied. If the -W switch is used, the points' */
6448/* heights are already provided, so the 3D orientation test is applied */
6449/* directly. If neither switch is used, the incircle test is applied. */
6450/* */
6451/*****************************************************************************/
6452
6453#ifdef ANSI_DECLARATORS
6454REAL nonregular(struct mesh *m, struct behavior *b,
6455 vertex pa, vertex pb, vertex pc, vertex pd)
6456#else /* not ANSI_DECLARATORS */
6457REAL nonregular(m, b, pa, pb, pc, pd)
6458struct mesh *m;
6459struct behavior *b;
6460vertex pa;
6461vertex pb;
6462vertex pc;
6463vertex pd;
6464#endif /* not ANSI_DECLARATORS */
6465
6466{
6467 if (b->weighted == 0) {
6468 return incircle(m, b, pa, pb, pc, pd);
6469 } else if (b->weighted == 1) {
6470 return orient3d(m, b, pa, pb, pc, pd,
6471 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
6472 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
6473 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
6474 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
6475 } else {
6476 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
6477 }
6478}
6479
6480/*****************************************************************************/
6481/* */
6482/* findcircumcenter() Find the circumcenter of a triangle. */
6483/* */
6484/* The result is returned both in terms of x-y coordinates and xi-eta */
6485/* (barycentric) coordinates. The xi-eta coordinate system is defined in */
6486/* terms of the triangle: the origin of the triangle is the origin of the */
6487/* coordinate system; the destination of the triangle is one unit along the */
6488/* xi axis; and the apex of the triangle is one unit along the eta axis. */
6489/* This procedure also returns the square of the length of the triangle's */
6490/* shortest edge. */
6491/* */
6492/*****************************************************************************/
6493
6494#ifdef ANSI_DECLARATORS
6495void findcircumcenter(struct mesh *m, struct behavior *b,
6496 vertex torg, vertex tdest, vertex tapex,
6497 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
6498#else /* not ANSI_DECLARATORS */
6499void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
6500 offcenter)
6501struct mesh *m;
6502struct behavior *b;
6503vertex torg;
6504vertex tdest;
6505vertex tapex;
6506vertex circumcenter;
6507REAL *xi;
6508REAL *eta;
6509int offcenter;
6510#endif /* not ANSI_DECLARATORS */
6511
6512{
6513 REAL xdo, ydo, xao, yao;
6514 REAL dodist, aodist, dadist;
6515 REAL denominator;
6516 REAL dx, dy, dxoff, dyoff;
6517
6518 m->circumcentercount++;
6519
6520 /* Compute the circumcenter of the triangle. */
6521 xdo = tdest[0] - torg[0];
6522 ydo = tdest[1] - torg[1];
6523 xao = tapex[0] - torg[0];
6524 yao = tapex[1] - torg[1];
6525 dodist = xdo * xdo + ydo * ydo;
6526 aodist = xao * xao + yao * yao;
6527 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
6528 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
6529 if (b->noexact) {
6530 denominator = 0.5 / (xdo * yao - xao * ydo);
6531 } else {
6532 /* Use the counterclockwise() routine to ensure a positive (and */
6533 /* reasonably accurate) result, avoiding any possibility of */
6534 /* division by zero. */
6535 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
6536 /* Don't count the above as an orientation test. */
6537 m->counterclockcount--;
6538 }
6539 dx = (yao * dodist - ydo * aodist) * denominator;
6540 dy = (xdo * aodist - xao * dodist) * denominator;
6541
6542 /* Find the (squared) length of the triangle's shortest edge. This */
6543 /* serves as a conservative estimate of the insertion radius of the */
6544 /* circumcenter's parent. The estimate is used to ensure that */
6545 /* the algorithm terminates even if very small angles appear in */
6546 /* the input PSLG. */
6547 if ((dodist < aodist) && (dodist < dadist)) {
6548 if (offcenter && (b->offconstant > 0.0)) {
6549 /* Find the position of the off-center, as described by Alper Ungor. */
6550 dxoff = 0.5 * xdo - b->offconstant * ydo;
6551 dyoff = 0.5 * ydo + b->offconstant * xdo;
6552 /* If the off-center is closer to the origin than the */
6553 /* circumcenter, use the off-center instead. */
6554 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6555 dx = dxoff;
6556 dy = dyoff;
6557 }
6558 }
6559 } else if (aodist < dadist) {
6560 if (offcenter && (b->offconstant > 0.0)) {
6561 dxoff = 0.5 * xao + b->offconstant * yao;
6562 dyoff = 0.5 * yao - b->offconstant * xao;
6563 /* If the off-center is closer to the origin than the */
6564 /* circumcenter, use the off-center instead. */
6565 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6566 dx = dxoff;
6567 dy = dyoff;
6568 }
6569 }
6570 } else {
6571 if (offcenter && (b->offconstant > 0.0)) {
6572 dxoff = 0.5 * (tapex[0] - tdest[0]) -
6573 b->offconstant * (tapex[1] - tdest[1]);
6574 dyoff = 0.5 * (tapex[1] - tdest[1]) +
6575 b->offconstant * (tapex[0] - tdest[0]);
6576 /* If the off-center is closer to the destination than the */
6577 /* circumcenter, use the off-center instead. */
6578 if (dxoff * dxoff + dyoff * dyoff <
6579 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
6580 dx = xdo + dxoff;
6581 dy = ydo + dyoff;
6582 }
6583 }
6584 }
6585
6586 circumcenter[0] = torg[0] + dx;
6587 circumcenter[1] = torg[1] + dy;
6588
6589 /* To interpolate vertex attributes for the new vertex inserted at */
6590 /* the circumcenter, define a coordinate system with a xi-axis, */
6591 /* directed from the triangle's origin to its destination, and */
6592 /* an eta-axis, directed from its origin to its apex. */
6593 /* Calculate the xi and eta coordinates of the circumcenter. */
6594 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
6595 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
6596}
6597
6598/** **/
6599/** **/
6600/********* Geometric primitives end here *********/
6601
6602/*****************************************************************************/
6603/* */
6604/* triangleinit() Initialize some variables. */
6605/* */
6606/*****************************************************************************/
6607
6608#ifdef ANSI_DECLARATORS
6609void triangleinit(struct mesh *m)
6610#else /* not ANSI_DECLARATORS */
6611void triangleinit(m)
6612struct mesh *m;
6613#endif /* not ANSI_DECLARATORS */
6614
6615{
6616 poolzero(&m->vertices);
6617 poolzero(&m->triangles);
6618 poolzero(&m->subsegs);
6619 poolzero(&m->viri);
6620 poolzero(&m->badsubsegs);
6621 poolzero(&m->badtriangles);
6622 poolzero(&m->flipstackers);
6623 poolzero(&m->splaynodes);
6624
6625 m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */
6626 m->undeads = 0; /* No eliminated input vertices yet. */
6627 m->samples = 1; /* Point location should take at least one sample. */
6628 m->checksegments = 0; /* There are no segments in the triangulation yet. */
6629 m->checkquality = 0; /* The quality triangulation stage has not begun. */
6630 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
6631 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
6632 randomseed = 1;
6633
6634 exactinit(); /* Initialize exact arithmetic constants. */
6635}
6636
6637/*****************************************************************************/
6638/* */
6639/* randomnation() Generate a random number between 0 and `choices' - 1. */
6640/* */
6641/* This is a simple linear congruential random number generator. Hence, it */
6642/* is a bad random number generator, but good enough for most randomized */
6643/* geometric algorithms. */
6644/* */
6645/*****************************************************************************/
6646
6647#ifdef ANSI_DECLARATORS
6648uintptr_t randomnation(unsigned int choices)
6649#else /* not ANSI_DECLARATORS */
6650uintptr_t randomnation(choices)
6651unsigned int choices;
6652#endif /* not ANSI_DECLARATORS */
6653
6654{
6655 randomseed = (randomseed * 1366l + 150889l) % 714025l;
6656 return randomseed / (714025l / choices + 1);
6657}
6658
6659/********* Mesh quality testing routines begin here *********/
6660/** **/
6661/** **/
6662
6663/*****************************************************************************/
6664/* */
6665/* checkmesh() Test the mesh for topological consistency. */
6666/* */
6667/*****************************************************************************/
6668
6669#ifndef REDUCED
6670
6671#ifdef ANSI_DECLARATORS
6672void checkmesh(struct mesh *m, struct behavior *b)
6673#else /* not ANSI_DECLARATORS */
6674void checkmesh(m, b)
6675struct mesh *m;
6676struct behavior *b;
6677#endif /* not ANSI_DECLARATORS */
6678
6679{
6680 struct otri triangleloop;
6681 struct otri oppotri, oppooppotri;
6682 vertex triorg, tridest, triapex;
6683 vertex oppoorg, oppodest;
6684 int horrors;
6685 int saveexact;
6686 triangle ptr; /* Temporary variable used by sym(). */
6687
6688 /* Temporarily turn on exact arithmetic if it's off. */
6689 saveexact = b->noexact;
6690 b->noexact = 0;
6691 if (!b->quiet) {
6692 printf(" Checking consistency of mesh...\n");
6693 }
6694 horrors = 0;
6695 /* Run through the list of triangles, checking each one. */
6696 traversalinit(&m->triangles);
6697 triangleloop.tri = triangletraverse(m);
6698 while (triangleloop.tri != (triangle *) NULL) {
6699 /* Check all three edges of the triangle. */
6700 for (triangleloop.orient = 0; triangleloop.orient < 3;
6701 triangleloop.orient++) {
6702 org(triangleloop, triorg);
6703 dest(triangleloop, tridest);
6704 if (triangleloop.orient == 0) { /* Only test for inversion once. */
6705 /* Test if the triangle is flat or inverted. */
6706 apex(triangleloop, triapex);
6707 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
6708 printf(" !! !! Inverted ");
6709 printtriangle(m, b, &triangleloop);
6710 horrors++;
6711 }
6712 }
6713 /* Find the neighboring triangle on this edge. */
6714 sym(triangleloop, oppotri);
6715 if (oppotri.tri != m->dummytri) {
6716 /* Check that the triangle's neighbor knows it's a neighbor. */
6717 sym(oppotri, oppooppotri);
6718 if ((triangleloop.tri != oppooppotri.tri)
6719 || (triangleloop.orient != oppooppotri.orient)) {
6720 printf(" !! !! Asymmetric triangle-triangle bond:\n");
6721 if (triangleloop.tri == oppooppotri.tri) {
6722 printf(" (Right triangle, wrong orientation)\n");
6723 }
6724 printf(" First ");
6725 printtriangle(m, b, &triangleloop);
6726 printf(" Second (nonreciprocating) ");
6727 printtriangle(m, b, &oppotri);
6728 horrors++;
6729 }
6730 /* Check that both triangles agree on the identities */
6731 /* of their shared vertices. */
6732 org(oppotri, oppoorg);
6733 dest(oppotri, oppodest);
6734 if ((triorg != oppodest) || (tridest != oppoorg)) {
6735 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
6736 );
6737 printf(" First mismatched ");
6738 printtriangle(m, b, &triangleloop);
6739 printf(" Second mismatched ");
6740 printtriangle(m, b, &oppotri);
6741 horrors++;
6742 }
6743 }
6744 }
6745 triangleloop.tri = triangletraverse(m);
6746 }
6747 if (horrors == 0) {
6748 if (!b->quiet) {
6749 printf(" In my studied opinion, the mesh appears to be consistent.\n");
6750 }
6751 } else if (horrors == 1) {
6752 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
6753 } else {
6754 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
6755 }
6756 /* Restore the status of exact arithmetic. */
6757 b->noexact = saveexact;
6758}
6759
6760#endif /* not REDUCED */
6761
6762/*****************************************************************************/
6763/* */
6764/* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */
6765/* */
6766/*****************************************************************************/
6767
6768#ifndef REDUCED
6769
6770#ifdef ANSI_DECLARATORS
6771void checkdelaunay(struct mesh *m, struct behavior *b)
6772#else /* not ANSI_DECLARATORS */
6773void checkdelaunay(m, b)
6774struct mesh *m;
6775struct behavior *b;
6776#endif /* not ANSI_DECLARATORS */
6777
6778{
6779 struct otri triangleloop;
6780 struct otri oppotri;
6781 struct osub opposubseg;
6782 vertex triorg, tridest, triapex;
6783 vertex oppoapex;
6784 int shouldbedelaunay;
6785 int horrors;
6786 int saveexact;
6787 triangle ptr; /* Temporary variable used by sym(). */
6788 subseg sptr; /* Temporary variable used by tspivot(). */
6789
6790 /* Temporarily turn on exact arithmetic if it's off. */
6791 saveexact = b->noexact;
6792 b->noexact = 0;
6793 if (!b->quiet) {
6794 printf(" Checking Delaunay property of mesh...\n");
6795 }
6796 horrors = 0;
6797 /* Run through the list of triangles, checking each one. */
6798 traversalinit(&m->triangles);
6799 triangleloop.tri = triangletraverse(m);
6800 while (triangleloop.tri != (triangle *) NULL) {
6801 /* Check all three edges of the triangle. */
6802 for (triangleloop.orient = 0; triangleloop.orient < 3;
6803 triangleloop.orient++) {
6804 org(triangleloop, triorg);
6805 dest(triangleloop, tridest);
6806 apex(triangleloop, triapex);
6807 sym(triangleloop, oppotri);
6808 apex(oppotri, oppoapex);
6809 /* Only test that the edge is locally Delaunay if there is an */
6810 /* adjoining triangle whose pointer is larger (to ensure that */
6811 /* each pair isn't tested twice). */
6812 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
6813 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
6814 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
6815 (triorg != m->infvertex3) &&
6816 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
6817 (tridest != m->infvertex3) &&
6818 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
6819 (triapex != m->infvertex3) &&
6820 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
6821 (oppoapex != m->infvertex3);
6822 if (m->checksegments && shouldbedelaunay) {
6823 /* If a subsegment separates the triangles, then the edge is */
6824 /* constrained, so no local Delaunay test should be done. */
6825 tspivot(triangleloop, opposubseg);
6826 if (opposubseg.ss != m->dummysub){
6827 shouldbedelaunay = 0;
6828 }
6829 }
6830 if (shouldbedelaunay) {
6831 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
6832 if (!b->weighted) {
6833 printf(" !! !! Non-Delaunay pair of triangles:\n");
6834 printf(" First non-Delaunay ");
6835 printtriangle(m, b, &triangleloop);
6836 printf(" Second non-Delaunay ");
6837 } else {
6838 printf(" !! !! Non-regular pair of triangles:\n");
6839 printf(" First non-regular ");
6840 printtriangle(m, b, &triangleloop);
6841 printf(" Second non-regular ");
6842 }
6843 printtriangle(m, b, &oppotri);
6844 horrors++;
6845 }
6846 }
6847 }
6848 triangleloop.tri = triangletraverse(m);
6849 }
6850 if (horrors == 0) {
6851 if (!b->quiet) {
6852 printf(
6853 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
6854 }
6855 } else if (horrors == 1) {
6856 printf(
6857 " !! !! !! !! Precisely one terrifying transgression identified.\n");
6858 } else {
6859 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
6860 }
6861 /* Restore the status of exact arithmetic. */
6862 b->noexact = saveexact;
6863}
6864
6865#endif /* not REDUCED */
6866
6867/*****************************************************************************/
6868/* */
6869/* enqueuebadtriang() Add a bad triangle data structure to the end of a */
6870/* queue. */
6871/* */
6872/* The queue is actually a set of 4096 queues. I use multiple queues to */
6873/* give priority to smaller angles. I originally implemented a heap, but */
6874/* the queues are faster by a larger margin than I'd suspected. */
6875/* */
6876/*****************************************************************************/
6877
6878#ifndef CDT_ONLY
6879
6880#ifdef ANSI_DECLARATORS
6881void enqueuebadtriang(struct mesh *m, struct behavior *b,
6882 struct badtriang *badtri)
6883#else /* not ANSI_DECLARATORS */
6884void enqueuebadtriang(m, b, badtri)
6885struct mesh *m;
6886struct behavior *b;
6887struct badtriang *badtri;
6888#endif /* not ANSI_DECLARATORS */
6889
6890{
6891 REAL length, multiplier;
6892 int exponent, expincrement;
6893 int queuenumber;
6894 int posexponent;
6895 int i;
6896
6897 if (b->verbose > 2) {
6898 printf(" Queueing bad triangle:\n");
6899 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
6900 badtri->triangorg[0], badtri->triangorg[1],
6901 badtri->triangdest[0], badtri->triangdest[1],
6902 badtri->triangapex[0], badtri->triangapex[1]);
6903 }
6904
6905 /* Determine the appropriate queue to put the bad triangle into. */
6906 /* Recall that the key is the square of its shortest edge length. */
6907 if (badtri->key >= 1.0) {
6908 length = badtri->key;
6909 posexponent = 1;
6910 } else {
6911 /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */
6912 /* fact and use the reciprocal of `badtri->key', which is > 1.0. */
6913 length = 1.0 / badtri->key;
6914 posexponent = 0;
6915 }
6916 /* `length' is approximately 2.0 to what exponent? The following code */
6917 /* determines the answer in time logarithmic in the exponent. */
6918 exponent = 0;
6919 while (length > 2.0) {
6920 /* Find an approximation by repeated squaring of two. */
6921 expincrement = 1;
6922 multiplier = 0.5;
6923 while (length * multiplier * multiplier > 1.0) {
6924 expincrement *= 2;
6925 multiplier *= multiplier;
6926 }
6927 /* Reduce the value of `length', then iterate if necessary. */
6928 exponent += expincrement;
6929 length *= multiplier;
6930 }
6931 /* `length' is approximately squareroot(2.0) to what exponent? */
6932 exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
6933 /* `exponent' is now in the range 0...2047 for IEEE double precision. */
6934 /* Choose a queue in the range 0...4095. The shortest edges have the */
6935 /* highest priority (queue 4095). */
6936 if (posexponent) {
6937 queuenumber = 2047 - exponent;
6938 } else {
6939 queuenumber = 2048 + exponent;
6940 }
6941
6942 /* Are we inserting into an empty queue? */
6943 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
6944 /* Yes, we are inserting into an empty queue. */
6945 /* Will this become the highest-priority queue? */
6946 if (queuenumber > m->firstnonemptyq) {
6947 /* Yes, this is the highest-priority queue. */
6948 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
6949 m->firstnonemptyq = queuenumber;
6950 } else {
6951 /* No, this is not the highest-priority queue. */
6952 /* Find the queue with next higher priority. */
6953 i = queuenumber + 1;
6954 while (m->queuefront[i] == (struct badtriang *) NULL) {
6955 i++;
6956 }
6957 /* Mark the newly nonempty queue as following a higher-priority queue. */
6958 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
6959 m->nextnonemptyq[i] = queuenumber;
6960 }
6961 /* Put the bad triangle at the beginning of the (empty) queue. */
6962 m->queuefront[queuenumber] = badtri;
6963 } else {
6964 /* Add the bad triangle to the end of an already nonempty queue. */
6965 m->queuetail[queuenumber]->nexttriang = badtri;
6966 }
6967 /* Maintain a pointer to the last triangle of the queue. */
6968 m->queuetail[queuenumber] = badtri;
6969 /* Newly enqueued bad triangle has no successor in the queue. */
6970 badtri->nexttriang = (struct badtriang *) NULL;
6971}
6972
6973#endif /* not CDT_ONLY */
6974
6975/*****************************************************************************/
6976/* */
6977/* enqueuebadtri() Add a bad triangle to the end of a queue. */
6978/* */
6979/* Allocates a badtriang data structure for the triangle, then passes it to */
6980/* enqueuebadtriang(). */
6981/* */
6982/*****************************************************************************/
6983
6984#ifndef CDT_ONLY
6985
6986#ifdef ANSI_DECLARATORS
6987void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
6988 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
6989#else /* not ANSI_DECLARATORS */
6990void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
6991struct mesh *m;
6992struct behavior *b;
6993struct otri *enqtri;
6994REAL minedge;
6995vertex enqapex;
6996vertex enqorg;
6997vertex enqdest;
6998#endif /* not ANSI_DECLARATORS */
6999
7000{
7001 struct badtriang *newbad;
7002
7003 /* Allocate space for the bad triangle. */
7004 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
7005 newbad->poortri = encode(*enqtri);
7006 newbad->key = minedge;
7007 newbad->triangapex = enqapex;
7008 newbad->triangorg = enqorg;
7009 newbad->triangdest = enqdest;
7010 enqueuebadtriang(m, b, newbad);
7011}
7012
7013#endif /* not CDT_ONLY */
7014
7015/*****************************************************************************/
7016/* */
7017/* dequeuebadtriang() Remove a triangle from the front of the queue. */
7018/* */
7019/*****************************************************************************/
7020
7021#ifndef CDT_ONLY
7022
7023#ifdef ANSI_DECLARATORS
7024struct badtriang *dequeuebadtriang(struct mesh *m)
7025#else /* not ANSI_DECLARATORS */
7026struct badtriang *dequeuebadtriang(m)
7027struct mesh *m;
7028#endif /* not ANSI_DECLARATORS */
7029
7030{
7031 struct badtriang *result;
7032
7033 /* If no queues are nonempty, return NULL. */
7034 if (m->firstnonemptyq < 0) {
7035 return (struct badtriang *) NULL;
7036 }
7037 /* Find the first triangle of the highest-priority queue. */
7038 result = m->queuefront[m->firstnonemptyq];
7039 /* Remove the triangle from the queue. */
7040 m->queuefront[m->firstnonemptyq] = result->nexttriang;
7041 /* If this queue is now empty, note the new highest-priority */
7042 /* nonempty queue. */
7043 if (result == m->queuetail[m->firstnonemptyq]) {
7044 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
7045 }
7046 return result;
7047}
7048
7049#endif /* not CDT_ONLY */
7050
7051/*****************************************************************************/
7052/* */
7053/* checkseg4encroach() Check a subsegment to see if it is encroached; add */
7054/* it to the list if it is. */
7055/* */
7056/* A subsegment is encroached if there is a vertex in its diametral lens. */
7057/* For Ruppert's algorithm (-D switch), the "diametral lens" is the */
7058/* diametral circle. For Chew's algorithm (default), the diametral lens is */
7059/* just big enough to enclose two isosceles triangles whose bases are the */
7060/* subsegment. Each of the two isosceles triangles has two angles equal */
7061/* to `b->minangle'. */
7062/* */
7063/* Chew's algorithm does not require diametral lenses at all--but they save */
7064/* time. Any vertex inside a subsegment's diametral lens implies that the */
7065/* triangle adjoining the subsegment will be too skinny, so it's only a */
7066/* matter of time before the encroaching vertex is deleted by Chew's */
7067/* algorithm. It's faster to simply not insert the doomed vertex in the */
7068/* first place, which is why I use diametral lenses with Chew's algorithm. */
7069/* */
7070/* Returns a nonzero value if the subsegment is encroached. */
7071/* */
7072/*****************************************************************************/
7073
7074#ifndef CDT_ONLY
7075
7076#ifdef ANSI_DECLARATORS
7077int checkseg4encroach(struct mesh *m, struct behavior *b,
7078 struct osub *testsubseg)
7079#else /* not ANSI_DECLARATORS */
7080int checkseg4encroach(m, b, testsubseg)
7081struct mesh *m;
7082struct behavior *b;
7083struct osub *testsubseg;
7084#endif /* not ANSI_DECLARATORS */
7085
7086{
7087 struct otri neighbortri;
7088 struct osub testsym;
7089 struct badsubseg *encroachedseg;
7090 REAL dotproduct;
7091 int encroached;
7092 int sides;
7093 vertex eorg, edest, eapex;
7094 triangle ptr; /* Temporary variable used by stpivot(). */
7095
7096 encroached = 0;
7097 sides = 0;
7098
7099 sorg(*testsubseg, eorg);
7100 sdest(*testsubseg, edest);
7101 /* Check one neighbor of the subsegment. */
7102 stpivot(*testsubseg, neighbortri);
7103 /* Does the neighbor exist, or is this a boundary edge? */
7104 if (neighbortri.tri != m->dummytri) {
7105 sides++;
7106 /* Find a vertex opposite this subsegment. */
7107 apex(neighbortri, eapex);
7108 /* Check whether the apex is in the diametral lens of the subsegment */
7109 /* (the diametral circle if `conformdel' is set). A dot product */
7110 /* of two sides of the triangle is used to check whether the angle */
7111 /* at the apex is greater than (180 - 2 `minangle') degrees (for */
7112 /* lenses; 90 degrees for diametral circles). */
7113 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7114 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7115 if (dotproduct < 0.0) {
7116 if (b->conformdel ||
7117 (dotproduct * dotproduct >=
7118 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7119 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7120 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7121 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7122 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7123 encroached = 1;
7124 }
7125 }
7126 }
7127 /* Check the other neighbor of the subsegment. */
7128 ssym(*testsubseg, testsym);
7129 stpivot(testsym, neighbortri);
7130 /* Does the neighbor exist, or is this a boundary edge? */
7131 if (neighbortri.tri != m->dummytri) {
7132 sides++;
7133 /* Find the other vertex opposite this subsegment. */
7134 apex(neighbortri, eapex);
7135 /* Check whether the apex is in the diametral lens of the subsegment */
7136 /* (or the diametral circle, if `conformdel' is set). */
7137 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7138 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7139 if (dotproduct < 0.0) {
7140 if (b->conformdel ||
7141 (dotproduct * dotproduct >=
7142 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7143 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7144 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7145 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7146 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7147 encroached += 2;
7148 }
7149 }
7150 }
7151
7152 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
7153 if (b->verbose > 2) {
7154 printf(
7155 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
7156 eorg[0], eorg[1], edest[0], edest[1]);
7157 }
7158 /* Add the subsegment to the list of encroached subsegments. */
7159 /* Be sure to get the orientation right. */
7160 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
7161 if (encroached == 1) {
7162 encroachedseg->encsubseg = sencode(*testsubseg);
7163 encroachedseg->subsegorg = eorg;
7164 encroachedseg->subsegdest = edest;
7165 } else {
7166 encroachedseg->encsubseg = sencode(testsym);
7167 encroachedseg->subsegorg = edest;
7168 encroachedseg->subsegdest = eorg;
7169 }
7170 }
7171
7172 return encroached;
7173}
7174
7175#endif /* not CDT_ONLY */
7176
7177/*****************************************************************************/
7178/* */
7179/* testtriangle() Test a triangle for quality and size. */
7180/* */
7181/* Tests a triangle to see if it satisfies the minimum angle condition and */
7182/* the maximum area condition. Triangles that aren't up to spec are added */
7183/* to the bad triangle queue. */
7184/* */
7185/*****************************************************************************/
7186
7187#ifndef CDT_ONLY
7188
7189#ifdef ANSI_DECLARATORS
7190void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
7191#else /* not ANSI_DECLARATORS */
7192void testtriangle(m, b, testtri)
7193struct mesh *m;
7194struct behavior *b;
7195struct otri *testtri;
7196#endif /* not ANSI_DECLARATORS */
7197
7198{
7199 struct otri tri1, tri2;
7200 struct osub testsub;
7201 vertex torg, tdest, tapex;
7202 vertex base1, base2;
7203 vertex org1, dest1, org2, dest2;
7204 vertex joinvertex;
7205 REAL dxod, dyod, dxda, dyda, dxao, dyao;
7206 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
7207 REAL apexlen, orglen, destlen, minedge;
7208 REAL angle;
7209 REAL area;
7210 REAL dist1, dist2;
7211 subseg sptr; /* Temporary variable used by tspivot(). */
7212 triangle ptr; /* Temporary variable used by oprev() and dnext(). */
7213
7214 org(*testtri, torg);
7215 dest(*testtri, tdest);
7216 apex(*testtri, tapex);
7217 dxod = torg[0] - tdest[0];
7218 dyod = torg[1] - tdest[1];
7219 dxda = tdest[0] - tapex[0];
7220 dyda = tdest[1] - tapex[1];
7221 dxao = tapex[0] - torg[0];
7222 dyao = tapex[1] - torg[1];
7223 dxod2 = dxod * dxod;
7224 dyod2 = dyod * dyod;
7225 dxda2 = dxda * dxda;
7226 dyda2 = dyda * dyda;
7227 dxao2 = dxao * dxao;
7228 dyao2 = dyao * dyao;
7229 /* Find the lengths of the triangle's three edges. */
7230 apexlen = dxod2 + dyod2;
7231 orglen = dxda2 + dyda2;
7232 destlen = dxao2 + dyao2;
7233
7234 if ((apexlen < orglen) && (apexlen < destlen)) {
7235 /* The edge opposite the apex is shortest. */
7236 minedge = apexlen;
7237 /* Find the square of the cosine of the angle at the apex. */
7238 angle = dxda * dxao + dyda * dyao;
7239 angle = angle * angle / (orglen * destlen);
7240 base1 = torg;
7241 base2 = tdest;
7242 otricopy(*testtri, tri1);
7243 } else if (orglen < destlen) {
7244 /* The edge opposite the origin is shortest. */
7245 minedge = orglen;
7246 /* Find the square of the cosine of the angle at the origin. */
7247 angle = dxod * dxao + dyod * dyao;
7248 angle = angle * angle / (apexlen * destlen);
7249 base1 = tdest;
7250 base2 = tapex;
7251 lnext(*testtri, tri1);
7252 } else {
7253 /* The edge opposite the destination is shortest. */
7254 minedge = destlen;
7255 /* Find the square of the cosine of the angle at the destination. */
7256 angle = dxod * dxda + dyod * dyda;
7257 angle = angle * angle / (apexlen * orglen);
7258 base1 = tapex;
7259 base2 = torg;
7260 lprev(*testtri, tri1);
7261 }
7262
7263 if (b->vararea || b->fixedarea || b->usertest) {
7264 /* Check whether the area is larger than permitted. */
7265 area = 0.5 * (dxod * dyda - dyod * dxda);
7266 if (b->fixedarea && (area > b->maxarea)) {
7267 /* Add this triangle to the list of bad triangles. */
7268 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7269 return;
7270 }
7271
7272 /* Nonpositive area constraints are treated as unconstrained. */
7273 if ((b->vararea) && (area > areabound(*testtri)) &&
7274 (areabound(*testtri) > 0.0)) {
7275 /* Add this triangle to the list of bad triangles. */
7276 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7277 return;
7278 }
7279
7280 if (b->usertest) {
7281 /* Check whether the user thinks this triangle is too large. */
7282 if (triunsuitable(torg, tdest, tapex, area)) {
7283 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7284 return;
7285 }
7286 }
7287 }
7288
7289 /* Check whether the angle is smaller than permitted. */
7290 if (angle > b->goodangle) {
7291 /* Use the rules of Miller, Pav, and Walkington to decide that certain */
7292 /* triangles should not be split, even if they have bad angles. */
7293 /* A skinny triangle is not split if its shortest edge subtends a */
7294 /* small input angle, and both endpoints of the edge lie on a */
7295 /* concentric circular shell. For convenience, I make a small */
7296 /* adjustment to that rule: I check if the endpoints of the edge */
7297 /* both lie in segment interiors, equidistant from the apex where */
7298 /* the two segments meet. */
7299 /* First, check if both points lie in segment interiors. */
7300 if ((vertextype(base1) == SEGMENTVERTEX) &&
7301 (vertextype(base2) == SEGMENTVERTEX)) {
7302 /* Check if both points lie in a common segment. If they do, the */
7303 /* skinny triangle is enqueued to be split as usual. */
7304 tspivot(tri1, testsub);
7305 if (testsub.ss == m->dummysub) {
7306 /* No common segment. Find a subsegment that contains `torg'. */
7307 otricopy(tri1, tri2);
7308 do {
7309 oprevself(tri1);
7310 tspivot(tri1, testsub);
7311 } while (testsub.ss == m->dummysub);
7312 /* Find the endpoints of the containing segment. */
7313 segorg(testsub, org1);
7314 segdest(testsub, dest1);
7315 /* Find a subsegment that contains `tdest'. */
7316 do {
7317 dnextself(tri2);
7318 tspivot(tri2, testsub);
7319 } while (testsub.ss == m->dummysub);
7320 /* Find the endpoints of the containing segment. */
7321 segorg(testsub, org2);
7322 segdest(testsub, dest2);
7323 /* Check if the two containing segments have an endpoint in common. */
7324 joinvertex = (vertex) NULL;
7325 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
7326 joinvertex = dest1;
7327 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
7328 joinvertex = org1;
7329 }
7330 if (joinvertex != (vertex) NULL) {
7331 /* Compute the distance from the common endpoint (of the two */
7332 /* segments) to each of the endpoints of the shortest edge. */
7333 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
7334 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
7335 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
7336 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
7337 /* If the two distances are equal, don't split the triangle. */
7338 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
7339 /* Return now to avoid enqueueing the bad triangle. */
7340 return;
7341 }
7342 }
7343 }
7344 }
7345
7346 /* Add this triangle to the list of bad triangles. */
7347 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7348 }
7349}
7350
7351#endif /* not CDT_ONLY */
7352
7353/** **/
7354/** **/
7355/********* Mesh quality testing routines end here *********/
7356
7357/********* Point location routines begin here *********/
7358/** **/
7359/** **/
7360
7361/*****************************************************************************/
7362/* */
7363/* makevertexmap() Construct a mapping from vertices to triangles to */
7364/* improve the speed of point location for segment */
7365/* insertion. */
7366/* */
7367/* Traverses all the triangles, and provides each corner of each triangle */
7368/* with a pointer to that triangle. Of course, pointers will be */
7369/* overwritten by other pointers because (almost) each vertex is a corner */
7370/* of several triangles, but in the end every vertex will point to some */
7371/* triangle that contains it. */
7372/* */
7373/*****************************************************************************/
7374
7375#ifdef ANSI_DECLARATORS
7376void makevertexmap(struct mesh *m, struct behavior *b)
7377#else /* not ANSI_DECLARATORS */
7378void makevertexmap(m, b)
7379struct mesh *m;
7380struct behavior *b;
7381#endif /* not ANSI_DECLARATORS */
7382
7383{
7384 struct otri triangleloop;
7385 vertex triorg;
7386
7387 if (b->verbose) {
7388 printf(" Constructing mapping from vertices to triangles.\n");
7389 }
7390 traversalinit(&m->triangles);
7391 triangleloop.tri = triangletraverse(m);
7392 while (triangleloop.tri != (triangle *) NULL) {
7393 /* Check all three vertices of the triangle. */
7394 for (triangleloop.orient = 0; triangleloop.orient < 3;
7395 triangleloop.orient++) {
7396 org(triangleloop, triorg);
7397 setvertex2tri(triorg, encode(triangleloop));
7398 }
7399 triangleloop.tri = triangletraverse(m);
7400 }
7401}
7402
7403/*****************************************************************************/
7404/* */
7405/* preciselocate() Find a triangle or edge containing a given point. */
7406/* */
7407/* Begins its search from `searchtri'. It is important that `searchtri' */
7408/* be a handle with the property that `searchpoint' is strictly to the left */
7409/* of the edge denoted by `searchtri', or is collinear with that edge and */
7410/* does not intersect that edge. (In particular, `searchpoint' should not */
7411/* be the origin or destination of that edge.) */
7412/* */
7413/* These conditions are imposed because preciselocate() is normally used in */
7414/* one of two situations: */
7415/* */
7416/* (1) To try to find the location to insert a new point. Normally, we */
7417/* know an edge that the point is strictly to the left of. In the */
7418/* incremental Delaunay algorithm, that edge is a bounding box edge. */
7419/* In Ruppert's Delaunay refinement algorithm for quality meshing, */
7420/* that edge is the shortest edge of the triangle whose circumcenter */
7421/* is being inserted. */
7422/* */
7423/* (2) To try to find an existing point. In this case, any edge on the */
7424/* convex hull is a good starting edge. You must screen out the */
7425/* possibility that the vertex sought is an endpoint of the starting */
7426/* edge before you call preciselocate(). */
7427/* */
7428/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7429/* */
7430/* This implementation differs from that given by Guibas and Stolfi. It */
7431/* walks from triangle to triangle, crossing an edge only if `searchpoint' */
7432/* is on the other side of the line containing that edge. After entering */
7433/* a triangle, there are two edges by which one can leave that triangle. */
7434/* If both edges are valid (`searchpoint' is on the other side of both */
7435/* edges), one of the two is chosen by drawing a line perpendicular to */
7436/* the entry edge (whose endpoints are `forg' and `fdest') passing through */
7437/* `fapex'. Depending on which side of this perpendicular `searchpoint' */
7438/* falls on, an exit edge is chosen. */
7439/* */
7440/* This implementation is empirically faster than the Guibas and Stolfi */
7441/* point location routine (which I originally used), which tends to spiral */
7442/* in toward its target. */
7443/* */
7444/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7445/* is a handle whose origin is the existing vertex. */
7446/* */
7447/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7448/* handle whose primary edge is the edge on which the point lies. */
7449/* */
7450/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7451/* `searchtri' is a handle on the triangle that contains the point. */
7452/* */
7453/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7454/* handle whose primary edge the point is to the right of. This might */
7455/* occur when the circumcenter of a triangle falls just slightly outside */
7456/* the mesh due to floating-point roundoff error. It also occurs when */
7457/* seeking a hole or region point that a foolish user has placed outside */
7458/* the mesh. */
7459/* */
7460/* If `stopatsubsegment' is nonzero, the search will stop if it tries to */
7461/* walk through a subsegment, and will return OUTSIDE. */
7462/* */
7463/* WARNING: This routine is designed for convex triangulations, and will */
7464/* not generally work after the holes and concavities have been carved. */
7465/* However, it can still be used to find the circumcenter of a triangle, as */
7466/* long as the search is begun from the triangle in question. */
7467/* */
7468/*****************************************************************************/
7469
7470#ifdef ANSI_DECLARATORS
7472 vertex searchpoint, struct otri *searchtri,
7473 int stopatsubsegment)
7474#else /* not ANSI_DECLARATORS */
7475enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
7476struct mesh *m;
7477struct behavior *b;
7478vertex searchpoint;
7479struct otri *searchtri;
7480int stopatsubsegment;
7481#endif /* not ANSI_DECLARATORS */
7482
7483{
7484 struct otri backtracktri;
7485 struct osub checkedge;
7486 vertex forg, fdest, fapex;
7487 REAL orgorient, destorient;
7488 int moveleft;
7489 triangle ptr; /* Temporary variable used by sym(). */
7490 subseg sptr; /* Temporary variable used by tspivot(). */
7491
7492 if (b->verbose > 2) {
7493 printf(" Searching for point (%.12g, %.12g).\n",
7494 searchpoint[0], searchpoint[1]);
7495 }
7496 /* Where are we? */
7497 org(*searchtri, forg);
7498 dest(*searchtri, fdest);
7499 apex(*searchtri, fapex);
7500 while (1) {
7501 if (b->verbose > 2) {
7502 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7503 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
7504 }
7505 /* Check whether the apex is the point we seek. */
7506 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
7507 lprevself(*searchtri);
7508 return ONVERTEX;
7509 }
7510 /* Does the point lie on the other side of the line defined by the */
7511 /* triangle edge opposite the triangle's destination? */
7512 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
7513 /* Does the point lie on the other side of the line defined by the */
7514 /* triangle edge opposite the triangle's origin? */
7515 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
7516 if (destorient > 0.0) {
7517 if (orgorient > 0.0) {
7518 /* Move left if the inner product of (fapex - searchpoint) and */
7519 /* (fdest - forg) is positive. This is equivalent to drawing */
7520 /* a line perpendicular to the line (forg, fdest) and passing */
7521 /* through `fapex', and determining which side of this line */
7522 /* `searchpoint' falls on. */
7523 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
7524 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
7525 } else {
7526 moveleft = 1;
7527 }
7528 } else {
7529 if (orgorient > 0.0) {
7530 moveleft = 0;
7531 } else {
7532 /* The point we seek must be on the boundary of or inside this */
7533 /* triangle. */
7534 if (destorient == 0.0) {
7535 lprevself(*searchtri);
7536 return ONEDGE;
7537 }
7538 if (orgorient == 0.0) {
7539 lnextself(*searchtri);
7540 return ONEDGE;
7541 }
7542 return INTRIANGLE;
7543 }
7544 }
7545
7546 /* Move to another triangle. Leave a trace `backtracktri' in case */
7547 /* floating-point roundoff or some such bogey causes us to walk */
7548 /* off a boundary of the triangulation. */
7549 if (moveleft) {
7550 lprev(*searchtri, backtracktri);
7551 fdest = fapex;
7552 } else {
7553 lnext(*searchtri, backtracktri);
7554 forg = fapex;
7555 }
7556 sym(backtracktri, *searchtri);
7557
7558 if (m->checksegments && stopatsubsegment) {
7559 /* Check for walking through a subsegment. */
7560 tspivot(backtracktri, checkedge);
7561 if (checkedge.ss != m->dummysub) {
7562 /* Go back to the last triangle. */
7563 otricopy(backtracktri, *searchtri);
7564 return OUTSIDE;
7565 }
7566 }
7567 /* Check for walking right out of the triangulation. */
7568 if (searchtri->tri == m->dummytri) {
7569 /* Go back to the last triangle. */
7570 otricopy(backtracktri, *searchtri);
7571 return OUTSIDE;
7572 }
7573
7574 apex(*searchtri, fapex);
7575 }
7576}
7577
7578/*****************************************************************************/
7579/* */
7580/* locate() Find a triangle or edge containing a given point. */
7581/* */
7582/* Searching begins from one of: the input `searchtri', a recently */
7583/* encountered triangle `recenttri', or from a triangle chosen from a */
7584/* random sample. The choice is made by determining which triangle's */
7585/* origin is closest to the point we are searching for. Normally, */
7586/* `searchtri' should be a handle on the convex hull of the triangulation. */
7587/* */
7588/* Details on the random sampling method can be found in the Mucke, Saias, */
7589/* and Zhu paper cited in the header of this code. */
7590/* */
7591/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7592/* */
7593/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7594/* is a handle whose origin is the existing vertex. */
7595/* */
7596/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7597/* handle whose primary edge is the edge on which the point lies. */
7598/* */
7599/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7600/* `searchtri' is a handle on the triangle that contains the point. */
7601/* */
7602/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7603/* handle whose primary edge the point is to the right of. This might */
7604/* occur when the circumcenter of a triangle falls just slightly outside */
7605/* the mesh due to floating-point roundoff error. It also occurs when */
7606/* seeking a hole or region point that a foolish user has placed outside */
7607/* the mesh. */
7608/* */
7609/* WARNING: This routine is designed for convex triangulations, and will */
7610/* not generally work after the holes and concavities have been carved. */
7611/* */
7612/*****************************************************************************/
7613
7614#ifdef ANSI_DECLARATORS
7615enum locateresult locate(struct mesh *m, struct behavior *b,
7616 vertex searchpoint, struct otri *searchtri)
7617#else /* not ANSI_DECLARATORS */
7618enum locateresult locate(m, b, searchpoint, searchtri)
7619struct mesh *m;
7620struct behavior *b;
7621vertex searchpoint;
7622struct otri *searchtri;
7623#endif /* not ANSI_DECLARATORS */
7624
7625{
7626 VOID **sampleblock;
7627 char *firsttri;
7628 struct otri sampletri;
7629 vertex torg, tdest;
7630 uintptr_t alignptr;
7631 REAL searchdist, dist;
7632 REAL ahead;
7633 long samplesperblock, totalsamplesleft, samplesleft;
7634 long population, totalpopulation;
7635 triangle ptr; /* Temporary variable used by sym(). */
7636
7637 if (b->verbose > 2) {
7638 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
7639 searchpoint[0], searchpoint[1]);
7640 }
7641 /* Record the distance from the suggested starting triangle to the */
7642 /* point we seek. */
7643 org(*searchtri, torg);
7644 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7645 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7646 if (b->verbose > 2) {
7647 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
7648 torg[0], torg[1]);
7649 }
7650
7651 /* If a recently encountered triangle has been recorded and has not been */
7652 /* deallocated, test it as a good starting point. */
7653 if (m->recenttri.tri != (triangle *) NULL) {
7654 if (!deadtri(m->recenttri.tri)) {
7655 org(m->recenttri, torg);
7656 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7657 otricopy(m->recenttri, *searchtri);
7658 return ONVERTEX;
7659 }
7660 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7661 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7662 if (dist < searchdist) {
7663 otricopy(m->recenttri, *searchtri);
7664 searchdist = dist;
7665 if (b->verbose > 2) {
7666 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
7667 torg[0], torg[1]);
7668 }
7669 }
7670 }
7671 }
7672
7673 /* The number of random samples taken is proportional to the cube root of */
7674 /* the number of triangles in the mesh. The next bit of code assumes */
7675 /* that the number of triangles increases monotonically (or at least */
7676 /* doesn't decrease enough to matter). */
7677 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
7678 m->triangles.items) {
7679 m->samples++;
7680 }
7681
7682 /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */
7683 /* from each block of triangles (except the first)--until we meet the */
7684 /* sample quota. The ceiling means that blocks at the end might be */
7685 /* neglected, but I don't care. */
7686 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
7687 /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */
7688 /* from the first block of triangles. */
7689 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
7690 m->triangles.maxitems + 1;
7691 totalsamplesleft = m->samples;
7692 population = m->triangles.itemsfirstblock;
7693 totalpopulation = m->triangles.maxitems;
7694 sampleblock = m->triangles.firstblock;
7695 sampletri.orient = 0;
7696 while (totalsamplesleft > 0) {
7697 /* If we're in the last block, `population' needs to be corrected. */
7698 if (population > totalpopulation) {
7699 population = totalpopulation;
7700 }
7701 /* Find a pointer to the first triangle in the block. */
7702 alignptr = (uintptr_t) (sampleblock + 1);
7703 firsttri = (char *) (alignptr +
7704 (uintptr_t) m->triangles.alignbytes -
7705 (alignptr %
7706 (uintptr_t) m->triangles.alignbytes));
7707
7708 /* Choose `samplesleft' randomly sampled triangles in this block. */
7709 do {
7710 sampletri.tri = (triangle *) (firsttri +
7711 (randomnation((unsigned int) population) *
7712 m->triangles.itembytes));
7713 if (!deadtri(sampletri.tri)) {
7714 org(sampletri, torg);
7715 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7716 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7717 if (dist < searchdist) {
7718 otricopy(sampletri, *searchtri);
7719 searchdist = dist;
7720 if (b->verbose > 2) {
7721 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
7722 torg[0], torg[1]);
7723 }
7724 }
7725 }
7726
7727 samplesleft--;
7728 totalsamplesleft--;
7729 } while ((samplesleft > 0) && (totalsamplesleft > 0));
7730
7731 if (totalsamplesleft > 0) {
7732 sampleblock = (VOID **) *sampleblock;
7733 samplesleft = samplesperblock;
7734 totalpopulation -= population;
7735 population = TRIPERBLOCK;
7736 }
7737 }
7738
7739 /* Where are we? */
7740 org(*searchtri, torg);
7741 dest(*searchtri, tdest);
7742 /* Check the starting triangle's vertices. */
7743 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7744 return ONVERTEX;
7745 }
7746 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
7747 lnextself(*searchtri);
7748 return ONVERTEX;
7749 }
7750 /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
7751 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
7752 if (ahead < 0.0) {
7753 /* Turn around so that `searchpoint' is to the left of the */
7754 /* edge specified by `searchtri'. */
7755 symself(*searchtri);
7756 } else if (ahead == 0.0) {
7757 /* Check if `searchpoint' is between `torg' and `tdest'. */
7758 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
7759 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
7760 return ONEDGE;
7761 }
7762 }
7763 return preciselocate(m, b, searchpoint, searchtri, 0);
7764}
7765
7766/** **/
7767/** **/
7768/********* Point location routines end here *********/
7769
7770/********* Mesh transformation routines begin here *********/
7771/** **/
7772/** **/
7773
7774/*****************************************************************************/
7775/* */
7776/* insertsubseg() Create a new subsegment and insert it between two */
7777/* triangles. */
7778/* */
7779/* The new subsegment is inserted at the edge described by the handle */
7780/* `tri'. Its vertices are properly initialized. The marker `subsegmark' */
7781/* is applied to the subsegment and, if appropriate, its vertices. */
7782/* */
7783/*****************************************************************************/
7784
7785#ifdef ANSI_DECLARATORS
7786void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
7787 int subsegmark)
7788#else /* not ANSI_DECLARATORS */
7789void insertsubseg(m, b, tri, subsegmark)
7790struct mesh *m;
7791struct behavior *b;
7792struct otri *tri; /* Edge at which to insert the new subsegment. */
7793int subsegmark; /* Marker for the new subsegment. */
7794#endif /* not ANSI_DECLARATORS */
7795
7796{
7797 struct otri oppotri;
7798 struct osub newsubseg;
7799 vertex triorg, tridest;
7800 triangle ptr; /* Temporary variable used by sym(). */
7801 subseg sptr; /* Temporary variable used by tspivot(). */
7802
7803 org(*tri, triorg);
7804 dest(*tri, tridest);
7805 /* Mark vertices if possible. */
7806 if (vertexmark(triorg) == 0) {
7807 setvertexmark(triorg, subsegmark);
7808 }
7809 if (vertexmark(tridest) == 0) {
7810 setvertexmark(tridest, subsegmark);
7811 }
7812 /* Check if there's already a subsegment here. */
7813 tspivot(*tri, newsubseg);
7814 if (newsubseg.ss == m->dummysub) {
7815 /* Make new subsegment and initialize its vertices. */
7816 makesubseg(m, &newsubseg);
7817 setsorg(newsubseg, tridest);
7818 setsdest(newsubseg, triorg);
7819 setsegorg(newsubseg, tridest);
7820 setsegdest(newsubseg, triorg);
7821 /* Bond new subsegment to the two triangles it is sandwiched between. */
7822 /* Note that the facing triangle `oppotri' might be equal to */
7823 /* `dummytri' (outer space), but the new subsegment is bonded to it */
7824 /* all the same. */
7825 tsbond(*tri, newsubseg);
7826 sym(*tri, oppotri);
7827 ssymself(newsubseg);
7828 tsbond(oppotri, newsubseg);
7829 setmark(newsubseg, subsegmark);
7830 if (b->verbose > 2) {
7831 printf(" Inserting new ");
7832 printsubseg(m, b, &newsubseg);
7833 }
7834 } else {
7835 if (mark(newsubseg) == 0) {
7836 setmark(newsubseg, subsegmark);
7837 }
7838 }
7839}
7840
7841/*****************************************************************************/
7842/* */
7843/* Terminology */
7844/* */
7845/* A "local transformation" replaces a small set of triangles with another */
7846/* set of triangles. This may or may not involve inserting or deleting a */
7847/* vertex. */
7848/* */
7849/* The term "casing" is used to describe the set of triangles that are */
7850/* attached to the triangles being transformed, but are not transformed */
7851/* themselves. Think of the casing as a fixed hollow structure inside */
7852/* which all the action happens. A "casing" is only defined relative to */
7853/* a single transformation; each occurrence of a transformation will */
7854/* involve a different casing. */
7855/* */
7856/*****************************************************************************/
7857
7858/*****************************************************************************/
7859/* */
7860/* flip() Transform two triangles to two different triangles by flipping */
7861/* an edge counterclockwise within a quadrilateral. */
7862/* */
7863/* Imagine the original triangles, abc and bad, oriented so that the */
7864/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
7865/* and the vertex a on the right. The vertex c lies below the edge, and */
7866/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
7867/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
7868/* */
7869/* The triangles abc and bad are deleted and replaced by the triangles cdb */
7870/* and dca. The triangles that represent abc and bad are NOT deallocated; */
7871/* they are reused for dca and cdb, respectively. Hence, any handles that */
7872/* may have held the original triangles are still valid, although not */
7873/* directed as they were before. */
7874/* */
7875/* Upon completion of this routine, the `flipedge' handle holds the edge */
7876/* dc of triangle dca, and is directed down, from vertex d to vertex c. */
7877/* (Hence, the two triangles have rotated counterclockwise.) */
7878/* */
7879/* WARNING: This transformation is geometrically valid only if the */
7880/* quadrilateral adbc is convex. Furthermore, this transformation is */
7881/* valid only if there is not a subsegment between the triangles abc and */
7882/* bad. This routine does not check either of these preconditions, and */
7883/* it is the responsibility of the calling routine to ensure that they are */
7884/* met. If they are not, the streets shall be filled with wailing and */
7885/* gnashing of teeth. */
7886/* */
7887/*****************************************************************************/
7888
7889#ifdef ANSI_DECLARATORS
7890void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
7891#else /* not ANSI_DECLARATORS */
7892void flip(m, b, flipedge)
7893struct mesh *m;
7894struct behavior *b;
7895struct otri *flipedge; /* Handle for the triangle abc. */
7896#endif /* not ANSI_DECLARATORS */
7897
7898{
7899 struct otri botleft, botright;
7900 struct otri topleft, topright;
7901 struct otri top;
7902 struct otri botlcasing, botrcasing;
7903 struct otri toplcasing, toprcasing;
7904 struct osub botlsubseg, botrsubseg;
7905 struct osub toplsubseg, toprsubseg;
7906 vertex leftvertex, rightvertex, botvertex;
7907 vertex farvertex;
7908 triangle ptr; /* Temporary variable used by sym(). */
7909 subseg sptr; /* Temporary variable used by tspivot(). */
7910
7911 /* Identify the vertices of the quadrilateral. */
7912 org(*flipedge, rightvertex);
7913 dest(*flipedge, leftvertex);
7914 apex(*flipedge, botvertex);
7915 sym(*flipedge, top);
7916#ifdef SELF_CHECK
7917 if (top.tri == m->dummytri) {
7918 printf("Internal error in flip(): Attempt to flip on boundary.\n");
7919 lnextself(*flipedge);
7920 return;
7921 }
7922 if (m->checksegments) {
7923 tspivot(*flipedge, toplsubseg);
7924 if (toplsubseg.ss != m->dummysub) {
7925 printf("Internal error in flip(): Attempt to flip a segment.\n");
7926 lnextself(*flipedge);
7927 return;
7928 }
7929 }
7930#endif /* SELF_CHECK */
7931 apex(top, farvertex);
7932
7933 /* Identify the casing of the quadrilateral. */
7934 lprev(top, topleft);
7935 sym(topleft, toplcasing);
7936 lnext(top, topright);
7937 sym(topright, toprcasing);
7938 lnext(*flipedge, botleft);
7939 sym(botleft, botlcasing);
7940 lprev(*flipedge, botright);
7941 sym(botright, botrcasing);
7942 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
7943 bond(topleft, botlcasing);
7944 bond(botleft, botrcasing);
7945 bond(botright, toprcasing);
7946 bond(topright, toplcasing);
7947
7948 if (m->checksegments) {
7949 /* Check for subsegments and rebond them to the quadrilateral. */
7950 tspivot(topleft, toplsubseg);
7951 tspivot(botleft, botlsubseg);
7952 tspivot(botright, botrsubseg);
7953 tspivot(topright, toprsubseg);
7954 if (toplsubseg.ss == m->dummysub) {
7955 tsdissolve(topright);
7956 } else {
7957 tsbond(topright, toplsubseg);
7958 }
7959 if (botlsubseg.ss == m->dummysub) {
7960 tsdissolve(topleft);
7961 } else {
7962 tsbond(topleft, botlsubseg);
7963 }
7964 if (botrsubseg.ss == m->dummysub) {
7965 tsdissolve(botleft);
7966 } else {
7967 tsbond(botleft, botrsubseg);
7968 }
7969 if (toprsubseg.ss == m->dummysub) {
7970 tsdissolve(botright);
7971 } else {
7972 tsbond(botright, toprsubseg);
7973 }
7974 }
7975
7976 /* New vertex assignments for the rotated quadrilateral. */
7977 setorg(*flipedge, farvertex);
7978 setdest(*flipedge, botvertex);
7979 setapex(*flipedge, rightvertex);
7980 setorg(top, botvertex);
7981 setdest(top, farvertex);
7982 setapex(top, leftvertex);
7983 if (b->verbose > 2) {
7984 printf(" Edge flip results in left ");
7985 printtriangle(m, b, &top);
7986 printf(" and right ");
7987 printtriangle(m, b, flipedge);
7988 }
7989}
7990
7991/*****************************************************************************/
7992/* */
7993/* unflip() Transform two triangles to two different triangles by */
7994/* flipping an edge clockwise within a quadrilateral. Reverses */
7995/* the flip() operation so that the data structures representing */
7996/* the triangles are back where they were before the flip(). */
7997/* */
7998/* Imagine the original triangles, abc and bad, oriented so that the */
7999/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
8000/* and the vertex a on the right. The vertex c lies below the edge, and */
8001/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
8002/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
8003/* */
8004/* The triangles abc and bad are deleted and replaced by the triangles cdb */
8005/* and dca. The triangles that represent abc and bad are NOT deallocated; */
8006/* they are reused for cdb and dca, respectively. Hence, any handles that */
8007/* may have held the original triangles are still valid, although not */
8008/* directed as they were before. */
8009/* */
8010/* Upon completion of this routine, the `flipedge' handle holds the edge */
8011/* cd of triangle cdb, and is directed up, from vertex c to vertex d. */
8012/* (Hence, the two triangles have rotated clockwise.) */
8013/* */
8014/* WARNING: This transformation is geometrically valid only if the */
8015/* quadrilateral adbc is convex. Furthermore, this transformation is */
8016/* valid only if there is not a subsegment between the triangles abc and */
8017/* bad. This routine does not check either of these preconditions, and */
8018/* it is the responsibility of the calling routine to ensure that they are */
8019/* met. If they are not, the streets shall be filled with wailing and */
8020/* gnashing of teeth. */
8021/* */
8022/*****************************************************************************/
8023
8024#ifdef ANSI_DECLARATORS
8025void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
8026#else /* not ANSI_DECLARATORS */
8027void unflip(m, b, flipedge)
8028struct mesh *m;
8029struct behavior *b;
8030struct otri *flipedge; /* Handle for the triangle abc. */
8031#endif /* not ANSI_DECLARATORS */
8032
8033{
8034 struct otri botleft, botright;
8035 struct otri topleft, topright;
8036 struct otri top;
8037 struct otri botlcasing, botrcasing;
8038 struct otri toplcasing, toprcasing;
8039 struct osub botlsubseg, botrsubseg;
8040 struct osub toplsubseg, toprsubseg;
8041 vertex leftvertex, rightvertex, botvertex;
8042 vertex farvertex;
8043 triangle ptr; /* Temporary variable used by sym(). */
8044 subseg sptr; /* Temporary variable used by tspivot(). */
8045
8046 /* Identify the vertices of the quadrilateral. */
8047 org(*flipedge, rightvertex);
8048 dest(*flipedge, leftvertex);
8049 apex(*flipedge, botvertex);
8050 sym(*flipedge, top);
8051#ifdef SELF_CHECK
8052 if (top.tri == m->dummytri) {
8053 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
8054 lnextself(*flipedge);
8055 return;
8056 }
8057 if (m->checksegments) {
8058 tspivot(*flipedge, toplsubseg);
8059 if (toplsubseg.ss != m->dummysub) {
8060 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
8061 lnextself(*flipedge);
8062 return;
8063 }
8064 }
8065#endif /* SELF_CHECK */
8066 apex(top, farvertex);
8067
8068 /* Identify the casing of the quadrilateral. */
8069 lprev(top, topleft);
8070 sym(topleft, toplcasing);
8071 lnext(top, topright);
8072 sym(topright, toprcasing);
8073 lnext(*flipedge, botleft);
8074 sym(botleft, botlcasing);
8075 lprev(*flipedge, botright);
8076 sym(botright, botrcasing);
8077 /* Rotate the quadrilateral one-quarter turn clockwise. */
8078 bond(topleft, toprcasing);
8079 bond(botleft, toplcasing);
8080 bond(botright, botlcasing);
8081 bond(topright, botrcasing);
8082
8083 if (m->checksegments) {
8084 /* Check for subsegments and rebond them to the quadrilateral. */
8085 tspivot(topleft, toplsubseg);
8086 tspivot(botleft, botlsubseg);
8087 tspivot(botright, botrsubseg);
8088 tspivot(topright, toprsubseg);
8089 if (toplsubseg.ss == m->dummysub) {
8090 tsdissolve(botleft);
8091 } else {
8092 tsbond(botleft, toplsubseg);
8093 }
8094 if (botlsubseg.ss == m->dummysub) {
8095 tsdissolve(botright);
8096 } else {
8097 tsbond(botright, botlsubseg);
8098 }
8099 if (botrsubseg.ss == m->dummysub) {
8100 tsdissolve(topright);
8101 } else {
8102 tsbond(topright, botrsubseg);
8103 }
8104 if (toprsubseg.ss == m->dummysub) {
8105 tsdissolve(topleft);
8106 } else {
8107 tsbond(topleft, toprsubseg);
8108 }
8109 }
8110
8111 /* New vertex assignments for the rotated quadrilateral. */
8112 setorg(*flipedge, botvertex);
8113 setdest(*flipedge, farvertex);
8114 setapex(*flipedge, leftvertex);
8115 setorg(top, farvertex);
8116 setdest(top, botvertex);
8117 setapex(top, rightvertex);
8118 if (b->verbose > 2) {
8119 printf(" Edge unflip results in left ");
8120 printtriangle(m, b, flipedge);
8121 printf(" and right ");
8122 printtriangle(m, b, &top);
8123 }
8124}
8125
8126/*****************************************************************************/
8127/* */
8128/* insertvertex() Insert a vertex into a Delaunay triangulation, */
8129/* performing flips as necessary to maintain the Delaunay */
8130/* property. */
8131/* */
8132/* The point `insertvertex' is located. If `searchtri.tri' is not NULL, */
8133/* the search for the containing triangle begins from `searchtri'. If */
8134/* `searchtri.tri' is NULL, a full point location procedure is called. */
8135/* If `insertvertex' is found inside a triangle, the triangle is split into */
8136/* three; if `insertvertex' lies on an edge, the edge is split in two, */
8137/* thereby splitting the two adjacent triangles into four. Edge flips are */
8138/* used to restore the Delaunay property. If `insertvertex' lies on an */
8139/* existing vertex, no action is taken, and the value DUPLICATEVERTEX is */
8140/* returned. On return, `searchtri' is set to a handle whose origin is the */
8141/* existing vertex. */
8142/* */
8143/* Normally, the parameter `splitseg' is set to NULL, implying that no */
8144/* subsegment should be split. In this case, if `insertvertex' is found to */
8145/* lie on a segment, no action is taken, and the value VIOLATINGVERTEX is */
8146/* returned. On return, `searchtri' is set to a handle whose primary edge */
8147/* is the violated subsegment. */
8148/* */
8149/* If the calling routine wishes to split a subsegment by inserting a */
8150/* vertex in it, the parameter `splitseg' should be that subsegment. In */
8151/* this case, `searchtri' MUST be the triangle handle reached by pivoting */
8152/* from that subsegment; no point location is done. */
8153/* */
8154/* `segmentflaws' and `triflaws' are flags that indicate whether or not */
8155/* there should be checks for the creation of encroached subsegments or bad */
8156/* quality triangles. If a newly inserted vertex encroaches upon */
8157/* subsegments, these subsegments are added to the list of subsegments to */
8158/* be split if `segmentflaws' is set. If bad triangles are created, these */
8159/* are added to the queue if `triflaws' is set. */
8160/* */
8161/* If a duplicate vertex or violated segment does not prevent the vertex */
8162/* from being inserted, the return value will be ENCROACHINGVERTEX if the */
8163/* vertex encroaches upon a subsegment (and checking is enabled), or */
8164/* SUCCESSFULVERTEX otherwise. In either case, `searchtri' is set to a */
8165/* handle whose origin is the newly inserted vertex. */
8166/* */
8167/* insertvertex() does not use flip() for reasons of speed; some */
8168/* information can be reused from edge flip to edge flip, like the */
8169/* locations of subsegments. */
8170/* */
8171/*****************************************************************************/
8172
8173#ifdef ANSI_DECLARATORS
8175 vertex newvertex, struct otri *searchtri,
8176 struct osub *splitseg,
8177 int segmentflaws, int triflaws )
8178#else /* not ANSI_DECLARATORS */
8179enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
8180 segmentflaws, triflaws)
8181struct mesh *m;
8182struct behavior *b;
8183vertex newvertex;
8184struct otri *searchtri;
8185struct osub *splitseg;
8186int segmentflaws;
8187int triflaws;
8188#endif /* not ANSI_DECLARATORS */
8189
8190{
8191
8192 struct otri horiz;
8193 struct otri top;
8194 struct otri botleft, botright;
8195 struct otri topleft, topright;
8196 struct otri newbotleft, newbotright;
8197 struct otri newtopright;
8198 struct otri botlcasing, botrcasing;
8199 struct otri toplcasing, toprcasing;
8200 struct otri testtri;
8201 struct osub botlsubseg, botrsubseg;
8202 struct osub toplsubseg, toprsubseg;
8203 struct osub brokensubseg;
8204 struct osub checksubseg;
8205 struct osub rightsubseg;
8206 struct osub newsubseg;
8207 struct badsubseg *encroached;
8208 struct flipstacker *newflip;
8209 vertex first;
8210 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
8211 vertex segmentorg, segmentdest;
8212 REAL attrib;
8213 REAL area;
8214 enum insertvertexresult success;
8215 enum locateresult intersect;
8216 int doflip;
8217 int mirrorflag;
8218 int enq;
8219 int i;
8220 triangle ptr; /* Temporary variable used by sym(). */
8221 subseg sptr; /* Temporary variable used by spivot() and tspivot(). */
8222
8223
8224 (void)triflaws; /*LM: added to suppress warning */
8225
8226 if (b->verbose > 1) {
8227 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
8228 }
8229
8230 if (splitseg == (struct osub *) NULL) {
8231 /* Find the location of the vertex to be inserted. Check if a good */
8232 /* starting triangle has already been provided by the caller. */
8233 if (searchtri->tri == m->dummytri) {
8234 /* Find a boundary triangle. */
8235 horiz.tri = m->dummytri;
8236 horiz.orient = 0;
8237 symself(horiz);
8238 /* Search for a triangle containing `newvertex'. */
8239 intersect = locate(m, b, newvertex, &horiz);
8240 } else {
8241 /* Start searching from the triangle provided by the caller. */
8242 otricopy(*searchtri, horiz);
8243 intersect = preciselocate(m, b, newvertex, &horiz, 1);
8244 }
8245 } else {
8246 /* The calling routine provides the subsegment in which */
8247 /* the vertex is inserted. */
8248 otricopy(*searchtri, horiz);
8249 intersect = ONEDGE;
8250 }
8251
8252 if (intersect == ONVERTEX) {
8253 /* There's already a vertex there. Return in `searchtri' a triangle */
8254 /* whose origin is the existing vertex. */
8255 otricopy(horiz, *searchtri);
8256 otricopy(horiz, m->recenttri);
8257 return DUPLICATEVERTEX;
8258 }
8259 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
8260 /* The vertex falls on an edge or boundary. */
8261 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
8262 /* Check whether the vertex falls on a subsegment. */
8263 tspivot(horiz, brokensubseg);
8264 if (brokensubseg.ss != m->dummysub) {
8265 /* The vertex falls on a subsegment, and hence will not be inserted. */
8266 if (segmentflaws) {
8267 enq = b->nobisect != 2;
8268 if (enq && (b->nobisect == 1)) {
8269 /* This subsegment may be split only if it is an */
8270 /* internal boundary. */
8271 sym(horiz, testtri);
8272 enq = testtri.tri != m->dummytri;
8273 }
8274 if (enq) {
8275 /* Add the subsegment to the list of encroached subsegments. */
8276 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
8277 encroached->encsubseg = sencode(brokensubseg);
8278 sorg(brokensubseg, encroached->subsegorg);
8279 sdest(brokensubseg, encroached->subsegdest);
8280 if (b->verbose > 2) {
8281 printf(
8282 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
8283 encroached->subsegorg[0], encroached->subsegorg[1],
8284 encroached->subsegdest[0], encroached->subsegdest[1]);
8285 }
8286 }
8287 }
8288 /* Return a handle whose primary edge contains the vertex, */
8289 /* which has not been inserted. */
8290 otricopy(horiz, *searchtri);
8291 otricopy(horiz, m->recenttri);
8292 return VIOLATINGVERTEX;
8293 }
8294 }
8295
8296 /* Insert the vertex on an edge, dividing one triangle into two (if */
8297 /* the edge lies on a boundary) or two triangles into four. */
8298 lprev(horiz, botright);
8299 sym(botright, botrcasing);
8300 sym(horiz, topright);
8301 /* Is there a second triangle? (Or does this edge lie on a boundary?) */
8302 mirrorflag = topright.tri != m->dummytri;
8303 if (mirrorflag) {
8304 lnextself(topright);
8305 sym(topright, toprcasing);
8306 maketriangle(m, b, &newtopright);
8307 } else {
8308 /* Splitting a boundary edge increases the number of boundary edges. */
8309 m->hullsize++;
8310 }
8311 maketriangle(m, b, &newbotright);
8312
8313 /* Set the vertices of changed and new triangles. */
8314 org(horiz, rightvertex);
8315 dest(horiz, leftvertex);
8316 apex(horiz, botvertex);
8317 setorg(newbotright, botvertex);
8318 setdest(newbotright, rightvertex);
8319 setapex(newbotright, newvertex);
8320 setorg(horiz, newvertex);
8321 for (i = 0; i < m->eextras; i++) {
8322 /* Set the element attributes of a new triangle. */
8323 setelemattribute(newbotright, i, elemattribute(botright, i));
8324 }
8325 if (b->vararea) {
8326 /* Set the area constraint of a new triangle. */
8327 setareabound(newbotright, areabound(botright));
8328 }
8329 if (mirrorflag) {
8330 dest(topright, topvertex);
8331 setorg(newtopright, rightvertex);
8332 setdest(newtopright, topvertex);
8333 setapex(newtopright, newvertex);
8334 setorg(topright, newvertex);
8335 for (i = 0; i < m->eextras; i++) {
8336 /* Set the element attributes of another new triangle. */
8337 setelemattribute(newtopright, i, elemattribute(topright, i));
8338 }
8339 if (b->vararea) {
8340 /* Set the area constraint of another new triangle. */
8341 setareabound(newtopright, areabound(topright));
8342 }
8343 }
8344
8345 /* There may be subsegments that need to be bonded */
8346 /* to the new triangle(s). */
8347 if (m->checksegments) {
8348 tspivot(botright, botrsubseg);
8349 if (botrsubseg.ss != m->dummysub) {
8350 tsdissolve(botright);
8351 tsbond(newbotright, botrsubseg);
8352 }
8353 if (mirrorflag) {
8354 tspivot(topright, toprsubseg);
8355 if (toprsubseg.ss != m->dummysub) {
8356 tsdissolve(topright);
8357 tsbond(newtopright, toprsubseg);
8358 }
8359 }
8360 }
8361
8362 /* Bond the new triangle(s) to the surrounding triangles. */
8363 bond(newbotright, botrcasing);
8364 lprevself(newbotright);
8365 bond(newbotright, botright);
8366 lprevself(newbotright);
8367 if (mirrorflag) {
8368 bond(newtopright, toprcasing);
8369 lnextself(newtopright);
8370 bond(newtopright, topright);
8371 lnextself(newtopright);
8372 bond(newtopright, newbotright);
8373 }
8374
8375 if (splitseg != (struct osub *) NULL) {
8376 /* Split the subsegment into two. */
8377 setsdest(*splitseg, newvertex);
8378 segorg(*splitseg, segmentorg);
8379 segdest(*splitseg, segmentdest);
8380 ssymself(*splitseg);
8381 spivot(*splitseg, rightsubseg);
8382 insertsubseg(m, b, &newbotright, mark(*splitseg));
8383 tspivot(newbotright, newsubseg);
8384 setsegorg(newsubseg, segmentorg);
8385 setsegdest(newsubseg, segmentdest);
8386 sbond(*splitseg, newsubseg);
8387 ssymself(newsubseg);
8388 sbond(newsubseg, rightsubseg);
8389 ssymself(*splitseg);
8390 /* Transfer the subsegment's boundary marker to the vertex */
8391 /* if required. */
8392 if (vertexmark(newvertex) == 0) {
8393 setvertexmark(newvertex, mark(*splitseg));
8394 }
8395 }
8396
8397 if (m->checkquality) {
8398 poolrestart(&m->flipstackers);
8399 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8400 m->lastflip->flippedtri = encode(horiz);
8401 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
8402 }
8403
8404#ifdef SELF_CHECK
8405 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
8406 printf("Internal error in insertvertex():\n");
8407 printf(
8408 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
8409 }
8410 if (mirrorflag) {
8411 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
8412 printf("Internal error in insertvertex():\n");
8413 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
8414 }
8415 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
8416 printf("Internal error in insertvertex():\n");
8417 printf(
8418 " Clockwise triangle after edge vertex insertion (top right).\n");
8419 }
8420 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
8421 printf("Internal error in insertvertex():\n");
8422 printf(
8423 " Clockwise triangle after edge vertex insertion (top left).\n");
8424 }
8425 }
8426 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
8427 printf("Internal error in insertvertex():\n");
8428 printf(
8429 " Clockwise triangle after edge vertex insertion (bottom left).\n");
8430 }
8431 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
8432 printf("Internal error in insertvertex():\n");
8433 printf(
8434 " Clockwise triangle after edge vertex insertion (bottom right).\n");
8435 }
8436#endif /* SELF_CHECK */
8437 if (b->verbose > 2) {
8438 printf(" Updating bottom left ");
8439 printtriangle(m, b, &botright);
8440 if (mirrorflag) {
8441 printf(" Updating top left ");
8442 printtriangle(m, b, &topright);
8443 printf(" Creating top right ");
8444 printtriangle(m, b, &newtopright);
8445 }
8446 printf(" Creating bottom right ");
8447 printtriangle(m, b, &newbotright);
8448 }
8449
8450 /* Position `horiz' on the first edge to check for */
8451 /* the Delaunay property. */
8452 lnextself(horiz);
8453 } else {
8454 /* Insert the vertex in a triangle, splitting it into three. */
8455 lnext(horiz, botleft);
8456 lprev(horiz, botright);
8457 sym(botleft, botlcasing);
8458 sym(botright, botrcasing);
8459 maketriangle(m, b, &newbotleft);
8460 maketriangle(m, b, &newbotright);
8461
8462 /* Set the vertices of changed and new triangles. */
8463 org(horiz, rightvertex);
8464 dest(horiz, leftvertex);
8465 apex(horiz, botvertex);
8466 setorg(newbotleft, leftvertex);
8467 setdest(newbotleft, botvertex);
8468 setapex(newbotleft, newvertex);
8469 setorg(newbotright, botvertex);
8470 setdest(newbotright, rightvertex);
8471 setapex(newbotright, newvertex);
8472 setapex(horiz, newvertex);
8473 for (i = 0; i < m->eextras; i++) {
8474 /* Set the element attributes of the new triangles. */
8475 attrib = elemattribute(horiz, i);
8476 setelemattribute(newbotleft, i, attrib);
8477 setelemattribute(newbotright, i, attrib);
8478 }
8479 if (b->vararea) {
8480 /* Set the area constraint of the new triangles. */
8481 area = areabound(horiz);
8482 setareabound(newbotleft, area);
8483 setareabound(newbotright, area);
8484 }
8485
8486 /* There may be subsegments that need to be bonded */
8487 /* to the new triangles. */
8488 if (m->checksegments) {
8489 tspivot(botleft, botlsubseg);
8490 if (botlsubseg.ss != m->dummysub) {
8491 tsdissolve(botleft);
8492 tsbond(newbotleft, botlsubseg);
8493 }
8494 tspivot(botright, botrsubseg);
8495 if (botrsubseg.ss != m->dummysub) {
8496 tsdissolve(botright);
8497 tsbond(newbotright, botrsubseg);
8498 }
8499 }
8500
8501 /* Bond the new triangles to the surrounding triangles. */
8502 bond(newbotleft, botlcasing);
8503 bond(newbotright, botrcasing);
8504 lnextself(newbotleft);
8505 lprevself(newbotright);
8506 bond(newbotleft, newbotright);
8507 lnextself(newbotleft);
8508 bond(botleft, newbotleft);
8509 lprevself(newbotright);
8510 bond(botright, newbotright);
8511
8512 if (m->checkquality) {
8513 poolrestart(&m->flipstackers);
8514 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8515 m->lastflip->flippedtri = encode(horiz);
8516 m->lastflip->prevflip = (struct flipstacker *) NULL;
8517 }
8518
8519#ifdef SELF_CHECK
8520 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
8521 printf("Internal error in insertvertex():\n");
8522 printf(" Clockwise triangle prior to vertex insertion.\n");
8523 }
8524 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
8525 printf("Internal error in insertvertex():\n");
8526 printf(" Clockwise triangle after vertex insertion (top).\n");
8527 }
8528 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
8529 printf("Internal error in insertvertex():\n");
8530 printf(" Clockwise triangle after vertex insertion (left).\n");
8531 }
8532 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
8533 printf("Internal error in insertvertex():\n");
8534 printf(" Clockwise triangle after vertex insertion (right).\n");
8535 }
8536#endif /* SELF_CHECK */
8537 if (b->verbose > 2) {
8538 printf(" Updating top ");
8539 printtriangle(m, b, &horiz);
8540 printf(" Creating left ");
8541 printtriangle(m, b, &newbotleft);
8542 printf(" Creating right ");
8543 printtriangle(m, b, &newbotright);
8544 }
8545 }
8546
8547 /* The insertion is successful by default, unless an encroached */
8548 /* subsegment is found. */
8549 success = SUCCESSFULVERTEX;
8550 /* Circle around the newly inserted vertex, checking each edge opposite */
8551 /* it for the Delaunay property. Non-Delaunay edges are flipped. */
8552 /* `horiz' is always the edge being checked. `first' marks where to */
8553 /* stop circling. */
8554 org(horiz, first);
8555 rightvertex = first;
8556 dest(horiz, leftvertex);
8557 /* Circle until finished. */
8558 while (1) {
8559 /* By default, the edge will be flipped. */
8560 doflip = 1;
8561
8562 if (m->checksegments) {
8563 /* Check for a subsegment, which cannot be flipped. */
8564 tspivot(horiz, checksubseg);
8565 if (checksubseg.ss != m->dummysub) {
8566 /* The edge is a subsegment and cannot be flipped. */
8567 doflip = 0;
8568#ifndef CDT_ONLY
8569 if (segmentflaws) {
8570 /* Does the new vertex encroach upon this subsegment? */
8571 if (checkseg4encroach(m, b, &checksubseg)) {
8572 success = ENCROACHINGVERTEX;
8573 }
8574 }
8575#endif /* not CDT_ONLY */
8576 }
8577 }
8578
8579 if (doflip) {
8580 /* Check if the edge is a boundary edge. */
8581 sym(horiz, top);
8582 if (top.tri == m->dummytri) {
8583 /* The edge is a boundary edge and cannot be flipped. */
8584 doflip = 0;
8585 } else {
8586 /* Find the vertex on the other side of the edge. */
8587 apex(top, farvertex);
8588 /* In the incremental Delaunay triangulation algorithm, any of */
8589 /* `leftvertex', `rightvertex', and `farvertex' could be vertices */
8590 /* of the triangular bounding box. These vertices must be */
8591 /* treated as if they are infinitely distant, even though their */
8592 /* "coordinates" are not. */
8593 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
8594 (leftvertex == m->infvertex3)) {
8595 /* `leftvertex' is infinitely distant. Check the convexity of */
8596 /* the boundary of the triangulation. 'farvertex' might be */
8597 /* infinite as well, but trust me, this same condition should */
8598 /* be applied. */
8599 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
8600 > 0.0;
8601 } else if ((rightvertex == m->infvertex1) ||
8602 (rightvertex == m->infvertex2) ||
8603 (rightvertex == m->infvertex3)) {
8604 /* `rightvertex' is infinitely distant. Check the convexity of */
8605 /* the boundary of the triangulation. 'farvertex' might be */
8606 /* infinite as well, but trust me, this same condition should */
8607 /* be applied. */
8608 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
8609 > 0.0;
8610 } else if ((farvertex == m->infvertex1) ||
8611 (farvertex == m->infvertex2) ||
8612 (farvertex == m->infvertex3)) {
8613 /* `farvertex' is infinitely distant and cannot be inside */
8614 /* the circumcircle of the triangle `horiz'. */
8615 doflip = 0;
8616 } else {
8617 /* Test whether the edge is locally Delaunay. */
8618 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
8619 farvertex) > 0.0;
8620 }
8621 if (doflip) {
8622 /* We made it! Flip the edge `horiz' by rotating its containing */
8623 /* quadrilateral (the two triangles adjacent to `horiz'). */
8624 /* Identify the casing of the quadrilateral. */
8625 lprev(top, topleft);
8626 sym(topleft, toplcasing);
8627 lnext(top, topright);
8628 sym(topright, toprcasing);
8629 lnext(horiz, botleft);
8630 sym(botleft, botlcasing);
8631 lprev(horiz, botright);
8632 sym(botright, botrcasing);
8633 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
8634 bond(topleft, botlcasing);
8635 bond(botleft, botrcasing);
8636 bond(botright, toprcasing);
8637 bond(topright, toplcasing);
8638 if (m->checksegments) {
8639 /* Check for subsegments and rebond them to the quadrilateral. */
8640 tspivot(topleft, toplsubseg);
8641 tspivot(botleft, botlsubseg);
8642 tspivot(botright, botrsubseg);
8643 tspivot(topright, toprsubseg);
8644 if (toplsubseg.ss == m->dummysub) {
8645 tsdissolve(topright);
8646 } else {
8647 tsbond(topright, toplsubseg);
8648 }
8649 if (botlsubseg.ss == m->dummysub) {
8650 tsdissolve(topleft);
8651 } else {
8652 tsbond(topleft, botlsubseg);
8653 }
8654 if (botrsubseg.ss == m->dummysub) {
8655 tsdissolve(botleft);
8656 } else {
8657 tsbond(botleft, botrsubseg);
8658 }
8659 if (toprsubseg.ss == m->dummysub) {
8660 tsdissolve(botright);
8661 } else {
8662 tsbond(botright, toprsubseg);
8663 }
8664 }
8665 /* New vertex assignments for the rotated quadrilateral. */
8666 setorg(horiz, farvertex);
8667 setdest(horiz, newvertex);
8668 setapex(horiz, rightvertex);
8669 setorg(top, newvertex);
8670 setdest(top, farvertex);
8671 setapex(top, leftvertex);
8672 for (i = 0; i < m->eextras; i++) {
8673 /* Take the average of the two triangles' attributes. */
8674 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
8675 setelemattribute(top, i, attrib);
8676 setelemattribute(horiz, i, attrib);
8677 }
8678 if (b->vararea) {
8679 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
8680 area = -1.0;
8681 } else {
8682 /* Take the average of the two triangles' area constraints. */
8683 /* This prevents small area constraints from migrating a */
8684 /* long, long way from their original location due to flips. */
8685 area = 0.5 * (areabound(top) + areabound(horiz));
8686 }
8687 setareabound(top, area);
8688 setareabound(horiz, area);
8689 }
8690
8691 if (m->checkquality) {
8692 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8693 newflip->flippedtri = encode(horiz);
8694 newflip->prevflip = m->lastflip;
8695 m->lastflip = newflip;
8696 }
8697
8698#ifdef SELF_CHECK
8699 if (newvertex != (vertex) NULL) {
8700 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
8701 0.0) {
8702 printf("Internal error in insertvertex():\n");
8703 printf(" Clockwise triangle prior to edge flip (bottom).\n");
8704 }
8705 /* The following test has been removed because constrainededge() */
8706 /* sometimes generates inverted triangles that insertvertex() */
8707 /* removes. */
8708/*
8709 if (counterclockwise(m, b, rightvertex, farvertex, leftvertex) <
8710 0.0) {
8711 printf("Internal error in insertvertex():\n");
8712 printf(" Clockwise triangle prior to edge flip (top).\n");
8713 }
8714*/
8715 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
8716 0.0) {
8717 printf("Internal error in insertvertex():\n");
8718 printf(" Clockwise triangle after edge flip (left).\n");
8719 }
8720 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
8721 0.0) {
8722 printf("Internal error in insertvertex():\n");
8723 printf(" Clockwise triangle after edge flip (right).\n");
8724 }
8725 }
8726#endif /* SELF_CHECK */
8727 if (b->verbose > 2) {
8728 printf(" Edge flip results in left ");
8729 lnextself(topleft);
8730 printtriangle(m, b, &topleft);
8731 printf(" and right ");
8732 printtriangle(m, b, &horiz);
8733 }
8734 /* On the next iterations, consider the two edges that were */
8735 /* exposed (this is, are now visible to the newly inserted */
8736 /* vertex) by the edge flip. */
8737 lprevself(horiz);
8738 leftvertex = farvertex;
8739 }
8740 }
8741 }
8742 if (!doflip) {
8743 /* The handle `horiz' is accepted as locally Delaunay. */
8744#ifndef CDT_ONLY
8745 if (triflaws) {
8746 /* Check the triangle `horiz' for quality. */
8747 testtriangle(m, b, &horiz);
8748 }
8749#endif /* not CDT_ONLY */
8750 /* Look for the next edge around the newly inserted vertex. */
8751 lnextself(horiz);
8752 sym(horiz, testtri);
8753 /* Check for finishing a complete revolution about the new vertex, or */
8754 /* falling outside of the triangulation. The latter will happen */
8755 /* when a vertex is inserted at a boundary. */
8756 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
8757 /* We're done. Return a triangle whose origin is the new vertex. */
8758 lnext(horiz, *searchtri);
8759 lnext(horiz, m->recenttri);
8760 return success;
8761 }
8762 /* Finish finding the next edge around the newly inserted vertex. */
8763 lnext(testtri, horiz);
8764 rightvertex = leftvertex;
8765 dest(horiz, leftvertex);
8766 }
8767 }
8768}
8769
8770/*****************************************************************************/
8771/* */
8772/* triangulatepolygon() Find the Delaunay triangulation of a polygon that */
8773/* has a certain "nice" shape. This includes the */
8774/* polygons that result from deletion of a vertex or */
8775/* insertion of a segment. */
8776/* */
8777/* This is a conceptually difficult routine. The starting assumption is */
8778/* that we have a polygon with n sides. n - 1 of these sides are currently */
8779/* represented as edges in the mesh. One side, called the "base", need not */
8780/* be. */
8781/* */
8782/* Inside the polygon is a structure I call a "fan", consisting of n - 1 */
8783/* triangles that share a common origin. For each of these triangles, the */
8784/* edge opposite the origin is one of the sides of the polygon. The */
8785/* primary edge of each triangle is the edge directed from the origin to */
8786/* the destination; note that this is not the same edge that is a side of */
8787/* the polygon. `firstedge' is the primary edge of the first triangle. */
8788/* From there, the triangles follow in counterclockwise order about the */
8789/* polygon, until `lastedge', the primary edge of the last triangle. */
8790/* `firstedge' and `lastedge' are probably connected to other triangles */
8791/* beyond the extremes of the fan, but their identity is not important, as */
8792/* long as the fan remains connected to them. */
8793/* */
8794/* Imagine the polygon oriented so that its base is at the bottom. This */
8795/* puts `firstedge' on the far right, and `lastedge' on the far left. */
8796/* The right vertex of the base is the destination of `firstedge', and the */
8797/* left vertex of the base is the apex of `lastedge'. */
8798/* */
8799/* The challenge now is to find the right sequence of edge flips to */
8800/* transform the fan into a Delaunay triangulation of the polygon. Each */
8801/* edge flip effectively removes one triangle from the fan, committing it */
8802/* to the polygon. The resulting polygon has one fewer edge. If `doflip' */
8803/* is set, the final flip will be performed, resulting in a fan of one */
8804/* (useless?) triangle. If `doflip' is not set, the final flip is not */
8805/* performed, resulting in a fan of two triangles, and an unfinished */
8806/* triangular polygon that is not yet filled out with a single triangle. */
8807/* On completion of the routine, `lastedge' is the last remaining triangle, */
8808/* or the leftmost of the last two. */
8809/* */
8810/* Although the flips are performed in the order described above, the */
8811/* decisions about what flips to perform are made in precisely the reverse */
8812/* order. The recursive triangulatepolygon() procedure makes a decision, */
8813/* uses up to two recursive calls to triangulate the "subproblems" */
8814/* (polygons with fewer edges), and then performs an edge flip. */
8815/* */
8816/* The "decision" it makes is which vertex of the polygon should be */
8817/* connected to the base. This decision is made by testing every possible */
8818/* vertex. Once the best vertex is found, the two edges that connect this */
8819/* vertex to the base become the bases for two smaller polygons. These */
8820/* are triangulated recursively. Unfortunately, this approach can take */
8821/* O(n^2) time not only in the worst case, but in many common cases. It's */
8822/* rarely a big deal for vertex deletion, where n is rarely larger than */
8823/* ten, but it could be a big deal for segment insertion, especially if */
8824/* there's a lot of long segments that each cut many triangles. I ought to */
8825/* code a faster algorithm some day. */
8826/* */
8827/* The `edgecount' parameter is the number of sides of the polygon, */
8828/* including its base. `triflaws' is a flag that determines whether the */
8829/* new triangles should be tested for quality, and enqueued if they are */
8830/* bad. */
8831/* */
8832/*****************************************************************************/
8833
8834#ifdef ANSI_DECLARATORS
8835void triangulatepolygon(struct mesh *m, struct behavior *b,
8836 struct otri *firstedge, struct otri *lastedge,
8837 int edgecount, int doflip, int triflaws)
8838#else /* not ANSI_DECLARATORS */
8839void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
8840struct mesh *m;
8841struct behavior *b;
8842struct otri *firstedge;
8843struct otri *lastedge;
8844int edgecount;
8845int doflip;
8846int triflaws;
8847#endif /* not ANSI_DECLARATORS */
8848
8849{
8850 struct otri testtri;
8851 struct otri besttri;
8852 struct otri tempedge;
8853 vertex leftbasevertex, rightbasevertex;
8854 vertex testvertex;
8855 vertex bestvertex;
8856 int bestnumber;
8857 int i;
8858 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8859
8860 /* Identify the base vertices. */
8861 apex(*lastedge, leftbasevertex);
8862 dest(*firstedge, rightbasevertex);
8863 if (b->verbose > 2) {
8864 printf(" Triangulating interior polygon at edge\n");
8865 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
8866 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
8867 }
8868 /* Find the best vertex to connect the base to. */
8869 onext(*firstedge, besttri);
8870 dest(besttri, bestvertex);
8871 otricopy(besttri, testtri);
8872 bestnumber = 1;
8873 for (i = 2; i <= edgecount - 2; i++) {
8874 onextself(testtri);
8875 dest(testtri, testvertex);
8876 /* Is this a better vertex? */
8877 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
8878 testvertex) > 0.0) {
8879 otricopy(testtri, besttri);
8880 bestvertex = testvertex;
8881 bestnumber = i;
8882 }
8883 }
8884 if (b->verbose > 2) {
8885 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
8886 bestvertex[1]);
8887 }
8888 if (bestnumber > 1) {
8889 /* Recursively triangulate the smaller polygon on the right. */
8890 oprev(besttri, tempedge);
8891 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
8892 triflaws);
8893 }
8894 if (bestnumber < edgecount - 2) {
8895 /* Recursively triangulate the smaller polygon on the left. */
8896 sym(besttri, tempedge);
8897 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
8898 triflaws);
8899 /* Find `besttri' again; it may have been lost to edge flips. */
8900 sym(tempedge, besttri);
8901 }
8902 if (doflip) {
8903 /* Do one final edge flip. */
8904 flip(m, b, &besttri);
8905#ifndef CDT_ONLY
8906 if (triflaws) {
8907 /* Check the quality of the newly committed triangle. */
8908 sym(besttri, testtri);
8909 testtriangle(m, b, &testtri);
8910 }
8911#endif /* not CDT_ONLY */
8912 }
8913 /* Return the base triangle. */
8914 otricopy(besttri, *lastedge);
8915}
8916
8917/*****************************************************************************/
8918/* */
8919/* deletevertex() Delete a vertex from a Delaunay triangulation, ensuring */
8920/* that the triangulation remains Delaunay. */
8921/* */
8922/* The origin of `deltri' is deleted. The union of the triangles adjacent */
8923/* to this vertex is a polygon, for which the Delaunay triangulation is */
8924/* found. Two triangles are removed from the mesh. */
8925/* */
8926/* Only interior vertices that do not lie on segments or boundaries may be */
8927/* deleted. */
8928/* */
8929/*****************************************************************************/
8930
8931#ifndef CDT_ONLY
8932
8933#ifdef ANSI_DECLARATORS
8934void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
8935#else /* not ANSI_DECLARATORS */
8936void deletevertex(m, b, deltri)
8937struct mesh *m;
8938struct behavior *b;
8939struct otri *deltri;
8940#endif /* not ANSI_DECLARATORS */
8941
8942{
8943 struct otri countingtri;
8944 struct otri firstedge, lastedge;
8945 struct otri deltriright;
8946 struct otri lefttri, righttri;
8947 struct otri leftcasing, rightcasing;
8948 struct osub leftsubseg, rightsubseg;
8949 vertex delvertex;
8950 vertex neworg;
8951 int edgecount;
8952 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8953 subseg sptr; /* Temporary variable used by tspivot(). */
8954
8955 org(*deltri, delvertex);
8956 if (b->verbose > 1) {
8957 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
8958 }
8959 vertexdealloc(m, delvertex);
8960
8961 /* Count the degree of the vertex being deleted. */
8962 onext(*deltri, countingtri);
8963 edgecount = 1;
8964 while (!otriequal(*deltri, countingtri)) {
8965#ifdef SELF_CHECK
8966 if (countingtri.tri == m->dummytri) {
8967 printf("Internal error in deletevertex():\n");
8968 printf(" Attempt to delete boundary vertex.\n");
8969 internalerror();
8970 }
8971#endif /* SELF_CHECK */
8972 edgecount++;
8973 onextself(countingtri);
8974 }
8975
8976#ifdef SELF_CHECK
8977 if (edgecount < 3) {
8978 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
8979 edgecount);
8980 internalerror();
8981 }
8982#endif /* SELF_CHECK */
8983 if (edgecount > 3) {
8984 /* Triangulate the polygon defined by the union of all triangles */
8985 /* adjacent to the vertex being deleted. Check the quality of */
8986 /* the resulting triangles. */
8987 onext(*deltri, firstedge);
8988 oprev(*deltri, lastedge);
8989 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
8990 !b->nobisect);
8991 }
8992 /* Splice out two triangles. */
8993 lprev(*deltri, deltriright);
8994 dnext(*deltri, lefttri);
8995 sym(lefttri, leftcasing);
8996 oprev(deltriright, righttri);
8997 sym(righttri, rightcasing);
8998 bond(*deltri, leftcasing);
8999 bond(deltriright, rightcasing);
9000 tspivot(lefttri, leftsubseg);
9001 if (leftsubseg.ss != m->dummysub) {
9002 tsbond(*deltri, leftsubseg);
9003 }
9004 tspivot(righttri, rightsubseg);
9005 if (rightsubseg.ss != m->dummysub) {
9006 tsbond(deltriright, rightsubseg);
9007 }
9008
9009 /* Set the new origin of `deltri' and check its quality. */
9010 org(lefttri, neworg);
9011 setorg(*deltri, neworg);
9012 if (!b->nobisect) {
9013 testtriangle(m, b, deltri);
9014 }
9015
9016 /* Delete the two spliced-out triangles. */
9017 triangledealloc(m, lefttri.tri);
9018 triangledealloc(m, righttri.tri);
9019}
9020
9021#endif /* not CDT_ONLY */
9022
9023/*****************************************************************************/
9024/* */
9025/* undovertex() Undo the most recent vertex insertion. */
9026/* */
9027/* Walks through the list of transformations (flips and a vertex insertion) */
9028/* in the reverse of the order in which they were done, and undoes them. */
9029/* The inserted vertex is removed from the triangulation and deallocated. */
9030/* Two triangles (possibly just one) are also deallocated. */
9031/* */
9032/*****************************************************************************/
9033
9034#ifndef CDT_ONLY
9035
9036#ifdef ANSI_DECLARATORS
9037void undovertex(struct mesh *m, struct behavior *b)
9038#else /* not ANSI_DECLARATORS */
9039void undovertex(m, b)
9040struct mesh *m;
9041struct behavior *b;
9042#endif /* not ANSI_DECLARATORS */
9043
9044{
9045 struct otri fliptri;
9046 struct otri botleft, botright, topright;
9047 struct otri botlcasing, botrcasing, toprcasing;
9048 struct otri gluetri;
9049 struct osub botlsubseg, botrsubseg, toprsubseg;
9050 vertex botvertex, rightvertex;
9051 triangle ptr; /* Temporary variable used by sym(). */
9052 subseg sptr; /* Temporary variable used by tspivot(). */
9053
9054 /* Walk through the list of transformations (flips and a vertex insertion) */
9055 /* in the reverse of the order in which they were done, and undo them. */
9056 while (m->lastflip != (struct flipstacker *) NULL) {
9057 /* Find a triangle involved in the last unreversed transformation. */
9058 decode(m->lastflip->flippedtri, fliptri);
9059
9060 /* We are reversing one of three transformations: a trisection of one */
9061 /* triangle into three (by inserting a vertex in the triangle), a */
9062 /* bisection of two triangles into four (by inserting a vertex in an */
9063 /* edge), or an edge flip. */
9064 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
9065 /* Restore a triangle that was split into three triangles, */
9066 /* so it is again one triangle. */
9067 dprev(fliptri, botleft);
9068 lnextself(botleft);
9069 onext(fliptri, botright);
9070 lprevself(botright);
9071 sym(botleft, botlcasing);
9072 sym(botright, botrcasing);
9073 dest(botleft, botvertex);
9074
9075 setapex(fliptri, botvertex);
9076 lnextself(fliptri);
9077 bond(fliptri, botlcasing);
9078 tspivot(botleft, botlsubseg);
9079 tsbond(fliptri, botlsubseg);
9080 lnextself(fliptri);
9081 bond(fliptri, botrcasing);
9082 tspivot(botright, botrsubseg);
9083 tsbond(fliptri, botrsubseg);
9084
9085 /* Delete the two spliced-out triangles. */
9086 triangledealloc(m, botleft.tri);
9087 triangledealloc(m, botright.tri);
9088 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
9089 /* Restore two triangles that were split into four triangles, */
9090 /* so they are again two triangles. */
9091 lprev(fliptri, gluetri);
9092 sym(gluetri, botright);
9093 lnextself(botright);
9094 sym(botright, botrcasing);
9095 dest(botright, rightvertex);
9096
9097 setorg(fliptri, rightvertex);
9098 bond(gluetri, botrcasing);
9099 tspivot(botright, botrsubseg);
9100 tsbond(gluetri, botrsubseg);
9101
9102 /* Delete the spliced-out triangle. */
9103 triangledealloc(m, botright.tri);
9104
9105 sym(fliptri, gluetri);
9106 if (gluetri.tri != m->dummytri) {
9107 lnextself(gluetri);
9108 dnext(gluetri, topright);
9109 sym(topright, toprcasing);
9110
9111 setorg(gluetri, rightvertex);
9112 bond(gluetri, toprcasing);
9113 tspivot(topright, toprsubseg);
9114 tsbond(gluetri, toprsubseg);
9115
9116 /* Delete the spliced-out triangle. */
9117 triangledealloc(m, topright.tri);
9118 }
9119
9120 /* This is the end of the list, sneakily encoded. */
9121 m->lastflip->prevflip = (struct flipstacker *) NULL;
9122 } else {
9123 /* Undo an edge flip. */
9124 unflip(m, b, &fliptri);
9125 }
9126
9127 /* Go on and process the next transformation. */
9128 m->lastflip = m->lastflip->prevflip;
9129 }
9130}
9131
9132#endif /* not CDT_ONLY */
9133
9134/** **/
9135/** **/
9136/********* Mesh transformation routines end here *********/
9137
9138/********* Divide-and-conquer Delaunay triangulation begins here *********/
9139/** **/
9140/** **/
9141
9142/*****************************************************************************/
9143/* */
9144/* The divide-and-conquer bounding box */
9145/* */
9146/* I originally implemented the divide-and-conquer and incremental Delaunay */
9147/* triangulations using the edge-based data structure presented by Guibas */
9148/* and Stolfi. Switching to a triangle-based data structure doubled the */
9149/* speed. However, I had to think of a few extra tricks to maintain the */
9150/* elegance of the original algorithms. */
9151/* */
9152/* The "bounding box" used by my variant of the divide-and-conquer */
9153/* algorithm uses one triangle for each edge of the convex hull of the */
9154/* triangulation. These bounding triangles all share a common apical */
9155/* vertex, which is represented by NULL and which represents nothing. */
9156/* The bounding triangles are linked in a circular fan about this NULL */
9157/* vertex, and the edges on the convex hull of the triangulation appear */
9158/* opposite the NULL vertex. You might find it easiest to imagine that */
9159/* the NULL vertex is a point in 3D space behind the center of the */
9160/* triangulation, and that the bounding triangles form a sort of cone. */
9161/* */
9162/* This bounding box makes it easy to represent degenerate cases. For */
9163/* instance, the triangulation of two vertices is a single edge. This edge */
9164/* is represented by two bounding box triangles, one on each "side" of the */
9165/* edge. These triangles are also linked together in a fan about the NULL */
9166/* vertex. */
9167/* */
9168/* The bounding box also makes it easy to traverse the convex hull, as the */
9169/* divide-and-conquer algorithm needs to do. */
9170/* */
9171/*****************************************************************************/
9172
9173/*****************************************************************************/
9174/* */
9175/* vertexsort() Sort an array of vertices by x-coordinate, using the */
9176/* y-coordinate as a secondary key. */
9177/* */
9178/* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */
9179/* the usual quicksort mistakes. */
9180/* */
9181/*****************************************************************************/
9182
9183#ifdef ANSI_DECLARATORS
9184void vertexsort(vertex *sortarray, int arraysize)
9185#else /* not ANSI_DECLARATORS */
9186void vertexsort(sortarray, arraysize)
9187vertex *sortarray;
9188int arraysize;
9189#endif /* not ANSI_DECLARATORS */
9190
9191{
9192 int left, right;
9193 int pivot;
9194 REAL pivotx, pivoty;
9195 vertex temp;
9196
9197 if (arraysize == 2) {
9198 /* Recursive base case. */
9199 if ((sortarray[0][0] > sortarray[1][0]) ||
9200 ((sortarray[0][0] == sortarray[1][0]) &&
9201 (sortarray[0][1] > sortarray[1][1]))) {
9202 temp = sortarray[1];
9203 sortarray[1] = sortarray[0];
9204 sortarray[0] = temp;
9205 }
9206 return;
9207 }
9208 /* Choose a random pivot to split the array. */
9209 pivot = (int) randomnation((unsigned int) arraysize);
9210 pivotx = sortarray[pivot][0];
9211 pivoty = sortarray[pivot][1];
9212 /* Split the array. */
9213 left = -1;
9214 right = arraysize;
9215 while (left < right) {
9216 /* Search for a vertex whose x-coordinate is too large for the left. */
9217 do {
9218 left++;
9219 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
9220 ((sortarray[left][0] == pivotx) &&
9221 (sortarray[left][1] < pivoty))));
9222 /* Search for a vertex whose x-coordinate is too small for the right. */
9223 do {
9224 right--;
9225 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
9226 ((sortarray[right][0] == pivotx) &&
9227 (sortarray[right][1] > pivoty))));
9228 if (left < right) {
9229 /* Swap the left and right vertices. */
9230 temp = sortarray[left];
9231 sortarray[left] = sortarray[right];
9232 sortarray[right] = temp;
9233 }
9234 }
9235 if (left > 1) {
9236 /* Recursively sort the left subset. */
9237 vertexsort(sortarray, left);
9238 }
9239 if (right < arraysize - 2) {
9240 /* Recursively sort the right subset. */
9241 vertexsort(&sortarray[right + 1], arraysize - right - 1);
9242 }
9243}
9244
9245/*****************************************************************************/
9246/* */
9247/* vertexmedian() An order statistic algorithm, almost. Shuffles an */
9248/* array of vertices so that the first `median' vertices */
9249/* occur lexicographically before the remaining vertices. */
9250/* */
9251/* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */
9252/* if axis == 1. Very similar to the vertexsort() procedure, but runs in */
9253/* randomized linear time. */
9254/* */
9255/*****************************************************************************/
9256
9257#ifdef ANSI_DECLARATORS
9258void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
9259#else /* not ANSI_DECLARATORS */
9260void vertexmedian(sortarray, arraysize, median, axis)
9261vertex *sortarray;
9262int arraysize;
9263int median;
9264int axis;
9265#endif /* not ANSI_DECLARATORS */
9266
9267{
9268 int left, right;
9269 int pivot;
9270 REAL pivot1, pivot2;
9271 vertex temp;
9272
9273 if (arraysize == 2) {
9274 /* Recursive base case. */
9275 if ((sortarray[0][axis] > sortarray[1][axis]) ||
9276 ((sortarray[0][axis] == sortarray[1][axis]) &&
9277 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
9278 temp = sortarray[1];
9279 sortarray[1] = sortarray[0];
9280 sortarray[0] = temp;
9281 }
9282 return;
9283 }
9284 /* Choose a random pivot to split the array. */
9285 pivot = (int) randomnation((unsigned int) arraysize);
9286 pivot1 = sortarray[pivot][axis];
9287 pivot2 = sortarray[pivot][1 - axis];
9288 /* Split the array. */
9289 left = -1;
9290 right = arraysize;
9291 while (left < right) {
9292 /* Search for a vertex whose x-coordinate is too large for the left. */
9293 do {
9294 left++;
9295 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
9296 ((sortarray[left][axis] == pivot1) &&
9297 (sortarray[left][1 - axis] < pivot2))));
9298 /* Search for a vertex whose x-coordinate is too small for the right. */
9299 do {
9300 right--;
9301 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
9302 ((sortarray[right][axis] == pivot1) &&
9303 (sortarray[right][1 - axis] > pivot2))));
9304 if (left < right) {
9305 /* Swap the left and right vertices. */
9306 temp = sortarray[left];
9307 sortarray[left] = sortarray[right];
9308 sortarray[right] = temp;
9309 }
9310 }
9311 /* Unlike in vertexsort(), at most one of the following */
9312 /* conditionals is true. */
9313 if (left > median) {
9314 /* Recursively shuffle the left subset. */
9315 vertexmedian(sortarray, left, median, axis);
9316 }
9317 if (right < median - 1) {
9318 /* Recursively shuffle the right subset. */
9319 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
9320 median - right - 1, axis);
9321 }
9322}
9323
9324/*****************************************************************************/
9325/* */
9326/* alternateaxes() Sorts the vertices as appropriate for the divide-and- */
9327/* conquer algorithm with alternating cuts. */
9328/* */
9329/* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */
9330/* For the base case, subsets containing only two or three vertices are */
9331/* always sorted by x-coordinate. */
9332/* */
9333/*****************************************************************************/
9334
9335#ifdef ANSI_DECLARATORS
9336void alternateaxes(vertex *sortarray, int arraysize, int axis)
9337#else /* not ANSI_DECLARATORS */
9338void alternateaxes(sortarray, arraysize, axis)
9339vertex *sortarray;
9340int arraysize;
9341int axis;
9342#endif /* not ANSI_DECLARATORS */
9343
9344{
9345 int divider;
9346
9347 divider = arraysize >> 1;
9348 if (arraysize <= 3) {
9349 /* Recursive base case: subsets of two or three vertices will be */
9350 /* handled specially, and should always be sorted by x-coordinate. */
9351 axis = 0;
9352 }
9353 /* Partition with a horizontal or vertical cut. */
9354 vertexmedian(sortarray, arraysize, divider, axis);
9355 /* Recursively partition the subsets with a cross cut. */
9356 if (arraysize - divider >= 2) {
9357 if (divider >= 2) {
9358 alternateaxes(sortarray, divider, 1 - axis);
9359 }
9360 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
9361 }
9362}
9363
9364/*****************************************************************************/
9365/* */
9366/* mergehulls() Merge two adjacent Delaunay triangulations into a */
9367/* single Delaunay triangulation. */
9368/* */
9369/* This is similar to the algorithm given by Guibas and Stolfi, but uses */
9370/* a triangle-based, rather than edge-based, data structure. */
9371/* */
9372/* The algorithm walks up the gap between the two triangulations, knitting */
9373/* them together. As they are merged, some of their bounding triangles */
9374/* are converted into real triangles of the triangulation. The procedure */
9375/* pulls each hull's bounding triangles apart, then knits them together */
9376/* like the teeth of two gears. The Delaunay property determines, at each */
9377/* step, whether the next "tooth" is a bounding triangle of the left hull */
9378/* or the right. When a bounding triangle becomes real, its apex is */
9379/* changed from NULL to a real vertex. */
9380/* */
9381/* Only two new triangles need to be allocated. These become new bounding */
9382/* triangles at the top and bottom of the seam. They are used to connect */
9383/* the remaining bounding triangles (those that have not been converted */
9384/* into real triangles) into a single fan. */
9385/* */
9386/* On entry, `farleft' and `innerleft' are bounding triangles of the left */
9387/* triangulation. The origin of `farleft' is the leftmost vertex, and */
9388/* the destination of `innerleft' is the rightmost vertex of the */
9389/* triangulation. Similarly, `innerright' and `farright' are bounding */
9390/* triangles of the right triangulation. The origin of `innerright' and */
9391/* destination of `farright' are the leftmost and rightmost vertices. */
9392/* */
9393/* On completion, the origin of `farleft' is the leftmost vertex of the */
9394/* merged triangulation, and the destination of `farright' is the rightmost */
9395/* vertex. */
9396/* */
9397/*****************************************************************************/
9398
9399#ifdef ANSI_DECLARATORS
9400void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
9401 struct otri *innerleft, struct otri *innerright,
9402 struct otri *farright, int axis)
9403#else /* not ANSI_DECLARATORS */
9404void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
9405struct mesh *m;
9406struct behavior *b;
9407struct otri *farleft;
9408struct otri *innerleft;
9409struct otri *innerright;
9410struct otri *farright;
9411int axis;
9412#endif /* not ANSI_DECLARATORS */
9413
9414{
9415 struct otri leftcand, rightcand;
9416 struct otri baseedge;
9417 struct otri nextedge;
9418 struct otri sidecasing, topcasing, outercasing;
9419 struct otri checkedge;
9420 vertex innerleftdest;
9421 vertex innerrightorg;
9422 vertex innerleftapex, innerrightapex;
9423 vertex farleftpt, farrightpt;
9424 vertex farleftapex, farrightapex;
9425 vertex lowerleft, lowerright;
9426 vertex upperleft, upperright;
9427 vertex nextapex;
9428 vertex checkvertex;
9429 int changemade;
9430 int badedge;
9431 int leftfinished, rightfinished;
9432 triangle ptr; /* Temporary variable used by sym(). */
9433
9434 dest(*innerleft, innerleftdest);
9435 apex(*innerleft, innerleftapex);
9436 org(*innerright, innerrightorg);
9437 apex(*innerright, innerrightapex);
9438 /* Special treatment for horizontal cuts. */
9439 if (b->dwyer && (axis == 1)) {
9440 org(*farleft, farleftpt);
9441 apex(*farleft, farleftapex);
9442 dest(*farright, farrightpt);
9443 apex(*farright, farrightapex);
9444 /* The pointers to the extremal vertices are shifted to point to the */
9445 /* topmost and bottommost vertex of each hull, rather than the */
9446 /* leftmost and rightmost vertices. */
9447 while (farleftapex[1] < farleftpt[1]) {
9448 lnextself(*farleft);
9449 symself(*farleft);
9450 farleftpt = farleftapex;
9451 apex(*farleft, farleftapex);
9452 }
9453 sym(*innerleft, checkedge);
9454 apex(checkedge, checkvertex);
9455 while (checkvertex[1] > innerleftdest[1]) {
9456 lnext(checkedge, *innerleft);
9457 innerleftapex = innerleftdest;
9458 innerleftdest = checkvertex;
9459 sym(*innerleft, checkedge);
9460 apex(checkedge, checkvertex);
9461 }
9462 while (innerrightapex[1] < innerrightorg[1]) {
9463 lnextself(*innerright);
9464 symself(*innerright);
9465 innerrightorg = innerrightapex;
9466 apex(*innerright, innerrightapex);
9467 }
9468 sym(*farright, checkedge);
9469 apex(checkedge, checkvertex);
9470 while (checkvertex[1] > farrightpt[1]) {
9471 lnext(checkedge, *farright);
9472 farrightapex = farrightpt;
9473 farrightpt = checkvertex;
9474 sym(*farright, checkedge);
9475 apex(checkedge, checkvertex);
9476 }
9477 }
9478 /* Find a line tangent to and below both hulls. */
9479 do {
9480 changemade = 0;
9481 /* Make innerleftdest the "bottommost" vertex of the left hull. */
9482 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
9483 0.0) {
9484 lprevself(*innerleft);
9485 symself(*innerleft);
9486 innerleftdest = innerleftapex;
9487 apex(*innerleft, innerleftapex);
9488 changemade = 1;
9489 }
9490 /* Make innerrightorg the "bottommost" vertex of the right hull. */
9491 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
9492 0.0) {
9493 lnextself(*innerright);
9494 symself(*innerright);
9495 innerrightorg = innerrightapex;
9496 apex(*innerright, innerrightapex);
9497 changemade = 1;
9498 }
9499 } while (changemade);
9500 /* Find the two candidates to be the next "gear tooth." */
9501 sym(*innerleft, leftcand);
9502 sym(*innerright, rightcand);
9503 /* Create the bottom new bounding triangle. */
9504 maketriangle(m, b, &baseedge);
9505 /* Connect it to the bounding boxes of the left and right triangulations. */
9506 bond(baseedge, *innerleft);
9507 lnextself(baseedge);
9508 bond(baseedge, *innerright);
9509 lnextself(baseedge);
9510 setorg(baseedge, innerrightorg);
9511 setdest(baseedge, innerleftdest);
9512 /* Apex is intentionally left NULL. */
9513 if (b->verbose > 2) {
9514 printf(" Creating base bounding ");
9515 printtriangle(m, b, &baseedge);
9516 }
9517 /* Fix the extreme triangles if necessary. */
9518 org(*farleft, farleftpt);
9519 if (innerleftdest == farleftpt) {
9520 lnext(baseedge, *farleft);
9521 }
9522 dest(*farright, farrightpt);
9523 if (innerrightorg == farrightpt) {
9524 lprev(baseedge, *farright);
9525 }
9526 /* The vertices of the current knitting edge. */
9527 lowerleft = innerleftdest;
9528 lowerright = innerrightorg;
9529 /* The candidate vertices for knitting. */
9530 apex(leftcand, upperleft);
9531 apex(rightcand, upperright);
9532 /* Walk up the gap between the two triangulations, knitting them together. */
9533 while (1) {
9534 /* Have we reached the top? (This isn't quite the right question, */
9535 /* because even though the left triangulation might seem finished now, */
9536 /* moving up on the right triangulation might reveal a new vertex of */
9537 /* the left triangulation. And vice-versa.) */
9538 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
9539 0.0;
9540 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
9541 <= 0.0;
9542 if (leftfinished && rightfinished) {
9543 /* Create the top new bounding triangle. */
9544 maketriangle(m, b, &nextedge);
9545 setorg(nextedge, lowerleft);
9546 setdest(nextedge, lowerright);
9547 /* Apex is intentionally left NULL. */
9548 /* Connect it to the bounding boxes of the two triangulations. */
9549 bond(nextedge, baseedge);
9550 lnextself(nextedge);
9551 bond(nextedge, rightcand);
9552 lnextself(nextedge);
9553 bond(nextedge, leftcand);
9554 if (b->verbose > 2) {
9555 printf(" Creating top bounding ");
9556 printtriangle(m, b, &nextedge);
9557 }
9558 /* Special treatment for horizontal cuts. */
9559 if (b->dwyer && (axis == 1)) {
9560 org(*farleft, farleftpt);
9561 apex(*farleft, farleftapex);
9562 dest(*farright, farrightpt);
9563 apex(*farright, farrightapex);
9564 sym(*farleft, checkedge);
9565 apex(checkedge, checkvertex);
9566 /* The pointers to the extremal vertices are restored to the */
9567 /* leftmost and rightmost vertices (rather than topmost and */
9568 /* bottommost). */
9569 while (checkvertex[0] < farleftpt[0]) {
9570 lprev(checkedge, *farleft);
9571 farleftapex = farleftpt;
9572 farleftpt = checkvertex;
9573 sym(*farleft, checkedge);
9574 apex(checkedge, checkvertex);
9575 }
9576 while (farrightapex[0] > farrightpt[0]) {
9577 lprevself(*farright);
9578 symself(*farright);
9579 farrightpt = farrightapex;
9580 apex(*farright, farrightapex);
9581 }
9582 }
9583 return;
9584 }
9585 /* Consider eliminating edges from the left triangulation. */
9586 if (!leftfinished) {
9587 /* What vertex would be exposed if an edge were deleted? */
9588 lprev(leftcand, nextedge);
9589 symself(nextedge);
9590 apex(nextedge, nextapex);
9591 /* If nextapex is NULL, then no vertex would be exposed; the */
9592 /* triangulation would have been eaten right through. */
9593 if (nextapex != (vertex) NULL) {
9594 /* Check whether the edge is Delaunay. */
9595 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
9596 0.0;
9597 while (badedge) {
9598 /* Eliminate the edge with an edge flip. As a result, the */
9599 /* left triangulation will have one more boundary triangle. */
9600 lnextself(nextedge);
9601 sym(nextedge, topcasing);
9602 lnextself(nextedge);
9603 sym(nextedge, sidecasing);
9604 bond(nextedge, topcasing);
9605 bond(leftcand, sidecasing);
9606 lnextself(leftcand);
9607 sym(leftcand, outercasing);
9608 lprevself(nextedge);
9609 bond(nextedge, outercasing);
9610 /* Correct the vertices to reflect the edge flip. */
9611 setorg(leftcand, lowerleft);
9612 setdest(leftcand, NULL);
9613 setapex(leftcand, nextapex);
9614 setorg(nextedge, NULL);
9615 setdest(nextedge, upperleft);
9616 setapex(nextedge, nextapex);
9617 /* Consider the newly exposed vertex. */
9618 upperleft = nextapex;
9619 /* What vertex would be exposed if another edge were deleted? */
9620 otricopy(sidecasing, nextedge);
9621 apex(nextedge, nextapex);
9622 if (nextapex != (vertex) NULL) {
9623 /* Check whether the edge is Delaunay. */
9624 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
9625 nextapex) > 0.0;
9626 } else {
9627 /* Avoid eating right through the triangulation. */
9628 badedge = 0;
9629 }
9630 }
9631 }
9632 }
9633 /* Consider eliminating edges from the right triangulation. */
9634 if (!rightfinished) {
9635 /* What vertex would be exposed if an edge were deleted? */
9636 lnext(rightcand, nextedge);
9637 symself(nextedge);
9638 apex(nextedge, nextapex);
9639 /* If nextapex is NULL, then no vertex would be exposed; the */
9640 /* triangulation would have been eaten right through. */
9641 if (nextapex != (vertex) NULL) {
9642 /* Check whether the edge is Delaunay. */
9643 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
9644 0.0;
9645 while (badedge) {
9646 /* Eliminate the edge with an edge flip. As a result, the */
9647 /* right triangulation will have one more boundary triangle. */
9648 lprevself(nextedge);
9649 sym(nextedge, topcasing);
9650 lprevself(nextedge);
9651 sym(nextedge, sidecasing);
9652 bond(nextedge, topcasing);
9653 bond(rightcand, sidecasing);
9654 lprevself(rightcand);
9655 sym(rightcand, outercasing);
9656 lnextself(nextedge);
9657 bond(nextedge, outercasing);
9658 /* Correct the vertices to reflect the edge flip. */
9659 setorg(rightcand, NULL);
9660 setdest(rightcand, lowerright);
9661 setapex(rightcand, nextapex);
9662 setorg(nextedge, upperright);
9663 setdest(nextedge, NULL);
9664 setapex(nextedge, nextapex);
9665 /* Consider the newly exposed vertex. */
9666 upperright = nextapex;
9667 /* What vertex would be exposed if another edge were deleted? */
9668 otricopy(sidecasing, nextedge);
9669 apex(nextedge, nextapex);
9670 if (nextapex != (vertex) NULL) {
9671 /* Check whether the edge is Delaunay. */
9672 badedge = incircle(m, b, lowerleft, lowerright, upperright,
9673 nextapex) > 0.0;
9674 } else {
9675 /* Avoid eating right through the triangulation. */
9676 badedge = 0;
9677 }
9678 }
9679 }
9680 }
9681 if (leftfinished || (!rightfinished &&
9682 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
9683 0.0))) {
9684 /* Knit the triangulations, adding an edge from `lowerleft' */
9685 /* to `upperright'. */
9686 bond(baseedge, rightcand);
9687 lprev(rightcand, baseedge);
9688 setdest(baseedge, lowerleft);
9689 lowerright = upperright;
9690 sym(baseedge, rightcand);
9691 apex(rightcand, upperright);
9692 } else {
9693 /* Knit the triangulations, adding an edge from `upperleft' */
9694 /* to `lowerright'. */
9695 bond(baseedge, leftcand);
9696 lnext(leftcand, baseedge);
9697 setorg(baseedge, lowerright);
9698 lowerleft = upperleft;
9699 sym(baseedge, leftcand);
9700 apex(leftcand, upperleft);
9701 }
9702 if (b->verbose > 2) {
9703 printf(" Connecting ");
9704 printtriangle(m, b, &baseedge);
9705 }
9706 }
9707}
9708
9709/*****************************************************************************/
9710/* */
9711/* divconqrecurse() Recursively form a Delaunay triangulation by the */
9712/* divide-and-conquer method. */
9713/* */
9714/* Recursively breaks down the problem into smaller pieces, which are */
9715/* knitted together by mergehulls(). The base cases (problems of two or */
9716/* three vertices) are handled specially here. */
9717/* */
9718/* On completion, `farleft' and `farright' are bounding triangles such that */
9719/* the origin of `farleft' is the leftmost vertex (breaking ties by */
9720/* choosing the highest leftmost vertex), and the destination of */
9721/* `farright' is the rightmost vertex (breaking ties by choosing the */
9722/* lowest rightmost vertex). */
9723/* */
9724/*****************************************************************************/
9725
9726#ifdef ANSI_DECLARATORS
9727void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
9728 int vertices, int axis,
9729 struct otri *farleft, struct otri *farright)
9730#else /* not ANSI_DECLARATORS */
9731void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
9732struct mesh *m;
9733struct behavior *b;
9734vertex *sortarray;
9735int vertices;
9736int axis;
9737struct otri *farleft;
9738struct otri *farright;
9739#endif /* not ANSI_DECLARATORS */
9740
9741{
9742 struct otri midtri, tri1, tri2, tri3;
9743 struct otri innerleft, innerright;
9744 REAL area;
9745 int divider;
9746
9747 if (b->verbose > 2) {
9748 printf(" Triangulating %d vertices.\n", vertices);
9749 }
9750 if (vertices == 2) {
9751 /* The triangulation of two vertices is an edge. An edge is */
9752 /* represented by two bounding triangles. */
9753 maketriangle(m, b, farleft);
9754 setorg(*farleft, sortarray[0]);
9755 setdest(*farleft, sortarray[1]);
9756 /* The apex is intentionally left NULL. */
9757 maketriangle(m, b, farright);
9758 setorg(*farright, sortarray[1]);
9759 setdest(*farright, sortarray[0]);
9760 /* The apex is intentionally left NULL. */
9761 bond(*farleft, *farright);
9762 lprevself(*farleft);
9763 lnextself(*farright);
9764 bond(*farleft, *farright);
9765 lprevself(*farleft);
9766 lnextself(*farright);
9767 bond(*farleft, *farright);
9768 if (b->verbose > 2) {
9769 printf(" Creating ");
9770 printtriangle(m, b, farleft);
9771 printf(" Creating ");
9772 printtriangle(m, b, farright);
9773 }
9774 /* Ensure that the origin of `farleft' is sortarray[0]. */
9775 lprev(*farright, *farleft);
9776 return;
9777 } else if (vertices == 3) {
9778 /* The triangulation of three vertices is either a triangle (with */
9779 /* three bounding triangles) or two edges (with four bounding */
9780 /* triangles). In either case, four triangles are created. */
9781 maketriangle(m, b, &midtri);
9782 maketriangle(m, b, &tri1);
9783 maketriangle(m, b, &tri2);
9784 maketriangle(m, b, &tri3);
9785 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
9786 if (area == 0.0) {
9787 /* Three collinear vertices; the triangulation is two edges. */
9788 setorg(midtri, sortarray[0]);
9789 setdest(midtri, sortarray[1]);
9790 setorg(tri1, sortarray[1]);
9791 setdest(tri1, sortarray[0]);
9792 setorg(tri2, sortarray[2]);
9793 setdest(tri2, sortarray[1]);
9794 setorg(tri3, sortarray[1]);
9795 setdest(tri3, sortarray[2]);
9796 /* All apices are intentionally left NULL. */
9797 bond(midtri, tri1);
9798 bond(tri2, tri3);
9799 lnextself(midtri);
9800 lprevself(tri1);
9801 lnextself(tri2);
9802 lprevself(tri3);
9803 bond(midtri, tri3);
9804 bond(tri1, tri2);
9805 lnextself(midtri);
9806 lprevself(tri1);
9807 lnextself(tri2);
9808 lprevself(tri3);
9809 bond(midtri, tri1);
9810 bond(tri2, tri3);
9811 /* Ensure that the origin of `farleft' is sortarray[0]. */
9812 otricopy(tri1, *farleft);
9813 /* Ensure that the destination of `farright' is sortarray[2]. */
9814 otricopy(tri2, *farright);
9815 } else {
9816 /* The three vertices are not collinear; the triangulation is one */
9817 /* triangle, namely `midtri'. */
9818 setorg(midtri, sortarray[0]);
9819 setdest(tri1, sortarray[0]);
9820 setorg(tri3, sortarray[0]);
9821 /* Apices of tri1, tri2, and tri3 are left NULL. */
9822 if (area > 0.0) {
9823 /* The vertices are in counterclockwise order. */
9824 setdest(midtri, sortarray[1]);
9825 setorg(tri1, sortarray[1]);
9826 setdest(tri2, sortarray[1]);
9827 setapex(midtri, sortarray[2]);
9828 setorg(tri2, sortarray[2]);
9829 setdest(tri3, sortarray[2]);
9830 } else {
9831 /* The vertices are in clockwise order. */
9832 setdest(midtri, sortarray[2]);
9833 setorg(tri1, sortarray[2]);
9834 setdest(tri2, sortarray[2]);
9835 setapex(midtri, sortarray[1]);
9836 setorg(tri2, sortarray[1]);
9837 setdest(tri3, sortarray[1]);
9838 }
9839 /* The topology does not depend on how the vertices are ordered. */
9840 bond(midtri, tri1);
9841 lnextself(midtri);
9842 bond(midtri, tri2);
9843 lnextself(midtri);
9844 bond(midtri, tri3);
9845 lprevself(tri1);
9846 lnextself(tri2);
9847 bond(tri1, tri2);
9848 lprevself(tri1);
9849 lprevself(tri3);
9850 bond(tri1, tri3);
9851 lnextself(tri2);
9852 lprevself(tri3);
9853 bond(tri2, tri3);
9854 /* Ensure that the origin of `farleft' is sortarray[0]. */
9855 otricopy(tri1, *farleft);
9856 /* Ensure that the destination of `farright' is sortarray[2]. */
9857 if (area > 0.0) {
9858 otricopy(tri2, *farright);
9859 } else {
9860 lnext(*farleft, *farright);
9861 }
9862 }
9863 if (b->verbose > 2) {
9864 printf(" Creating ");
9865 printtriangle(m, b, &midtri);
9866 printf(" Creating ");
9867 printtriangle(m, b, &tri1);
9868 printf(" Creating ");
9869 printtriangle(m, b, &tri2);
9870 printf(" Creating ");
9871 printtriangle(m, b, &tri3);
9872 }
9873 return;
9874 } else {
9875 /* Split the vertices in half. */
9876 divider = vertices >> 1;
9877 /* Recursively triangulate each half. */
9878 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
9879 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
9880 &innerright, farright);
9881 if (b->verbose > 1) {
9882 printf(" Joining triangulations with %d and %d vertices.\n", divider,
9883 vertices - divider);
9884 }
9885 /* Merge the two triangulations into one. */
9886 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
9887 }
9888}
9889
9890#ifdef ANSI_DECLARATORS
9891long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
9892#else /* not ANSI_DECLARATORS */
9893long removeghosts(m, b, startghost)
9894struct mesh *m;
9895struct behavior *b;
9896struct otri *startghost;
9897#endif /* not ANSI_DECLARATORS */
9898
9899{
9900 struct otri searchedge;
9901 struct otri dissolveedge;
9902 struct otri deadtriangle;
9903 vertex markorg;
9904 long hullsize;
9905 triangle ptr; /* Temporary variable used by sym(). */
9906
9907 if (b->verbose) {
9908 printf(" Removing ghost triangles.\n");
9909 }
9910 /* Find an edge on the convex hull to start point location from. */
9911 lprev(*startghost, searchedge);
9912 symself(searchedge);
9913 m->dummytri[0] = encode(searchedge);
9914 /* Remove the bounding box and count the convex hull edges. */
9915 otricopy(*startghost, dissolveedge);
9916 hullsize = 0;
9917 do {
9918 hullsize++;
9919 lnext(dissolveedge, deadtriangle);
9920 lprevself(dissolveedge);
9921 symself(dissolveedge);
9922 /* If no PSLG is involved, set the boundary markers of all the vertices */
9923 /* on the convex hull. If a PSLG is used, this step is done later. */
9924 if (!b->poly) {
9925 /* Watch out for the case where all the input vertices are collinear. */
9926 if (dissolveedge.tri != m->dummytri) {
9927 org(dissolveedge, markorg);
9928 if (vertexmark(markorg) == 0) {
9929 setvertexmark(markorg, 1);
9930 }
9931 }
9932 }
9933 /* Remove a bounding triangle from a convex hull triangle. */
9934 dissolve(dissolveedge);
9935 /* Find the next bounding triangle. */
9936 sym(deadtriangle, dissolveedge);
9937 /* Delete the bounding triangle. */
9938 triangledealloc(m, deadtriangle.tri);
9939 } while (!otriequal(dissolveedge, *startghost));
9940 return hullsize;
9941}
9942
9943/*****************************************************************************/
9944/* */
9945/* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */
9946/* conquer method. */
9947/* */
9948/* Sorts the vertices, calls a recursive procedure to triangulate them, and */
9949/* removes the bounding box, setting boundary markers as appropriate. */
9950/* */
9951/*****************************************************************************/
9952
9953#ifdef ANSI_DECLARATORS
9954long divconqdelaunay(struct mesh *m, struct behavior *b)
9955#else /* not ANSI_DECLARATORS */
9956long divconqdelaunay(m, b)
9957struct mesh *m;
9958struct behavior *b;
9959#endif /* not ANSI_DECLARATORS */
9960
9961{
9962 vertex *sortarray;
9963 struct otri hullleft, hullright;
9964 int divider;
9965 int i, j;
9966
9967 if (b->verbose) {
9968 printf(" Sorting vertices.\n");
9969 }
9970
9971 /* Allocate an array of pointers to vertices for sorting. */
9972 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
9973 traversalinit(&m->vertices);
9974 for (i = 0; i < m->invertices; i++) {
9975 sortarray[i] = vertextraverse(m);
9976 }
9977 /* Sort the vertices. */
9978 vertexsort(sortarray, m->invertices);
9979 /* Discard duplicate vertices, which can really mess up the algorithm. */
9980 i = 0;
9981 for (j = 1; j < m->invertices; j++) {
9982 if ((sortarray[i][0] == sortarray[j][0])
9983 && (sortarray[i][1] == sortarray[j][1])) {
9984 if (!b->quiet) {
9985 printf(
9986"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
9987 sortarray[j][0], sortarray[j][1]);
9988 }
9989 setvertextype(sortarray[j], UNDEADVERTEX);
9990 m->undeads++;
9991 } else {
9992 i++;
9993 sortarray[i] = sortarray[j];
9994 }
9995 }
9996 i++;
9997 if (b->dwyer) {
9998 /* Re-sort the array of vertices to accommodate alternating cuts. */
9999 divider = i >> 1;
10000 if (i - divider >= 2) {
10001 if (divider >= 2) {
10002 alternateaxes(sortarray, divider, 1);
10003 }
10004 alternateaxes(&sortarray[divider], i - divider, 1);
10005 }
10006 }
10007
10008 if (b->verbose) {
10009 printf(" Forming triangulation.\n");
10010 }
10011
10012 /* Form the Delaunay triangulation. */
10013 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10014 trifree((VOID *) sortarray);
10015
10016 return removeghosts(m, b, &hullleft);
10017}
10018
10019/** **/
10020/** **/
10021/********* Divide-and-conquer Delaunay triangulation ends here *********/
10022
10023/********* Incremental Delaunay triangulation begins here *********/
10024/** **/
10025/** **/
10026
10027/*****************************************************************************/
10028/* */
10029/* boundingbox() Form an "infinite" bounding triangle to insert vertices */
10030/* into. */
10031/* */
10032/* The vertices at "infinity" are assigned finite coordinates, which are */
10033/* used by the point location routines, but (mostly) ignored by the */
10034/* Delaunay edge flip routines. */
10035/* */
10036/*****************************************************************************/
10037
10038#ifndef REDUCED
10039
10040#ifdef ANSI_DECLARATORS
10041void boundingbox(struct mesh *m, struct behavior *b)
10042#else /* not ANSI_DECLARATORS */
10043void boundingbox(m, b)
10044struct mesh *m;
10045struct behavior *b;
10046#endif /* not ANSI_DECLARATORS */
10047
10048{
10049 struct otri inftri; /* Handle for the triangular bounding box. */
10050 REAL width;
10051
10052 if (b->verbose) {
10053 printf(" Creating triangular bounding box.\n");
10054 }
10055 /* Find the width (or height, whichever is larger) of the triangulation. */
10056 width = m->xmax - m->xmin;
10057 if (m->ymax - m->ymin > width) {
10058 width = m->ymax - m->ymin;
10059 }
10060 if (width == 0.0) {
10061 width = 1.0;
10062 }
10063 /* Create the vertices of the bounding box. */
10064 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10065 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10066 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10067 m->infvertex1[0] = m->xmin - 50.0 * width;
10068 m->infvertex1[1] = m->ymin - 40.0 * width;
10069 m->infvertex2[0] = m->xmax + 50.0 * width;
10070 m->infvertex2[1] = m->ymin - 40.0 * width;
10071 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10072 m->infvertex3[1] = m->ymax + 60.0 * width;
10073
10074 /* Create the bounding box. */
10075 maketriangle(m, b, &inftri);
10076 setorg(inftri, m->infvertex1);
10077 setdest(inftri, m->infvertex2);
10078 setapex(inftri, m->infvertex3);
10079 /* Link dummytri to the bounding box so we can always find an */
10080 /* edge to begin searching (point location) from. */
10081 m->dummytri[0] = (triangle) inftri.tri;
10082 if (b->verbose > 2) {
10083 printf(" Creating ");
10084 printtriangle(m, b, &inftri);
10085 }
10086}
10087
10088#endif /* not REDUCED */
10089
10090/*****************************************************************************/
10091/* */
10092/* removebox() Remove the "infinite" bounding triangle, setting boundary */
10093/* markers as appropriate. */
10094/* */
10095/* The triangular bounding box has three boundary triangles (one for each */
10096/* side of the bounding box), and a bunch of triangles fanning out from */
10097/* the three bounding box vertices (one triangle for each edge of the */
10098/* convex hull of the inner mesh). This routine removes these triangles. */
10099/* */
10100/* Returns the number of edges on the convex hull of the triangulation. */
10101/* */
10102/*****************************************************************************/
10103
10104#ifndef REDUCED
10105
10106#ifdef ANSI_DECLARATORS
10107long removebox(struct mesh *m, struct behavior *b)
10108#else /* not ANSI_DECLARATORS */
10109long removebox(m, b)
10110struct mesh *m;
10111struct behavior *b;
10112#endif /* not ANSI_DECLARATORS */
10113
10114{
10115 struct otri deadtriangle;
10116 struct otri searchedge;
10117 struct otri checkedge;
10118 struct otri nextedge, finaledge, dissolveedge;
10119 vertex markorg;
10120 long hullsize;
10121 triangle ptr; /* Temporary variable used by sym(). */
10122
10123 if (b->verbose) {
10124 printf(" Removing triangular bounding box.\n");
10125 }
10126 /* Find a boundary triangle. */
10127 nextedge.tri = m->dummytri;
10128 nextedge.orient = 0;
10129 symself(nextedge);
10130 /* Mark a place to stop. */
10131 lprev(nextedge, finaledge);
10132 lnextself(nextedge);
10133 symself(nextedge);
10134 /* Find a triangle (on the boundary of the vertex set) that isn't */
10135 /* a bounding box triangle. */
10136 lprev(nextedge, searchedge);
10137 symself(searchedge);
10138 /* Check whether nextedge is another boundary triangle */
10139 /* adjacent to the first one. */
10140 lnext(nextedge, checkedge);
10141 symself(checkedge);
10142 if (checkedge.tri == m->dummytri) {
10143 /* Go on to the next triangle. There are only three boundary */
10144 /* triangles, and this next triangle cannot be the third one, */
10145 /* so it's safe to stop here. */
10146 lprevself(searchedge);
10147 symself(searchedge);
10148 }
10149 /* Find a new boundary edge to search from, as the current search */
10150 /* edge lies on a bounding box triangle and will be deleted. */
10151 m->dummytri[0] = encode(searchedge);
10152 hullsize = -2l;
10153 while (!otriequal(nextedge, finaledge)) {
10154 hullsize++;
10155 lprev(nextedge, dissolveedge);
10156 symself(dissolveedge);
10157 /* If not using a PSLG, the vertices should be marked now. */
10158 /* (If using a PSLG, markhull() will do the job.) */
10159 if (!b->poly) {
10160 /* Be careful! One must check for the case where all the input */
10161 /* vertices are collinear, and thus all the triangles are part of */
10162 /* the bounding box. Otherwise, the setvertexmark() call below */
10163 /* will cause a bad pointer reference. */
10164 if (dissolveedge.tri != m->dummytri) {
10165 org(dissolveedge, markorg);
10166 if (vertexmark(markorg) == 0) {
10167 setvertexmark(markorg, 1);
10168 }
10169 }
10170 }
10171 /* Disconnect the bounding box triangle from the mesh triangle. */
10172 dissolve(dissolveedge);
10173 lnext(nextedge, deadtriangle);
10174 sym(deadtriangle, nextedge);
10175 /* Get rid of the bounding box triangle. */
10176 triangledealloc(m, deadtriangle.tri);
10177 /* Do we need to turn the corner? */
10178 if (nextedge.tri == m->dummytri) {
10179 /* Turn the corner. */
10180 otricopy(dissolveedge, nextedge);
10181 }
10182 }
10183 triangledealloc(m, finaledge.tri);
10184
10185 trifree((VOID *) m->infvertex1); /* Deallocate the bounding box vertices. */
10186 trifree((VOID *) m->infvertex2);
10187 trifree((VOID *) m->infvertex3);
10188
10189 return hullsize;
10190}
10191
10192#endif /* not REDUCED */
10193
10194/*****************************************************************************/
10195/* */
10196/* incrementaldelaunay() Form a Delaunay triangulation by incrementally */
10197/* inserting vertices. */
10198/* */
10199/* Returns the number of edges on the convex hull of the triangulation. */
10200/* */
10201/*****************************************************************************/
10202
10203#ifndef REDUCED
10204
10205#ifdef ANSI_DECLARATORS
10206long incrementaldelaunay(struct mesh *m, struct behavior *b)
10207#else /* not ANSI_DECLARATORS */
10208long incrementaldelaunay(m, b)
10209struct mesh *m;
10210struct behavior *b;
10211#endif /* not ANSI_DECLARATORS */
10212
10213{
10214 struct otri starttri;
10215 vertex vertexloop;
10216
10217 /* Create a triangular bounding box. */
10218 boundingbox(m, b);
10219 if (b->verbose) {
10220 printf(" Incrementally inserting vertices.\n");
10221 }
10222 traversalinit(&m->vertices);
10223 vertexloop = vertextraverse(m);
10224 while (vertexloop != (vertex) NULL) {
10225 starttri.tri = m->dummytri;
10226 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10227 == DUPLICATEVERTEX) {
10228 if (!b->quiet) {
10229 printf(
10230"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10231 vertexloop[0], vertexloop[1]);
10232 }
10233 setvertextype(vertexloop, UNDEADVERTEX);
10234 m->undeads++;
10235 }
10236 vertexloop = vertextraverse(m);
10237 }
10238 /* Remove the bounding box. */
10239 return removebox(m, b);
10240}
10241
10242#endif /* not REDUCED */
10243
10244/** **/
10245/** **/
10246/********* Incremental Delaunay triangulation ends here *********/
10247
10248/********* Sweepline Delaunay triangulation begins here *********/
10249/** **/
10250/** **/
10251
10252#ifndef REDUCED
10253
10254#ifdef ANSI_DECLARATORS
10255void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10256#else /* not ANSI_DECLARATORS */
10257void eventheapinsert(heap, heapsize, newevent)
10258struct event **heap;
10259int heapsize;
10260struct event *newevent;
10261#endif /* not ANSI_DECLARATORS */
10262
10263{
10264 REAL eventx, eventy;
10265 int eventnum;
10266 int parent;
10267 int notdone;
10268
10269 eventx = newevent->xkey;
10270 eventy = newevent->ykey;
10271 eventnum = heapsize;
10272 notdone = eventnum > 0;
10273 while (notdone) {
10274 parent = (eventnum - 1) >> 1;
10275 if ((heap[parent]->ykey < eventy) ||
10276 ((heap[parent]->ykey == eventy)
10277 && (heap[parent]->xkey <= eventx))) {
10278 notdone = 0;
10279 } else {
10280 heap[eventnum] = heap[parent];
10281 heap[eventnum]->heapposition = eventnum;
10282
10283 eventnum = parent;
10284 notdone = eventnum > 0;
10285 }
10286 }
10287 heap[eventnum] = newevent;
10288 newevent->heapposition = eventnum;
10289}
10290
10291#endif /* not REDUCED */
10292
10293#ifndef REDUCED
10294
10295#ifdef ANSI_DECLARATORS
10296void eventheapify(struct event **heap, int heapsize, int eventnum)
10297#else /* not ANSI_DECLARATORS */
10298void eventheapify(heap, heapsize, eventnum)
10299struct event **heap;
10300int heapsize;
10301int eventnum;
10302#endif /* not ANSI_DECLARATORS */
10303
10304{
10305 struct event *thisevent;
10306 REAL eventx, eventy;
10307 int leftchild, rightchild;
10308 int smallest;
10309 int notdone;
10310
10311 thisevent = heap[eventnum];
10312 eventx = thisevent->xkey;
10313 eventy = thisevent->ykey;
10314 leftchild = 2 * eventnum + 1;
10315 notdone = leftchild < heapsize;
10316 while (notdone) {
10317 if ((heap[leftchild]->ykey < eventy) ||
10318 ((heap[leftchild]->ykey == eventy)
10319 && (heap[leftchild]->xkey < eventx))) {
10320 smallest = leftchild;
10321 } else {
10322 smallest = eventnum;
10323 }
10324 rightchild = leftchild + 1;
10325 if (rightchild < heapsize) {
10326 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10327 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10328 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10329 smallest = rightchild;
10330 }
10331 }
10332 if (smallest == eventnum) {
10333 notdone = 0;
10334 } else {
10335 heap[eventnum] = heap[smallest];
10336 heap[eventnum]->heapposition = eventnum;
10337 heap[smallest] = thisevent;
10338 thisevent->heapposition = smallest;
10339
10340 eventnum = smallest;
10341 leftchild = 2 * eventnum + 1;
10342 notdone = leftchild < heapsize;
10343 }
10344 }
10345}
10346
10347#endif /* not REDUCED */
10348
10349#ifndef REDUCED
10350
10351#ifdef ANSI_DECLARATORS
10352void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10353#else /* not ANSI_DECLARATORS */
10354void eventheapdelete(heap, heapsize, eventnum)
10355struct event **heap;
10356int heapsize;
10357int eventnum;
10358#endif /* not ANSI_DECLARATORS */
10359
10360{
10361 struct event *moveevent;
10362 REAL eventx, eventy;
10363 int parent;
10364 int notdone;
10365
10366 moveevent = heap[heapsize - 1];
10367 if (eventnum > 0) {
10368 eventx = moveevent->xkey;
10369 eventy = moveevent->ykey;
10370 do {
10371 parent = (eventnum - 1) >> 1;
10372 if ((heap[parent]->ykey < eventy) ||
10373 ((heap[parent]->ykey == eventy)
10374 && (heap[parent]->xkey <= eventx))) {
10375 notdone = 0;
10376 } else {
10377 heap[eventnum] = heap[parent];
10378 heap[eventnum]->heapposition = eventnum;
10379
10380 eventnum = parent;
10381 notdone = eventnum > 0;
10382 }
10383 } while (notdone);
10384 }
10385 heap[eventnum] = moveevent;
10386 moveevent->heapposition = eventnum;
10387 eventheapify(heap, heapsize - 1, eventnum);
10388}
10389
10390#endif /* not REDUCED */
10391
10392#ifndef REDUCED
10393
10394#ifdef ANSI_DECLARATORS
10395void createeventheap(struct mesh *m, struct event ***eventheap,
10396 struct event **events, struct event **freeevents)
10397#else /* not ANSI_DECLARATORS */
10398void createeventheap(m, eventheap, events, freeevents)
10399struct mesh *m;
10400struct event ***eventheap;
10401struct event **events;
10402struct event **freeevents;
10403#endif /* not ANSI_DECLARATORS */
10404
10405{
10406 vertex thisvertex;
10407 int maxevents;
10408 int i;
10409
10410 maxevents = (3 * m->invertices) / 2;
10411 *eventheap = (struct event **) trimalloc(maxevents *
10412 (int) sizeof(struct event *));
10413 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10414 traversalinit(&m->vertices);
10415 for (i = 0; i < m->invertices; i++) {
10416 thisvertex = vertextraverse(m);
10417 (*events)[i].eventptr = (VOID *) thisvertex;
10418 (*events)[i].xkey = thisvertex[0];
10419 (*events)[i].ykey = thisvertex[1];
10420 eventheapinsert(*eventheap, i, *events + i);
10421 }
10422 *freeevents = (struct event *) NULL;
10423 for (i = maxevents - 1; i >= m->invertices; i--) {
10424 (*events)[i].eventptr = (VOID *) *freeevents;
10425 *freeevents = *events + i;
10426 }
10427}
10428
10429#endif /* not REDUCED */
10430
10431#ifndef REDUCED
10432
10433#ifdef ANSI_DECLARATORS
10434int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10435#else /* not ANSI_DECLARATORS */
10436int rightofhyperbola(m, fronttri, newsite)
10437struct mesh *m;
10438struct otri *fronttri;
10439vertex newsite;
10440#endif /* not ANSI_DECLARATORS */
10441
10442{
10443 vertex leftvertex, rightvertex;
10444 REAL dxa, dya, dxb, dyb;
10445
10446 m->hyperbolacount++;
10447
10448 dest(*fronttri, leftvertex);
10449 apex(*fronttri, rightvertex);
10450 if ((leftvertex[1] < rightvertex[1]) ||
10451 ((leftvertex[1] == rightvertex[1]) &&
10452 (leftvertex[0] < rightvertex[0]))) {
10453 if (newsite[0] >= rightvertex[0]) {
10454 return 1;
10455 }
10456 } else {
10457 if (newsite[0] <= leftvertex[0]) {
10458 return 0;
10459 }
10460 }
10461 dxa = leftvertex[0] - newsite[0];
10462 dya = leftvertex[1] - newsite[1];
10463 dxb = rightvertex[0] - newsite[0];
10464 dyb = rightvertex[1] - newsite[1];
10465 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10466}
10467
10468#endif /* not REDUCED */
10469
10470#ifndef REDUCED
10471
10472#ifdef ANSI_DECLARATORS
10473REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10474#else /* not ANSI_DECLARATORS */
10475REAL circletop(m, pa, pb, pc, ccwabc)
10476struct mesh *m;
10477vertex pa;
10478vertex pb;
10479vertex pc;
10480REAL ccwabc;
10481#endif /* not ANSI_DECLARATORS */
10482
10483{
10484 REAL xac, yac, xbc, ybc, xab, yab;
10485 REAL aclen2, bclen2, ablen2;
10486
10487 m->circletopcount++;
10488
10489 xac = pa[0] - pc[0];
10490 yac = pa[1] - pc[1];
10491 xbc = pb[0] - pc[0];
10492 ybc = pb[1] - pc[1];
10493 xab = pa[0] - pb[0];
10494 yab = pa[1] - pb[1];
10495 aclen2 = xac * xac + yac * yac;
10496 bclen2 = xbc * xbc + ybc * ybc;
10497 ablen2 = xab * xab + yab * yab;
10498 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10499 / (2.0 * ccwabc);
10500}
10501
10502#endif /* not REDUCED */
10503
10504#ifndef REDUCED
10505
10506#ifdef ANSI_DECLARATORS
10507void check4deadevent(struct otri *checktri, struct event **freeevents,
10508 struct event **eventheap, int *heapsize)
10509#else /* not ANSI_DECLARATORS */
10510void check4deadevent(checktri, freeevents, eventheap, heapsize)
10511struct otri *checktri;
10512struct event **freeevents;
10513struct event **eventheap;
10514int *heapsize;
10515#endif /* not ANSI_DECLARATORS */
10516
10517{
10518 struct event *deadevent;
10519 vertex eventvertex;
10520 int eventnum;
10521
10522 org(*checktri, eventvertex);
10523 if (eventvertex != (vertex) NULL) {
10524 deadevent = (struct event *) eventvertex;
10525 eventnum = deadevent->heapposition;
10526 deadevent->eventptr = (VOID *) *freeevents;
10527 *freeevents = deadevent;
10528 eventheapdelete(eventheap, *heapsize, eventnum);
10529 (*heapsize)--;
10530 setorg(*checktri, NULL);
10531 }
10532}
10533
10534#endif /* not REDUCED */
10535
10536#ifndef REDUCED
10537
10538#ifdef ANSI_DECLARATORS
10539struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10540 vertex searchpoint, struct otri *searchtri)
10541#else /* not ANSI_DECLARATORS */
10542struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10543struct mesh *m;
10544struct splaynode *splaytree;
10545vertex searchpoint;
10546struct otri *searchtri;
10547#endif /* not ANSI_DECLARATORS */
10548
10549{
10550 struct splaynode *child, *grandchild;
10551 struct splaynode *lefttree, *righttree;
10552 struct splaynode *leftright;
10553 vertex checkvertex;
10554 int rightofroot, rightofchild;
10555
10556 if (splaytree == (struct splaynode *) NULL) {
10557 return (struct splaynode *) NULL;
10558 }
10559 dest(splaytree->keyedge, checkvertex);
10560 if (checkvertex == splaytree->keydest) {
10561 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10562 if (rightofroot) {
10563 otricopy(splaytree->keyedge, *searchtri);
10564 child = splaytree->rchild;
10565 } else {
10566 child = splaytree->lchild;
10567 }
10568 if (child == (struct splaynode *) NULL) {
10569 return splaytree;
10570 }
10571 dest(child->keyedge, checkvertex);
10572 if (checkvertex != child->keydest) {
10573 child = splay(m, child, searchpoint, searchtri);
10574 if (child == (struct splaynode *) NULL) {
10575 if (rightofroot) {
10576 splaytree->rchild = (struct splaynode *) NULL;
10577 } else {
10578 splaytree->lchild = (struct splaynode *) NULL;
10579 }
10580 return splaytree;
10581 }
10582 }
10583 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10584 if (rightofchild) {
10585 otricopy(child->keyedge, *searchtri);
10586 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10587 child->rchild = grandchild;
10588 } else {
10589 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10590 child->lchild = grandchild;
10591 }
10592 if (grandchild == (struct splaynode *) NULL) {
10593 if (rightofroot) {
10594 splaytree->rchild = child->lchild;
10595 child->lchild = splaytree;
10596 } else {
10597 splaytree->lchild = child->rchild;
10598 child->rchild = splaytree;
10599 }
10600 return child;
10601 }
10602 if (rightofchild) {
10603 if (rightofroot) {
10604 splaytree->rchild = child->lchild;
10605 child->lchild = splaytree;
10606 } else {
10607 splaytree->lchild = grandchild->rchild;
10608 grandchild->rchild = splaytree;
10609 }
10610 child->rchild = grandchild->lchild;
10611 grandchild->lchild = child;
10612 } else {
10613 if (rightofroot) {
10614 splaytree->rchild = grandchild->lchild;
10615 grandchild->lchild = splaytree;
10616 } else {
10617 splaytree->lchild = child->rchild;
10618 child->rchild = splaytree;
10619 }
10620 child->lchild = grandchild->rchild;
10621 grandchild->rchild = child;
10622 }
10623 return grandchild;
10624 } else {
10625 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10626 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10627
10628 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10629 if (lefttree == (struct splaynode *) NULL) {
10630 return righttree;
10631 } else if (righttree == (struct splaynode *) NULL) {
10632 return lefttree;
10633 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10634 lefttree->rchild = righttree->lchild;
10635 righttree->lchild = lefttree;
10636 return righttree;
10637 } else if (righttree->lchild == (struct splaynode *) NULL) {
10638 righttree->lchild = lefttree->rchild;
10639 lefttree->rchild = righttree;
10640 return lefttree;
10641 } else {
10642/* printf("Holy Toledo!!!\n"); */
10643 leftright = lefttree->rchild;
10644 while (leftright->rchild != (struct splaynode *) NULL) {
10645 leftright = leftright->rchild;
10646 }
10647 leftright->rchild = righttree;
10648 return lefttree;
10649 }
10650 }
10651}
10652
10653#endif /* not REDUCED */
10654
10655#ifndef REDUCED
10656
10657#ifdef ANSI_DECLARATORS
10658struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10659 struct otri *newkey, vertex searchpoint)
10660#else /* not ANSI_DECLARATORS */
10661struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10662struct mesh *m;
10663struct splaynode *splayroot;
10664struct otri *newkey;
10665vertex searchpoint;
10666#endif /* not ANSI_DECLARATORS */
10667
10668{
10669 struct splaynode *newsplaynode;
10670
10671 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10672 otricopy(*newkey, newsplaynode->keyedge);
10673 dest(*newkey, newsplaynode->keydest);
10674 if (splayroot == (struct splaynode *) NULL) {
10675 newsplaynode->lchild = (struct splaynode *) NULL;
10676 newsplaynode->rchild = (struct splaynode *) NULL;
10677 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10678 newsplaynode->lchild = splayroot;
10679 newsplaynode->rchild = splayroot->rchild;
10680 splayroot->rchild = (struct splaynode *) NULL;
10681 } else {
10682 newsplaynode->lchild = splayroot->lchild;
10683 newsplaynode->rchild = splayroot;
10684 splayroot->lchild = (struct splaynode *) NULL;
10685 }
10686 return newsplaynode;
10687}
10688
10689#endif /* not REDUCED */
10690
10691#ifndef REDUCED
10692
10693#ifdef ANSI_DECLARATORS
10694struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10695 struct splaynode *splayroot,
10696 struct otri *newkey,
10697 vertex pa, vertex pb, vertex pc, REAL topy)
10698#else /* not ANSI_DECLARATORS */
10699struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10700struct mesh *m;
10701struct behavior *b;
10702struct splaynode *splayroot;
10703struct otri *newkey;
10704vertex pa;
10705vertex pb;
10706vertex pc;
10707REAL topy;
10708#endif /* not ANSI_DECLARATORS */
10709
10710{
10711 REAL ccwabc;
10712 REAL xac, yac, xbc, ybc;
10713 REAL aclen2, bclen2;
10714 REAL searchpoint[2];
10715 struct otri dummytri;
10716
10717 ccwabc = counterclockwise(m, b, pa, pb, pc);
10718 xac = pa[0] - pc[0];
10719 yac = pa[1] - pc[1];
10720 xbc = pb[0] - pc[0];
10721 ybc = pb[1] - pc[1];
10722 aclen2 = xac * xac + yac * yac;
10723 bclen2 = xbc * xbc + ybc * ybc;
10724 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10725 searchpoint[1] = topy;
10726 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10727 newkey, (vertex) searchpoint);
10728}
10729
10730#endif /* not REDUCED */
10731
10732#ifndef REDUCED
10733
10734#ifdef ANSI_DECLARATORS
10735struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10736 struct otri *bottommost, vertex searchvertex,
10737 struct otri *searchtri, int *farright)
10738#else /* not ANSI_DECLARATORS */
10739struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10740 searchtri, farright)
10741struct mesh *m;
10742struct splaynode *splayroot;
10743struct otri *bottommost;
10744vertex searchvertex;
10745struct otri *searchtri;
10746int *farright;
10747#endif /* not ANSI_DECLARATORS */
10748
10749{
10750 int farrightflag;
10751 triangle ptr; /* Temporary variable used by onext(). */
10752
10753 otricopy(*bottommost, *searchtri);
10754 splayroot = splay(m, splayroot, searchvertex, searchtri);
10755
10756 farrightflag = 0;
10757 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10758 onextself(*searchtri);
10759 farrightflag = otriequal(*searchtri, *bottommost);
10760 }
10761 *farright = farrightflag;
10762 return splayroot;
10763}
10764
10765#endif /* not REDUCED */
10766
10767#ifndef REDUCED
10768
10769#ifdef ANSI_DECLARATORS
10770long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10771#else /* not ANSI_DECLARATORS */
10772long sweeplinedelaunay(m, b)
10773struct mesh *m;
10774struct behavior *b;
10775#endif /* not ANSI_DECLARATORS */
10776
10777{
10778 struct event **eventheap;
10779 struct event *events;
10780 struct event *freeevents;
10781 struct event *nextevent;
10782 struct event *newevent;
10783 struct splaynode *splayroot;
10784 struct otri bottommost;
10785 struct otri searchtri;
10786 struct otri fliptri;
10787 struct otri lefttri, righttri, farlefttri, farrighttri;
10788 struct otri inserttri;
10789 vertex firstvertex, secondvertex;
10790 vertex nextvertex, lastvertex;
10791 vertex connectvertex;
10792 vertex leftvertex, midvertex, rightvertex;
10793 REAL lefttest, righttest;
10794 int heapsize;
10795 int check4events, farrightflag;
10796 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
10797
10798 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10800 splayroot = (struct splaynode *) NULL;
10801
10802 if (b->verbose) {
10803 printf(" Placing vertices in event heap.\n");
10804 }
10805 createeventheap(m, &eventheap, &events, &freeevents);
10806 heapsize = m->invertices;
10807
10808 if (b->verbose) {
10809 printf(" Forming triangulation.\n");
10810 }
10811 maketriangle(m, b, &lefttri);
10812 maketriangle(m, b, &righttri);
10813 bond(lefttri, righttri);
10814 lnextself(lefttri);
10815 lprevself(righttri);
10816 bond(lefttri, righttri);
10817 lnextself(lefttri);
10818 lprevself(righttri);
10819 bond(lefttri, righttri);
10820 firstvertex = (vertex) eventheap[0]->eventptr;
10821 eventheap[0]->eventptr = (VOID *) freeevents;
10822 freeevents = eventheap[0];
10823 eventheapdelete(eventheap, heapsize, 0);
10824 heapsize--;
10825 do {
10826 if (heapsize == 0) {
10827 printf("Error: Input vertices are all identical.\n");
10828 triexit(1);
10829 }
10830 secondvertex = (vertex) eventheap[0]->eventptr;
10831 eventheap[0]->eventptr = (VOID *) freeevents;
10832 freeevents = eventheap[0];
10833 eventheapdelete(eventheap, heapsize, 0);
10834 heapsize--;
10835 if ((firstvertex[0] == secondvertex[0]) &&
10836 (firstvertex[1] == secondvertex[1])) {
10837 if (!b->quiet) {
10838 printf(
10839"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10840 secondvertex[0], secondvertex[1]);
10841 }
10842 setvertextype(secondvertex, UNDEADVERTEX);
10843 m->undeads++;
10844 }
10845 } while ((firstvertex[0] == secondvertex[0]) &&
10846 (firstvertex[1] == secondvertex[1]));
10847 setorg(lefttri, firstvertex);
10848 setdest(lefttri, secondvertex);
10849 setorg(righttri, secondvertex);
10850 setdest(righttri, firstvertex);
10851 lprev(lefttri, bottommost);
10852 lastvertex = secondvertex;
10853 while (heapsize > 0) {
10854 nextevent = eventheap[0];
10855 eventheapdelete(eventheap, heapsize, 0);
10856 heapsize--;
10857 check4events = 1;
10858 if (nextevent->xkey < m->xmin) {
10859 decode(nextevent->eventptr, fliptri);
10860 oprev(fliptri, farlefttri);
10861 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10862 onext(fliptri, farrighttri);
10863 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10864
10865 if (otriequal(farlefttri, bottommost)) {
10866 lprev(fliptri, bottommost);
10867 }
10868 flip(m, b, &fliptri);
10869 setapex(fliptri, NULL);
10870 lprev(fliptri, lefttri);
10871 lnext(fliptri, righttri);
10872 sym(lefttri, farlefttri);
10873
10874 if (randomnation(SAMPLERATE) == 0) {
10875 symself(fliptri);
10876 dest(fliptri, leftvertex);
10877 apex(fliptri, midvertex);
10878 org(fliptri, rightvertex);
10879 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10880 midvertex, rightvertex, nextevent->ykey);
10881 }
10882 } else {
10883 nextvertex = (vertex) nextevent->eventptr;
10884 if ((nextvertex[0] == lastvertex[0]) &&
10885 (nextvertex[1] == lastvertex[1])) {
10886 if (!b->quiet) {
10887 printf(
10888"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10889 nextvertex[0], nextvertex[1]);
10890 }
10891 setvertextype(nextvertex, UNDEADVERTEX);
10892 m->undeads++;
10893 check4events = 0;
10894 } else {
10895 lastvertex = nextvertex;
10896
10897 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10898 &searchtri, &farrightflag);
10899/*
10900 otricopy(bottommost, searchtri);
10901 farrightflag = 0;
10902 while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) {
10903 onextself(searchtri);
10904 farrightflag = otriequal(searchtri, bottommost);
10905 }
10906*/
10907
10908 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10909
10910 otricopy(searchtri, farrighttri);
10911 sym(searchtri, farlefttri);
10912 maketriangle(m, b, &lefttri);
10913 maketriangle(m, b, &righttri);
10914 dest(farrighttri, connectvertex);
10915 setorg(lefttri, connectvertex);
10916 setdest(lefttri, nextvertex);
10917 setorg(righttri, nextvertex);
10918 setdest(righttri, connectvertex);
10919 bond(lefttri, righttri);
10920 lnextself(lefttri);
10921 lprevself(righttri);
10922 bond(lefttri, righttri);
10923 lnextself(lefttri);
10924 lprevself(righttri);
10925 bond(lefttri, farlefttri);
10926 bond(righttri, farrighttri);
10927 if (!farrightflag && otriequal(farrighttri, bottommost)) {
10928 otricopy(lefttri, bottommost);
10929 }
10930
10931 if (randomnation(SAMPLERATE) == 0) {
10932 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
10933 } else if (randomnation(SAMPLERATE) == 0) {
10934 lnext(righttri, inserttri);
10935 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
10936 }
10937 }
10938 }
10939 nextevent->eventptr = (VOID *) freeevents;
10940 freeevents = nextevent;
10941
10942 if (check4events) {
10943 apex(farlefttri, leftvertex);
10944 dest(lefttri, midvertex);
10945 apex(lefttri, rightvertex);
10946 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10947 if (lefttest > 0.0) {
10948 newevent = freeevents;
10949 freeevents = (struct event *) freeevents->eventptr;
10950 newevent->xkey = m->xminextreme;
10951 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10952 lefttest);
10953 newevent->eventptr = (VOID *) encode(lefttri);
10954 eventheapinsert(eventheap, heapsize, newevent);
10955 heapsize++;
10956 setorg(lefttri, newevent);
10957 }
10958 apex(righttri, leftvertex);
10959 org(righttri, midvertex);
10960 apex(farrighttri, rightvertex);
10961 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10962 if (righttest > 0.0) {
10963 newevent = freeevents;
10964 freeevents = (struct event *) freeevents->eventptr;
10965 newevent->xkey = m->xminextreme;
10966 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10967 righttest);
10968 newevent->eventptr = (VOID *) encode(farrighttri);
10969 eventheapinsert(eventheap, heapsize, newevent);
10970 heapsize++;
10971 setorg(farrighttri, newevent);
10972 }
10973 }
10974 }
10975
10976 pooldeinit(&m->splaynodes);
10977 lprevself(bottommost);
10978 return removeghosts(m, b, &bottommost);
10979}
10980
10981#endif /* not REDUCED */
10982
10983/** **/
10984/** **/
10985/********* Sweepline Delaunay triangulation ends here *********/
10986
10987/********* General mesh construction routines begin here *********/
10988/** **/
10989/** **/
10990
10991/*****************************************************************************/
10992/* */
10993/* delaunay() Form a Delaunay triangulation. */
10994/* */
10995/*****************************************************************************/
10996
10997#ifdef ANSI_DECLARATORS
10998long delaunay(struct mesh *m, struct behavior *b)
10999#else /* not ANSI_DECLARATORS */
11000long delaunay(m, b)
11001struct mesh *m;
11002struct behavior *b;
11003#endif /* not ANSI_DECLARATORS */
11004
11005{
11006 long hulledges;
11007
11008 m->eextras = 0;
11010
11011#ifdef REDUCED
11012 if (!b->quiet) {
11013 printf(
11014 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11015 }
11016 hulledges = divconqdelaunay(m, b);
11017#else /* not REDUCED */
11018 if (!b->quiet) {
11019 printf("Constructing Delaunay triangulation ");
11020 if (b->incremental) {
11021 printf("by incremental method.\n");
11022 } else if (b->sweepline) {
11023 printf("by sweepline method.\n");
11024 } else {
11025 printf("by divide-and-conquer method.\n");
11026 }
11027 }
11028 if (b->incremental) {
11029 hulledges = incrementaldelaunay(m, b);
11030 } else if (b->sweepline) {
11031 hulledges = sweeplinedelaunay(m, b);
11032 } else {
11033 hulledges = divconqdelaunay(m, b);
11034 }
11035#endif /* not REDUCED */
11036
11037 if (m->triangles.items == 0) {
11038 /* The input vertices were all collinear, so there are no triangles. */
11039 return 0l;
11040 } else {
11041 return hulledges;
11042 }
11043}
11044
11045/*****************************************************************************/
11046/* */
11047/* reconstruct() Reconstruct a triangulation from its .ele (and possibly */
11048/* .poly) file. Used when the -r switch is used. */
11049/* */
11050/* Reads an .ele file and reconstructs the original mesh. If the -p switch */
11051/* is used, this procedure will also read a .poly file and reconstruct the */
11052/* subsegments of the original mesh. If the -a switch is used, this */
11053/* procedure will also read an .area file and set a maximum area constraint */
11054/* on each triangle. */
11055/* */
11056/* Vertices that are not corners of triangles, such as nodes on edges of */
11057/* subparametric elements, are discarded. */
11058/* */
11059/* This routine finds the adjacencies between triangles (and subsegments) */
11060/* by forming one stack of triangles for each vertex. Each triangle is on */
11061/* three different stacks simultaneously. Each triangle's subsegment */
11062/* pointers are used to link the items in each stack. This memory-saving */
11063/* feature makes the code harder to read. The most important thing to keep */
11064/* in mind is that each triangle is removed from a stack precisely when */
11065/* the corresponding pointer is adjusted to refer to a subsegment rather */
11066/* than the next triangle of the stack. */
11067/* */
11068/*****************************************************************************/
11069
11070#ifndef CDT_ONLY
11071
11072#ifdef TRILIBRARY
11073
11074#ifdef ANSI_DECLARATORS
11075int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11076 REAL *triangleattriblist, REAL *trianglearealist,
11077 int elements, int corners, int attribs,
11078 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11079#else /* not ANSI_DECLARATORS */
11080int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11081 elements, corners, attribs, segmentlist, segmentmarkerlist,
11082 numberofsegments)
11083struct mesh *m;
11084struct behavior *b;
11085int *trianglelist;
11086REAL *triangleattriblist;
11087REAL *trianglearealist;
11088int elements;
11089int corners;
11090int attribs;
11091int *segmentlist;
11092int *segmentmarkerlist;
11093int numberofsegments;
11094#endif /* not ANSI_DECLARATORS */
11095
11096#else /* not TRILIBRARY */
11097
11098#ifdef ANSI_DECLARATORS
11099long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11100 char *areafilename, char *polyfilename, FILE *polyfile)
11101#else /* not ANSI_DECLARATORS */
11102long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11103struct mesh *m;
11104struct behavior *b;
11105char *elefilename;
11106char *areafilename;
11107char *polyfilename;
11108FILE *polyfile;
11109#endif /* not ANSI_DECLARATORS */
11110
11111#endif /* not TRILIBRARY */
11112
11113{
11114#ifdef TRILIBRARY
11115 int vertexindex;
11116 int attribindex;
11117#else /* not TRILIBRARY */
11118 FILE *elefile;
11119 FILE *areafile;
11120 char inputline[INPUTLINESIZE];
11121 char *stringptr;
11122 int areaelements;
11123#endif /* not TRILIBRARY */
11124 struct otri triangleloop;
11125 struct otri triangleleft;
11126 struct otri checktri;
11127 struct otri checkleft;
11128 struct otri checkneighbor;
11129 struct osub subsegloop;
11130 triangle *vertexarray;
11131 triangle *prevlink;
11132 triangle nexttri;
11133 vertex tdest, tapex;
11134 vertex checkdest, checkapex;
11135 vertex shorg;
11136 vertex killvertex;
11137 vertex segmentorg, segmentdest;
11138 REAL area;
11139 int corner[3];
11140 int end[2];
11141 int killvertexindex;
11142 int incorners;
11143 int segmentmarkers;
11144 int boundmarker;
11145 int aroundvertex;
11146 long hullsize;
11147 int notfound;
11148 long elementnumber, segmentnumber;
11149 int i, j;
11150 triangle ptr; /* Temporary variable used by sym(). */
11151
11152#ifdef TRILIBRARY
11153 m->inelements = elements;
11154 incorners = corners;
11155 if (incorners < 3) {
11156 printf("Error: Triangles must have at least 3 vertices.\n");
11157 triexit(1);
11158 }
11159 m->eextras = attribs;
11160#else /* not TRILIBRARY */
11161 /* Read the triangles from an .ele file. */
11162 if (!b->quiet) {
11163 printf("Opening %s.\n", elefilename);
11164 }
11165 elefile = fopen(elefilename, "r");
11166 if (elefile == (FILE *) NULL) {
11167 printf(" Error: Cannot access file %s.\n", elefilename);
11168 triexit(1);
11169 }
11170 /* Read number of triangles, number of vertices per triangle, and */
11171 /* number of triangle attributes from .ele file. */
11172 stringptr = readline(inputline, elefile, elefilename);
11173 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11174 stringptr = findfield(stringptr);
11175 if (*stringptr == '\0') {
11176 incorners = 3;
11177 } else {
11178 incorners = (int) strtol(stringptr, &stringptr, 0);
11179 if (incorners < 3) {
11180 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11181 elefilename);
11182 triexit(1);
11183 }
11184 }
11185 stringptr = findfield(stringptr);
11186 if (*stringptr == '\0') {
11187 m->eextras = 0;
11188 } else {
11189 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11190 }
11191#endif /* not TRILIBRARY */
11192
11194
11195 /* Create the triangles. */
11196 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11197 maketriangle(m, b, &triangleloop);
11198 /* Mark the triangle as living. */
11199 triangleloop.tri[3] = (triangle) triangleloop.tri;
11200 }
11201
11202 segmentmarkers = 0;
11203 if (b->poly) {
11204#ifdef TRILIBRARY
11205 m->insegments = numberofsegments;
11206 segmentmarkers = segmentmarkerlist != (int *) NULL;
11207#else /* not TRILIBRARY */
11208 /* Read number of segments and number of segment */
11209 /* boundary markers from .poly file. */
11210 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11211 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11212 stringptr = findfield(stringptr);
11213 if (*stringptr != '\0') {
11214 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11215 }
11216#endif /* not TRILIBRARY */
11217
11218 /* Create the subsegments. */
11219 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11220 makesubseg(m, &subsegloop);
11221 /* Mark the subsegment as living. */
11222 subsegloop.ss[2] = (subseg) subsegloop.ss;
11223 }
11224 }
11225
11226#ifdef TRILIBRARY
11227 vertexindex = 0;
11228 attribindex = 0;
11229#else /* not TRILIBRARY */
11230 if (b->vararea) {
11231 /* Open an .area file, check for consistency with the .ele file. */
11232 if (!b->quiet) {
11233 printf("Opening %s.\n", areafilename);
11234 }
11235 areafile = fopen(areafilename, "r");
11236 if (areafile == (FILE *) NULL) {
11237 printf(" Error: Cannot access file %s.\n", areafilename);
11238 triexit(1);
11239 }
11240 stringptr = readline(inputline, areafile, areafilename);
11241 areaelements = (int) strtol(stringptr, &stringptr, 0);
11242 if (areaelements != m->inelements) {
11243 printf("Error: %s and %s disagree on number of triangles.\n",
11244 elefilename, areafilename);
11245 triexit(1);
11246 }
11247 }
11248#endif /* not TRILIBRARY */
11249
11250 if (!b->quiet) {
11251 printf("Reconstructing mesh.\n");
11252 }
11253 /* Allocate a temporary array that maps each vertex to some adjacent */
11254 /* triangle. I took care to allocate all the permanent memory for */
11255 /* triangles and subsegments first. */
11256 vertexarray = (triangle *) trimalloc(m->vertices.items *
11257 (int) sizeof(triangle));
11258 /* Each vertex is initially unrepresented. */
11259 for (i = 0; i < m->vertices.items; i++) {
11260 vertexarray[i] = (triangle) m->dummytri;
11261 }
11262
11263 if (b->verbose) {
11264 printf(" Assembling triangles.\n");
11265 }
11266 /* Read the triangles from the .ele file, and link */
11267 /* together those that share an edge. */
11268 traversalinit(&m->triangles);
11269 triangleloop.tri = triangletraverse(m);
11270 elementnumber = b->firstnumber;
11271 while (triangleloop.tri != (triangle *) NULL) {
11272#ifdef TRILIBRARY
11273 /* Copy the triangle's three corners. */
11274 for (j = 0; j < 3; j++) {
11275 corner[j] = trianglelist[vertexindex++];
11276 if ((corner[j] < b->firstnumber) ||
11277 (corner[j] >= b->firstnumber + m->invertices)) {
11278 printf("Error: Triangle %ld has an invalid vertex index.\n",
11279 elementnumber);
11280 triexit(1);
11281 }
11282 }
11283#else /* not TRILIBRARY */
11284 /* Read triangle number and the triangle's three corners. */
11285 stringptr = readline(inputline, elefile, elefilename);
11286 for (j = 0; j < 3; j++) {
11287 stringptr = findfield(stringptr);
11288 if (*stringptr == '\0') {
11289 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11290 elementnumber, j + 1, elefilename);
11291 triexit(1);
11292 } else {
11293 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11294 if ((corner[j] < b->firstnumber) ||
11295 (corner[j] >= b->firstnumber + m->invertices)) {
11296 printf("Error: Triangle %ld has an invalid vertex index.\n",
11297 elementnumber);
11298 triexit(1);
11299 }
11300 }
11301 }
11302#endif /* not TRILIBRARY */
11303
11304 /* Find out about (and throw away) extra nodes. */
11305 for (j = 3; j < incorners; j++) {
11306#ifdef TRILIBRARY
11307 killvertexindex = trianglelist[vertexindex++];
11308#else /* not TRILIBRARY */
11309 stringptr = findfield(stringptr);
11310 if (*stringptr != '\0') {
11311 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11312#endif /* not TRILIBRARY */
11313 if ((killvertexindex >= b->firstnumber) &&
11314 (killvertexindex < b->firstnumber + m->invertices)) {
11315 /* Delete the non-corner vertex if it's not already deleted. */
11316 killvertex = getvertex(m, b, killvertexindex);
11317 if (vertextype(killvertex) != DEADVERTEX) {
11318 vertexdealloc(m, killvertex);
11319 }
11320 }
11321#ifndef TRILIBRARY
11322 }
11323#endif /* not TRILIBRARY */
11324 }
11325
11326 /* Read the triangle's attributes. */
11327 for (j = 0; j < m->eextras; j++) {
11328#ifdef TRILIBRARY
11329 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11330#else /* not TRILIBRARY */
11331 stringptr = findfield(stringptr);
11332 if (*stringptr == '\0') {
11333 setelemattribute(triangleloop, j, 0);
11334 } else {
11335 setelemattribute(triangleloop, j,
11336 (REAL) strtod(stringptr, &stringptr));
11337 }
11338#endif /* not TRILIBRARY */
11339 }
11340
11341 if (b->vararea) {
11342#ifdef TRILIBRARY
11343 area = trianglearealist[elementnumber - b->firstnumber];
11344#else /* not TRILIBRARY */
11345 /* Read an area constraint from the .area file. */
11346 stringptr = readline(inputline, areafile, areafilename);
11347 stringptr = findfield(stringptr);
11348 if (*stringptr == '\0') {
11349 area = -1.0; /* No constraint on this triangle. */
11350 } else {
11351 area = (REAL) strtod(stringptr, &stringptr);
11352 }
11353#endif /* not TRILIBRARY */
11354 setareabound(triangleloop, area);
11355 }
11356
11357 /* Set the triangle's vertices. */
11358 triangleloop.orient = 0;
11359 setorg(triangleloop, getvertex(m, b, corner[0]));
11360 setdest(triangleloop, getvertex(m, b, corner[1]));
11361 setapex(triangleloop, getvertex(m, b, corner[2]));
11362 /* Try linking the triangle to others that share these vertices. */
11363 for (triangleloop.orient = 0; triangleloop.orient < 3;
11364 triangleloop.orient++) {
11365 /* Take the number for the origin of triangleloop. */
11366 aroundvertex = corner[triangleloop.orient];
11367 /* Look for other triangles having this vertex. */
11368 nexttri = vertexarray[aroundvertex - b->firstnumber];
11369 /* Link the current triangle to the next one in the stack. */
11370 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11371 /* Push the current triangle onto the stack. */
11372 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11373 decode(nexttri, checktri);
11374 if (checktri.tri != m->dummytri) {
11375 dest(triangleloop, tdest);
11376 apex(triangleloop, tapex);
11377 /* Look for other triangles that share an edge. */
11378 do {
11379 dest(checktri, checkdest);
11380 apex(checktri, checkapex);
11381 if (tapex == checkdest) {
11382 /* The two triangles share an edge; bond them together. */
11383 lprev(triangleloop, triangleleft);
11384 bond(triangleleft, checktri);
11385 }
11386 if (tdest == checkapex) {
11387 /* The two triangles share an edge; bond them together. */
11388 lprev(checktri, checkleft);
11389 bond(triangleloop, checkleft);
11390 }
11391 /* Find the next triangle in the stack. */
11392 nexttri = checktri.tri[6 + checktri.orient];
11393 decode(nexttri, checktri);
11394 } while (checktri.tri != m->dummytri);
11395 }
11396 }
11397 triangleloop.tri = triangletraverse(m);
11398 elementnumber++;
11399 }
11400
11401#ifdef TRILIBRARY
11402 vertexindex = 0;
11403#else /* not TRILIBRARY */
11404 fclose(elefile);
11405 if (b->vararea) {
11406 fclose(areafile);
11407 }
11408#endif /* not TRILIBRARY */
11409
11410 hullsize = 0; /* Prepare to count the boundary edges. */
11411 if (b->poly) {
11412 if (b->verbose) {
11413 printf(" Marking segments in triangulation.\n");
11414 }
11415 /* Read the segments from the .poly file, and link them */
11416 /* to their neighboring triangles. */
11417 boundmarker = 0;
11418 traversalinit(&m->subsegs);
11419 subsegloop.ss = subsegtraverse(m);
11420 segmentnumber = b->firstnumber;
11421 while (subsegloop.ss != (subseg *) NULL) {
11422#ifdef TRILIBRARY
11423 end[0] = segmentlist[vertexindex++];
11424 end[1] = segmentlist[vertexindex++];
11425 if (segmentmarkers) {
11426 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11427 }
11428#else /* not TRILIBRARY */
11429 /* Read the endpoints of each segment, and possibly a boundary marker. */
11430 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11431 /* Skip the first (segment number) field. */
11432 stringptr = findfield(stringptr);
11433 if (*stringptr == '\0') {
11434 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11435 polyfilename);
11436 triexit(1);
11437 } else {
11438 end[0] = (int) strtol(stringptr, &stringptr, 0);
11439 }
11440 stringptr = findfield(stringptr);
11441 if (*stringptr == '\0') {
11442 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11443 segmentnumber, polyfilename);
11444 triexit(1);
11445 } else {
11446 end[1] = (int) strtol(stringptr, &stringptr, 0);
11447 }
11448 if (segmentmarkers) {
11449 stringptr = findfield(stringptr);
11450 if (*stringptr == '\0') {
11451 boundmarker = 0;
11452 } else {
11453 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11454 }
11455 }
11456#endif /* not TRILIBRARY */
11457 for (j = 0; j < 2; j++) {
11458 if ((end[j] < b->firstnumber) ||
11459 (end[j] >= b->firstnumber + m->invertices)) {
11460 printf("Error: Segment %ld has an invalid vertex index.\n",
11461 segmentnumber);
11462 triexit(1);
11463 }
11464 }
11465
11466 /* set the subsegment's vertices. */
11467 subsegloop.ssorient = 0;
11468 segmentorg = getvertex(m, b, end[0]);
11469 segmentdest = getvertex(m, b, end[1]);
11470 setsorg(subsegloop, segmentorg);
11471 setsdest(subsegloop, segmentdest);
11472 setsegorg(subsegloop, segmentorg);
11473 setsegdest(subsegloop, segmentdest);
11474 setmark(subsegloop, boundmarker);
11475 /* Try linking the subsegment to triangles that share these vertices. */
11476 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11477 subsegloop.ssorient++) {
11478 /* Take the number for the destination of subsegloop. */
11479 aroundvertex = end[1 - subsegloop.ssorient];
11480 /* Look for triangles having this vertex. */
11481 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11482 nexttri = vertexarray[aroundvertex - b->firstnumber];
11483 decode(nexttri, checktri);
11484 sorg(subsegloop, shorg);
11485 notfound = 1;
11486 /* Look for triangles having this edge. Note that I'm only */
11487 /* comparing each triangle's destination with the subsegment; */
11488 /* each triangle's apex is handled through a different vertex. */
11489 /* Because each triangle appears on three vertices' lists, each */
11490 /* occurrence of a triangle on a list can (and does) represent */
11491 /* an edge. In this way, most edges are represented twice, and */
11492 /* every triangle-subsegment bond is represented once. */
11493 while (notfound && (checktri.tri != m->dummytri)) {
11494 dest(checktri, checkdest);
11495 if (shorg == checkdest) {
11496 /* We have a match. Remove this triangle from the list. */
11497 *prevlink = checktri.tri[6 + checktri.orient];
11498 /* Bond the subsegment to the triangle. */
11499 tsbond(checktri, subsegloop);
11500 /* Check if this is a boundary edge. */
11501 sym(checktri, checkneighbor);
11502 if (checkneighbor.tri == m->dummytri) {
11503 /* The next line doesn't insert a subsegment (because there's */
11504 /* already one there), but it sets the boundary markers of */
11505 /* the existing subsegment and its vertices. */
11506 insertsubseg(m, b, &checktri, 1);
11507 hullsize++;
11508 }
11509 notfound = 0;
11510 }
11511 /* Find the next triangle in the stack. */
11512 prevlink = &checktri.tri[6 + checktri.orient];
11513 nexttri = checktri.tri[6 + checktri.orient];
11514 decode(nexttri, checktri);
11515 }
11516 }
11517 subsegloop.ss = subsegtraverse(m);
11518 segmentnumber++;
11519 }
11520 }
11521
11522 /* Mark the remaining edges as not being attached to any subsegment. */
11523 /* Also, count the (yet uncounted) boundary edges. */
11524 for (i = 0; i < m->vertices.items; i++) {
11525 /* Search the stack of triangles adjacent to a vertex. */
11526 nexttri = vertexarray[i];
11527 decode(nexttri, checktri);
11528 while (checktri.tri != m->dummytri) {
11529 /* Find the next triangle in the stack before this */
11530 /* information gets overwritten. */
11531 nexttri = checktri.tri[6 + checktri.orient];
11532 /* No adjacent subsegment. (This overwrites the stack info.) */
11533 tsdissolve(checktri);
11534 sym(checktri, checkneighbor);
11535 if (checkneighbor.tri == m->dummytri) {
11536 insertsubseg(m, b, &checktri, 1);
11537 hullsize++;
11538 }
11539 decode(nexttri, checktri);
11540 }
11541 }
11542
11543 trifree((VOID *) vertexarray);
11544 return hullsize;
11545}
11546
11547#endif /* not CDT_ONLY */
11548
11549/** **/
11550/** **/
11551/********* General mesh construction routines end here *********/
11552
11553/********* Segment insertion begins here *********/
11554/** **/
11555/** **/
11556
11557/*****************************************************************************/
11558/* */
11559/* finddirection() Find the first triangle on the path from one point */
11560/* to another. */
11561/* */
11562/* Finds the triangle that intersects a line segment drawn from the */
11563/* origin of `searchtri' to the point `searchpoint', and returns the result */
11564/* in `searchtri'. The origin of `searchtri' does not change, even though */
11565/* the triangle returned may differ from the one passed in. This routine */
11566/* is used to find the direction to move in to get from one point to */
11567/* another. */
11568/* */
11569/* The return value notes whether the destination or apex of the found */
11570/* triangle is collinear with the two points in question. */
11571/* */
11572/*****************************************************************************/
11573
11574#ifdef ANSI_DECLARATORS
11576 struct otri *searchtri,
11577 vertex searchpoint)
11578#else /* not ANSI_DECLARATORS */
11579enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11580struct mesh *m;
11581struct behavior *b;
11582struct otri *searchtri;
11583vertex searchpoint;
11584#endif /* not ANSI_DECLARATORS */
11585
11586{
11587 struct otri checktri;
11588 vertex startvertex;
11589 vertex leftvertex, rightvertex;
11590 REAL leftccw, rightccw;
11591 int leftflag, rightflag;
11592 triangle ptr; /* Temporary variable used by onext() and oprev(). */
11593
11594 org(*searchtri, startvertex);
11595 dest(*searchtri, rightvertex);
11596 apex(*searchtri, leftvertex);
11597 /* Is `searchpoint' to the left? */
11598 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11599 leftflag = leftccw > 0.0;
11600 /* Is `searchpoint' to the right? */
11601 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11602 rightflag = rightccw > 0.0;
11603 if (leftflag && rightflag) {
11604 /* `searchtri' faces directly away from `searchpoint'. We could go left */
11605 /* or right. Ask whether it's a triangle or a boundary on the left. */
11606 onext(*searchtri, checktri);
11607 if (checktri.tri == m->dummytri) {
11608 leftflag = 0;
11609 } else {
11610 rightflag = 0;
11611 }
11612 }
11613 while (leftflag) {
11614 /* Turn left until satisfied. */
11615 onextself(*searchtri);
11616 if (searchtri->tri == m->dummytri) {
11617 printf("Internal error in finddirection(): Unable to find a\n");
11618 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11619 startvertex[1]);
11620 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11621 internalerror();
11622 }
11623 apex(*searchtri, leftvertex);
11624 rightccw = leftccw;
11625 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11626 leftflag = leftccw > 0.0;
11627 }
11628 while (rightflag) {
11629 /* Turn right until satisfied. */
11630 oprevself(*searchtri);
11631 if (searchtri->tri == m->dummytri) {
11632 printf("Internal error in finddirection(): Unable to find a\n");
11633 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11634 startvertex[1]);
11635 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11636 internalerror();
11637 }
11638 dest(*searchtri, rightvertex);
11639 leftccw = rightccw;
11640 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11641 rightflag = rightccw > 0.0;
11642 }
11643 if (leftccw == 0.0) {
11644 return LEFTCOLLINEAR;
11645 } else if (rightccw == 0.0) {
11646 return RIGHTCOLLINEAR;
11647 } else {
11648 return WITHIN;
11649 }
11650}
11651
11652/*****************************************************************************/
11653/* */
11654/* segmentintersection() Find the intersection of an existing segment */
11655/* and a segment that is being inserted. Insert */
11656/* a vertex at the intersection, splitting an */
11657/* existing subsegment. */
11658/* */
11659/* The segment being inserted connects the apex of splittri to endpoint2. */
11660/* splitsubseg is the subsegment being split, and MUST adjoin splittri. */
11661/* Hence, endpoints of the subsegment being split are the origin and */
11662/* destination of splittri. */
11663/* */
11664/* On completion, splittri is a handle having the newly inserted */
11665/* intersection point as its origin, and endpoint1 as its destination. */
11666/* */
11667/*****************************************************************************/
11668
11669#ifdef ANSI_DECLARATORS
11670void segmentintersection(struct mesh *m, struct behavior *b,
11671 struct otri *splittri, struct osub *splitsubseg,
11672 vertex endpoint2)
11673#else /* not ANSI_DECLARATORS */
11674void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11675struct mesh *m;
11676struct behavior *b;
11677struct otri *splittri;
11678struct osub *splitsubseg;
11679vertex endpoint2;
11680#endif /* not ANSI_DECLARATORS */
11681
11682{
11683 struct osub opposubseg;
11684 vertex endpoint1;
11685 vertex torg, tdest;
11686 vertex leftvertex, rightvertex;
11687 vertex newvertex;
11688 enum insertvertexresult success;
11689 /* enum finddirectionresult collinear; LM: remove unsed variable warning */
11690 REAL ex, ey;
11691 REAL tx, ty;
11692 REAL etx, ety;
11693 REAL split, denom;
11694 int i;
11695 triangle ptr; /* Temporary variable used by onext(). */
11696 subseg sptr; /* Temporary variable used by snext(). */
11697
11698 /* Find the other three segment endpoints. */
11699 apex(*splittri, endpoint1);
11700 org(*splittri, torg);
11701 dest(*splittri, tdest);
11702 /* Segment intersection formulae; see the Antonio reference. */
11703 tx = tdest[0] - torg[0];
11704 ty = tdest[1] - torg[1];
11705 ex = endpoint2[0] - endpoint1[0];
11706 ey = endpoint2[1] - endpoint1[1];
11707 etx = torg[0] - endpoint2[0];
11708 ety = torg[1] - endpoint2[1];
11709 denom = ty * ex - tx * ey;
11710 if (denom == 0.0) {
11711 printf("Internal error in segmentintersection():");
11712 printf(" Attempt to find intersection of parallel segments.\n");
11713 internalerror();
11714 }
11715 split = (ey * etx - ex * ety) / denom;
11716 /* Create the new vertex. */
11717 newvertex = (vertex) poolalloc(&m->vertices);
11718 /* Interpolate its coordinate and attributes. */
11719 for (i = 0; i < 2 + m->nextras; i++) {
11720 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11721 }
11722 setvertexmark(newvertex, mark(*splitsubseg));
11723 setvertextype(newvertex, INPUTVERTEX);
11724 if (b->verbose > 1) {
11725 printf(
11726 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11727 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11728 }
11729 /* Insert the intersection vertex. This should always succeed. */
11730 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11731 if (success != SUCCESSFULVERTEX) {
11732 printf("Internal error in segmentintersection():\n");
11733 printf(" Failure to split a segment.\n");
11734 internalerror();
11735 }
11736 /* Record a triangle whose origin is the new vertex. */
11737 setvertex2tri(newvertex, encode(*splittri));
11738 if (m->steinerleft > 0) {
11739 m->steinerleft--;
11740 }
11741
11742 /* Divide the segment into two, and correct the segment endpoints. */
11743 ssymself(*splitsubseg);
11744 spivot(*splitsubseg, opposubseg);
11745 sdissolve(*splitsubseg);
11746 sdissolve(opposubseg);
11747 do {
11748 setsegorg(*splitsubseg, newvertex);
11749 snextself(*splitsubseg);
11750 } while (splitsubseg->ss != m->dummysub);
11751 do {
11752 setsegorg(opposubseg, newvertex);
11753 snextself(opposubseg);
11754 } while (opposubseg.ss != m->dummysub);
11755
11756 /* Inserting the vertex may have caused edge flips. We wish to rediscover */
11757 /* the edge connecting endpoint1 to the new intersection vertex. */
11758 /* collinear = LN: remove unsed variable warning */
11759 finddirection(m, b, splittri, endpoint1);
11760 dest(*splittri, rightvertex);
11761 apex(*splittri, leftvertex);
11762 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11763 onextself(*splittri);
11764 } else if ((rightvertex[0] != endpoint1[0]) ||
11765 (rightvertex[1] != endpoint1[1])) {
11766 printf("Internal error in segmentintersection():\n");
11767 printf(" Topological inconsistency after splitting a segment.\n");
11768 internalerror();
11769 }
11770 /* `splittri' should have destination endpoint1. */
11771}
11772
11773/*****************************************************************************/
11774/* */
11775/* scoutsegment() Scout the first triangle on the path from one endpoint */
11776/* to another, and check for completion (reaching the */
11777/* second endpoint), a collinear vertex, or the */
11778/* intersection of two segments. */
11779/* */
11780/* Returns one if the entire segment is successfully inserted, and zero if */
11781/* the job must be finished by conformingedge() or constrainededge(). */
11782/* */
11783/* If the first triangle on the path has the second endpoint as its */
11784/* destination or apex, a subsegment is inserted and the job is done. */
11785/* */
11786/* If the first triangle on the path has a destination or apex that lies on */
11787/* the segment, a subsegment is inserted connecting the first endpoint to */
11788/* the collinear vertex, and the search is continued from the collinear */
11789/* vertex. */
11790/* */
11791/* If the first triangle on the path has a subsegment opposite its origin, */
11792/* then there is a segment that intersects the segment being inserted. */
11793/* Their intersection vertex is inserted, splitting the subsegment. */
11794/* */
11795/*****************************************************************************/
11796
11797#ifdef ANSI_DECLARATORS
11798int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11799 vertex endpoint2, int newmark)
11800#else /* not ANSI_DECLARATORS */
11801int scoutsegment(m, b, searchtri, endpoint2, newmark)
11802struct mesh *m;
11803struct behavior *b;
11804struct otri *searchtri;
11805vertex endpoint2;
11806int newmark;
11807#endif /* not ANSI_DECLARATORS */
11808
11809{
11810 struct otri crosstri;
11811 struct osub crosssubseg;
11812 vertex leftvertex, rightvertex;
11813 enum finddirectionresult collinear;
11814 subseg sptr; /* Temporary variable used by tspivot(). */
11815
11816 collinear = finddirection(m, b, searchtri, endpoint2);
11817 dest(*searchtri, rightvertex);
11818 apex(*searchtri, leftvertex);
11819 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11820 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11821 /* The segment is already an edge in the mesh. */
11822 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11823 lprevself(*searchtri);
11824 }
11825 /* Insert a subsegment, if there isn't already one there. */
11826 insertsubseg(m, b, searchtri, newmark);
11827 return 1;
11828 } else if (collinear == LEFTCOLLINEAR) {
11829 /* We've collided with a vertex between the segment's endpoints. */
11830 /* Make the collinear vertex be the triangle's origin. */
11831 lprevself(*searchtri);
11832 insertsubseg(m, b, searchtri, newmark);
11833 /* Insert the remainder of the segment. */
11834 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11835 } else if (collinear == RIGHTCOLLINEAR) {
11836 /* We've collided with a vertex between the segment's endpoints. */
11837 insertsubseg(m, b, searchtri, newmark);
11838 /* Make the collinear vertex be the triangle's origin. */
11839 lnextself(*searchtri);
11840 /* Insert the remainder of the segment. */
11841 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11842 } else {
11843 lnext(*searchtri, crosstri);
11844 tspivot(crosstri, crosssubseg);
11845 /* Check for a crossing segment. */
11846 if (crosssubseg.ss == m->dummysub) {
11847 return 0;
11848 } else {
11849 /* Insert a vertex at the intersection. */
11850 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11851 otricopy(crosstri, *searchtri);
11852 insertsubseg(m, b, searchtri, newmark);
11853 /* Insert the remainder of the segment. */
11854 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11855 }
11856 }
11857}
11858
11859/*****************************************************************************/
11860/* */
11861/* conformingedge() Force a segment into a conforming Delaunay */
11862/* triangulation by inserting a vertex at its midpoint, */
11863/* and recursively forcing in the two half-segments if */
11864/* necessary. */
11865/* */
11866/* Generates a sequence of subsegments connecting `endpoint1' to */
11867/* `endpoint2'. `newmark' is the boundary marker of the segment, assigned */
11868/* to each new splitting vertex and subsegment. */
11869/* */
11870/* Note that conformingedge() does not always maintain the conforming */
11871/* Delaunay property. Once inserted, segments are locked into place; */
11872/* vertices inserted later (to force other segments in) may render these */
11873/* fixed segments non-Delaunay. The conforming Delaunay property will be */
11874/* restored by enforcequality() by splitting encroached subsegments. */
11875/* */
11876/*****************************************************************************/
11877
11878#ifndef REDUCED
11879#ifndef CDT_ONLY
11880
11881#ifdef ANSI_DECLARATORS
11882void conformingedge(struct mesh *m, struct behavior *b,
11883 vertex endpoint1, vertex endpoint2, int newmark)
11884#else /* not ANSI_DECLARATORS */
11885void conformingedge(m, b, endpoint1, endpoint2, newmark)
11886struct mesh *m;
11887struct behavior *b;
11888vertex endpoint1;
11889vertex endpoint2;
11890int newmark;
11891#endif /* not ANSI_DECLARATORS */
11892
11893{
11894 struct otri searchtri1, searchtri2;
11895 struct osub brokensubseg;
11896 vertex newvertex;
11897 vertex midvertex1, midvertex2;
11898 enum insertvertexresult success;
11899 int i;
11900 subseg sptr; /* Temporary variable used by tspivot(). */
11901
11902 if (b->verbose > 2) {
11903 printf("Forcing segment into triangulation by recursive splitting:\n");
11904 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11905 endpoint2[0], endpoint2[1]);
11906 }
11907 /* Create a new vertex to insert in the middle of the segment. */
11908 newvertex = (vertex) poolalloc(&m->vertices);
11909 /* Interpolate coordinates and attributes. */
11910 for (i = 0; i < 2 + m->nextras; i++) {
11911 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11912 }
11913 setvertexmark(newvertex, newmark);
11914 setvertextype(newvertex, SEGMENTVERTEX);
11915 /* No known triangle to search from. */
11916 searchtri1.tri = m->dummytri;
11917 /* Attempt to insert the new vertex. */
11918 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11919 0, 0);
11920 if (success == DUPLICATEVERTEX) {
11921 if (b->verbose > 2) {
11922 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
11923 newvertex[0], newvertex[1]);
11924 }
11925 /* Use the vertex that's already there. */
11926 vertexdealloc(m, newvertex);
11927 org(searchtri1, newvertex);
11928 } else {
11929 if (success == VIOLATINGVERTEX) {
11930 if (b->verbose > 2) {
11931 printf(" Two segments intersect at (%.12g, %.12g).\n",
11932 newvertex[0], newvertex[1]);
11933 }
11934 /* By fluke, we've landed right on another segment. Split it. */
11935 tspivot(searchtri1, brokensubseg);
11936 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11937 0, 0);
11938 if (success != SUCCESSFULVERTEX) {
11939 printf("Internal error in conformingedge():\n");
11940 printf(" Failure to split a segment.\n");
11941 internalerror();
11942 }
11943 }
11944 /* The vertex has been inserted successfully. */
11945 if (m->steinerleft > 0) {
11946 m->steinerleft--;
11947 }
11948 }
11949 otricopy(searchtri1, searchtri2);
11950 /* `searchtri1' and `searchtri2' are fastened at their origins to */
11951 /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */
11952 /* respectively. First, we must get `searchtri2' out of the way so it */
11953 /* won't be invalidated during the insertion of the first half of the */
11954 /* segment. */
11955 finddirection(m, b, &searchtri2, endpoint2);
11956 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11957 /* The origin of searchtri1 may have changed if a collision with an */
11958 /* intervening vertex on the segment occurred. */
11959 org(searchtri1, midvertex1);
11960 conformingedge(m, b, midvertex1, endpoint1, newmark);
11961 }
11962 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11963 /* The origin of searchtri2 may have changed if a collision with an */
11964 /* intervening vertex on the segment occurred. */
11965 org(searchtri2, midvertex2);
11966 conformingedge(m, b, midvertex2, endpoint2, newmark);
11967 }
11968}
11969
11970#endif /* not CDT_ONLY */
11971#endif /* not REDUCED */
11972
11973/*****************************************************************************/
11974/* */
11975/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */
11976/* recursively from an existing vertex. Pay special */
11977/* attention to stacking inverted triangles. */
11978/* */
11979/* This is a support routine for inserting segments into a constrained */
11980/* Delaunay triangulation. */
11981/* */
11982/* The origin of fixuptri is treated as if it has just been inserted, and */
11983/* the local Delaunay condition needs to be enforced. It is only enforced */
11984/* in one sector, however, that being the angular range defined by */
11985/* fixuptri. */
11986/* */
11987/* This routine also needs to make decisions regarding the "stacking" of */
11988/* triangles. (Read the description of constrainededge() below before */
11989/* reading on here, so you understand the algorithm.) If the position of */
11990/* the new vertex (the origin of fixuptri) indicates that the vertex before */
11991/* it on the polygon is a reflex vertex, then "stack" the triangle by */
11992/* doing nothing. (fixuptri is an inverted triangle, which is how stacked */
11993/* triangles are identified.) */
11994/* */
11995/* Otherwise, check whether the vertex before that was a reflex vertex. */
11996/* If so, perform an edge flip, thereby eliminating an inverted triangle */
11997/* (popping it off the stack). The edge flip may result in the creation */
11998/* of a new inverted triangle, depending on whether or not the new vertex */
11999/* is visible to the vertex three edges behind on the polygon. */
12000/* */
12001/* If neither of the two vertices behind the new vertex are reflex */
12002/* vertices, fixuptri and fartri, the triangle opposite it, are not */
12003/* inverted; hence, ensure that the edge between them is locally Delaunay. */
12004/* */
12005/* `leftside' indicates whether or not fixuptri is to the left of the */
12006/* segment being inserted. (Imagine that the segment is pointing up from */
12007/* endpoint1 to endpoint2.) */
12008/* */
12009/*****************************************************************************/
12010
12011#ifdef ANSI_DECLARATORS
12012void delaunayfixup(struct mesh *m, struct behavior *b,
12013 struct otri *fixuptri, int leftside)
12014#else /* not ANSI_DECLARATORS */
12015void delaunayfixup(m, b, fixuptri, leftside)
12016struct mesh *m;
12017struct behavior *b;
12018struct otri *fixuptri;
12019int leftside;
12020#endif /* not ANSI_DECLARATORS */
12021
12022{
12023 struct otri neartri;
12024 struct otri fartri;
12025 struct osub faredge;
12026 vertex nearvertex, leftvertex, rightvertex, farvertex;
12027 triangle ptr; /* Temporary variable used by sym(). */
12028 subseg sptr; /* Temporary variable used by tspivot(). */
12029
12030 lnext(*fixuptri, neartri);
12031 sym(neartri, fartri);
12032 /* Check if the edge opposite the origin of fixuptri can be flipped. */
12033 if (fartri.tri == m->dummytri) {
12034 return;
12035 }
12036 tspivot(neartri, faredge);
12037 if (faredge.ss != m->dummysub) {
12038 return;
12039 }
12040 /* Find all the relevant vertices. */
12041 apex(neartri, nearvertex);
12042 org(neartri, leftvertex);
12043 dest(neartri, rightvertex);
12044 apex(fartri, farvertex);
12045 /* Check whether the previous polygon vertex is a reflex vertex. */
12046 if (leftside) {
12047 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12048 /* leftvertex is a reflex vertex too. Nothing can */
12049 /* be done until a convex section is found. */
12050 return;
12051 }
12052 } else {
12053 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12054 /* rightvertex is a reflex vertex too. Nothing can */
12055 /* be done until a convex section is found. */
12056 return;
12057 }
12058 }
12059 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12060 /* fartri is not an inverted triangle, and farvertex is not a reflex */
12061 /* vertex. As there are no reflex vertices, fixuptri isn't an */
12062 /* inverted triangle, either. Hence, test the edge between the */
12063 /* triangles to ensure it is locally Delaunay. */
12064 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12065 0.0) {
12066 return;
12067 }
12068 /* Not locally Delaunay; go on to an edge flip. */
12069 } /* else fartri is inverted; remove it from the stack by flipping. */
12070 flip(m, b, &neartri);
12071 lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */
12072 /* Recursively process the two triangles that result from the flip. */
12073 delaunayfixup(m, b, fixuptri, leftside);
12074 delaunayfixup(m, b, &fartri, leftside);
12075}
12076
12077/*****************************************************************************/
12078/* */
12079/* constrainededge() Force a segment into a constrained Delaunay */
12080/* triangulation by deleting the triangles it */
12081/* intersects, and triangulating the polygons that */
12082/* form on each side of it. */
12083/* */
12084/* Generates a single subsegment connecting `endpoint1' to `endpoint2'. */
12085/* The triangle `starttri' has `endpoint1' as its origin. `newmark' is the */
12086/* boundary marker of the segment. */
12087/* */
12088/* To insert a segment, every triangle whose interior intersects the */
12089/* segment is deleted. The union of these deleted triangles is a polygon */
12090/* (which is not necessarily monotone, but is close enough), which is */
12091/* divided into two polygons by the new segment. This routine's task is */
12092/* to generate the Delaunay triangulation of these two polygons. */
12093/* */
12094/* You might think of this routine's behavior as a two-step process. The */
12095/* first step is to walk from endpoint1 to endpoint2, flipping each edge */
12096/* encountered. This step creates a fan of edges connected to endpoint1, */
12097/* including the desired edge to endpoint2. The second step enforces the */
12098/* Delaunay condition on each side of the segment in an incremental manner: */
12099/* proceeding along the polygon from endpoint1 to endpoint2 (this is done */
12100/* independently on each side of the segment), each vertex is "enforced" */
12101/* as if it had just been inserted, but affecting only the previous */
12102/* vertices. The result is the same as if the vertices had been inserted */
12103/* in the order they appear on the polygon, so the result is Delaunay. */
12104/* */
12105/* In truth, constrainededge() interleaves these two steps. The procedure */
12106/* walks from endpoint1 to endpoint2, and each time an edge is encountered */
12107/* and flipped, the newly exposed vertex (at the far end of the flipped */
12108/* edge) is "enforced" upon the previously flipped edges, usually affecting */
12109/* only one side of the polygon (depending upon which side of the segment */
12110/* the vertex falls on). */
12111/* */
12112/* The algorithm is complicated by the need to handle polygons that are not */
12113/* convex. Although the polygon is not necessarily monotone, it can be */
12114/* triangulated in a manner similar to the stack-based algorithms for */
12115/* monotone polygons. For each reflex vertex (local concavity) of the */
12116/* polygon, there will be an inverted triangle formed by one of the edge */
12117/* flips. (An inverted triangle is one with negative area - that is, its */
12118/* vertices are arranged in clockwise order - and is best thought of as a */
12119/* wrinkle in the fabric of the mesh.) Each inverted triangle can be */
12120/* thought of as a reflex vertex pushed on the stack, waiting to be fixed */
12121/* later. */
12122/* */
12123/* A reflex vertex is popped from the stack when a vertex is inserted that */
12124/* is visible to the reflex vertex. (However, if the vertex behind the */
12125/* reflex vertex is not visible to the reflex vertex, a new inverted */
12126/* triangle will take its place on the stack.) These details are handled */
12127/* by the delaunayfixup() routine above. */
12128/* */
12129/*****************************************************************************/
12130
12131#ifdef ANSI_DECLARATORS
12132void constrainededge(struct mesh *m, struct behavior *b,
12133 struct otri *starttri, vertex endpoint2, int newmark)
12134#else /* not ANSI_DECLARATORS */
12135void constrainededge(m, b, starttri, endpoint2, newmark)
12136struct mesh *m;
12137struct behavior *b;
12138struct otri *starttri;
12139vertex endpoint2;
12140int newmark;
12141#endif /* not ANSI_DECLARATORS */
12142
12143{
12144 struct otri fixuptri, fixuptri2;
12145 struct osub crosssubseg;
12146 vertex endpoint1;
12147 vertex farvertex;
12148 REAL area;
12149 int collision;
12150 int done;
12151 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12152 subseg sptr; /* Temporary variable used by tspivot(). */
12153
12154 org(*starttri, endpoint1);
12155 lnext(*starttri, fixuptri);
12156 flip(m, b, &fixuptri);
12157 /* `collision' indicates whether we have found a vertex directly */
12158 /* between endpoint1 and endpoint2. */
12159 collision = 0;
12160 done = 0;
12161 do {
12162 org(fixuptri, farvertex);
12163 /* `farvertex' is the extreme point of the polygon we are "digging" */
12164 /* to get from endpoint1 to endpoint2. */
12165 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12166 oprev(fixuptri, fixuptri2);
12167 /* Enforce the Delaunay condition around endpoint2. */
12168 delaunayfixup(m, b, &fixuptri, 0);
12169 delaunayfixup(m, b, &fixuptri2, 1);
12170 done = 1;
12171 } else {
12172 /* Check whether farvertex is to the left or right of the segment */
12173 /* being inserted, to decide which edge of fixuptri to dig */
12174 /* through next. */
12175 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12176 if (area == 0.0) {
12177 /* We've collided with a vertex between endpoint1 and endpoint2. */
12178 collision = 1;
12179 oprev(fixuptri, fixuptri2);
12180 /* Enforce the Delaunay condition around farvertex. */
12181 delaunayfixup(m, b, &fixuptri, 0);
12182 delaunayfixup(m, b, &fixuptri2, 1);
12183 done = 1;
12184 } else {
12185 if (area > 0.0) { /* farvertex is to the left of the segment. */
12186 oprev(fixuptri, fixuptri2);
12187 /* Enforce the Delaunay condition around farvertex, on the */
12188 /* left side of the segment only. */
12189 delaunayfixup(m, b, &fixuptri2, 1);
12190 /* Flip the edge that crosses the segment. After the edge is */
12191 /* flipped, one of its endpoints is the fan vertex, and the */
12192 /* destination of fixuptri is the fan vertex. */
12193 lprevself(fixuptri);
12194 } else { /* farvertex is to the right of the segment. */
12195 delaunayfixup(m, b, &fixuptri, 0);
12196 /* Flip the edge that crosses the segment. After the edge is */
12197 /* flipped, one of its endpoints is the fan vertex, and the */
12198 /* destination of fixuptri is the fan vertex. */
12199 oprevself(fixuptri);
12200 }
12201 /* Check for two intersecting segments. */
12202 tspivot(fixuptri, crosssubseg);
12203 if (crosssubseg.ss == m->dummysub) {
12204 flip(m, b, &fixuptri); /* May create inverted triangle at left. */
12205 } else {
12206 /* We've collided with a segment between endpoint1 and endpoint2. */
12207 collision = 1;
12208 /* Insert a vertex at the intersection. */
12209 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12210 done = 1;
12211 }
12212 }
12213 }
12214 } while (!done);
12215 /* Insert a subsegment to make the segment permanent. */
12216 insertsubseg(m, b, &fixuptri, newmark);
12217 /* If there was a collision with an interceding vertex, install another */
12218 /* segment connecting that vertex with endpoint2. */
12219 if (collision) {
12220 /* Insert the remainder of the segment. */
12221 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12222 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12223 }
12224 }
12225}
12226
12227/*****************************************************************************/
12228/* */
12229/* insertsegment() Insert a PSLG segment into a triangulation. */
12230/* */
12231/*****************************************************************************/
12232
12233#ifdef ANSI_DECLARATORS
12234void insertsegment(struct mesh *m, struct behavior *b,
12235 vertex endpoint1, vertex endpoint2, int newmark)
12236#else /* not ANSI_DECLARATORS */
12237void insertsegment(m, b, endpoint1, endpoint2, newmark)
12238struct mesh *m;
12239struct behavior *b;
12240vertex endpoint1;
12241vertex endpoint2;
12242int newmark;
12243#endif /* not ANSI_DECLARATORS */
12244
12245{
12246 struct otri searchtri1, searchtri2;
12247 triangle encodedtri;
12248 vertex checkvertex;
12249 triangle ptr; /* Temporary variable used by sym(). */
12250
12251 if (b->verbose > 1) {
12252 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12253 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12254 }
12255
12256 /* Find a triangle whose origin is the segment's first endpoint. */
12257 checkvertex = (vertex) NULL;
12258 encodedtri = vertex2tri(endpoint1);
12259 if (encodedtri != (triangle) NULL) {
12260 decode(encodedtri, searchtri1);
12261 org(searchtri1, checkvertex);
12262 }
12263 if (checkvertex != endpoint1) {
12264 /* Find a boundary triangle to search from. */
12265 searchtri1.tri = m->dummytri;
12266 searchtri1.orient = 0;
12267 symself(searchtri1);
12268 /* Search for the segment's first endpoint by point location. */
12269 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12270 printf(
12271 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12272 printf(" (%.12g, %.12g) in triangulation.\n",
12273 endpoint1[0], endpoint1[1]);
12274 internalerror();
12275 }
12276 }
12277 /* Remember this triangle to improve subsequent point location. */
12278 otricopy(searchtri1, m->recenttri);
12279 /* Scout the beginnings of a path from the first endpoint */
12280 /* toward the second. */
12281 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12282 /* The segment was easily inserted. */
12283 return;
12284 }
12285 /* The first endpoint may have changed if a collision with an intervening */
12286 /* vertex on the segment occurred. */
12287 org(searchtri1, endpoint1);
12288
12289 /* Find a triangle whose origin is the segment's second endpoint. */
12290 checkvertex = (vertex) NULL;
12291 encodedtri = vertex2tri(endpoint2);
12292 if (encodedtri != (triangle) NULL) {
12293 decode(encodedtri, searchtri2);
12294 org(searchtri2, checkvertex);
12295 }
12296 if (checkvertex != endpoint2) {
12297 /* Find a boundary triangle to search from. */
12298 searchtri2.tri = m->dummytri;
12299 searchtri2.orient = 0;
12300 symself(searchtri2);
12301 /* Search for the segment's second endpoint by point location. */
12302 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12303 printf(
12304 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12305 printf(" (%.12g, %.12g) in triangulation.\n",
12306 endpoint2[0], endpoint2[1]);
12307 internalerror();
12308 }
12309 }
12310 /* Remember this triangle to improve subsequent point location. */
12311 otricopy(searchtri2, m->recenttri);
12312 /* Scout the beginnings of a path from the second endpoint */
12313 /* toward the first. */
12314 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12315 /* The segment was easily inserted. */
12316 return;
12317 }
12318 /* The second endpoint may have changed if a collision with an intervening */
12319 /* vertex on the segment occurred. */
12320 org(searchtri2, endpoint2);
12321
12322#ifndef REDUCED
12323#ifndef CDT_ONLY
12324 if (b->splitseg) {
12325 /* Insert vertices to force the segment into the triangulation. */
12326 conformingedge(m, b, endpoint1, endpoint2, newmark);
12327 } else {
12328#endif /* not CDT_ONLY */
12329#endif /* not REDUCED */
12330 /* Insert the segment directly into the triangulation. */
12331 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12332#ifndef REDUCED
12333#ifndef CDT_ONLY
12334 }
12335#endif /* not CDT_ONLY */
12336#endif /* not REDUCED */
12337}
12338
12339/*****************************************************************************/
12340/* */
12341/* markhull() Cover the convex hull of a triangulation with subsegments. */
12342/* */
12343/*****************************************************************************/
12344
12345#ifdef ANSI_DECLARATORS
12346void markhull(struct mesh *m, struct behavior *b)
12347#else /* not ANSI_DECLARATORS */
12348void markhull(m, b)
12349struct mesh *m;
12350struct behavior *b;
12351#endif /* not ANSI_DECLARATORS */
12352
12353{
12354 struct otri hulltri;
12355 struct otri nexttri;
12356 struct otri starttri;
12357 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12358
12359 /* Find a triangle handle on the hull. */
12360 hulltri.tri = m->dummytri;
12361 hulltri.orient = 0;
12362 symself(hulltri);
12363 /* Remember where we started so we know when to stop. */
12364 otricopy(hulltri, starttri);
12365 /* Go once counterclockwise around the convex hull. */
12366 do {
12367 /* Create a subsegment if there isn't already one here. */
12368 insertsubseg(m, b, &hulltri, 1);
12369 /* To find the next hull edge, go clockwise around the next vertex. */
12370 lnextself(hulltri);
12371 oprev(hulltri, nexttri);
12372 while (nexttri.tri != m->dummytri) {
12373 otricopy(nexttri, hulltri);
12374 oprev(hulltri, nexttri);
12375 }
12376 } while (!otriequal(hulltri, starttri));
12377}
12378
12379/*****************************************************************************/
12380/* */
12381/* formskeleton() Create the segments of a triangulation, including PSLG */
12382/* segments and edges on the convex hull. */
12383/* */
12384/* The PSLG segments are read from a .poly file. The return value is the */
12385/* number of segments in the file. */
12386/* */
12387/*****************************************************************************/
12388
12389#ifdef TRILIBRARY
12390
12391#ifdef ANSI_DECLARATORS
12392void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12393 int *segmentmarkerlist, int numberofsegments)
12394#else /* not ANSI_DECLARATORS */
12395void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12396struct mesh *m;
12397struct behavior *b;
12398int *segmentlist;
12399int *segmentmarkerlist;
12400int numberofsegments;
12401#endif /* not ANSI_DECLARATORS */
12402
12403#else /* not TRILIBRARY */
12404
12405#ifdef ANSI_DECLARATORS
12406void formskeleton(struct mesh *m, struct behavior *b,
12407 FILE *polyfile, char *polyfilename)
12408#else /* not ANSI_DECLARATORS */
12409void formskeleton(m, b, polyfile, polyfilename)
12410struct mesh *m;
12411struct behavior *b;
12412FILE *polyfile;
12413char *polyfilename;
12414#endif /* not ANSI_DECLARATORS */
12415
12416#endif /* not TRILIBRARY */
12417
12418{
12419#ifdef TRILIBRARY
12420 char polyfilename[6];
12421 int index;
12422#else /* not TRILIBRARY */
12423 char inputline[INPUTLINESIZE];
12424 char *stringptr;
12425#endif /* not TRILIBRARY */
12426 vertex endpoint1, endpoint2;
12427 int segmentmarkers;
12428 int end1, end2;
12429 int boundmarker;
12430 int i;
12431
12432 if (b->poly) {
12433 if (!b->quiet) {
12434 printf("Recovering segments in Delaunay triangulation.\n");
12435 }
12436#ifdef TRILIBRARY
12437 strcpy(polyfilename, "input");
12438 m->insegments = numberofsegments;
12439 segmentmarkers = segmentmarkerlist != (int *) NULL;
12440 index = 0;
12441#else /* not TRILIBRARY */
12442 /* Read the segments from a .poly file. */
12443 /* Read number of segments and number of boundary markers. */
12444 stringptr = readline(inputline, polyfile, polyfilename);
12445 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12446 stringptr = findfield(stringptr);
12447 if (*stringptr == '\0') {
12448 segmentmarkers = 0;
12449 } else {
12450 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12451 }
12452#endif /* not TRILIBRARY */
12453 /* If the input vertices are collinear, there is no triangulation, */
12454 /* so don't try to insert segments. */
12455 if (m->triangles.items == 0) {
12456 return;
12457 }
12458
12459 /* If segments are to be inserted, compute a mapping */
12460 /* from vertices to triangles. */
12461 if (m->insegments > 0) {
12462 makevertexmap(m, b);
12463 if (b->verbose) {
12464 printf(" Recovering PSLG segments.\n");
12465 }
12466 }
12467
12468 boundmarker = 0;
12469 /* Read and insert the segments. */
12470 for (i = 0; i < m->insegments; i++) {
12471#ifdef TRILIBRARY
12472 end1 = segmentlist[index++];
12473 end2 = segmentlist[index++];
12474 if (segmentmarkers) {
12475 boundmarker = segmentmarkerlist[i];
12476 }
12477#else /* not TRILIBRARY */
12478 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12479 stringptr = findfield(stringptr);
12480 if (*stringptr == '\0') {
12481 printf("Error: Segment %d has no endpoints in %s.\n",
12482 b->firstnumber + i, polyfilename);
12483 triexit(1);
12484 } else {
12485 end1 = (int) strtol(stringptr, &stringptr, 0);
12486 }
12487 stringptr = findfield(stringptr);
12488 if (*stringptr == '\0') {
12489 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12490 b->firstnumber + i, polyfilename);
12491 triexit(1);
12492 } else {
12493 end2 = (int) strtol(stringptr, &stringptr, 0);
12494 }
12495 if (segmentmarkers) {
12496 stringptr = findfield(stringptr);
12497 if (*stringptr == '\0') {
12498 boundmarker = 0;
12499 } else {
12500 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12501 }
12502 }
12503#endif /* not TRILIBRARY */
12504 if ((end1 < b->firstnumber) ||
12505 (end1 >= b->firstnumber + m->invertices)) {
12506 if (!b->quiet) {
12507 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12508 b->firstnumber + i, polyfilename);
12509 }
12510 } else if ((end2 < b->firstnumber) ||
12511 (end2 >= b->firstnumber + m->invertices)) {
12512 if (!b->quiet) {
12513 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12514 b->firstnumber + i, polyfilename);
12515 }
12516 } else {
12517 /* Find the vertices numbered `end1' and `end2'. */
12518 endpoint1 = getvertex(m, b, end1);
12519 endpoint2 = getvertex(m, b, end2);
12520 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12521 if (!b->quiet) {
12522 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12523 b->firstnumber + i, polyfilename);
12524 }
12525 } else {
12526 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12527 }
12528 }
12529 }
12530 } else {
12531 m->insegments = 0;
12532 }
12533 if (b->convex || !b->poly) {
12534 /* Enclose the convex hull with subsegments. */
12535 if (b->verbose) {
12536 printf(" Enclosing convex hull with segments.\n");
12537 }
12538 markhull(m, b);
12539 }
12540}
12541
12542/** **/
12543/** **/
12544/********* Segment insertion ends here *********/
12545
12546/********* Carving out holes and concavities begins here *********/
12547/** **/
12548/** **/
12549
12550/*****************************************************************************/
12551/* */
12552/* infecthull() Virally infect all of the triangles of the convex hull */
12553/* that are not protected by subsegments. Where there are */
12554/* subsegments, set boundary markers as appropriate. */
12555/* */
12556/*****************************************************************************/
12557
12558#ifdef ANSI_DECLARATORS
12559void infecthull(struct mesh *m, struct behavior *b)
12560#else /* not ANSI_DECLARATORS */
12561void infecthull(m, b)
12562struct mesh *m;
12563struct behavior *b;
12564#endif /* not ANSI_DECLARATORS */
12565
12566{
12567 struct otri hulltri;
12568 struct otri nexttri;
12569 struct otri starttri;
12570 struct osub hullsubseg;
12571 triangle **deadtriangle;
12572 vertex horg, hdest;
12573 triangle ptr; /* Temporary variable used by sym(). */
12574 subseg sptr; /* Temporary variable used by tspivot(). */
12575
12576 if (b->verbose) {
12577 printf(" Marking concavities (external triangles) for elimination.\n");
12578 }
12579 /* Find a triangle handle on the hull. */
12580 hulltri.tri = m->dummytri;
12581 hulltri.orient = 0;
12582 symself(hulltri);
12583 /* Remember where we started so we know when to stop. */
12584 otricopy(hulltri, starttri);
12585 /* Go once counterclockwise around the convex hull. */
12586 do {
12587 /* Ignore triangles that are already infected. */
12588 if (!infected(hulltri)) {
12589 /* Is the triangle protected by a subsegment? */
12590 tspivot(hulltri, hullsubseg);
12591 if (hullsubseg.ss == m->dummysub) {
12592 /* The triangle is not protected; infect it. */
12593 if (!infected(hulltri)) {
12594 infect(hulltri);
12595 deadtriangle = (triangle **) poolalloc(&m->viri);
12596 *deadtriangle = hulltri.tri;
12597 }
12598 } else {
12599 /* The triangle is protected; set boundary markers if appropriate. */
12600 if (mark(hullsubseg) == 0) {
12601 setmark(hullsubseg, 1);
12602 org(hulltri, horg);
12603 dest(hulltri, hdest);
12604 if (vertexmark(horg) == 0) {
12605 setvertexmark(horg, 1);
12606 }
12607 if (vertexmark(hdest) == 0) {
12608 setvertexmark(hdest, 1);
12609 }
12610 }
12611 }
12612 }
12613 /* To find the next hull edge, go clockwise around the next vertex. */
12614 lnextself(hulltri);
12615 oprev(hulltri, nexttri);
12616 while (nexttri.tri != m->dummytri) {
12617 otricopy(nexttri, hulltri);
12618 oprev(hulltri, nexttri);
12619 }
12620 } while (!otriequal(hulltri, starttri));
12621}
12622
12623/*****************************************************************************/
12624/* */
12625/* plague() Spread the virus from all infected triangles to any neighbors */
12626/* not protected by subsegments. Delete all infected triangles. */
12627/* */
12628/* This is the procedure that actually creates holes and concavities. */
12629/* */
12630/* This procedure operates in two phases. The first phase identifies all */
12631/* the triangles that will die, and marks them as infected. They are */
12632/* marked to ensure that each triangle is added to the virus pool only */
12633/* once, so the procedure will terminate. */
12634/* */
12635/* The second phase actually eliminates the infected triangles. It also */
12636/* eliminates orphaned vertices. */
12637/* */
12638/*****************************************************************************/
12639
12640#ifdef ANSI_DECLARATORS
12641void plague(struct mesh *m, struct behavior *b)
12642#else /* not ANSI_DECLARATORS */
12643void plague(m, b)
12644struct mesh *m;
12645struct behavior *b;
12646#endif /* not ANSI_DECLARATORS */
12647
12648{
12649 struct otri testtri;
12650 struct otri neighbor;
12651 triangle **virusloop;
12652 triangle **deadtriangle;
12653 struct osub neighborsubseg;
12654 vertex testvertex;
12655 vertex norg, ndest;
12656 vertex deadorg, deaddest, deadapex;
12657 int killorg;
12658 triangle ptr; /* Temporary variable used by sym() and onext(). */
12659 subseg sptr; /* Temporary variable used by tspivot(). */
12660
12661 if (b->verbose) {
12662 printf(" Marking neighbors of marked triangles.\n");
12663 }
12664 /* Loop through all the infected triangles, spreading the virus to */
12665 /* their neighbors, then to their neighbors' neighbors. */
12666 traversalinit(&m->viri);
12667 virusloop = (triangle **) traverse(&m->viri);
12668 while (virusloop != (triangle **) NULL) {
12669 testtri.tri = *virusloop;
12670 /* A triangle is marked as infected by messing with one of its pointers */
12671 /* to subsegments, setting it to an illegal value. Hence, we have to */
12672 /* temporarily uninfect this triangle so that we can examine its */
12673 /* adjacent subsegments. */
12674 uninfect(testtri);
12675 if (b->verbose > 2) {
12676 /* Assign the triangle an orientation for convenience in */
12677 /* checking its vertices. */
12678 testtri.orient = 0;
12679 org(testtri, deadorg);
12680 dest(testtri, deaddest);
12681 apex(testtri, deadapex);
12682 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12683 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12684 deadapex[0], deadapex[1]);
12685 }
12686 /* Check each of the triangle's three neighbors. */
12687 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12688 /* Find the neighbor. */
12689 sym(testtri, neighbor);
12690 /* Check for a subsegment between the triangle and its neighbor. */
12691 tspivot(testtri, neighborsubseg);
12692 /* Check if the neighbor is nonexistent or already infected. */
12693 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12694 if (neighborsubseg.ss != m->dummysub) {
12695 /* There is a subsegment separating the triangle from its */
12696 /* neighbor, but both triangles are dying, so the subsegment */
12697 /* dies too. */
12698 subsegdealloc(m, neighborsubseg.ss);
12699 if (neighbor.tri != m->dummytri) {
12700 /* Make sure the subsegment doesn't get deallocated again */
12701 /* later when the infected neighbor is visited. */
12702 uninfect(neighbor);
12703 tsdissolve(neighbor);
12704 infect(neighbor);
12705 }
12706 }
12707 } else { /* The neighbor exists and is not infected. */
12708 if (neighborsubseg.ss == m->dummysub) {
12709 /* There is no subsegment protecting the neighbor, so */
12710 /* the neighbor becomes infected. */
12711 if (b->verbose > 2) {
12712 org(neighbor, deadorg);
12713 dest(neighbor, deaddest);
12714 apex(neighbor, deadapex);
12715 printf(
12716 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12717 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12718 deadapex[0], deadapex[1]);
12719 }
12720 infect(neighbor);
12721 /* Ensure that the neighbor's neighbors will be infected. */
12722 deadtriangle = (triangle **) poolalloc(&m->viri);
12723 *deadtriangle = neighbor.tri;
12724 } else { /* The neighbor is protected by a subsegment. */
12725 /* Remove this triangle from the subsegment. */
12726 stdissolve(neighborsubseg);
12727 /* The subsegment becomes a boundary. Set markers accordingly. */
12728 if (mark(neighborsubseg) == 0) {
12729 setmark(neighborsubseg, 1);
12730 }
12731 org(neighbor, norg);
12732 dest(neighbor, ndest);
12733 if (vertexmark(norg) == 0) {
12734 setvertexmark(norg, 1);
12735 }
12736 if (vertexmark(ndest) == 0) {
12737 setvertexmark(ndest, 1);
12738 }
12739 }
12740 }
12741 }
12742 /* Remark the triangle as infected, so it doesn't get added to the */
12743 /* virus pool again. */
12744 infect(testtri);
12745 virusloop = (triangle **) traverse(&m->viri);
12746 }
12747
12748 if (b->verbose) {
12749 printf(" Deleting marked triangles.\n");
12750 }
12751
12752 traversalinit(&m->viri);
12753 virusloop = (triangle **) traverse(&m->viri);
12754 while (virusloop != (triangle **) NULL) {
12755 testtri.tri = *virusloop;
12756
12757 /* Check each of the three corners of the triangle for elimination. */
12758 /* This is done by walking around each vertex, checking if it is */
12759 /* still connected to at least one live triangle. */
12760 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12761 org(testtri, testvertex);
12762 /* Check if the vertex has already been tested. */
12763 if (testvertex != (vertex) NULL) {
12764 killorg = 1;
12765 /* Mark the corner of the triangle as having been tested. */
12766 setorg(testtri, NULL);
12767 /* Walk counterclockwise about the vertex. */
12768 onext(testtri, neighbor);
12769 /* Stop upon reaching a boundary or the starting triangle. */
12770 while ((neighbor.tri != m->dummytri) &&
12771 (!otriequal(neighbor, testtri))) {
12772 if (infected(neighbor)) {
12773 /* Mark the corner of this triangle as having been tested. */
12774 setorg(neighbor, NULL);
12775 } else {
12776 /* A live triangle. The vertex survives. */
12777 killorg = 0;
12778 }
12779 /* Walk counterclockwise about the vertex. */
12780 onextself(neighbor);
12781 }
12782 /* If we reached a boundary, we must walk clockwise as well. */
12783 if (neighbor.tri == m->dummytri) {
12784 /* Walk clockwise about the vertex. */
12785 oprev(testtri, neighbor);
12786 /* Stop upon reaching a boundary. */
12787 while (neighbor.tri != m->dummytri) {
12788 if (infected(neighbor)) {
12789 /* Mark the corner of this triangle as having been tested. */
12790 setorg(neighbor, NULL);
12791 } else {
12792 /* A live triangle. The vertex survives. */
12793 killorg = 0;
12794 }
12795 /* Walk clockwise about the vertex. */
12796 oprevself(neighbor);
12797 }
12798 }
12799 if (killorg) {
12800 if (b->verbose > 1) {
12801 printf(" Deleting vertex (%.12g, %.12g)\n",
12802 testvertex[0], testvertex[1]);
12803 }
12804 setvertextype(testvertex, UNDEADVERTEX);
12805 m->undeads++;
12806 }
12807 }
12808 }
12809
12810 /* Record changes in the number of boundary edges, and disconnect */
12811 /* dead triangles from their neighbors. */
12812 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12813 sym(testtri, neighbor);
12814 if (neighbor.tri == m->dummytri) {
12815 /* There is no neighboring triangle on this edge, so this edge */
12816 /* is a boundary edge. This triangle is being deleted, so this */
12817 /* boundary edge is deleted. */
12818 m->hullsize--;
12819 } else {
12820 /* Disconnect the triangle from its neighbor. */
12821 dissolve(neighbor);
12822 /* There is a neighboring triangle on this edge, so this edge */
12823 /* becomes a boundary edge when this triangle is deleted. */
12824 m->hullsize++;
12825 }
12826 }
12827 /* Return the dead triangle to the pool of triangles. */
12828 triangledealloc(m, testtri.tri);
12829 virusloop = (triangle **) traverse(&m->viri);
12830 }
12831 /* Empty the virus pool. */
12832 poolrestart(&m->viri);
12833}
12834
12835/*****************************************************************************/
12836/* */
12837/* regionplague() Spread regional attributes and/or area constraints */
12838/* (from a .poly file) throughout the mesh. */
12839/* */
12840/* This procedure operates in two phases. The first phase spreads an */
12841/* attribute and/or an area constraint through a (segment-bounded) region. */
12842/* The triangles are marked to ensure that each triangle is added to the */
12843/* virus pool only once, so the procedure will terminate. */
12844/* */
12845/* The second phase uninfects all infected triangles, returning them to */
12846/* normal. */
12847/* */
12848/*****************************************************************************/
12849
12850#ifdef ANSI_DECLARATORS
12851void regionplague(struct mesh *m, struct behavior *b,
12852 REAL attribute, REAL area)
12853#else /* not ANSI_DECLARATORS */
12854void regionplague(m, b, attribute, area)
12855struct mesh *m;
12856struct behavior *b;
12857REAL attribute;
12858REAL area;
12859#endif /* not ANSI_DECLARATORS */
12860
12861{
12862 struct otri testtri;
12863 struct otri neighbor;
12864 triangle **virusloop;
12865 triangle **regiontri;
12866 struct osub neighborsubseg;
12867 vertex regionorg, regiondest, regionapex;
12868 triangle ptr; /* Temporary variable used by sym() and onext(). */
12869 subseg sptr; /* Temporary variable used by tspivot(). */
12870
12871 if (b->verbose > 1) {
12872 printf(" Marking neighbors of marked triangles.\n");
12873 }
12874 /* Loop through all the infected triangles, spreading the attribute */
12875 /* and/or area constraint to their neighbors, then to their neighbors' */
12876 /* neighbors. */
12877 traversalinit(&m->viri);
12878 virusloop = (triangle **) traverse(&m->viri);
12879 while (virusloop != (triangle **) NULL) {
12880 testtri.tri = *virusloop;
12881 /* A triangle is marked as infected by messing with one of its pointers */
12882 /* to subsegments, setting it to an illegal value. Hence, we have to */
12883 /* temporarily uninfect this triangle so that we can examine its */
12884 /* adjacent subsegments. */
12885 uninfect(testtri);
12886 if (b->regionattrib) {
12887 /* Set an attribute. */
12888 setelemattribute(testtri, m->eextras, attribute);
12889 }
12890 if (b->vararea) {
12891 /* Set an area constraint. */
12892 setareabound(testtri, area);
12893 }
12894 if (b->verbose > 2) {
12895 /* Assign the triangle an orientation for convenience in */
12896 /* checking its vertices. */
12897 testtri.orient = 0;
12898 org(testtri, regionorg);
12899 dest(testtri, regiondest);
12900 apex(testtri, regionapex);
12901 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12902 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12903 regionapex[0], regionapex[1]);
12904 }
12905 /* Check each of the triangle's three neighbors. */
12906 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12907 /* Find the neighbor. */
12908 sym(testtri, neighbor);
12909 /* Check for a subsegment between the triangle and its neighbor. */
12910 tspivot(testtri, neighborsubseg);
12911 /* Make sure the neighbor exists, is not already infected, and */
12912 /* isn't protected by a subsegment. */
12913 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12914 && (neighborsubseg.ss == m->dummysub)) {
12915 if (b->verbose > 2) {
12916 org(neighbor, regionorg);
12917 dest(neighbor, regiondest);
12918 apex(neighbor, regionapex);
12919 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12920 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12921 regionapex[0], regionapex[1]);
12922 }
12923 /* Infect the neighbor. */
12924 infect(neighbor);
12925 /* Ensure that the neighbor's neighbors will be infected. */
12926 regiontri = (triangle **) poolalloc(&m->viri);
12927 *regiontri = neighbor.tri;
12928 }
12929 }
12930 /* Remark the triangle as infected, so it doesn't get added to the */
12931 /* virus pool again. */
12932 infect(testtri);
12933 virusloop = (triangle **) traverse(&m->viri);
12934 }
12935
12936 /* Uninfect all triangles. */
12937 if (b->verbose > 1) {
12938 printf(" Unmarking marked triangles.\n");
12939 }
12940 traversalinit(&m->viri);
12941 virusloop = (triangle **) traverse(&m->viri);
12942 while (virusloop != (triangle **) NULL) {
12943 testtri.tri = *virusloop;
12944 uninfect(testtri);
12945 virusloop = (triangle **) traverse(&m->viri);
12946 }
12947 /* Empty the virus pool. */
12948 poolrestart(&m->viri);
12949}
12950
12951/*****************************************************************************/
12952/* */
12953/* carveholes() Find the holes and infect them. Find the area */
12954/* constraints and infect them. Infect the convex hull. */
12955/* Spread the infection and kill triangles. Spread the */
12956/* area constraints. */
12957/* */
12958/* This routine mainly calls other routines to carry out all these */
12959/* functions. */
12960/* */
12961/*****************************************************************************/
12962
12963#ifdef ANSI_DECLARATORS
12964void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12965 REAL *regionlist, int regions)
12966#else /* not ANSI_DECLARATORS */
12967void carveholes(m, b, holelist, holes, regionlist, regions)
12968struct mesh *m;
12969struct behavior *b;
12970REAL *holelist;
12971int holes;
12972REAL *regionlist;
12973int regions;
12974#endif /* not ANSI_DECLARATORS */
12975
12976{
12977 struct otri searchtri;
12978 struct otri triangleloop;
12979 struct otri *regiontris;
12980 triangle **holetri;
12981 triangle **regiontri;
12982 vertex searchorg, searchdest;
12983 enum locateresult intersect;
12984 int i;
12985 triangle ptr; /* Temporary variable used by sym(). */
12986
12987 if (!(b->quiet || (b->noholes && b->convex))) {
12988 printf("Removing unwanted triangles.\n");
12989 if (b->verbose && (holes > 0)) {
12990 printf(" Marking holes for elimination.\n");
12991 }
12992 }
12993
12994 if (regions > 0) {
12995 /* Allocate storage for the triangles in which region points fall. */
12996 regiontris = (struct otri *) trimalloc(regions *
12997 (int) sizeof(struct otri));
12998 } else {
12999 regiontris = (struct otri *) NULL;
13000 }
13001
13002 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13003 /* Initialize a pool of viri to be used for holes, concavities, */
13004 /* regional attributes, and/or regional area constraints. */
13005 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13006 }
13007
13008 if (!b->convex) {
13009 /* Mark as infected any unprotected triangles on the boundary. */
13010 /* This is one way by which concavities are created. */
13011 infecthull(m, b);
13012 }
13013
13014 if ((holes > 0) && !b->noholes) {
13015 /* Infect each triangle in which a hole lies. */
13016 for (i = 0; i < 2 * holes; i += 2) {
13017 /* Ignore holes that aren't within the bounds of the mesh. */
13018 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13019 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13020 /* Start searching from some triangle on the outer boundary. */
13021 searchtri.tri = m->dummytri;
13022 searchtri.orient = 0;
13023 symself(searchtri);
13024 /* Ensure that the hole is to the left of this boundary edge; */
13025 /* otherwise, locate() will falsely report that the hole */
13026 /* falls within the starting triangle. */
13027 org(searchtri, searchorg);
13028 dest(searchtri, searchdest);
13029 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13030 0.0) {
13031 /* Find a triangle that contains the hole. */
13032 intersect = locate(m, b, &holelist[i], &searchtri);
13033 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13034 /* Infect the triangle. This is done by marking the triangle */
13035 /* as infected and including the triangle in the virus pool. */
13036 infect(searchtri);
13037 holetri = (triangle **) poolalloc(&m->viri);
13038 *holetri = searchtri.tri;
13039 }
13040 }
13041 }
13042 }
13043 }
13044
13045 /* Now, we have to find all the regions BEFORE we carve the holes, because */
13046 /* locate() won't work when the triangulation is no longer convex. */
13047 /* (Incidentally, this is the reason why regional attributes and area */
13048 /* constraints can't be used when refining a preexisting mesh, which */
13049 /* might not be convex; they can only be used with a freshly */
13050 /* triangulated PSLG.) */
13051 if (regions > 0) {
13052 /* Find the starting triangle for each region. */
13053 for (i = 0; i < regions; i++) {
13054 regiontris[i].tri = m->dummytri;
13055 /* Ignore region points that aren't within the bounds of the mesh. */
13056 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13057 (regionlist[4 * i + 1] >= m->ymin) &&
13058 (regionlist[4 * i + 1] <= m->ymax)) {
13059 /* Start searching from some triangle on the outer boundary. */
13060 searchtri.tri = m->dummytri;
13061 searchtri.orient = 0;
13062 symself(searchtri);
13063 /* Ensure that the region point is to the left of this boundary */
13064 /* edge; otherwise, locate() will falsely report that the */
13065 /* region point falls within the starting triangle. */
13066 org(searchtri, searchorg);
13067 dest(searchtri, searchdest);
13068 if (counterclockwise(m, b, searchorg, searchdest, &regionlist[4 * i]) >
13069 0.0) {
13070 /* Find a triangle that contains the region point. */
13071 intersect = locate(m, b, &regionlist[4 * i], &searchtri);
13072 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13073 /* Record the triangle for processing after the */
13074 /* holes have been carved. */
13075 otricopy(searchtri, regiontris[i]);
13076 }
13077 }
13078 }
13079 }
13080 }
13081
13082 if (m->viri.items > 0) {
13083 /* Carve the holes and concavities. */
13084 plague(m, b);
13085 }
13086 /* The virus pool should be empty now. */
13087
13088 if (regions > 0) {
13089 if (!b->quiet) {
13090 if (b->regionattrib) {
13091 if (b->vararea) {
13092 printf("Spreading regional attributes and area constraints.\n");
13093 } else {
13094 printf("Spreading regional attributes.\n");
13095 }
13096 } else {
13097 printf("Spreading regional area constraints.\n");
13098 }
13099 }
13100 if (b->regionattrib && !b->refine) {
13101 /* Assign every triangle a regional attribute of zero. */
13102 traversalinit(&m->triangles);
13103 triangleloop.orient = 0;
13104 triangleloop.tri = triangletraverse(m);
13105 while (triangleloop.tri != (triangle *) NULL) {
13106 setelemattribute(triangleloop, m->eextras, 0.0);
13107 triangleloop.tri = triangletraverse(m);
13108 }
13109 }
13110 for (i = 0; i < regions; i++) {
13111 if (regiontris[i].tri != m->dummytri) {
13112 /* Make sure the triangle under consideration still exists. */
13113 /* It may have been eaten by the virus. */
13114 if (!deadtri(regiontris[i].tri)) {
13115 /* Put one triangle in the virus pool. */
13116 infect(regiontris[i]);
13117 regiontri = (triangle **) poolalloc(&m->viri);
13118 *regiontri = regiontris[i].tri;
13119 /* Apply one region's attribute and/or area constraint. */
13120 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13121 /* The virus pool should be empty now. */
13122 }
13123 }
13124 }
13125 if (b->regionattrib && !b->refine) {
13126 /* Note the fact that each triangle has an additional attribute. */
13127 m->eextras++;
13128 }
13129 }
13130
13131 /* Free up memory. */
13132 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13133 pooldeinit(&m->viri);
13134 }
13135 if (regions > 0) {
13136 trifree((VOID *) regiontris);
13137 }
13138}
13139
13140/** **/
13141/** **/
13142/********* Carving out holes and concavities ends here *********/
13143
13144/********* Mesh quality maintenance begins here *********/
13145/** **/
13146/** **/
13147
13148/*****************************************************************************/
13149/* */
13150/* tallyencs() Traverse the entire list of subsegments, and check each */
13151/* to see if it is encroached. If so, add it to the list. */
13152/* */
13153/*****************************************************************************/
13154
13155#ifndef CDT_ONLY
13156
13157#ifdef ANSI_DECLARATORS
13158void tallyencs(struct mesh *m, struct behavior *b)
13159#else /* not ANSI_DECLARATORS */
13160void tallyencs(m, b)
13161struct mesh *m;
13162struct behavior *b;
13163#endif /* not ANSI_DECLARATORS */
13164
13165{
13166 struct osub subsegloop;
13167 int dummy;
13168
13169 traversalinit(&m->subsegs);
13170 subsegloop.ssorient = 0;
13171 subsegloop.ss = subsegtraverse(m);
13172 while (subsegloop.ss != (subseg *) NULL) {
13173 /* If the segment is encroached, add it to the list. */
13174 dummy = checkseg4encroach(m, b, &subsegloop);
13175 subsegloop.ss = subsegtraverse(m);
13176 }
13177}
13178
13179#endif /* not CDT_ONLY */
13180
13181/*****************************************************************************/
13182/* */
13183/* precisionerror() Print an error message for precision problems. */
13184/* */
13185/*****************************************************************************/
13186
13187#ifndef CDT_ONLY
13188
13189void precisionerror()
13190{
13191 printf("Try increasing the area criterion and/or reducing the minimum\n");
13192 printf(" allowable angle so that tiny triangles are not created.\n");
13193#ifdef SINGLE
13194 printf("Alternatively, try recompiling me with double precision\n");
13195 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13196 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13197#endif /* SINGLE */
13198}
13199
13200#endif /* not CDT_ONLY */
13201
13202/*****************************************************************************/
13203/* */
13204/* splitencsegs() Split all the encroached subsegments. */
13205/* */
13206/* Each encroached subsegment is repaired by splitting it - inserting a */
13207/* vertex at or near its midpoint. Newly inserted vertices may encroach */
13208/* upon other subsegments; these are also repaired. */
13209/* */
13210/* `triflaws' is a flag that specifies whether one should take note of new */
13211/* bad triangles that result from inserting vertices to repair encroached */
13212/* subsegments. */
13213/* */
13214/*****************************************************************************/
13215
13216#ifndef CDT_ONLY
13217
13218#ifdef ANSI_DECLARATORS
13219void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13220#else /* not ANSI_DECLARATORS */
13221void splitencsegs(m, b, triflaws)
13222struct mesh *m;
13223struct behavior *b;
13224int triflaws;
13225#endif /* not ANSI_DECLARATORS */
13226
13227{
13228 struct otri enctri;
13229 struct otri testtri;
13230 struct osub testsh;
13231 struct osub currentenc;
13232 struct badsubseg *encloop;
13233 vertex eorg, edest, eapex;
13234 vertex newvertex;
13235 enum insertvertexresult success;
13236 REAL segmentlength, nearestpoweroftwo;
13237 REAL split;
13238 REAL multiplier, divisor;
13239 int acuteorg, acuteorg2, acutedest, acutedest2;
13240 int dummy;
13241 int i;
13242 triangle ptr; /* Temporary variable used by stpivot(). */
13243 subseg sptr; /* Temporary variable used by snext(). */
13244
13245 /* Note that steinerleft == -1 if an unlimited number */
13246 /* of Steiner points is allowed. */
13247 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13248 traversalinit(&m->badsubsegs);
13249 encloop = badsubsegtraverse(m);
13250 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13251 sdecode(encloop->encsubseg, currentenc);
13252 sorg(currentenc, eorg);
13253 sdest(currentenc, edest);
13254 /* Make sure that this segment is still the same segment it was */
13255 /* when it was determined to be encroached. If the segment was */
13256 /* enqueued multiple times (because several newly inserted */
13257 /* vertices encroached it), it may have already been split. */
13258 if (!deadsubseg(currentenc.ss) &&
13259 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13260 /* To decide where to split a segment, we need to know if the */
13261 /* segment shares an endpoint with an adjacent segment. */
13262 /* The concern is that, if we simply split every encroached */
13263 /* segment in its center, two adjacent segments with a small */
13264 /* angle between them might lead to an infinite loop; each */
13265 /* vertex added to split one segment will encroach upon the */
13266 /* other segment, which must then be split with a vertex that */
13267 /* will encroach upon the first segment, and so on forever. */
13268 /* To avoid this, imagine a set of concentric circles, whose */
13269 /* radii are powers of two, about each segment endpoint. */
13270 /* These concentric circles determine where the segment is */
13271 /* split. (If both endpoints are shared with adjacent */
13272 /* segments, split the segment in the middle, and apply the */
13273 /* concentric circles for later splittings.) */
13274
13275 /* Is the origin shared with another segment? */
13276 stpivot(currentenc, enctri);
13277 lnext(enctri, testtri);
13278 tspivot(testtri, testsh);
13279 acuteorg = testsh.ss != m->dummysub;
13280 /* Is the destination shared with another segment? */
13281 lnextself(testtri);
13282 tspivot(testtri, testsh);
13283 acutedest = testsh.ss != m->dummysub;
13284
13285 /* If we're using Chew's algorithm (rather than Ruppert's) */
13286 /* to define encroachment, delete free vertices from the */
13287 /* subsegment's diametral circle. */
13288 if (!b->conformdel && !acuteorg && !acutedest) {
13289 apex(enctri, eapex);
13290 while ((vertextype(eapex) == FREEVERTEX) &&
13291 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13292 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13293 deletevertex(m, b, &testtri);
13294 stpivot(currentenc, enctri);
13295 apex(enctri, eapex);
13296 lprev(enctri, testtri);
13297 }
13298 }
13299
13300 /* Now, check the other side of the segment, if there's a triangle */
13301 /* there. */
13302 sym(enctri, testtri);
13303 if (testtri.tri != m->dummytri) {
13304 /* Is the destination shared with another segment? */
13305 lnextself(testtri);
13306 tspivot(testtri, testsh);
13307 acutedest2 = testsh.ss != m->dummysub;
13308 acutedest = acutedest || acutedest2;
13309 /* Is the origin shared with another segment? */
13310 lnextself(testtri);
13311 tspivot(testtri, testsh);
13312 acuteorg2 = testsh.ss != m->dummysub;
13313 acuteorg = acuteorg || acuteorg2;
13314
13315 /* Delete free vertices from the subsegment's diametral circle. */
13316 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13317 org(testtri, eapex);
13318 while ((vertextype(eapex) == FREEVERTEX) &&
13319 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13320 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13321 deletevertex(m, b, &testtri);
13322 sym(enctri, testtri);
13323 apex(testtri, eapex);
13324 lprevself(testtri);
13325 }
13326 }
13327 }
13328
13329 /* Use the concentric circles if exactly one endpoint is shared */
13330 /* with another adjacent segment. */
13331 if (acuteorg || acutedest) {
13332 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13333 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13334 /* Find the power of two that most evenly splits the segment. */
13335 /* The worst case is a 2:1 ratio between subsegment lengths. */
13336 nearestpoweroftwo = 1.0;
13337 while (segmentlength > 3.0 * nearestpoweroftwo) {
13338 nearestpoweroftwo *= 2.0;
13339 }
13340 while (segmentlength < 1.5 * nearestpoweroftwo) {
13341 nearestpoweroftwo *= 0.5;
13342 }
13343 /* Where do we split the segment? */
13344 split = nearestpoweroftwo / segmentlength;
13345 if (acutedest) {
13346 split = 1.0 - split;
13347 }
13348 } else {
13349 /* If we're not worried about adjacent segments, split */
13350 /* this segment in the middle. */
13351 split = 0.5;
13352 }
13353
13354 /* Create the new vertex. */
13355 newvertex = (vertex) poolalloc(&m->vertices);
13356 /* Interpolate its coordinate and attributes. */
13357 for (i = 0; i < 2 + m->nextras; i++) {
13358 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13359 }
13360
13361 if (!b->noexact) {
13362 /* Roundoff in the above calculation may yield a `newvertex' */
13363 /* that is not precisely collinear with `eorg' and `edest'. */
13364 /* Improve collinearity by one step of iterative refinement. */
13365 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13366 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13367 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13368 if ((multiplier != 0.0) && (divisor != 0.0)) {
13369 multiplier = multiplier / divisor;
13370 /* Watch out for NANs. */
13371 if (multiplier == multiplier) {
13372 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13373 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13374 }
13375 }
13376 }
13377
13378 setvertexmark(newvertex, mark(currentenc));
13379 setvertextype(newvertex, SEGMENTVERTEX);
13380 if (b->verbose > 1) {
13381 printf(
13382 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13383 eorg[0], eorg[1], edest[0], edest[1],
13384 newvertex[0], newvertex[1]);
13385 }
13386 /* Check whether the new vertex lies on an endpoint. */
13387 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13388 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13389 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13390 newvertex[0], newvertex[1]);
13391 printf("I attempted to split a segment to a smaller size than\n");
13392 printf(" can be accommodated by the finite precision of\n");
13393 printf(" floating point arithmetic.\n");
13394 precisionerror();
13395 triexit(1);
13396 }
13397 /* Insert the splitting vertex. This should always succeed. */
13398 success = insertvertex(m, b, newvertex, &enctri, &currentenc,
13399 1, triflaws);
13400 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13401 printf("Internal error in splitencsegs():\n");
13402 printf(" Failure to split a segment.\n");
13403 internalerror();
13404 }
13405 if (m->steinerleft > 0) {
13406 m->steinerleft--;
13407 }
13408 /* Check the two new subsegments to see if they're encroached. */
13409 dummy = checkseg4encroach(m, b, &currentenc);
13410 snextself(currentenc);
13411 dummy = checkseg4encroach(m, b, &currentenc);
13412 }
13413
13414 badsubsegdealloc(m, encloop);
13415 encloop = badsubsegtraverse(m);
13416 }
13417 }
13418}
13419
13420#endif /* not CDT_ONLY */
13421
13422/*****************************************************************************/
13423/* */
13424/* tallyfaces() Test every triangle in the mesh for quality measures. */
13425/* */
13426/*****************************************************************************/
13427
13428#ifndef CDT_ONLY
13429
13430#ifdef ANSI_DECLARATORS
13431void tallyfaces(struct mesh *m, struct behavior *b)
13432#else /* not ANSI_DECLARATORS */
13433void tallyfaces(m, b)
13434struct mesh *m;
13435struct behavior *b;
13436#endif /* not ANSI_DECLARATORS */
13437
13438{
13439 struct otri triangleloop;
13440
13441 if (b->verbose) {
13442 printf(" Making a list of bad triangles.\n");
13443 }
13444 traversalinit(&m->triangles);
13445 triangleloop.orient = 0;
13446 triangleloop.tri = triangletraverse(m);
13447 while (triangleloop.tri != (triangle *) NULL) {
13448 /* If the triangle is bad, enqueue it. */
13449 testtriangle(m, b, &triangleloop);
13450 triangleloop.tri = triangletraverse(m);
13451 }
13452}
13453
13454#endif /* not CDT_ONLY */
13455
13456/*****************************************************************************/
13457/* */
13458/* splittriangle() Inserts a vertex at the circumcenter of a triangle. */
13459/* Deletes the newly inserted vertex if it encroaches */
13460/* upon a segment. */
13461/* */
13462/*****************************************************************************/
13463
13464#ifndef CDT_ONLY
13465
13466#ifdef ANSI_DECLARATORS
13467void splittriangle(struct mesh *m, struct behavior *b,
13468 struct badtriang *badtri)
13469#else /* not ANSI_DECLARATORS */
13470void splittriangle(m, b, badtri)
13471struct mesh *m;
13472struct behavior *b;
13473struct badtriang *badtri;
13474#endif /* not ANSI_DECLARATORS */
13475
13476{
13477 struct otri badotri;
13478 vertex borg, bdest, bapex;
13479 vertex newvertex;
13480 REAL xi, eta;
13481 enum insertvertexresult success;
13482 int errorflag;
13483 int i;
13484
13485 decode(badtri->poortri, badotri);
13486 org(badotri, borg);
13487 dest(badotri, bdest);
13488 apex(badotri, bapex);
13489 /* Make sure that this triangle is still the same triangle it was */
13490 /* when it was tested and determined to be of bad quality. */
13491 /* Subsequent transformations may have made it a different triangle. */
13492 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13493 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13494 if (b->verbose > 1) {
13495 printf(" Splitting this triangle at its circumcenter:\n");
13496 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13497 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13498 }
13499
13500 errorflag = 0;
13501 /* Create a new vertex at the triangle's circumcenter. */
13502 newvertex = (vertex) poolalloc(&m->vertices);
13503 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13504
13505 /* Check whether the new vertex lies on a triangle vertex. */
13506 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13507 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13508 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13509 if (!b->quiet) {
13510 printf(
13511 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13512 newvertex[0], newvertex[1]);
13513 errorflag = 1;
13514 }
13515 vertexdealloc(m, newvertex);
13516 } else {
13517 for (i = 2; i < 2 + m->nextras; i++) {
13518 /* Interpolate the vertex attributes at the circumcenter. */
13519 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13520 + eta * (bapex[i] - borg[i]);
13521 }
13522 /* The new vertex must be in the interior, and therefore is a */
13523 /* free vertex with a marker of zero. */
13524 setvertexmark(newvertex, 0);
13525 setvertextype(newvertex, FREEVERTEX);
13526
13527 /* Ensure that the handle `badotri' does not represent the longest */
13528 /* edge of the triangle. This ensures that the circumcenter must */
13529 /* fall to the left of this edge, so point location will work. */
13530 /* (If the angle org-apex-dest exceeds 90 degrees, then the */
13531 /* circumcenter lies outside the org-dest edge, and eta is */
13532 /* negative. Roundoff error might prevent eta from being */
13533 /* negative when it should be, so I test eta against xi.) */
13534 if (eta < xi) {
13535 lprevself(badotri);
13536 }
13537
13538 /* Insert the circumcenter, searching from the edge of the triangle, */
13539 /* and maintain the Delaunay property of the triangulation. */
13540 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13541 1, 1);
13542 if (success == SUCCESSFULVERTEX) {
13543 if (m->steinerleft > 0) {
13544 m->steinerleft--;
13545 }
13546 } else if (success == ENCROACHINGVERTEX) {
13547 /* If the newly inserted vertex encroaches upon a subsegment, */
13548 /* delete the new vertex. */
13549 undovertex(m, b);
13550 if (b->verbose > 1) {
13551 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13552 }
13553 vertexdealloc(m, newvertex);
13554 } else if (success == VIOLATINGVERTEX) {
13555 /* Failed to insert the new vertex, but some subsegment was */
13556 /* marked as being encroached. */
13557 vertexdealloc(m, newvertex);
13558 } else { /* success == DUPLICATEVERTEX */
13559 /* Couldn't insert the new vertex because a vertex is already there. */
13560 if (!b->quiet) {
13561 printf(
13562 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13563 newvertex[0], newvertex[1]);
13564 errorflag = 1;
13565 }
13566 vertexdealloc(m, newvertex);
13567 }
13568 }
13569 if (errorflag) {
13570 if (b->verbose) {
13571 printf(" The new vertex is at the circumcenter of triangle\n");
13572 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13573 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13574 }
13575 printf("This probably means that I am trying to refine triangles\n");
13576 printf(" to a smaller size than can be accommodated by the finite\n");
13577 printf(" precision of floating point arithmetic. (You can be\n");
13578 printf(" sure of this if I fail to terminate.)\n");
13579 precisionerror();
13580 }
13581 }
13582}
13583
13584#endif /* not CDT_ONLY */
13585
13586/*****************************************************************************/
13587/* */
13588/* enforcequality() Remove all the encroached subsegments and bad */
13589/* triangles from the triangulation. */
13590/* */
13591/*****************************************************************************/
13592
13593#ifndef CDT_ONLY
13594
13595#ifdef ANSI_DECLARATORS
13596void enforcequality(struct mesh *m, struct behavior *b)
13597#else /* not ANSI_DECLARATORS */
13598void enforcequality(m, b)
13599struct mesh *m;
13600struct behavior *b;
13601#endif /* not ANSI_DECLARATORS */
13602
13603{
13604 struct badtriang *badtri;
13605 int i;
13606
13607 if (!b->quiet) {
13608 printf("Adding Steiner points to enforce quality.\n");
13609 }
13610 /* Initialize the pool of encroached subsegments. */
13611 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13613 if (b->verbose) {
13614 printf(" Looking for encroached subsegments.\n");
13615 }
13616 /* Test all segments to see if they're encroached. */
13617 tallyencs(m, b);
13618 if (b->verbose && (m->badsubsegs.items > 0)) {
13619 printf(" Splitting encroached subsegments.\n");
13620 }
13621 /* Fix encroached subsegments without noting bad triangles. */
13622 splitencsegs(m, b, 0);
13623 /* At this point, if we haven't run out of Steiner points, the */
13624 /* triangulation should be (conforming) Delaunay. */
13625
13626 /* Next, we worry about enforcing triangle quality. */
13627 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13628 /* Initialize the pool of bad triangles. */
13629 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13630 BADTRIPERBLOCK, 0);
13631 /* Initialize the queues of bad triangles. */
13632 for (i = 0; i < 4096; i++) {
13633 m->queuefront[i] = (struct badtriang *) NULL;
13634 }
13635 m->firstnonemptyq = -1;
13636 /* Test all triangles to see if they're bad. */
13637 tallyfaces(m, b);
13638 /* Initialize the pool of recently flipped triangles. */
13639 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13641 m->checkquality = 1;
13642 if (b->verbose) {
13643 printf(" Splitting bad triangles.\n");
13644 }
13645 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13646 /* Fix one bad triangle by inserting a vertex at its circumcenter. */
13647 badtri = dequeuebadtriang(m);
13648 splittriangle(m, b, badtri);
13649 if (m->badsubsegs.items > 0) {
13650 /* Put bad triangle back in queue for another try later. */
13651 enqueuebadtriang(m, b, badtri);
13652 /* Fix any encroached subsegments that resulted. */
13653 /* Record any new bad triangles that result. */
13654 splitencsegs(m, b, 1);
13655 } else {
13656 /* Return the bad triangle to the pool. */
13657 pooldealloc(&m->badtriangles, (VOID *) badtri);
13658 }
13659 }
13660 }
13661 /* At this point, if the "-D" switch was selected and we haven't run out */
13662 /* of Steiner points, the triangulation should be (conforming) Delaunay */
13663 /* and have no low-quality triangles. */
13664
13665 /* Might we have run out of Steiner points too soon? */
13666 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13667 (m->steinerleft == 0)) {
13668 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13669 if (m->badsubsegs.items == 1) {
13670 printf(" one encroached subsegment, and therefore might not be truly\n"
13671 );
13672 } else {
13673 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13674 , m->badsubsegs.items);
13675 }
13676 printf(" Delaunay. If the Delaunay property is important to you,\n");
13677 printf(" try increasing the number of Steiner points (controlled by\n");
13678 printf(" the -S switch) slightly and try again.\n\n");
13679 }
13680}
13681
13682#endif /* not CDT_ONLY */
13683
13684/** **/
13685/** **/
13686/********* Mesh quality maintenance ends here *********/
13687
13688/*****************************************************************************/
13689/* */
13690/* highorder() Create extra nodes for quadratic subparametric elements. */
13691/* */
13692/*****************************************************************************/
13693
13694#ifdef ANSI_DECLARATORS
13695void highorder(struct mesh *m, struct behavior *b)
13696#else /* not ANSI_DECLARATORS */
13697void highorder(m, b)
13698struct mesh *m;
13699struct behavior *b;
13700#endif /* not ANSI_DECLARATORS */
13701
13702{
13703 struct otri triangleloop, trisym;
13704 struct osub checkmark;
13705 vertex newvertex;
13706 vertex torg, tdest;
13707 int i;
13708 triangle ptr; /* Temporary variable used by sym(). */
13709 subseg sptr; /* Temporary variable used by tspivot(). */
13710
13711 if (!b->quiet) {
13712 printf("Adding vertices for second-order triangles.\n");
13713 }
13714 /* The following line ensures that dead items in the pool of nodes */
13715 /* cannot be allocated for the extra nodes associated with high */
13716 /* order elements. This ensures that the primary nodes (at the */
13717 /* corners of elements) will occur earlier in the output files, and */
13718 /* have lower indices, than the extra nodes. */
13719 m->vertices.deaditemstack = (VOID *) NULL;
13720
13721 traversalinit(&m->triangles);
13722 triangleloop.tri = triangletraverse(m);
13723 /* To loop over the set of edges, loop over all triangles, and look at */
13724 /* the three edges of each triangle. If there isn't another triangle */
13725 /* adjacent to the edge, operate on the edge. If there is another */
13726 /* adjacent triangle, operate on the edge only if the current triangle */
13727 /* has a smaller pointer than its neighbor. This way, each edge is */
13728 /* considered only once. */
13729 while (triangleloop.tri != (triangle *) NULL) {
13730 for (triangleloop.orient = 0; triangleloop.orient < 3;
13731 triangleloop.orient++) {
13732 sym(triangleloop, trisym);
13733 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13734 org(triangleloop, torg);
13735 dest(triangleloop, tdest);
13736 /* Create a new node in the middle of the edge. Interpolate */
13737 /* its attributes. */
13738 newvertex = (vertex) poolalloc(&m->vertices);
13739 for (i = 0; i < 2 + m->nextras; i++) {
13740 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13741 }
13742 /* Set the new node's marker to zero or one, depending on */
13743 /* whether it lies on a boundary. */
13744 setvertexmark(newvertex, trisym.tri == m->dummytri);
13745 setvertextype(newvertex,
13746 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13747 if (b->usesegments) {
13748 tspivot(triangleloop, checkmark);
13749 /* If this edge is a segment, transfer the marker to the new node. */
13750 if (checkmark.ss != m->dummysub) {
13751 setvertexmark(newvertex, mark(checkmark));
13752 setvertextype(newvertex, SEGMENTVERTEX);
13753 }
13754 }
13755 if (b->verbose > 1) {
13756 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13757 }
13758 /* Record the new node in the (one or two) adjacent elements. */
13759 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13760 (triangle) newvertex;
13761 if (trisym.tri != m->dummytri) {
13762 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13763 }
13764 }
13765 }
13766 triangleloop.tri = triangletraverse(m);
13767 }
13768}
13769
13770/********* File I/O routines begin here *********/
13771/** **/
13772/** **/
13773
13774/*****************************************************************************/
13775/* */
13776/* readline() Read a nonempty line from a file. */
13777/* */
13778/* A line is considered "nonempty" if it contains something that looks like */
13779/* a number. Comments (prefaced by `#') are ignored. */
13780/* */
13781/*****************************************************************************/
13782
13783#ifndef TRILIBRARY
13784
13785#ifdef ANSI_DECLARATORS
13786char *readline(char *string, FILE *infile, char *infilename)
13787#else /* not ANSI_DECLARATORS */
13788char *readline(string, infile, infilename)
13789char *string;
13790FILE *infile;
13791char *infilename;
13792#endif /* not ANSI_DECLARATORS */
13793
13794{
13795 char *result;
13796
13797 /* Search for something that looks like a number. */
13798 do {
13799 result = fgets(string, INPUTLINESIZE, infile);
13800 if (result == (char *) NULL) {
13801 printf(" Error: Unexpected end of file in %s.\n", infilename);
13802 triexit(1);
13803 }
13804 /* Skip anything that doesn't look like a number, a comment, */
13805 /* or the end of a line. */
13806 while ((*result != '\0') && (*result != '#')
13807 && (*result != '.') && (*result != '+') && (*result != '-')
13808 && ((*result < '0') || (*result > '9'))) {
13809 result++;
13810 }
13811 /* If it's a comment or end of line, read another line and try again. */
13812 } while ((*result == '#') || (*result == '\0'));
13813 return result;
13814}
13815
13816#endif /* not TRILIBRARY */
13817
13818/*****************************************************************************/
13819/* */
13820/* findfield() Find the next field of a string. */
13821/* */
13822/* Jumps past the current field by searching for whitespace, then jumps */
13823/* past the whitespace to find the next field. */
13824/* */
13825/*****************************************************************************/
13826
13827#ifndef TRILIBRARY
13828
13829#ifdef ANSI_DECLARATORS
13830char *findfield(char *string)
13831#else /* not ANSI_DECLARATORS */
13832char *findfield(string)
13833char *string;
13834#endif /* not ANSI_DECLARATORS */
13835
13836{
13837 char *result;
13838
13839 result = string;
13840 /* Skip the current field. Stop upon reaching whitespace. */
13841 while ((*result != '\0') && (*result != '#')
13842 && (*result != ' ') && (*result != '\t')) {
13843 result++;
13844 }
13845 /* Now skip the whitespace and anything else that doesn't look like a */
13846 /* number, a comment, or the end of a line. */
13847 while ((*result != '\0') && (*result != '#')
13848 && (*result != '.') && (*result != '+') && (*result != '-')
13849 && ((*result < '0') || (*result > '9'))) {
13850 result++;
13851 }
13852 /* Check for a comment (prefixed with `#'). */
13853 if (*result == '#') {
13854 *result = '\0';
13855 }
13856 return result;
13857}
13858
13859#endif /* not TRILIBRARY */
13860
13861/*****************************************************************************/
13862/* */
13863/* readnodes() Read the vertices from a file, which may be a .node or */
13864/* .poly file. */
13865/* */
13866/*****************************************************************************/
13867
13868#ifndef TRILIBRARY
13869
13870#ifdef ANSI_DECLARATORS
13871void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13872 char *polyfilename, FILE **polyfile)
13873#else /* not ANSI_DECLARATORS */
13874void readnodes(m, b, nodefilename, polyfilename, polyfile)
13875struct mesh *m;
13876struct behavior *b;
13877char *nodefilename;
13878char *polyfilename;
13879FILE **polyfile;
13880#endif /* not ANSI_DECLARATORS */
13881
13882{
13883 FILE *infile;
13884 vertex vertexloop;
13885 char inputline[INPUTLINESIZE];
13886 char *stringptr;
13887 char *infilename;
13888 REAL x, y;
13889 int firstnode;
13890 int nodemarkers;
13891 int currentmarker;
13892 int i, j;
13893
13894 if (b->poly) {
13895 /* Read the vertices from a .poly file. */
13896 if (!b->quiet) {
13897 printf("Opening %s.\n", polyfilename);
13898 }
13899 *polyfile = fopen(polyfilename, "r");
13900 if (*polyfile == (FILE *) NULL) {
13901 printf(" Error: Cannot access file %s.\n", polyfilename);
13902 triexit(1);
13903 }
13904 /* Read number of vertices, number of dimensions, number of vertex */
13905 /* attributes, and number of boundary markers. */
13906 stringptr = readline(inputline, *polyfile, polyfilename);
13907 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13908 stringptr = findfield(stringptr);
13909 if (*stringptr == '\0') {
13910 m->mesh_dim = 2;
13911 } else {
13912 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13913 }
13914 stringptr = findfield(stringptr);
13915 if (*stringptr == '\0') {
13916 m->nextras = 0;
13917 } else {
13918 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13919 }
13920 stringptr = findfield(stringptr);
13921 if (*stringptr == '\0') {
13922 nodemarkers = 0;
13923 } else {
13924 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13925 }
13926 if (m->invertices > 0) {
13927 infile = *polyfile;
13928 infilename = polyfilename;
13929 m->readnodefile = 0;
13930 } else {
13931 /* If the .poly file claims there are zero vertices, that means that */
13932 /* the vertices should be read from a separate .node file. */
13933 m->readnodefile = 1;
13934 infilename = nodefilename;
13935 }
13936 } else {
13937 m->readnodefile = 1;
13938 infilename = nodefilename;
13939 *polyfile = (FILE *) NULL;
13940 }
13941
13942 if (m->readnodefile) {
13943 /* Read the vertices from a .node file. */
13944 if (!b->quiet) {
13945 printf("Opening %s.\n", nodefilename);
13946 }
13947 infile = fopen(nodefilename, "r");
13948 if (infile == (FILE *) NULL) {
13949 printf(" Error: Cannot access file %s.\n", nodefilename);
13950 triexit(1);
13951 }
13952 /* Read number of vertices, number of dimensions, number of vertex */
13953 /* attributes, and number of boundary markers. */
13954 stringptr = readline(inputline, infile, nodefilename);
13955 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13956 stringptr = findfield(stringptr);
13957 if (*stringptr == '\0') {
13958 m->mesh_dim = 2;
13959 } else {
13960 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13961 }
13962 stringptr = findfield(stringptr);
13963 if (*stringptr == '\0') {
13964 m->nextras = 0;
13965 } else {
13966 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13967 }
13968 stringptr = findfield(stringptr);
13969 if (*stringptr == '\0') {
13970 nodemarkers = 0;
13971 } else {
13972 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13973 }
13974 }
13975
13976 if (m->invertices < 3) {
13977 printf("Error: Input must have at least three input vertices.\n");
13978 triexit(1);
13979 }
13980 if (m->mesh_dim != 2) {
13981 printf("Error: Triangle only works with two-dimensional meshes.\n");
13982 triexit(1);
13983 }
13984 if (m->nextras == 0) {
13985 b->weighted = 0;
13986 }
13987
13989
13990 /* Read the vertices. */
13991 for (i = 0; i < m->invertices; i++) {
13992 vertexloop = (vertex) poolalloc(&m->vertices);
13993 stringptr = readline(inputline, infile, infilename);
13994 if (i == 0) {
13995 firstnode = (int) strtol(stringptr, &stringptr, 0);
13996 if ((firstnode == 0) || (firstnode == 1)) {
13997 b->firstnumber = firstnode;
13998 }
13999 }
14000 stringptr = findfield(stringptr);
14001 if (*stringptr == '\0') {
14002 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14003 triexit(1);
14004 }
14005 x = (REAL) strtod(stringptr, &stringptr);
14006 stringptr = findfield(stringptr);
14007 if (*stringptr == '\0') {
14008 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14009 triexit(1);
14010 }
14011 y = (REAL) strtod(stringptr, &stringptr);
14012 vertexloop[0] = x;
14013 vertexloop[1] = y;
14014 /* Read the vertex attributes. */
14015 for (j = 2; j < 2 + m->nextras; j++) {
14016 stringptr = findfield(stringptr);
14017 if (*stringptr == '\0') {
14018 vertexloop[j] = 0.0;
14019 } else {
14020 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14021 }
14022 }
14023 if (nodemarkers) {
14024 /* Read a vertex marker. */
14025 stringptr = findfield(stringptr);
14026 if (*stringptr == '\0') {
14027 setvertexmark(vertexloop, 0);
14028 } else {
14029 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14030 setvertexmark(vertexloop, currentmarker);
14031 }
14032 } else {
14033 /* If no markers are specified in the file, they default to zero. */
14034 setvertexmark(vertexloop, 0);
14035 }
14036 setvertextype(vertexloop, INPUTVERTEX);
14037 /* Determine the smallest and largest x and y coordinates. */
14038 if (i == 0) {
14039 m->xmin = m->xmax = x;
14040 m->ymin = m->ymax = y;
14041 } else {
14042 m->xmin = (x < m->xmin) ? x : m->xmin;
14043 m->xmax = (x > m->xmax) ? x : m->xmax;
14044 m->ymin = (y < m->ymin) ? y : m->ymin;
14045 m->ymax = (y > m->ymax) ? y : m->ymax;
14046 }
14047 }
14048 if (m->readnodefile) {
14049 fclose(infile);
14050 }
14051
14052 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14053 /* Delaunay algorithm. */
14054 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14055}
14056
14057#endif /* not TRILIBRARY */
14058
14059/*****************************************************************************/
14060/* */
14061/* transfernodes() Read the vertices from memory. */
14062/* */
14063/*****************************************************************************/
14064
14065#ifdef TRILIBRARY
14066
14067#ifdef ANSI_DECLARATORS
14068void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14069 REAL *pointattriblist, int *pointmarkerlist,
14070 int numberofpoints, int numberofpointattribs)
14071#else /* not ANSI_DECLARATORS */
14072void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14073 numberofpoints, numberofpointattribs)
14074struct mesh *m;
14075struct behavior *b;
14076REAL *pointlist;
14077REAL *pointattriblist;
14078int *pointmarkerlist;
14079int numberofpoints;
14080int numberofpointattribs;
14081#endif /* not ANSI_DECLARATORS */
14082
14083{
14084 vertex vertexloop;
14085 REAL x, y;
14086 int i, j;
14087 int coordindex;
14088 int attribindex;
14089
14090 m->invertices = numberofpoints;
14091 m->mesh_dim = 2;
14092 m->nextras = numberofpointattribs;
14093 m->readnodefile = 0;
14094 if (m->invertices < 3) {
14095 printf("Error: Input must have at least three input vertices.\n");
14096 triexit(1);
14097 }
14098 if (m->nextras == 0) {
14099 b->weighted = 0;
14100 }
14101
14103
14104 /* Read the vertices. */
14105 coordindex = 0;
14106 attribindex = 0;
14107 for (i = 0; i < m->invertices; i++) {
14108 vertexloop = (vertex) poolalloc(&m->vertices);
14109 /* Read the vertex coordinates. */
14110 x = vertexloop[0] = pointlist[coordindex++];
14111 y = vertexloop[1] = pointlist[coordindex++];
14112 /* Read the vertex attributes. */
14113 for (j = 0; j < numberofpointattribs; j++) {
14114 vertexloop[2 + j] = pointattriblist[attribindex++];
14115 }
14116 if (pointmarkerlist != (int *) NULL) {
14117 /* Read a vertex marker. */
14118 setvertexmark(vertexloop, pointmarkerlist[i]);
14119 } else {
14120 /* If no markers are specified, they default to zero. */
14121 setvertexmark(vertexloop, 0);
14122 }
14123 setvertextype(vertexloop, INPUTVERTEX);
14124 /* Determine the smallest and largest x and y coordinates. */
14125 if (i == 0) {
14126 m->xmin = m->xmax = x;
14127 m->ymin = m->ymax = y;
14128 } else {
14129 m->xmin = (x < m->xmin) ? x : m->xmin;
14130 m->xmax = (x > m->xmax) ? x : m->xmax;
14131 m->ymin = (y < m->ymin) ? y : m->ymin;
14132 m->ymax = (y > m->ymax) ? y : m->ymax;
14133 }
14134 }
14135
14136 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14137 /* Delaunay algorithm. */
14138 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14139}
14140
14141#endif /* TRILIBRARY */
14142
14143/*****************************************************************************/
14144/* */
14145/* readholes() Read the holes, and possibly regional attributes and area */
14146/* constraints, from a .poly file. */
14147/* */
14148/*****************************************************************************/
14149
14150#ifndef TRILIBRARY
14151
14152#ifdef ANSI_DECLARATORS
14153void readholes(struct mesh *m, struct behavior *b,
14154 FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14155 REAL **rlist, int *regions)
14156#else /* not ANSI_DECLARATORS */
14157void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14158struct mesh *m;
14159struct behavior *b;
14160FILE *polyfile;
14161char *polyfilename;
14162REAL **hlist;
14163int *holes;
14164REAL **rlist;
14165int *regions;
14166#endif /* not ANSI_DECLARATORS */
14167
14168{
14169 REAL *holelist;
14170 REAL *regionlist;
14171 char inputline[INPUTLINESIZE];
14172 char *stringptr;
14173 int index;
14174 int i;
14175
14176 /* Read the holes. */
14177 stringptr = readline(inputline, polyfile, polyfilename);
14178 *holes = (int) strtol(stringptr, &stringptr, 0);
14179 if (*holes > 0) {
14180 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14181 *hlist = holelist;
14182 for (i = 0; i < 2 * *holes; i += 2) {
14183 stringptr = readline(inputline, polyfile, polyfilename);
14184 stringptr = findfield(stringptr);
14185 if (*stringptr == '\0') {
14186 printf("Error: Hole %d has no x coordinate.\n",
14187 b->firstnumber + (i >> 1));
14188 triexit(1);
14189 } else {
14190 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14191 }
14192 stringptr = findfield(stringptr);
14193 if (*stringptr == '\0') {
14194 printf("Error: Hole %d has no y coordinate.\n",
14195 b->firstnumber + (i >> 1));
14196 triexit(1);
14197 } else {
14198 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14199 }
14200 }
14201 } else {
14202 *hlist = (REAL *) NULL;
14203 }
14204
14205#ifndef CDT_ONLY
14206 if ((b->regionattrib || b->vararea) && !b->refine) {
14207 /* Read the area constraints. */
14208 stringptr = readline(inputline, polyfile, polyfilename);
14209 *regions = (int) strtol(stringptr, &stringptr, 0);
14210 if (*regions > 0) {
14211 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14212 *rlist = regionlist;
14213 index = 0;
14214 for (i = 0; i < *regions; i++) {
14215 stringptr = readline(inputline, polyfile, polyfilename);
14216 stringptr = findfield(stringptr);
14217 if (*stringptr == '\0') {
14218 printf("Error: Region %d has no x coordinate.\n",
14219 b->firstnumber + i);
14220 triexit(1);
14221 } else {
14222 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14223 }
14224 stringptr = findfield(stringptr);
14225 if (*stringptr == '\0') {
14226 printf("Error: Region %d has no y coordinate.\n",
14227 b->firstnumber + i);
14228 triexit(1);
14229 } else {
14230 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14231 }
14232 stringptr = findfield(stringptr);
14233 if (*stringptr == '\0') {
14234 printf(
14235 "Error: Region %d has no region attribute or area constraint.\n",
14236 b->firstnumber + i);
14237 triexit(1);
14238 } else {
14239 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14240 }
14241 stringptr = findfield(stringptr);
14242 if (*stringptr == '\0') {
14243 regionlist[index] = regionlist[index - 1];
14244 } else {
14245 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14246 }
14247 index++;
14248 }
14249 }
14250 } else {
14251 /* Set `*regions' to zero to avoid an accidental free() later. */
14252 *regions = 0;
14253 *rlist = (REAL *) NULL;
14254 }
14255#endif /* not CDT_ONLY */
14256
14257 fclose(polyfile);
14258}
14259
14260#endif /* not TRILIBRARY */
14261
14262/*****************************************************************************/
14263/* */
14264/* finishfile() Write the command line to the output file so the user */
14265/* can remember how the file was generated. Close the file. */
14266/* */
14267/*****************************************************************************/
14268
14269#ifndef TRILIBRARY
14270
14271#ifdef ANSI_DECLARATORS
14272void finishfile(FILE *outfile, int argc, char **argv)
14273#else /* not ANSI_DECLARATORS */
14274void finishfile(outfile, argc, argv)
14275FILE *outfile;
14276int argc;
14277char **argv;
14278#endif /* not ANSI_DECLARATORS */
14279
14280{
14281 int i;
14282
14283 fprintf(outfile, "# Generated by");
14284 for (i = 0; i < argc; i++) {
14285 fprintf(outfile, " ");
14286 fputs(argv[i], outfile);
14287 }
14288 fprintf(outfile, "\n");
14289 fclose(outfile);
14290}
14291
14292#endif /* not TRILIBRARY */
14293
14294/*****************************************************************************/
14295/* */
14296/* writenodes() Number the vertices and write them to a .node file. */
14297/* */
14298/* To save memory, the vertex numbers are written over the boundary markers */
14299/* after the vertices are written to a file. */
14300/* */
14301/*****************************************************************************/
14302
14303#ifdef TRILIBRARY
14304
14305#ifdef ANSI_DECLARATORS
14306void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14307 REAL **pointattriblist, int **pointmarkerlist)
14308#else /* not ANSI_DECLARATORS */
14309void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14310struct mesh *m;
14311struct behavior *b;
14312REAL **pointlist;
14313REAL **pointattriblist;
14314int **pointmarkerlist;
14315#endif /* not ANSI_DECLARATORS */
14316
14317#else /* not TRILIBRARY */
14318
14319#ifdef ANSI_DECLARATORS
14320void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14321 int argc, char **argv)
14322#else /* not ANSI_DECLARATORS */
14323void writenodes(m, b, nodefilename, argc, argv)
14324struct mesh *m;
14325struct behavior *b;
14326char *nodefilename;
14327int argc;
14328char **argv;
14329#endif /* not ANSI_DECLARATORS */
14330
14331#endif /* not TRILIBRARY */
14332
14333{
14334#ifdef TRILIBRARY
14335 REAL *plist;
14336 REAL *palist;
14337 int *pmlist;
14338 int coordindex;
14339 int attribindex;
14340#else /* not TRILIBRARY */
14341 FILE *outfile;
14342#endif /* not TRILIBRARY */
14343 vertex vertexloop;
14344 long outvertices;
14345 int vertexnumber;
14346 int i;
14347
14348 if (b->jettison) {
14349 outvertices = m->vertices.items - m->undeads;
14350 } else {
14351 outvertices = m->vertices.items;
14352 }
14353
14354#ifdef TRILIBRARY
14355 if (!b->quiet) {
14356 printf("Writing vertices.\n");
14357 }
14358 /* Allocate memory for output vertices if necessary. */
14359 if (*pointlist == (REAL *) NULL) {
14360 *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14361 }
14362 /* Allocate memory for output vertex attributes if necessary. */
14363 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14364 *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14365 sizeof(REAL)));
14366 }
14367 /* Allocate memory for output vertex markers if necessary. */
14368 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14369 *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14370 }
14371 plist = *pointlist;
14372 palist = *pointattriblist;
14373 pmlist = *pointmarkerlist;
14374 coordindex = 0;
14375 attribindex = 0;
14376#else /* not TRILIBRARY */
14377 if (!b->quiet) {
14378 printf("Writing %s.\n", nodefilename);
14379 }
14380 outfile = fopen(nodefilename, "w");
14381 if (outfile == (FILE *) NULL) {
14382 printf(" Error: Cannot create file %s.\n", nodefilename);
14383 triexit(1);
14384 }
14385 /* Number of vertices, number of dimensions, number of vertex attributes, */
14386 /* and number of boundary markers (zero or one). */
14387 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14388 m->nextras, 1 - b->nobound);
14389#endif /* not TRILIBRARY */
14390
14391 traversalinit(&m->vertices);
14392 vertexnumber = b->firstnumber;
14393 vertexloop = vertextraverse(m);
14394 while (vertexloop != (vertex) NULL) {
14395 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14396#ifdef TRILIBRARY
14397 /* X and y coordinates. */
14398 plist[coordindex++] = vertexloop[0];
14399 plist[coordindex++] = vertexloop[1];
14400 /* Vertex attributes. */
14401 for (i = 0; i < m->nextras; i++) {
14402 palist[attribindex++] = vertexloop[2 + i];
14403 }
14404 if (!b->nobound) {
14405 /* Copy the boundary marker. */
14406 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14407 }
14408#else /* not TRILIBRARY */
14409 /* Vertex number, x and y coordinates. */
14410 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14411 vertexloop[1]);
14412 for (i = 0; i < m->nextras; i++) {
14413 /* Write an attribute. */
14414 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14415 }
14416 if (b->nobound) {
14417 fprintf(outfile, "\n");
14418 } else {
14419 /* Write the boundary marker. */
14420 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14421 }
14422#endif /* not TRILIBRARY */
14423
14424 setvertexmark(vertexloop, vertexnumber);
14425 vertexnumber++;
14426 }
14427 vertexloop = vertextraverse(m);
14428 }
14429
14430#ifndef TRILIBRARY
14431 finishfile(outfile, argc, argv);
14432#endif /* not TRILIBRARY */
14433}
14434
14435/*****************************************************************************/
14436/* */
14437/* numbernodes() Number the vertices. */
14438/* */
14439/* Each vertex is assigned a marker equal to its number. */
14440/* */
14441/* Used when writenodes() is not called because no .node file is written. */
14442/* */
14443/*****************************************************************************/
14444
14445#ifdef ANSI_DECLARATORS
14446void numbernodes(struct mesh *m, struct behavior *b)
14447#else /* not ANSI_DECLARATORS */
14448void numbernodes(m, b)
14449struct mesh *m;
14450struct behavior *b;
14451#endif /* not ANSI_DECLARATORS */
14452
14453{
14454 vertex vertexloop;
14455 int vertexnumber;
14456
14457 traversalinit(&m->vertices);
14458 vertexnumber = b->firstnumber;
14459 vertexloop = vertextraverse(m);
14460 while (vertexloop != (vertex) NULL) {
14461 setvertexmark(vertexloop, vertexnumber);
14462 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14463 vertexnumber++;
14464 }
14465 vertexloop = vertextraverse(m);
14466 }
14467}
14468
14469/*****************************************************************************/
14470/* */
14471/* writeelements() Write the triangles to an .ele file. */
14472/* */
14473/*****************************************************************************/
14474
14475#ifdef TRILIBRARY
14476
14477#ifdef ANSI_DECLARATORS
14478void writeelements(struct mesh *m, struct behavior *b,
14479 int **trianglelist, REAL **triangleattriblist)
14480#else /* not ANSI_DECLARATORS */
14481void writeelements(m, b, trianglelist, triangleattriblist)
14482struct mesh *m;
14483struct behavior *b;
14484int **trianglelist;
14485REAL **triangleattriblist;
14486#endif /* not ANSI_DECLARATORS */
14487
14488#else /* not TRILIBRARY */
14489
14490#ifdef ANSI_DECLARATORS
14491void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14492 int argc, char **argv)
14493#else /* not ANSI_DECLARATORS */
14494void writeelements(m, b, elefilename, argc, argv)
14495struct mesh *m;
14496struct behavior *b;
14497char *elefilename;
14498int argc;
14499char **argv;
14500#endif /* not ANSI_DECLARATORS */
14501
14502#endif /* not TRILIBRARY */
14503
14504{
14505#ifdef TRILIBRARY
14506 int *tlist;
14507 REAL *talist;
14508 int vertexindex;
14509 int attribindex;
14510#else /* not TRILIBRARY */
14511 FILE *outfile;
14512#endif /* not TRILIBRARY */
14513 struct otri triangleloop;
14514 vertex p1, p2, p3;
14515 vertex mid1, mid2, mid3;
14516 long elementnumber;
14517 int i;
14518
14519#ifdef TRILIBRARY
14520 if (!b->quiet) {
14521 printf("Writing triangles.\n");
14522 }
14523 /* Allocate memory for output triangles if necessary. */
14524 if (*trianglelist == (int *) NULL) {
14525 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14526 ((b->order + 1) * (b->order + 2) /
14527 2) * sizeof(int)));
14528 }
14529 /* Allocate memory for output triangle attributes if necessary. */
14530 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14531 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14532 m->eextras *
14533 sizeof(REAL)));
14534 }
14535 tlist = *trianglelist;
14536 talist = *triangleattriblist;
14537 vertexindex = 0;
14538 attribindex = 0;
14539#else /* not TRILIBRARY */
14540 if (!b->quiet) {
14541 printf("Writing %s.\n", elefilename);
14542 }
14543 outfile = fopen(elefilename, "w");
14544 if (outfile == (FILE *) NULL) {
14545 printf(" Error: Cannot create file %s.\n", elefilename);
14546 triexit(1);
14547 }
14548 /* Number of triangles, vertices per triangle, attributes per triangle. */
14549 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14550 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14551#endif /* not TRILIBRARY */
14552
14553 traversalinit(&m->triangles);
14554 triangleloop.tri = triangletraverse(m);
14555 triangleloop.orient = 0;
14556 elementnumber = b->firstnumber;
14557 while (triangleloop.tri != (triangle *) NULL) {
14558 org(triangleloop, p1);
14559 dest(triangleloop, p2);
14560 apex(triangleloop, p3);
14561 if (b->order == 1) {
14562#ifdef TRILIBRARY
14563 tlist[vertexindex++] = vertexmark(p1);
14564 tlist[vertexindex++] = vertexmark(p2);
14565 tlist[vertexindex++] = vertexmark(p3);
14566#else /* not TRILIBRARY */
14567 /* Triangle number, indices for three vertices. */
14568 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14569 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14570#endif /* not TRILIBRARY */
14571 } else {
14572 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14573 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14574 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14575#ifdef TRILIBRARY
14576 tlist[vertexindex++] = vertexmark(p1);
14577 tlist[vertexindex++] = vertexmark(p2);
14578 tlist[vertexindex++] = vertexmark(p3);
14579 tlist[vertexindex++] = vertexmark(mid1);
14580 tlist[vertexindex++] = vertexmark(mid2);
14581 tlist[vertexindex++] = vertexmark(mid3);
14582#else /* not TRILIBRARY */
14583 /* Triangle number, indices for six vertices. */
14584 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14585 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14586 vertexmark(mid2), vertexmark(mid3));
14587#endif /* not TRILIBRARY */
14588 }
14589
14590#ifdef TRILIBRARY
14591 for (i = 0; i < m->eextras; i++) {
14592 talist[attribindex++] = elemattribute(triangleloop, i);
14593 }
14594#else /* not TRILIBRARY */
14595 for (i = 0; i < m->eextras; i++) {
14596 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14597 }
14598 fprintf(outfile, "\n");
14599#endif /* not TRILIBRARY */
14600
14601 triangleloop.tri = triangletraverse(m);
14602 elementnumber++;
14603 }
14604
14605#ifndef TRILIBRARY
14606 finishfile(outfile, argc, argv);
14607#endif /* not TRILIBRARY */
14608}
14609
14610/*****************************************************************************/
14611/* */
14612/* writepoly() Write the segments and holes to a .poly file. */
14613/* */
14614/*****************************************************************************/
14615
14616#ifdef TRILIBRARY
14617
14618#ifdef ANSI_DECLARATORS
14619void writepoly(struct mesh *m, struct behavior *b,
14620 int **segmentlist, int **segmentmarkerlist)
14621#else /* not ANSI_DECLARATORS */
14622void writepoly(m, b, segmentlist, segmentmarkerlist)
14623struct mesh *m;
14624struct behavior *b;
14625int **segmentlist;
14626int **segmentmarkerlist;
14627#endif /* not ANSI_DECLARATORS */
14628
14629#else /* not TRILIBRARY */
14630
14631#ifdef ANSI_DECLARATORS
14632void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14633 REAL *holelist, int holes, REAL *regionlist, int regions,
14634 int argc, char **argv)
14635#else /* not ANSI_DECLARATORS */
14636void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14637 argc, argv)
14638struct mesh *m;
14639struct behavior *b;
14640char *polyfilename;
14641REAL *holelist;
14642int holes;
14643REAL *regionlist;
14644int regions;
14645int argc;
14646char **argv;
14647#endif /* not ANSI_DECLARATORS */
14648
14649#endif /* not TRILIBRARY */
14650
14651{
14652#ifdef TRILIBRARY
14653 int *slist;
14654 int *smlist;
14655 int index;
14656#else /* not TRILIBRARY */
14657 FILE *outfile;
14658 long holenumber, regionnumber;
14659#endif /* not TRILIBRARY */
14660 struct osub subsegloop;
14661 vertex endpoint1, endpoint2;
14662 long subsegnumber;
14663
14664#ifdef TRILIBRARY
14665 if (!b->quiet) {
14666 printf("Writing segments.\n");
14667 }
14668 /* Allocate memory for output segments if necessary. */
14669 if (*segmentlist == (int *) NULL) {
14670 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14671 sizeof(int)));
14672 }
14673 /* Allocate memory for output segment markers if necessary. */
14674 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14675 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14676 sizeof(int)));
14677 }
14678 slist = *segmentlist;
14679 smlist = *segmentmarkerlist;
14680 index = 0;
14681#else /* not TRILIBRARY */
14682 if (!b->quiet) {
14683 printf("Writing %s.\n", polyfilename);
14684 }
14685 outfile = fopen(polyfilename, "w");
14686 if (outfile == (FILE *) NULL) {
14687 printf(" Error: Cannot create file %s.\n", polyfilename);
14688 triexit(1);
14689 }
14690 /* The zero indicates that the vertices are in a separate .node file. */
14691 /* Followed by number of dimensions, number of vertex attributes, */
14692 /* and number of boundary markers (zero or one). */
14693 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14694 1 - b->nobound);
14695 /* Number of segments, number of boundary markers (zero or one). */
14696 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14697#endif /* not TRILIBRARY */
14698
14699 traversalinit(&m->subsegs);
14700 subsegloop.ss = subsegtraverse(m);
14701 subsegloop.ssorient = 0;
14702 subsegnumber = b->firstnumber;
14703 while (subsegloop.ss != (subseg *) NULL) {
14704 sorg(subsegloop, endpoint1);
14705 sdest(subsegloop, endpoint2);
14706#ifdef TRILIBRARY
14707 /* Copy indices of the segment's two endpoints. */
14708 slist[index++] = vertexmark(endpoint1);
14709 slist[index++] = vertexmark(endpoint2);
14710 if (!b->nobound) {
14711 /* Copy the boundary marker. */
14712 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14713 }
14714#else /* not TRILIBRARY */
14715 /* Segment number, indices of its two endpoints, and possibly a marker. */
14716 if (b->nobound) {
14717 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14718 vertexmark(endpoint1), vertexmark(endpoint2));
14719 } else {
14720 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14721 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14722 }
14723#endif /* not TRILIBRARY */
14724
14725 subsegloop.ss = subsegtraverse(m);
14726 subsegnumber++;
14727 }
14728
14729#ifndef TRILIBRARY
14730#ifndef CDT_ONLY
14731 fprintf(outfile, "%d\n", holes);
14732 if (holes > 0) {
14733 for (holenumber = 0; holenumber < holes; holenumber++) {
14734 /* Hole number, x and y coordinates. */
14735 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14736 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14737 }
14738 }
14739 if (regions > 0) {
14740 fprintf(outfile, "%d\n", regions);
14741 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14742 /* Region number, x and y coordinates, attribute, maximum area. */
14743 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14744 b->firstnumber + regionnumber,
14745 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14746 regionlist[4 * regionnumber + 2],
14747 regionlist[4 * regionnumber + 3]);
14748 }
14749 }
14750#endif /* not CDT_ONLY */
14751
14752 finishfile(outfile, argc, argv);
14753#endif /* not TRILIBRARY */
14754}
14755
14756/*****************************************************************************/
14757/* */
14758/* writeedges() Write the edges to an .edge file. */
14759/* */
14760/*****************************************************************************/
14761
14762#ifdef TRILIBRARY
14763
14764#ifdef ANSI_DECLARATORS
14765void writeedges(struct mesh *m, struct behavior *b,
14766 int **edgelist, int **edgemarkerlist)
14767#else /* not ANSI_DECLARATORS */
14768void writeedges(m, b, edgelist, edgemarkerlist)
14769struct mesh *m;
14770struct behavior *b;
14771int **edgelist;
14772int **edgemarkerlist;
14773#endif /* not ANSI_DECLARATORS */
14774
14775#else /* not TRILIBRARY */
14776
14777#ifdef ANSI_DECLARATORS
14778void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14779 int argc, char **argv)
14780#else /* not ANSI_DECLARATORS */
14781void writeedges(m, b, edgefilename, argc, argv)
14782struct mesh *m;
14783struct behavior *b;
14784char *edgefilename;
14785int argc;
14786char **argv;
14787#endif /* not ANSI_DECLARATORS */
14788
14789#endif /* not TRILIBRARY */
14790
14791{
14792#ifdef TRILIBRARY
14793 int *elist;
14794 int *emlist;
14795 int index;
14796#else /* not TRILIBRARY */
14797 FILE *outfile;
14798#endif /* not TRILIBRARY */
14799 struct otri triangleloop, trisym;
14800 struct osub checkmark;
14801 vertex p1, p2;
14802 long edgenumber;
14803 triangle ptr; /* Temporary variable used by sym(). */
14804 subseg sptr; /* Temporary variable used by tspivot(). */
14805
14806#ifdef TRILIBRARY
14807 if (!b->quiet) {
14808 printf("Writing edges.\n");
14809 }
14810 /* Allocate memory for edges if necessary. */
14811 if (*edgelist == (int *) NULL) {
14812 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14813 }
14814 /* Allocate memory for edge markers if necessary. */
14815 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14816 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14817 }
14818 elist = *edgelist;
14819 emlist = *edgemarkerlist;
14820 index = 0;
14821#else /* not TRILIBRARY */
14822 if (!b->quiet) {
14823 printf("Writing %s.\n", edgefilename);
14824 }
14825 outfile = fopen(edgefilename, "w");
14826 if (outfile == (FILE *) NULL) {
14827 printf(" Error: Cannot create file %s.\n", edgefilename);
14828 triexit(1);
14829 }
14830 /* Number of edges, number of boundary markers (zero or one). */
14831 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14832#endif /* not TRILIBRARY */
14833
14834 traversalinit(&m->triangles);
14835 triangleloop.tri = triangletraverse(m);
14836 edgenumber = b->firstnumber;
14837 /* To loop over the set of edges, loop over all triangles, and look at */
14838 /* the three edges of each triangle. If there isn't another triangle */
14839 /* adjacent to the edge, operate on the edge. If there is another */
14840 /* adjacent triangle, operate on the edge only if the current triangle */
14841 /* has a smaller pointer than its neighbor. This way, each edge is */
14842 /* considered only once. */
14843 while (triangleloop.tri != (triangle *) NULL) {
14844 for (triangleloop.orient = 0; triangleloop.orient < 3;
14845 triangleloop.orient++) {
14846 sym(triangleloop, trisym);
14847 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14848 org(triangleloop, p1);
14849 dest(triangleloop, p2);
14850#ifdef TRILIBRARY
14851 elist[index++] = vertexmark(p1);
14852 elist[index++] = vertexmark(p2);
14853#endif /* TRILIBRARY */
14854 if (b->nobound) {
14855#ifndef TRILIBRARY
14856 /* Edge number, indices of two endpoints. */
14857 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14858 vertexmark(p1), vertexmark(p2));
14859#endif /* not TRILIBRARY */
14860 } else {
14861 /* Edge number, indices of two endpoints, and a boundary marker. */
14862 /* If there's no subsegment, the boundary marker is zero. */
14863 if (b->usesegments) {
14864 tspivot(triangleloop, checkmark);
14865 if (checkmark.ss == m->dummysub) {
14866#ifdef TRILIBRARY
14867 emlist[edgenumber - b->firstnumber] = 0;
14868#else /* not TRILIBRARY */
14869 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14870 vertexmark(p1), vertexmark(p2), 0);
14871#endif /* not TRILIBRARY */
14872 } else {
14873#ifdef TRILIBRARY
14874 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14875#else /* not TRILIBRARY */
14876 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14877 vertexmark(p1), vertexmark(p2), mark(checkmark));
14878#endif /* not TRILIBRARY */
14879 }
14880 } else {
14881#ifdef TRILIBRARY
14882 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14883#else /* not TRILIBRARY */
14884 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14885 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14886#endif /* not TRILIBRARY */
14887 }
14888 }
14889 edgenumber++;
14890 }
14891 }
14892 triangleloop.tri = triangletraverse(m);
14893 }
14894
14895#ifndef TRILIBRARY
14896 finishfile(outfile, argc, argv);
14897#endif /* not TRILIBRARY */
14898}
14899
14900/*****************************************************************************/
14901/* */
14902/* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */
14903/* file. */
14904/* */
14905/* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
14906/* Hence, the Voronoi vertices are listed by traversing the Delaunay */
14907/* triangles, and the Voronoi edges are listed by traversing the Delaunay */
14908/* edges. */
14909/* */
14910/* WARNING: In order to assign numbers to the Voronoi vertices, this */
14911/* procedure messes up the subsegments or the extra nodes of every */
14912/* element. Hence, you should call this procedure last. */
14913/* */
14914/*****************************************************************************/
14915
14916#ifdef TRILIBRARY
14917
14918#ifdef ANSI_DECLARATORS
14919void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14920 REAL **vpointattriblist, int **vpointmarkerlist,
14921 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14922#else /* not ANSI_DECLARATORS */
14923void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
14924 vedgelist, vedgemarkerlist, vnormlist)
14925struct mesh *m;
14926struct behavior *b;
14927REAL **vpointlist;
14928REAL **vpointattriblist;
14929int **vpointmarkerlist;
14930int **vedgelist;
14931int **vedgemarkerlist;
14932REAL **vnormlist;
14933#endif /* not ANSI_DECLARATORS */
14934
14935#else /* not TRILIBRARY */
14936
14937#ifdef ANSI_DECLARATORS
14938void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14939 char *vedgefilename, int argc, char **argv)
14940#else /* not ANSI_DECLARATORS */
14941void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
14942struct mesh *m;
14943struct behavior *b;
14944char *vnodefilename;
14945char *vedgefilename;
14946int argc;
14947char **argv;
14948#endif /* not ANSI_DECLARATORS */
14949
14950#endif /* not TRILIBRARY */
14951
14952{
14953#ifdef TRILIBRARY
14954 REAL *plist;
14955 REAL *palist;
14956 int *elist;
14957 REAL *normlist;
14958 int coordindex;
14959 int attribindex;
14960#else /* not TRILIBRARY */
14961 FILE *outfile;
14962#endif /* not TRILIBRARY */
14963 struct otri triangleloop, trisym;
14964 vertex torg, tdest, tapex;
14965 REAL circumcenter[2];
14966 REAL xi, eta;
14967 long vnodenumber, vedgenumber;
14968 int p1, p2;
14969 int i;
14970 triangle ptr; /* Temporary variable used by sym(). */
14971
14972#ifdef TRILIBRARY
14973 if (!b->quiet) {
14974 printf("Writing Voronoi vertices.\n");
14975 }
14976 /* Allocate memory for Voronoi vertices if necessary. */
14977 if (*vpointlist == (REAL *) NULL) {
14978 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
14979 sizeof(REAL)));
14980 }
14981 /* Allocate memory for Voronoi vertex attributes if necessary. */
14982 if (*vpointattriblist == (REAL *) NULL) {
14983 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14984 m->nextras * sizeof(REAL)));
14985 }
14986 *vpointmarkerlist = (int *) NULL;
14987 plist = *vpointlist;
14988 palist = *vpointattriblist;
14989 coordindex = 0;
14990 attribindex = 0;
14991#else /* not TRILIBRARY */
14992 if (!b->quiet) {
14993 printf("Writing %s.\n", vnodefilename);
14994 }
14995 outfile = fopen(vnodefilename, "w");
14996 if (outfile == (FILE *) NULL) {
14997 printf(" Error: Cannot create file %s.\n", vnodefilename);
14998 triexit(1);
14999 }
15000 /* Number of triangles, two dimensions, number of vertex attributes, */
15001 /* no markers. */
15002 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15003#endif /* not TRILIBRARY */
15004
15005 traversalinit(&m->triangles);
15006 triangleloop.tri = triangletraverse(m);
15007 triangleloop.orient = 0;
15008 vnodenumber = b->firstnumber;
15009 while (triangleloop.tri != (triangle *) NULL) {
15010 org(triangleloop, torg);
15011 dest(triangleloop, tdest);
15012 apex(triangleloop, tapex);
15013 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15014#ifdef TRILIBRARY
15015 /* X and y coordinates. */
15016 plist[coordindex++] = circumcenter[0];
15017 plist[coordindex++] = circumcenter[1];
15018 for (i = 2; i < 2 + m->nextras; i++) {
15019 /* Interpolate the vertex attributes at the circumcenter. */
15020 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15021 + eta * (tapex[i] - torg[i]);
15022 }
15023#else /* not TRILIBRARY */
15024 /* Voronoi vertex number, x and y coordinates. */
15025 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15026 circumcenter[1]);
15027 for (i = 2; i < 2 + m->nextras; i++) {
15028 /* Interpolate the vertex attributes at the circumcenter. */
15029 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15030 + eta * (tapex[i] - torg[i]));
15031 }
15032 fprintf(outfile, "\n");
15033#endif /* not TRILIBRARY */
15034
15035 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15036 triangleloop.tri = triangletraverse(m);
15037 vnodenumber++;
15038 }
15039
15040#ifndef TRILIBRARY
15041 finishfile(outfile, argc, argv);
15042#endif /* not TRILIBRARY */
15043
15044#ifdef TRILIBRARY
15045 if (!b->quiet) {
15046 printf("Writing Voronoi edges.\n");
15047 }
15048 /* Allocate memory for output Voronoi edges if necessary. */
15049 if (*vedgelist == (int *) NULL) {
15050 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15051 }
15052 *vedgemarkerlist = (int *) NULL;
15053 /* Allocate memory for output Voronoi norms if necessary. */
15054 if (*vnormlist == (REAL *) NULL) {
15055 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15056 }
15057 elist = *vedgelist;
15058 normlist = *vnormlist;
15059 coordindex = 0;
15060#else /* not TRILIBRARY */
15061 if (!b->quiet) {
15062 printf("Writing %s.\n", vedgefilename);
15063 }
15064 outfile = fopen(vedgefilename, "w");
15065 if (outfile == (FILE *) NULL) {
15066 printf(" Error: Cannot create file %s.\n", vedgefilename);
15067 triexit(1);
15068 }
15069 /* Number of edges, zero boundary markers. */
15070 fprintf(outfile, "%ld %d\n", m->edges, 0);
15071#endif /* not TRILIBRARY */
15072
15073 traversalinit(&m->triangles);
15074 triangleloop.tri = triangletraverse(m);
15075 vedgenumber = b->firstnumber;
15076 /* To loop over the set of edges, loop over all triangles, and look at */
15077 /* the three edges of each triangle. If there isn't another triangle */
15078 /* adjacent to the edge, operate on the edge. If there is another */
15079 /* adjacent triangle, operate on the edge only if the current triangle */
15080 /* has a smaller pointer than its neighbor. This way, each edge is */
15081 /* considered only once. */
15082 while (triangleloop.tri != (triangle *) NULL) {
15083 for (triangleloop.orient = 0; triangleloop.orient < 3;
15084 triangleloop.orient++) {
15085 sym(triangleloop, trisym);
15086 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15087 /* Find the number of this triangle (and Voronoi vertex). */
15088 p1 = * (int *) (triangleloop.tri + 6);
15089 if (trisym.tri == m->dummytri) {
15090 org(triangleloop, torg);
15091 dest(triangleloop, tdest);
15092#ifdef TRILIBRARY
15093 /* Copy an infinite ray. Index of one endpoint, and -1. */
15094 elist[coordindex] = p1;
15095 normlist[coordindex++] = tdest[1] - torg[1];
15096 elist[coordindex] = -1;
15097 normlist[coordindex++] = torg[0] - tdest[0];
15098#else /* not TRILIBRARY */
15099 /* Write an infinite ray. Edge number, index of one endpoint, -1, */
15100 /* and x and y coordinates of a vector representing the */
15101 /* direction of the ray. */
15102 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15103 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15104#endif /* not TRILIBRARY */
15105 } else {
15106 /* Find the number of the adjacent triangle (and Voronoi vertex). */
15107 p2 = * (int *) (trisym.tri + 6);
15108 /* Finite edge. Write indices of two endpoints. */
15109#ifdef TRILIBRARY
15110 elist[coordindex] = p1;
15111 normlist[coordindex++] = 0.0;
15112 elist[coordindex] = p2;
15113 normlist[coordindex++] = 0.0;
15114#else /* not TRILIBRARY */
15115 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15116#endif /* not TRILIBRARY */
15117 }
15118 vedgenumber++;
15119 }
15120 }
15121 triangleloop.tri = triangletraverse(m);
15122 }
15123
15124#ifndef TRILIBRARY
15125 finishfile(outfile, argc, argv);
15126#endif /* not TRILIBRARY */
15127}
15128
15129#ifdef TRILIBRARY
15130
15131#ifdef ANSI_DECLARATORS
15132void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15133#else /* not ANSI_DECLARATORS */
15134void writeneighbors(m, b, neighborlist)
15135struct mesh *m;
15136struct behavior *b;
15137int **neighborlist;
15138#endif /* not ANSI_DECLARATORS */
15139
15140#else /* not TRILIBRARY */
15141
15142#ifdef ANSI_DECLARATORS
15143void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15144 int argc, char **argv)
15145#else /* not ANSI_DECLARATORS */
15146void writeneighbors(m, b, neighborfilename, argc, argv)
15147struct mesh *m;
15148struct behavior *b;
15149char *neighborfilename;
15150int argc;
15151char **argv;
15152#endif /* not ANSI_DECLARATORS */
15153
15154#endif /* not TRILIBRARY */
15155
15156{
15157#ifdef TRILIBRARY
15158 int *nlist;
15159 int index;
15160#else /* not TRILIBRARY */
15161 FILE *outfile;
15162#endif /* not TRILIBRARY */
15163 struct otri triangleloop, trisym;
15164 long elementnumber;
15165 int neighbor1, neighbor2, neighbor3;
15166 triangle ptr; /* Temporary variable used by sym(). */
15167
15168#ifdef TRILIBRARY
15169 if (!b->quiet) {
15170 printf("Writing neighbors.\n");
15171 }
15172 /* Allocate memory for neighbors if necessary. */
15173 if (*neighborlist == (int *) NULL) {
15174 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15175 sizeof(int)));
15176 }
15177 nlist = *neighborlist;
15178 index = 0;
15179#else /* not TRILIBRARY */
15180 if (!b->quiet) {
15181 printf("Writing %s.\n", neighborfilename);
15182 }
15183 outfile = fopen(neighborfilename, "w");
15184 if (outfile == (FILE *) NULL) {
15185 printf(" Error: Cannot create file %s.\n", neighborfilename);
15186 triexit(1);
15187 }
15188 /* Number of triangles, three neighbors per triangle. */
15189 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15190#endif /* not TRILIBRARY */
15191
15192 traversalinit(&m->triangles);
15193 triangleloop.tri = triangletraverse(m);
15194 triangleloop.orient = 0;
15195 elementnumber = b->firstnumber;
15196 while (triangleloop.tri != (triangle *) NULL) {
15197 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15198 triangleloop.tri = triangletraverse(m);
15199 elementnumber++;
15200 }
15201 * (int *) (m->dummytri + 6) = -1;
15202
15203 traversalinit(&m->triangles);
15204 triangleloop.tri = triangletraverse(m);
15205 elementnumber = b->firstnumber;
15206 while (triangleloop.tri != (triangle *) NULL) {
15207 triangleloop.orient = 1;
15208 sym(triangleloop, trisym);
15209 neighbor1 = * (int *) (trisym.tri + 6);
15210 triangleloop.orient = 2;
15211 sym(triangleloop, trisym);
15212 neighbor2 = * (int *) (trisym.tri + 6);
15213 triangleloop.orient = 0;
15214 sym(triangleloop, trisym);
15215 neighbor3 = * (int *) (trisym.tri + 6);
15216#ifdef TRILIBRARY
15217 nlist[index++] = neighbor1;
15218 nlist[index++] = neighbor2;
15219 nlist[index++] = neighbor3;
15220#else /* not TRILIBRARY */
15221 /* Triangle number, neighboring triangle numbers. */
15222 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15223 neighbor1, neighbor2, neighbor3);
15224#endif /* not TRILIBRARY */
15225
15226 triangleloop.tri = triangletraverse(m);
15227 elementnumber++;
15228 }
15229
15230#ifndef TRILIBRARY
15231 finishfile(outfile, argc, argv);
15232#endif /* not TRILIBRARY */
15233}
15234
15235/*****************************************************************************/
15236/* */
15237/* writeoff() Write the triangulation to an .off file. */
15238/* */
15239/* OFF stands for the Object File Format, a format used by the Geometry */
15240/* Center's Geomview package. */
15241/* */
15242/*****************************************************************************/
15243
15244#ifndef TRILIBRARY
15245
15246#ifdef ANSI_DECLARATORS
15247void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15248 int argc, char **argv)
15249#else /* not ANSI_DECLARATORS */
15250void writeoff(m, b, offfilename, argc, argv)
15251struct mesh *m;
15252struct behavior *b;
15253char *offfilename;
15254int argc;
15255char **argv;
15256#endif /* not ANSI_DECLARATORS */
15257
15258{
15259 FILE *outfile;
15260 struct otri triangleloop;
15261 vertex vertexloop;
15262 vertex p1, p2, p3;
15263 long outvertices;
15264
15265 if (!b->quiet) {
15266 printf("Writing %s.\n", offfilename);
15267 }
15268
15269 if (b->jettison) {
15270 outvertices = m->vertices.items - m->undeads;
15271 } else {
15272 outvertices = m->vertices.items;
15273 }
15274
15275 outfile = fopen(offfilename, "w");
15276 if (outfile == (FILE *) NULL) {
15277 printf(" Error: Cannot create file %s.\n", offfilename);
15278 triexit(1);
15279 }
15280 /* Number of vertices, triangles, and edges. */
15281 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15282 m->edges);
15283
15284 /* Write the vertices. */
15285 traversalinit(&m->vertices);
15286 vertexloop = vertextraverse(m);
15287 while (vertexloop != (vertex) NULL) {
15288 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15289 /* The "0.0" is here because the OFF format uses 3D coordinates. */
15290 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15291 0.0);
15292 }
15293 vertexloop = vertextraverse(m);
15294 }
15295
15296 /* Write the triangles. */
15297 traversalinit(&m->triangles);
15298 triangleloop.tri = triangletraverse(m);
15299 triangleloop.orient = 0;
15300 while (triangleloop.tri != (triangle *) NULL) {
15301 org(triangleloop, p1);
15302 dest(triangleloop, p2);
15303 apex(triangleloop, p3);
15304 /* The "3" means a three-vertex polygon. */
15305 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15306 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15307 triangleloop.tri = triangletraverse(m);
15308 }
15309 finishfile(outfile, argc, argv);
15310}
15311
15312#endif /* not TRILIBRARY */
15313
15314/** **/
15315/** **/
15316/********* File I/O routines end here *********/
15317
15318/*****************************************************************************/
15319/* */
15320/* quality_statistics() Print statistics about the quality of the mesh. */
15321/* */
15322/*****************************************************************************/
15323
15324#ifdef ANSI_DECLARATORS
15325void quality_statistics(struct mesh *m, struct behavior *b)
15326#else /* not ANSI_DECLARATORS */
15327void quality_statistics(m, b)
15328struct mesh *m;
15329struct behavior *b;
15330#endif /* not ANSI_DECLARATORS */
15331
15332{
15333 struct otri triangleloop;
15334 vertex p[3];
15335 REAL cossquaretable[8];
15336 REAL ratiotable[16];
15337 REAL dx[3], dy[3];
15338 REAL edgelength[3];
15339 REAL dotproduct;
15340 REAL cossquare;
15341 REAL triarea;
15342 REAL shortest, longest;
15343 REAL trilongest2;
15344 REAL smallestarea, biggestarea;
15345 REAL triminaltitude2;
15346 REAL minaltitude;
15347 REAL triaspect2;
15348 REAL worstaspect;
15349 REAL smallestangle, biggestangle;
15350 REAL radconst, degconst;
15351 int angletable[18];
15352 int aspecttable[16];
15353 int aspectindex;
15354 int tendegree;
15355 int acutebiggest;
15356 int i, ii, j, k;
15357
15358 printf("Mesh quality statistics:\n\n");
15359 radconst = PI / 18.0;
15360 degconst = 180.0 / PI;
15361 for (i = 0; i < 8; i++) {
15362 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15363 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15364 }
15365 for (i = 0; i < 18; i++) {
15366 angletable[i] = 0;
15367 }
15368
15369 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15370 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15371 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15372 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15373 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15374 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15375 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15376 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15377 for (i = 0; i < 16; i++) {
15378 aspecttable[i] = 0;
15379 }
15380
15381 worstaspect = 0.0;
15382 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15383 minaltitude = minaltitude * minaltitude;
15384 shortest = minaltitude;
15385 longest = 0.0;
15386 smallestarea = minaltitude;
15387 biggestarea = 0.0;
15388 worstaspect = 0.0;
15389 smallestangle = 0.0;
15390 biggestangle = 2.0;
15391 acutebiggest = 1;
15392
15393 traversalinit(&m->triangles);
15394 triangleloop.tri = triangletraverse(m);
15395 triangleloop.orient = 0;
15396 while (triangleloop.tri != (triangle *) NULL) {
15397 org(triangleloop, p[0]);
15398 dest(triangleloop, p[1]);
15399 apex(triangleloop, p[2]);
15400 trilongest2 = 0.0;
15401
15402 for (i = 0; i < 3; i++) {
15403 j = plus1mod3[i];
15404 k = minus1mod3[i];
15405 dx[i] = p[j][0] - p[k][0];
15406 dy[i] = p[j][1] - p[k][1];
15407 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15408 if (edgelength[i] > trilongest2) {
15409 trilongest2 = edgelength[i];
15410 }
15411 if (edgelength[i] > longest) {
15412 longest = edgelength[i];
15413 }
15414 if (edgelength[i] < shortest) {
15415 shortest = edgelength[i];
15416 }
15417 }
15418
15419 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15420 if (triarea < smallestarea) {
15421 smallestarea = triarea;
15422 }
15423 if (triarea > biggestarea) {
15424 biggestarea = triarea;
15425 }
15426 triminaltitude2 = triarea * triarea / trilongest2;
15427 if (triminaltitude2 < minaltitude) {
15428 minaltitude = triminaltitude2;
15429 }
15430 triaspect2 = trilongest2 / triminaltitude2;
15431 if (triaspect2 > worstaspect) {
15432 worstaspect = triaspect2;
15433 }
15434 aspectindex = 0;
15435 while ((aspectindex < 15) &&
15436 (triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15437 ) {
15438 aspectindex++;
15439 }
15440 aspecttable[aspectindex]++;
15441
15442 for (i = 0; i < 3; i++) {
15443 j = plus1mod3[i];
15444 k = minus1mod3[i];
15445 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15446 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15447 tendegree = 8;
15448 for (ii = 7; ii >= 0; ii--) {
15449 if (cossquare > cossquaretable[ii]) {
15450 tendegree = ii;
15451 }
15452 }
15453 if (dotproduct <= 0.0) {
15454 angletable[tendegree]++;
15455 if (cossquare > smallestangle) {
15456 smallestangle = cossquare;
15457 }
15458 if (acutebiggest && (cossquare < biggestangle)) {
15459 biggestangle = cossquare;
15460 }
15461 } else {
15462 angletable[17 - tendegree]++;
15463 if (acutebiggest || (cossquare > biggestangle)) {
15464 biggestangle = cossquare;
15465 acutebiggest = 0;
15466 }
15467 }
15468 }
15469 triangleloop.tri = triangletraverse(m);
15470 }
15471
15472 shortest = sqrt(shortest);
15473 longest = sqrt(longest);
15474 minaltitude = sqrt(minaltitude);
15475 worstaspect = sqrt(worstaspect);
15476 smallestarea *= 0.5;
15477 biggestarea *= 0.5;
15478 if (smallestangle >= 1.0) {
15479 smallestangle = 0.0;
15480 } else {
15481 smallestangle = degconst * acos(sqrt(smallestangle));
15482 }
15483 if (biggestangle >= 1.0) {
15484 biggestangle = 180.0;
15485 } else {
15486 if (acutebiggest) {
15487 biggestangle = degconst * acos(sqrt(biggestangle));
15488 } else {
15489 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15490 }
15491 }
15492
15493 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15494 smallestarea, biggestarea);
15495 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15496 shortest, longest);
15497 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15498 minaltitude, worstaspect);
15499
15500 printf(" Triangle aspect ratio histogram:\n");
15501 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15502 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15503 aspecttable[8]);
15504 for (i = 1; i < 7; i++) {
15505 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15506 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15507 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15508 }
15509 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15510 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15511 aspecttable[15]);
15512 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15513
15514 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15515 smallestangle, biggestangle);
15516
15517 printf(" Angle histogram:\n");
15518 for (i = 0; i < 9; i++) {
15519 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15520 i * 10, i * 10 + 10, angletable[i],
15521 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15522 }
15523 printf("\n");
15524}
15525
15526/*****************************************************************************/
15527/* */
15528/* statistics() Print all sorts of cool facts. */
15529/* */
15530/*****************************************************************************/
15531
15532#ifdef ANSI_DECLARATORS
15533void statistics(struct mesh *m, struct behavior *b)
15534#else /* not ANSI_DECLARATORS */
15535void statistics(m, b)
15536struct mesh *m;
15537struct behavior *b;
15538#endif /* not ANSI_DECLARATORS */
15539
15540{
15541 printf("\nStatistics:\n\n");
15542 printf(" Input vertices: %d\n", m->invertices);
15543 if (b->refine) {
15544 printf(" Input triangles: %d\n", m->inelements);
15545 }
15546 if (b->poly) {
15547 printf(" Input segments: %d\n", m->insegments);
15548 if (!b->refine) {
15549 printf(" Input holes: %d\n", m->holes);
15550 }
15551 }
15552
15553 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15554 printf(" Mesh triangles: %ld\n", m->triangles.items);
15555 printf(" Mesh edges: %ld\n", m->edges);
15556 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15557 if (b->poly || b->refine) {
15558 printf(" Mesh interior boundary edges: %ld\n",
15559 m->subsegs.items - m->hullsize);
15560 printf(" Mesh subsegments (constrained edges): %ld\n",
15561 m->subsegs.items);
15562 }
15563 printf("\n");
15564
15565 if (b->verbose) {
15567 printf("Memory allocation statistics:\n\n");
15568 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15569 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15570 if (m->subsegs.maxitems > 0) {
15571 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15572 }
15573 if (m->viri.maxitems > 0) {
15574 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15575 }
15576 if (m->badsubsegs.maxitems > 0) {
15577 printf(" Maximum number of encroached subsegments: %ld\n",
15578 m->badsubsegs.maxitems);
15579 }
15580 if (m->badtriangles.maxitems > 0) {
15581 printf(" Maximum number of bad triangles: %ld\n",
15582 m->badtriangles.maxitems);
15583 }
15584 if (m->flipstackers.maxitems > 0) {
15585 printf(" Maximum number of stacked triangle flips: %ld\n",
15586 m->flipstackers.maxitems);
15587 }
15588 if (m->splaynodes.maxitems > 0) {
15589 printf(" Maximum number of splay tree nodes: %ld\n",
15590 m->splaynodes.maxitems);
15591 }
15592 printf(" Approximate heap memory use (bytes): %ld\n\n",
15593 m->vertices.maxitems * m->vertices.itembytes +
15594 m->triangles.maxitems * m->triangles.itembytes +
15595 m->subsegs.maxitems * m->subsegs.itembytes +
15596 m->viri.maxitems * m->viri.itembytes +
15597 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15598 m->badtriangles.maxitems * m->badtriangles.itembytes +
15599 m->flipstackers.maxitems * m->flipstackers.itembytes +
15600 m->splaynodes.maxitems * m->splaynodes.itembytes);
15601
15602 printf("Algorithmic statistics:\n\n");
15603 if (!b->weighted) {
15604 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15605 } else {
15606 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15607 }
15608 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15609 if (m->hyperbolacount > 0) {
15610 printf(" Number of right-of-hyperbola tests: %ld\n",
15611 m->hyperbolacount);
15612 }
15613 if (m->circletopcount > 0) {
15614 printf(" Number of circle top computations: %ld\n",
15615 m->circletopcount);
15616 }
15617 if (m->circumcentercount > 0) {
15618 printf(" Number of triangle circumcenter computations: %ld\n",
15619 m->circumcentercount);
15620 }
15621 printf("\n");
15622 }
15623}
15624
15625/*****************************************************************************/
15626/* */
15627/* main() or triangulate() Gosh, do everything. */
15628/* */
15629/* The sequence is roughly as follows. Many of these steps can be skipped, */
15630/* depending on the command line switches. */
15631/* */
15632/* - Initialize constants and parse the command line. */
15633/* - Read the vertices from a file and either */
15634/* - triangulate them (no -r), or */
15635/* - read an old mesh from files and reconstruct it (-r). */
15636/* - Insert the PSLG segments (-p), and possibly segments on the convex */
15637/* hull (-c). */
15638/* - Read the holes (-p), regional attributes (-pA), and regional area */
15639/* constraints (-pa). Carve the holes and concavities, and spread the */
15640/* regional attributes and area constraints. */
15641/* - Enforce the constraints on minimum angle (-q) and maximum area (-a). */
15642/* Also enforce the conforming Delaunay property (-q and -a). */
15643/* - Compute the number of edges in the resulting mesh. */
15644/* - Promote the mesh's linear triangles to higher order elements (-o). */
15645/* - Write the output files and print the statistics. */
15646/* - Check the consistency and Delaunay property of the mesh (-C). */
15647/* */
15648/*****************************************************************************/
15649
15650#ifdef TRILIBRARY
15651
15652#ifdef ANSI_DECLARATORS
15653void triangulate(char *triswitches, struct triangulateio *in,
15654 struct triangulateio *out, struct triangulateio *vorout)
15655#else /* not ANSI_DECLARATORS */
15656void triangulate(triswitches, in, out, vorout)
15657char *triswitches;
15658struct triangulateio *in;
15659struct triangulateio *out;
15660struct triangulateio *vorout;
15661#endif /* not ANSI_DECLARATORS */
15662
15663#else /* not TRILIBRARY */
15664
15665#ifdef ANSI_DECLARATORS
15666int main(int argc, char **argv)
15667#else /* not ANSI_DECLARATORS */
15668int main(argc, argv)
15669int argc;
15670char **argv;
15671#endif /* not ANSI_DECLARATORS */
15672
15673#endif /* not TRILIBRARY */
15674
15675{
15676 struct mesh m;
15677 struct behavior b;
15678 REAL *holearray; /* Array of holes. */
15679 REAL *regionarray; /* Array of regional attributes and area constraints. */
15680#ifndef TRILIBRARY
15681 FILE *polyfile;
15682#endif /* not TRILIBRARY */
15683#ifndef NO_TIMER
15684 /* Variables for timing the performance of Triangle. The types are */
15685 /* defined in sys/time.h. */
15686 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15687 struct timezone tz;
15688#endif /* not NO_TIMER */
15689
15690#ifndef NO_TIMER
15691 gettimeofday(&tv0, &tz);
15692#endif /* not NO_TIMER */
15693
15694 triangleinit(&m);
15695#ifdef TRILIBRARY
15696 parsecommandline(1, &triswitches, &b);
15697#else /* not TRILIBRARY */
15698 parsecommandline(argc, argv, &b);
15699#endif /* not TRILIBRARY */
15700 m.steinerleft = b.steiner;
15701
15702#ifdef TRILIBRARY
15706#else /* not TRILIBRARY */
15707 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15708#endif /* not TRILIBRARY */
15709
15710#ifndef NO_TIMER
15711 if (!b.quiet) {
15712 gettimeofday(&tv1, &tz);
15713 }
15714#endif /* not NO_TIMER */
15715
15716#ifdef CDT_ONLY
15717 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15718#else /* not CDT_ONLY */
15719 if (b.refine) {
15720 /* Read and reconstruct a mesh. */
15721#ifdef TRILIBRARY
15722 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15727 in->numberofsegments);
15728#else /* not TRILIBRARY */
15729 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15730 b.inpolyfilename, polyfile);
15731#endif /* not TRILIBRARY */
15732 } else {
15733 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15734 }
15735#endif /* not CDT_ONLY */
15736
15737#ifndef NO_TIMER
15738 if (!b.quiet) {
15739 gettimeofday(&tv2, &tz);
15740 if (b.refine) {
15741 printf("Mesh reconstruction");
15742 } else {
15743 printf("Delaunay");
15744 }
15745 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15746 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15747 }
15748#endif /* not NO_TIMER */
15749
15750 /* Ensure that no vertex can be mistaken for a triangular bounding */
15751 /* box vertex in insertvertex(). */
15752 m.infvertex1 = (vertex) NULL;
15753 m.infvertex2 = (vertex) NULL;
15754 m.infvertex3 = (vertex) NULL;
15755
15756 if (b.usesegments) {
15757 m.checksegments = 1; /* Segments will be introduced next. */
15758 if (!b.refine) {
15759 /* Insert PSLG segments and/or convex hull segments. */
15760#ifdef TRILIBRARY
15761 formskeleton(&m, &b, in->segmentlist,
15763#else /* not TRILIBRARY */
15764 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15765#endif /* not TRILIBRARY */
15766 }
15767 }
15768
15769#ifndef NO_TIMER
15770 if (!b.quiet) {
15771 gettimeofday(&tv3, &tz);
15772 if (b.usesegments && !b.refine) {
15773 printf("Segment milliseconds: %ld\n",
15774 1000l * (tv3.tv_sec - tv2.tv_sec) +
15775 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15776 }
15777 }
15778#endif /* not NO_TIMER */
15779
15780 if (b.poly && (m.triangles.items > 0)) {
15781#ifdef TRILIBRARY
15782 holearray = in->holelist;
15783 m.holes = in->numberofholes;
15784 regionarray = in->regionlist;
15785 m.regions = in->numberofregions;
15786#else /* not TRILIBRARY */
15787 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15788 &regionarray, &m.regions);
15789#endif /* not TRILIBRARY */
15790 if (!b.refine) {
15791 /* Carve out holes and concavities. */
15792 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15793 }
15794 } else {
15795 /* Without a PSLG, there can be no holes or regional attributes */
15796 /* or area constraints. The following are set to zero to avoid */
15797 /* an accidental free() later. */
15798 m.holes = 0;
15799 m.regions = 0;
15800 }
15801
15802#ifndef NO_TIMER
15803 if (!b.quiet) {
15804 gettimeofday(&tv4, &tz);
15805 if (b.poly && !b.refine) {
15806 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15807 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15808 }
15809 }
15810#endif /* not NO_TIMER */
15811
15812#ifndef CDT_ONLY
15813 if (b.quality && (m.triangles.items > 0)) {
15814 enforcequality(&m, &b); /* Enforce angle and area constraints. */
15815 }
15816#endif /* not CDT_ONLY */
15817
15818#ifndef NO_TIMER
15819 if (!b.quiet) {
15820 gettimeofday(&tv5, &tz);
15821#ifndef CDT_ONLY
15822 if (b.quality) {
15823 printf("Quality milliseconds: %ld\n",
15824 1000l * (tv5.tv_sec - tv4.tv_sec) +
15825 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15826 }
15827#endif /* not CDT_ONLY */
15828 }
15829#endif /* not NO_TIMER */
15830
15831 /* Calculate the number of edges. */
15832 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15833
15834 if (b.order > 1) {
15835 highorder(&m, &b); /* Promote elements to higher polynomial order. */
15836 }
15837 if (!b.quiet) {
15838 printf("\n");
15839 }
15840
15841#ifdef TRILIBRARY
15842 if (b.jettison) {
15843 out->numberofpoints = m.vertices.items - m.undeads;
15844 } else {
15845 out->numberofpoints = m.vertices.items;
15846 }
15847 out->numberofpointattributes = m.nextras;
15848 out->numberoftriangles = m.triangles.items;
15849 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15850 out->numberoftriangleattributes = m.eextras;
15851 out->numberofedges = m.edges;
15852 if (b.usesegments) {
15853 out->numberofsegments = m.subsegs.items;
15854 } else {
15855 out->numberofsegments = m.hullsize;
15856 }
15857 if (vorout != (struct triangulateio *) NULL) {
15858 vorout->numberofpoints = m.triangles.items;
15859 vorout->numberofpointattributes = m.nextras;
15860 vorout->numberofedges = m.edges;
15861 }
15862#endif /* TRILIBRARY */
15863 /* If not using iteration numbers, don't write a .node file if one was */
15864 /* read, because the original one would be overwritten! */
15865 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15866 if (!b.quiet) {
15867#ifdef TRILIBRARY
15868 printf("NOT writing vertices.\n");
15869#else /* not TRILIBRARY */
15870 printf("NOT writing a .node file.\n");
15871#endif /* not TRILIBRARY */
15872 }
15873 numbernodes(&m, &b); /* We must remember to number the vertices. */
15874 } else {
15875 /* writenodes() numbers the vertices too. */
15876#ifdef TRILIBRARY
15877 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15878 &out->pointmarkerlist);
15879#else /* not TRILIBRARY */
15880 writenodes(&m, &b, b.outnodefilename, argc, argv);
15881#endif /* TRILIBRARY */
15882 }
15883 if (b.noelewritten) {
15884 if (!b.quiet) {
15885#ifdef TRILIBRARY
15886 printf("NOT writing triangles.\n");
15887#else /* not TRILIBRARY */
15888 printf("NOT writing an .ele file.\n");
15889#endif /* not TRILIBRARY */
15890 }
15891 } else {
15892#ifdef TRILIBRARY
15894#else /* not TRILIBRARY */
15895 writeelements(&m, &b, b.outelefilename, argc, argv);
15896#endif /* not TRILIBRARY */
15897 }
15898 /* The -c switch (convex switch) causes a PSLG to be written */
15899 /* even if none was read. */
15900 if (b.poly || b.convex) {
15901 /* If not using iteration numbers, don't overwrite the .poly file. */
15902 if (b.nopolywritten || b.noiterationnum) {
15903 if (!b.quiet) {
15904#ifdef TRILIBRARY
15905 printf("NOT writing segments.\n");
15906#else /* not TRILIBRARY */
15907 printf("NOT writing a .poly file.\n");
15908#endif /* not TRILIBRARY */
15909 }
15910 } else {
15911#ifdef TRILIBRARY
15912 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15913 out->numberofholes = m.holes;
15914 out->numberofregions = m.regions;
15915 if (b.poly) {
15916 out->holelist = in->holelist;
15917 out->regionlist = in->regionlist;
15918 } else {
15919 out->holelist = (REAL *) NULL;
15920 out->regionlist = (REAL *) NULL;
15921 }
15922#else /* not TRILIBRARY */
15923 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15924 m.regions, argc, argv);
15925#endif /* not TRILIBRARY */
15926 }
15927 }
15928#ifndef TRILIBRARY
15929#ifndef CDT_ONLY
15930 if (m.regions > 0) {
15931 trifree((VOID *) regionarray);
15932 }
15933#endif /* not CDT_ONLY */
15934 if (m.holes > 0) {
15935 trifree((VOID *) holearray);
15936 }
15937 if (b.geomview) {
15938 writeoff(&m, &b, b.offfilename, argc, argv);
15939 }
15940#endif /* not TRILIBRARY */
15941 if (b.edgesout) {
15942#ifdef TRILIBRARY
15943 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15944#else /* not TRILIBRARY */
15945 writeedges(&m, &b, b.edgefilename, argc, argv);
15946#endif /* not TRILIBRARY */
15947 }
15948 if (b.voronoi) {
15949#ifdef TRILIBRARY
15950 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15951 &vorout->pointmarkerlist, &vorout->edgelist,
15952 &vorout->edgemarkerlist, &vorout->normlist);
15953#else /* not TRILIBRARY */
15954 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15955#endif /* not TRILIBRARY */
15956 }
15957 if (b.neighbors) {
15958#ifdef TRILIBRARY
15959 writeneighbors(&m, &b, &out->neighborlist);
15960#else /* not TRILIBRARY */
15961 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15962#endif /* not TRILIBRARY */
15963 }
15964
15965 if (!b.quiet) {
15966#ifndef NO_TIMER
15967 gettimeofday(&tv6, &tz);
15968 printf("\nOutput milliseconds: %ld\n",
15969 1000l * (tv6.tv_sec - tv5.tv_sec) +
15970 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15971 printf("Total running milliseconds: %ld\n",
15972 1000l * (tv6.tv_sec - tv0.tv_sec) +
15973 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15974#endif /* not NO_TIMER */
15975
15976 statistics(&m, &b);
15977 }
15978
15979#ifndef REDUCED
15980 if (b.docheck) {
15981 checkmesh(&m, &b);
15982 checkdelaunay(&m, &b);
15983 }
15984#endif /* not REDUCED */
15985
15986 triangledeinit(&m, &b);
15987#ifndef TRILIBRARY
15988 return 0;
15989#endif /* not TRILIBRARY */
15990}
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
int main()
Definition Prototype.cxx:12
#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
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
include TDocParser_001 C image html pict1_TDocParser_001 png width
float xmin
float ymin
float xmax
float ymax
TCanvas * alignment()
Definition alignment.C:1
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
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
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
Definition first.py:1
vertex subsegdest
Definition triangle.c:520
vertex subsegorg
Definition triangle.c:520
subseg encsubseg
Definition triangle.c:519
triangle poortri
Definition triangle.c:528
vertex triangapex
Definition triangle.c:530
vertex triangorg
Definition triangle.c:530
vertex triangdest
Definition triangle.c:530
struct badtriang * nexttriang
Definition triangle.c:531
REAL key
Definition triangle.c:529
int noexact
Definition triangle.c:759
int nopolywritten
Definition triangle.c:758
REAL maxarea
Definition triangle.c:769
int convex
Definition triangle.c:755
int steiner
Definition triangle.c:767
int conformdel
Definition triangle.c:759
int weighted
Definition triangle.c:755
REAL goodangle
Definition triangle.c:768
int dwyer
Definition triangle.c:760
int neighbors
Definition triangle.c:757
int noelewritten
Definition triangle.c:758
int order
Definition triangle.c:765
int poly
Definition triangle.c:754
int fixedarea
Definition triangle.c:754
int usesegments
Definition triangle.c:764
int sweepline
Definition triangle.c:760
int quiet
Definition triangle.c:763
int firstnumber
Definition triangle.c:756
int edgesout
Definition triangle.c:757
int refine
Definition triangle.c:754
int noholes
Definition triangle.c:759
int geomview
Definition triangle.c:757
int incremental
Definition triangle.c:760
int regionattrib
Definition triangle.c:755
int noiterationnum
Definition triangle.c:758
int nobisect
Definition triangle.c:766
int verbose
Definition triangle.c:763
int nobound
Definition triangle.c:758
int splitseg
Definition triangle.c:761
int vararea
Definition triangle.c:754
REAL offconstant
Definition triangle.c:768
int nonodewritten
Definition triangle.c:758
int voronoi
Definition triangle.c:757
int docheck
Definition triangle.c:762
int jettison
Definition triangle.c:755
int usertest
Definition triangle.c:754
int quality
Definition triangle.c:754
REAL minangle
Definition triangle.c:768
REAL ykey
Definition triangle.c:554
REAL xkey
Definition triangle.c:554
int heapposition
Definition triangle.c:556
VOID * eventptr
Definition triangle.c:555
struct flipstacker * prevflip
Definition triangle.c:540
triangle flippedtri
Definition triangle.c:539
int alignbytes
Definition triangle.c:605
int itembytes
Definition triangle.c:606
int pathitemsleft
Definition triangle.c:611
VOID * pathitem
Definition triangle.c:604
int itemsperblock
Definition triangle.c:607
VOID ** pathblock
Definition triangle.c:603
long maxitems
Definition triangle.c:609
VOID * deaditemstack
Definition triangle.c:602
VOID * nextitem
Definition triangle.c:601
long items
Definition triangle.c:609
VOID ** nowblock
Definition triangle.c:600
int unallocateditems
Definition triangle.c:610
int itemsfirstblock
Definition triangle.c:608
VOID ** firstblock
Definition triangle.c:600
int mesh_dim
Definition triangle.c:670
struct memorypool badtriangles
Definition triangle.c:643
long orient3dcount
Definition triangle.c:687
long edges
Definition triangle.c:669
int eextras
Definition triangle.c:672
struct badtriang * queuetail[4096]
Definition triangle.c:651
long circumcentercount
Definition triangle.c:689
struct memorypool flipstackers
Definition triangle.c:644
int inelements
Definition triangle.c:664
long samples
Definition triangle.c:683
int regions
Definition triangle.c:667
int invertices
Definition triangle.c:663
REAL ymin
Definition triangle.c:661
struct memorypool subsegs
Definition triangle.c:639
struct memorypool viri
Definition triangle.c:641
struct otri recenttri
Definition triangle.c:711
int firstnonemptyq
Definition triangle.c:653
long hullsize
Definition triangle.c:673
long incirclecount
Definition triangle.c:685
vertex infvertex3
Definition triangle.c:694
int vertex2triindex
Definition triangle.c:676
REAL ymax
Definition triangle.c:661
subseg * dummysubbase
Definition triangle.c:706
int nextnonemptyq[4096]
Definition triangle.c:652
REAL xmax
Definition triangle.c:661
struct memorypool triangles
Definition triangle.c:638
int steinerleft
Definition triangle.c:674
int insegments
Definition triangle.c:665
int holes
Definition triangle.c:666
REAL xmin
Definition triangle.c:661
struct memorypool splaynodes
Definition triangle.c:645
struct flipstacker * lastflip
Definition triangle.c:657
int checksegments
Definition triangle.c:680
long counterclockcount
Definition triangle.c:686
triangle * dummytribase
Definition triangle.c:699
struct memorypool vertices
Definition triangle.c:640
long circletopcount
Definition triangle.c:690
int nextras
Definition triangle.c:671
struct badtriang * queuefront[4096]
Definition triangle.c:650
int highorderindex
Definition triangle.c:677
int readnodefile
Definition triangle.c:682
int undeads
Definition triangle.c:668
vertex infvertex1
Definition triangle.c:694
subseg * dummysub
Definition triangle.c:705
int checkquality
Definition triangle.c:681
int vertexmarkindex
Definition triangle.c:675
long hyperbolacount
Definition triangle.c:688
REAL xminextreme
Definition triangle.c:662
int elemattribindex
Definition triangle.c:678
int areaboundindex
Definition triangle.c:679
triangle * dummytri
Definition triangle.c:698
struct memorypool badsubsegs
Definition triangle.c:642
vertex infvertex2
Definition triangle.c:694
int ssorient
Definition triangle.c:505
subseg * ss
Definition triangle.c:504
triangle * tri
Definition triangle.c:487
int orient
Definition triangle.c:488
vertex keydest
Definition triangle.c:572
struct splaynode * lchild
Definition triangle.c:573
struct otri keyedge
Definition triangle.c:571
struct splaynode * rchild
Definition triangle.c:573
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 uint64_t sum(uint64_t i)
Definition Factory.cxx:2345
#define SEGMENTVERTEX
Definition triangle.c:284
#define sdest(osub, vertexptr)
Definition triangle.c:1182
#define sorg(osub, vertexptr)
Definition triangle.c:1179
#define VIRUSPERBLOCK
Definition triangle.c:269
REAL splitter
Definition triangle.c:617
VOID * traverse(struct memorypool *pool)
Definition triangle.c:4102
void highorder(struct mesh *m, struct behavior *b)
Definition triangle.c:13695
#define apex(otri, vertexptr)
Definition triangle.c:1044
void makevertexmap(struct mesh *m, struct behavior *b)
Definition triangle.c:7376
#define Square(a, x, y)
Definition triangle.c:4813
#define dnext(otri1, otri2)
Definition triangle.c:987
void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, REAL **pointattriblist, int **pointmarkerlist)
Definition triangle.c:14306
finddirectionresult
Definition triangle.c:360
@ LEFTCOLLINEAR
Definition triangle.c:360
@ RIGHTCOLLINEAR
Definition triangle.c:360
@ WITHIN
Definition triangle.c:360
void numbernodes(struct mesh *m, struct behavior *b)
Definition triangle.c:14446
#define vertextype(vx)
Definition triangle.c:1289
void writepoly(struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist)
Definition triangle.c:14619
vertex getvertex(struct mesh *m, struct behavior *b, int number)
Definition triangle.c:4556
#define setelemattribute(otri, attnum, value)
Definition triangle.c:1103
#define setsorg(osub, vertexptr)
Definition triangle.c:1185
#define segdest(osub, vertexptr)
Definition triangle.c:1194
void poolrestart(struct memorypool *pool)
Definition triangle.c:3865
#define segorg(osub, vertexptr)
Definition triangle.c:1191
#define Two_Product(a, b, x, y)
Definition triangle.c:4790
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
Definition triangle.c:9258
#define sdecode(sptr, osub)
Definition triangle.c:1133
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
Definition triangle.c:8174
#define setorg(otri, vertexptr)
Definition triangle.c:1047
void exactinit()
Definition triangle.c:4864
REAL estimate(int elen, REAL *e)
Definition triangle.c:5088
#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:7471
#define elemattribute(otri, attnum)
Definition triangle.c:1100
#define FILENAMESIZE
Definition triangle.c:255
int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
Definition triangle.c:4938
void makesubseg(struct mesh *m, struct osub *newsubseg)
Definition triangle.c:4682
#define vertexmark(vx)
Definition triangle.c:1284
#define bond(otri1, otri2)
Definition triangle.c:1058
#define snextself(osub)
Definition triangle.c:1172
#define onextself(otri)
Definition triangle.c:967
#define encode(otri)
Definition triangle.c:922
void trifree(VOID *memptr)
Definition triangle.c:1415
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
Definition triangle.c:4357
void pooldealloc(struct memorypool *pool, VOID *dyingitem)
Definition triangle.c:4043
#define infect(otri)
Definition triangle.c:1085
#define INPUTLINESIZE
Definition triangle.c:260
#define tsdissolve(otri)
Definition triangle.c:1272
#define setsegorg(osub, vertexptr)
Definition triangle.c:1197
void alternateaxes(vertex *sortarray, int arraysize, int axis)
Definition triangle.c:9336
#define lnext(otri1, otri2)
Definition triangle.c:943
int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
Definition triangle.c:1337
void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
Definition triangle.c:15132
REAL ** triangle
Definition triangle.c:479
REAL iccerrboundB
Definition triangle.c:621
#define dissolve(otri)
Definition triangle.c:1067
#define mark(osub)
Definition triangle.c:1207
REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight, REAL permanent)
Definition triangle.c:5946
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
Definition triangle.c:11670
long divconqdelaunay(struct mesh *m, struct behavior *b)
Definition triangle.c:9954
#define Two_Product_Presplit(a, b, bhi, blo, x, y)
Definition triangle.c:4797
void regionplague(struct mesh *m, struct behavior *b, REAL attribute, REAL area)
Definition triangle.c:12851
REAL ccwerrboundB
Definition triangle.c:620
#define onext(otri1, otri2)
Definition triangle.c:963
#define TRIPERBLOCK
Definition triangle.c:266
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
Definition triangle.c:12012
void triangledeinit(struct mesh *m, struct behavior *b)
Definition triangle.c:4597
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
Definition triangle.c:3911
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
Definition triangle.c:7615
vertex vertextraverse(struct mesh *m)
Definition triangle.c:4470
#define oprevself(otri)
Definition triangle.c:979
#define SAMPLERATE
Definition triangle.c:301
#define lprev(otri1, otri2)
Definition triangle.c:952
#define killsubseg(sub)
Definition triangle.c:1243
#define FREEVERTEX
Definition triangle.c:285
triangle * triangletraverse(struct mesh *m)
Definition triangle.c:4378
#define tspivot(otri, osub)
Definition triangle.c:1253
#define STARTINDEX
#define ssymself(osub)
Definition triangle.c:1151
#define PI
Definition triangle.c:305
VOID * poolalloc(struct memorypool *pool)
Definition triangle.c:3980
REAL o3derrboundC
Definition triangle.c:622
int plus1mod3[3]
Definition triangle.c:903
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
Definition triangle.c:4638
void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
Definition triangle.c:3641
#define Two_Diff_Tail(a, b, x, y)
Definition triangle.c:4765
void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, REAL **vpointattriblist, int **vpointmarkerlist, int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
Definition triangle.c:14919
insertvertexresult
Definition triangle.c:352
@ SUCCESSFULVERTEX
Definition triangle.c:352
@ ENCROACHINGVERTEX
Definition triangle.c:352
@ VIOLATINGVERTEX
Definition triangle.c:352
@ DUPLICATEVERTEX
Definition triangle.c:353
void triexit(int status)
Definition triangle.c:1386
void poolzero(struct memorypool *pool)
Definition triangle.c:3831
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
Definition triangle.c:7786
#define dprev(otri1, otri2)
Definition triangle.c:999
#define vertex2tri(vx)
Definition triangle.c:1294
REAL ccwerrboundC
Definition triangle.c:620
uintptr_t randomseed
Definition triangle.c:626
#define lnextself(otri)
Definition triangle.c:947
#define areabound(otri)
Definition triangle.c:1108
#define DEADVERTEX
Definition triangle.c:286
void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments)
Definition triangle.c:12392
locateresult
Definition triangle.c:344
@ OUTSIDE
Definition triangle.c:344
@ INTRIANGLE
Definition triangle.c:344
@ ONVERTEX
Definition triangle.c:344
@ ONEDGE
Definition triangle.c:344
#define deadtri(tria)
Definition triangle.c:1118
#define setvertexmark(vx, value)
Definition triangle.c:1286
REAL o3derrboundB
Definition triangle.c:622
#define SPLAYNODEPERBLOCK
Definition triangle.c:277
void triangulate(char *triswitches, struct triangulateio *in, struct triangulateio *out, struct triangulateio *vorout)
Definition triangle.c:15653
#define setvertex2tri(vx, value)
Definition triangle.c:1296
#define deadsubseg(sub)
Definition triangle.c:1241
void initializevertexpool(struct mesh *m, struct behavior *b)
Definition triangle.c:4247
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
Definition triangle.c:8835
#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:9400
void parsecommandline(int argc, char **argv, struct behavior *b)
Definition triangle.c:3258
VOID * trimalloc(int size)
Definition triangle.c:1397
#define oprev(otri1, otri2)
Definition triangle.c:975
#define killtri(tria)
Definition triangle.c:1120
REAL epsilon
Definition triangle.c:618
#define BADSUBSEGPERBLOCK
Definition triangle.c:271
void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
Definition triangle.c:4403
#define INPUTVERTEX
Definition triangle.c:283
long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
Definition triangle.c:9891
void vertexdealloc(struct mesh *m, vertex dyingvertex)
Definition triangle.c:4449
void infecthull(struct mesh *m, struct behavior *b)
Definition triangle.c:12559
void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, REAL *regionlist, int regions)
Definition triangle.c:12964
#define setapex(otri, vertexptr)
Definition triangle.c:1053
#define UNDEADVERTEX
Definition triangle.c:287
#define dest(otri, vertexptr)
Definition triangle.c:1041
void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist, REAL *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs)
Definition triangle.c:14068
#define otricopy(otri1, otri2)
Definition triangle.c:1072
#define Two_Sum(a, b, x, y)
Definition triangle.c:4761
#define tsbond(otri, osub)
Definition triangle.c:1266
#define setmark(osub, value)
Definition triangle.c:1209
#define stdissolve(osub)
Definition triangle.c:1277
void initializetrisubpools(struct mesh *m, struct behavior *b)
Definition triangle.c:4290
#define BADTRIPERBLOCK
Definition triangle.c:273
int minus1mod3[3]
Definition triangle.c:904
void writeedges(struct mesh *m, struct behavior *b, int **edgelist, int **edgemarkerlist)
Definition triangle.c:14765
REAL ** subseg
Definition triangle.c:496
#define Two_One_Product(a1, a0, b, x3, x2, x1, x0)
Definition triangle.c:4838
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
Definition triangle.c:4832
long delaunay(struct mesh *m, struct behavior *b)
Definition triangle.c:10998
#define setdest(otri, vertexptr)
Definition triangle.c:1050
void markhull(struct mesh *m, struct behavior *b)
Definition triangle.c:12346
void vertexsort(vertex *sortarray, int arraysize)
Definition triangle.c:9184
REAL o3derrboundA
Definition triangle.c:622
REAL incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
Definition triangle.c:5864
#define dnextself(otri)
Definition triangle.c:991
#define stpivot(osub, otri)
Definition triangle.c:1260
#define VERTEXPERBLOCK
Definition triangle.c:268
REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
Definition triangle.c:5127
int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
Definition triangle.c:5032
#define decode(ptr, otri)
Definition triangle.c:913
#define otriequal(otri1, otri2)
Definition triangle.c:1078
#define org(otri, vertexptr)
Definition triangle.c:1038
#define sdissolve(osub)
Definition triangle.c:1221
void traversalinit(struct memorypool *pool)
Definition triangle.c:4066
#define symself(otri)
Definition triangle.c:937
#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:6454
void plague(struct mesh *m, struct behavior *b)
Definition triangle.c:12641
#define setsegdest(osub, vertexptr)
Definition triangle.c:1200
#define uninfect(otri)
Definition triangle.c:1089
#define lprevself(otri)
Definition triangle.c:956
REAL resulterrbound
Definition triangle.c:619
void internalerror()
Definition triangle.c:3242
#define FLIPSTACKERPERBLOCK
Definition triangle.c:275
REAL * vertex
Definition triangle.c:513
void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition triangle.c:8025
#define setvertextype(vx, value)
Definition triangle.c:1291
#define INEXACT
Definition triangle.c:250
uintptr_t randomnation(unsigned int choices)
Definition triangle.c:6648
void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes)
Definition triangle.c:4167
#define sym(otri1, otri2)
Definition triangle.c:933
void quality_statistics(struct mesh *m, struct behavior *b)
Definition triangle.c:15325
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition triangle.c:7890
#define sencode(osub)
Definition triangle.c:1142
REAL counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
Definition triangle.c:5216
void pooldeinit(struct memorypool *pool)
Definition triangle.c:3959
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
Definition triangle.c:11575
REAL ccwerrboundA
Definition triangle.c:620
REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
Definition triangle.c:5285
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
Definition triangle.c:12132
#define setsdest(osub, vertexptr)
Definition triangle.c:1188
REAL iccerrboundA
Definition triangle.c:621
#define spivot(osub1, osub2)
Definition triangle.c:1157
#define infected(otri)
Definition triangle.c:1095
#define ssym(osub1, osub2)
Definition triangle.c:1147
void writeelements(struct mesh *m, struct behavior *b, int **trianglelist, REAL **triangleattriblist)
Definition triangle.c:14478
void insertsegment(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
Definition triangle.c:12234
#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0)
Definition triangle.c:4828
void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
Definition triangle.c:3735
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
Definition triangle.c:9727
#define Fast_Two_Sum(a, b, x, y)
Definition triangle.c:4750
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
Definition triangle.c:11798
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:6495
#define Split(a, ahi, alo)
Definition triangle.c:4776
#define Absolute(a)
Definition triangle.c:4730
subseg * subsegtraverse(struct mesh *m)
Definition triangle.c:4424
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:6371
void statistics(struct mesh *m, struct behavior *b)
Definition triangle.c:15533
REAL iccerrboundC
Definition triangle.c:621
#define sbond(osub1, osub2)
Definition triangle.c:1214
#define setareabound(otri, value)
Definition triangle.c:1110
void triangleinit(struct mesh *m)
Definition triangle.c:6609
#define REAL
Definition triangle.h:277
#define VOID
Definition triangle.h:286