Chaste Commit::1fd4e48e3990e67db148bc1bc4cf6991a0049d0c
triangle.cpp
Go to the documentation of this file.
1
8/*****************************************************************************/
9/* */
10/* 888888888 ,o, / 888 */
11/* 888 88o88o " o8888o 88o8888o o88888o 888 o88888o */
12/* 888 888 888 88b 888 888 888 888 888 d888 88b */
13/* 888 888 888 o88^o888 888 888 "88888" 888 8888oo888 */
14/* 888 888 888 C888 888 888 888 / 888 q888 */
15/* 888 888 888 "88o^888 888 888 Cb 888 "88oooo" */
16/* "8oo8D */
17/* */
18/* A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator. */
19/* (triangle.c) */
20/* */
21/* Version 1.6 */
22/* July 28, 2005 */
23/* */
24/* Copyright 1993, 1995, 1997, 1998, 2002, 2005 */
25/* Jonathan Richard Shewchuk */
26/* 2360 Woolsey #H */
27/* Berkeley, California 94705-1927 */
28/* jrs@cs.berkeley.edu */
29/* */
30/* This program may be freely redistributed under the condition that the */
31/* copyright notices (including this entire header and the copyright */
32/* notice printed when the `-h' switch is selected) are not removed, and */
33/* no compensation is received. Private, research, and institutional */
34/* use is free. You may distribute modified versions of this code UNDER */
35/* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */
36/* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */
37/* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */
38/* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */
39/* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */
40/* WITH THE AUTHOR. (If you are not directly supplying this code to a */
41/* customer, and you are instead telling them how they can obtain it for */
42/* free, then you are not required to make any arrangement with me.) */
43/* */
44/* Hypertext instructions for Triangle are available on the Web at */
45/* */
46/* http://www.cs.cmu.edu/~quake/triangle.html */
47/* */
48/* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */
49/* whatsoever. This code is provided "as-is". Use at your own risk. */
50/* */
51/* Some of the references listed below are marked with an asterisk. [*] */
52/* These references are available for downloading from the Web page */
53/* */
54/* http://www.cs.cmu.edu/~quake/triangle.research.html */
55/* */
56/* Three papers discussing aspects of Triangle are available. A short */
57/* overview appears in "Triangle: Engineering a 2D Quality Mesh */
58/* Generator and Delaunay Triangulator," in Applied Computational */
59/* Geometry: Towards Geometric Engineering, Ming C. Lin and Dinesh */
60/* Manocha, editors, Lecture Notes in Computer Science volume 1148, */
61/* pages 203-222, Springer-Verlag, Berlin, May 1996 (from the First ACM */
62/* Workshop on Applied Computational Geometry). [*] */
63/* */
64/* The algorithms are discussed in the greatest detail in "Delaunay */
65/* Refinement Algorithms for Triangular Mesh Generation," Computational */
66/* Geometry: Theory and Applications 22(1-3):21-74, May 2002. [*] */
67/* */
68/* More detail about the data structures may be found in my dissertation: */
69/* "Delaunay Refinement Mesh Generation," Ph.D. thesis, Technical Report */
70/* CMU-CS-97-137, School of Computer Science, Carnegie Mellon University, */
71/* Pittsburgh, Pennsylvania, 18 May 1997. [*] */
72/* */
73/* Triangle was created as part of the Quake Project in the School of */
74/* Computer Science at Carnegie Mellon University. For further */
75/* information, see Hesheng Bao, Jacobo Bielak, Omar Ghattas, Loukas F. */
76/* Kallivokas, David R. O'Hallaron, Jonathan R. Shewchuk, and Jifeng Xu, */
77/* "Large-scale Simulation of Elastic Wave Propagation in Heterogeneous */
78/* Media on Parallel Computers," Computer Methods in Applied Mechanics */
79/* and Engineering 152(1-2):85-102, 22 January 1998. */
80/* */
81/* Triangle's Delaunay refinement algorithm for quality mesh generation is */
82/* a hybrid of one due to Jim Ruppert, "A Delaunay Refinement Algorithm */
83/* for Quality 2-Dimensional Mesh Generation," Journal of Algorithms */
84/* 18(3):548-585, May 1995 [*], and one due to L. Paul Chew, "Guaranteed- */
85/* Quality Mesh Generation for Curved Surfaces," Proceedings of the Ninth */
86/* Annual Symposium on Computational Geometry (San Diego, California), */
87/* pages 274-280, Association for Computing Machinery, May 1993, */
88/* http://portal.acm.org/citation.cfm?id=161150 . */
89/* */
90/* The Delaunay refinement algorithm has been modified so that it meshes */
91/* domains with small input angles well, as described in Gary L. Miller, */
92/* Steven E. Pav, and Noel J. Walkington, "When and Why Ruppert's */
93/* Algorithm Works," Twelfth International Meshing Roundtable, pages */
94/* 91-102, Sandia National Laboratories, September 2003. [*] */
95/* */
96/* My implementation of the divide-and-conquer and incremental Delaunay */
97/* triangulation algorithms follows closely the presentation of Guibas */
98/* and Stolfi, even though I use a triangle-based data structure instead */
99/* of their quad-edge data structure. (In fact, I originally implemented */
100/* Triangle using the quad-edge data structure, but the switch to a */
101/* triangle-based data structure sped Triangle by a factor of two.) The */
102/* mesh manipulation primitives and the two aforementioned Delaunay */
103/* triangulation algorithms are described by Leonidas J. Guibas and Jorge */
104/* Stolfi, "Primitives for the Manipulation of General Subdivisions and */
105/* the Computation of Voronoi Diagrams," ACM Transactions on Graphics */
106/* 4(2):74-123, April 1985, http://portal.acm.org/citation.cfm?id=282923 .*/
107/* */
108/* Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai */
109/* Lee and Bruce J. Schachter, "Two Algorithms for Constructing the */
110/* Delaunay Triangulation," International Journal of Computer and */
111/* Information Science 9(3):219-242, 1980. Triangle's improvement of the */
112/* divide-and-conquer algorithm by alternating between vertical and */
113/* horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and- */
114/* Conquer Algorithm for Constructing Delaunay Triangulations," */
115/* Algorithmica 2(2):137-151, 1987. */
116/* */
117/* The incremental insertion algorithm was first proposed by C. L. Lawson, */
118/* "Software for C1 Surface Interpolation," in Mathematical Software III, */
119/* John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977. */
120/* For point location, I use the algorithm of Ernst P. Mucke, Isaac */
121/* Saias, and Binhai Zhu, "Fast Randomized Point Location Without */
122/* Preprocessing in Two- and Three-Dimensional Delaunay Triangulations," */
123/* Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
124/* ACM, May 1996. [*] If I were to randomize the order of vertex */
125/* insertion (I currently don't bother), their result combined with the */
126/* result of Kenneth L. Clarkson and Peter W. Shor, "Applications of */
127/* Random Sampling in Computational Geometry II," Discrete & */
128/* Computational Geometry 4(1):387-421, 1989, would yield an expected */
129/* O(n^{4/3}) bound on running time. */
130/* */
131/* The O(n log n) sweepline Delaunay triangulation algorithm is taken from */
132/* Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams", */
133/* Algorithmica 2(2):153-174, 1987. A random sample of edges on the */
134/* boundary of the triangulation are maintained in a splay tree for the */
135/* purpose of point location. Splay trees are described by Daniel */
136/* Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
137/* Trees," Journal of the ACM 32(3):652-686, July 1985, */
138/* http://portal.acm.org/citation.cfm?id=3835 . */
139/* */
140/* The algorithms for exact computation of the signs of determinants are */
141/* described in Jonathan Richard Shewchuk, "Adaptive Precision Floating- */
142/* Point Arithmetic and Fast Robust Geometric Predicates," Discrete & */
143/* Computational Geometry 18(3):305-363, October 1997. (Also available */
144/* as Technical Report CMU-CS-96-140, School of Computer Science, */
145/* Carnegie Mellon University, Pittsburgh, Pennsylvania, May 1996.) [*] */
146/* An abbreviated version appears as Jonathan Richard Shewchuk, "Robust */
147/* Adaptive Floating-Point Geometric Predicates," Proceedings of the */
148/* Twelfth Annual Symposium on Computational Geometry, ACM, May 1996. [*] */
149/* Many of the ideas for my exact arithmetic routines originate with */
150/* Douglas M. Priest, "Algorithms for Arbitrary Precision Floating Point */
151/* Arithmetic," Tenth Symposium on Computer Arithmetic, pp. 132-143, IEEE */
152/* Computer Society Press, 1991. [*] Many of the ideas for the correct */
153/* evaluation of the signs of determinants are taken from Steven Fortune */
154/* and Christopher J. Van Wyk, "Efficient Exact Arithmetic for Computa- */
155/* tional Geometry," Proceedings of the Ninth Annual Symposium on */
156/* Computational Geometry, ACM, pp. 163-172, May 1993, and from Steven */
157/* Fortune, "Numerical Stability of Algorithms for 2D Delaunay Triangu- */
158/* lations," International Journal of Computational Geometry & Applica- */
159/* tions 5(1-2):193-213, March-June 1995. */
160/* */
161/* The method of inserting new vertices off-center (not precisely at the */
162/* circumcenter of every poor-quality triangle) is from Alper Ungor, */
163/* "Off-centers: A New Type of Steiner Points for Computing Size-Optimal */
164/* Quality-Guaranteed Delaunay Triangulations," Proceedings of LATIN */
165/* 2004 (Buenos Aires, Argentina), April 2004. */
166/* */
167/* For definitions of and results involving Delaunay triangulations, */
168/* constrained and conforming versions thereof, and other aspects of */
169/* triangular mesh generation, see the excellent survey by Marshall Bern */
170/* and David Eppstein, "Mesh Generation and Optimal Triangulation," in */
171/* Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang, */
172/* editors, World Scientific, Singapore, pp. 23-90, 1992. [*] */
173/* */
174/* The time for incrementally adding PSLG (planar straight line graph) */
175/* segments to create a constrained Delaunay triangulation is probably */
176/* O(t^2) per segment in the worst case and O(t) per segment in the */
177/* common case, where t is the number of triangles that intersect the */
178/* segment before it is inserted. This doesn't count point location, */
179/* which can be much more expensive. I could improve this to O(d log d) */
180/* time, but d is usually quite small, so it's not worth the bother. */
181/* (This note does not apply when the -s switch is used, invoking a */
182/* different method is used to insert segments.) */
183/* */
184/* The time for deleting a vertex from a Delaunay triangulation is O(d^2) */
185/* in the worst case and O(d) in the common case, where d is the degree */
186/* of the vertex being deleted. I could improve this to O(d log d) time, */
187/* but d is usually quite small, so it's not worth the bother. */
188/* */
189/* Ruppert's Delaunay refinement algorithm typically generates triangles */
190/* at a linear rate (constant time per triangle) after the initial */
191/* triangulation is formed. There may be pathological cases where */
192/* quadratic time is required, but these never arise in practice. */
193/* */
194/* The geometric predicates (circumcenter calculations, segment */
195/* intersection formulae, etc.) appear in my "Lecture Notes on Geometric */
196/* Robustness" at http://www.cs.berkeley.edu/~jrs/mesh . */
197/* */
198/* If you make any improvements to this code, please please please let me */
199/* know, so that I may obtain the improvements. Even if you don't change */
200/* the code, I'd still love to hear what it's being used for. */
201/* */
202/*****************************************************************************/
203
204/* For single precision (which will save some memory and reduce paging), */
205/* define the symbol SINGLE by using the -DSINGLE compiler switch or by */
206/* writing "#define SINGLE" below. */
207/* */
208/* For double precision (which will allow you to refine meshes to a smaller */
209/* edge length), leave SINGLE undefined. */
210/* */
211/* Double precision uses more memory, but improves the resolution of the */
212/* meshes you can generate with Triangle. It also reduces the likelihood */
213/* of a floating exception due to overflow. Finally, it is much faster */
214/* than single precision on 64-bit architectures like the DEC Alpha. I */
215/* recommend double precision unless you want to generate a mesh for which */
216/* you do not have enough memory. */
217
218/* #define SINGLE */
219
220#ifdef SINGLE
221#define REAL float
222#else /* not SINGLE */
223#define REAL double
224#endif /* not SINGLE */
225
226/* If yours is not a Unix system, define the NO_TIMER compiler switch to */
227/* remove the Unix-specific timing code. */
228
229/* #define NO_TIMER */
230
231/* To insert lots of self-checks for internal errors, define the SELF_CHECK */
232/* symbol. This will slow down the program significantly. It is best to */
233/* define the symbol using the -DSELF_CHECK compiler switch, but you could */
234/* write "#define SELF_CHECK" below. If you are modifying this code, I */
235/* recommend you turn self-checks on until your work is debugged. */
236
237/* #define SELF_CHECK */
238
239/* To compile Triangle as a callable object library (triangle.o), define the */
240/* TRILIBRARY symbol. Read the file triangle.h for details on how to call */
241/* the procedure triangulate() that results. */
242
243/* #define TRILIBRARY */
244
245/* It is possible to generate a smaller version of Triangle using one or */
246/* both of the following symbols. Define the REDUCED symbol to eliminate */
247/* all features that are primarily of research interest; specifically, the */
248/* -i, -F, -s, and -C switches. Define the CDT_ONLY symbol to eliminate */
249/* all meshing algorithms above and beyond constrained Delaunay */
250/* triangulation; specifically, the -r, -q, -a, -u, -D, -S, and -s */
251/* switches. These reductions are most likely to be useful when */
252/* generating an object library (triangle.o) by defining the TRILIBRARY */
253/* symbol. */
254
255/* #define REDUCED */
256/* #define CDT_ONLY */
257
258/* On some machines, my exact arithmetic routines might be defeated by the */
259/* use of internal extended precision floating-point registers. The best */
260/* way to solve this problem is to set the floating-point registers to use */
261/* single or double precision internally. On 80x86 processors, this may */
262/* be accomplished by setting the CPU86 symbol for the Microsoft C */
263/* compiler, or the LINUX symbol for the gcc compiler running on Linux. */
264/* */
265/* An inferior solution is to declare certain values as `volatile', thus */
266/* forcing them to be stored to memory and rounded off. Unfortunately, */
267/* this solution might slow Triangle down quite a bit. To use volatile */
268/* values, write "#define INEXACT volatile" below. Normally, however, */
269/* INEXACT should be defined to be nothing. ("#define INEXACT".) */
270/* */
271/* For more discussion, see http://www.cs.cmu.edu/~quake/robust.pc.html . */
272/* For yet more discussion, see Section 5 of my paper, "Adaptive Precision */
273/* Floating-Point Arithmetic and Fast Robust Geometric Predicates" (also */
274/* available as Section 6.6 of my dissertation). */
275
276/* #define CPU86 */
277/* #define LINUX */
278
279#define INEXACT /* Nothing */
280/* #define INEXACT volatile */
281
282/* Maximum number of characters in a file name (including the null). */
283
284#define FILENAMESIZE 2048
285
286/* Maximum number of characters in a line read from a file (including the */
287/* null). */
288
289#define INPUTLINESIZE 1024
290
291/* For efficiency, a variety of data structures are allocated in bulk. The */
292/* following constants determine how many of each structure is allocated */
293/* at once. */
294
295#define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */
296#define SUBSEGPERBLOCK 508 /* Number of subsegments allocated at once. */
297#define VERTEXPERBLOCK 4092 /* Number of vertices allocated at once. */
298#define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */
299/* Number of encroached subsegments allocated at once. */
300#define BADSUBSEGPERBLOCK 252
301/* Number of skinny triangles allocated at once. */
302#define BADTRIPERBLOCK 4092
303/* Number of flipped triangles allocated at once. */
304#define FLIPSTACKERPERBLOCK 252
305/* Number of splay tree nodes allocated at once. */
306#define SPLAYNODEPERBLOCK 508
307
308/* The vertex types. A DEADVERTEX has been deleted entirely. An */
309/* UNDEADVERTEX is not part of the mesh, but is written to the output */
310/* .node file and affects the node indexing in the other output files. */
311
312#define INPUTVERTEX 0
313#define SEGMENTVERTEX 1
314#define FREEVERTEX 2
315#define DEADVERTEX -32768
316#define UNDEADVERTEX -32767
317
318/* The next line is used to outsmart some very stupid compilers. If your */
319/* compiler is smarter, feel free to replace the "int" with "void". */
320/* Not that it matters. */
321
322/*Windows_Port_Begins*/
323#ifdef _MSC_VER
324#else
325 /*This gave me a whole lot of grief with Windows SDK*/
326 #define VOID int
327#endif
328/*Windows_Port_Begins*/
329
330/* Two constants for algorithms based on random sampling. Both constants */
331/* have been chosen empirically to optimize their respective algorithms. */
332
333/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */
334/* how large a random sample of triangles to inspect. */
335
336#define SAMPLEFACTOR 11
337
338/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
339/* of boundary edges should be maintained in the splay tree for point */
340/* location on the front. */
341
342#define SAMPLERATE 10
343
344/* A number that speaks for itself, every kissable digit. */
345
346#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
347
348/* Another fave. */
349
350#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
351
352/* And here's one for those of you who are intimidated by math. */
353
354#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
355
356#include <stdio.h>
357#include <stdlib.h>
358#include <string.h>
359#include <math.h>
360#ifndef NO_TIMER
361#ifdef _MSC_VER
362#include <time.h>
363#include <WinSock2.h>
364#include <windows.h>
365//The portion below is adapted from http://www.suacommunity.com/dictionary/gettimeofday-entry.php
366#if defined(_MSC_EXTENSIONS)
367 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
368#else
369 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
370#endif
371
372struct timezone
373{
374 int tz_minuteswest; /* minutes W of Greenwich */
375 int tz_dsttime; /* type of dst correction */
376};
377
378// Definition of a gettimeofday function
379
380int gettimeofday(struct timeval *tv, struct timezone *tz)
381{
382 // Define a structure to receive the current Windows filetime
383 FILETIME ft;
384
385 // Initialize the present time to 0 and the timezone to UTC
386 unsigned __int64 tmpres = 0;
387 static int tzflag = 0;
388
389 if (NULL != tv)
390 {
391 GetSystemTimeAsFileTime(&ft);
392
393 // The GetSystemTimeAsFileTime returns the number of 100 nanosecond
394 // intervals since Jan 1, 1601 in a structure. Copy the high bits to
395 // the 64 bit tmpres, shift it left by 32 then or in the low 32 bits.
396 tmpres |= ft.dwHighDateTime;
397 tmpres <<= 32;
398 tmpres |= ft.dwLowDateTime;
399
400 // Convert to microseconds by dividing by 10
401 tmpres /= 10;
402
403 // The Unix epoch starts on Jan 1 1970. Need to subtract the difference
404 // in seconds from Jan 1 1601.
405 tmpres -= DELTA_EPOCH_IN_MICROSECS;
406
407 // Finally change microseconds to seconds and place in the seconds value.
408 // The modulus picks up the microseconds.
409 tv->tv_sec = (long)(tmpres / 1000000UL);
410 tv->tv_usec = (long)(tmpres % 1000000UL);
411 }
412
413 if (NULL != tz)
414 {
415 if (!tzflag)
416 {
417 _tzset();
418 tzflag++;
419 }
420
421 // Adjust for the timezone west of Greenwich
422 tz->tz_minuteswest = _timezone / 60;
423 tz->tz_dsttime = _daylight;
424 }
425 return 0;
426}
427#else
428#include <sys/time.h>
429#endif
430#endif /* not NO_TIMER */
431#ifdef CPU86
432#include <float.h>
433#endif /* CPU86 */
434#ifdef LINUX
435#include <fpu_control.h>
436#endif /* LINUX */
437#ifdef TRILIBRARY
438#include "triangle.h"
439#endif /* TRILIBRARY */
440
441/* A few forward declarations. */
442
443#ifndef TRILIBRARY
444char *readline();
445char *findfield();
446#endif /* not TRILIBRARY */
447
448/* Labels that signify the result of point location. The result of a */
449/* search indicates that the point falls in the interior of a triangle, on */
450/* an edge, on a vertex, or outside the mesh. */
451
452enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
453
454/* Labels that signify the result of vertex insertion. The result indicates */
455/* that the vertex was inserted with complete success, was inserted but */
456/* encroaches upon a subsegment, was not inserted because it lies on a */
457/* segment, or was not inserted because another vertex occupies the same */
458/* location. */
459
460enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX,
461 DUPLICATEVERTEX};
462
463/* Labels that signify the result of direction finding. The result */
464/* indicates that a segment connecting the two query points falls within */
465/* the direction triangle, along the left edge of the direction triangle, */
466/* or along the right edge of the direction triangle. */
467
468enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
469
470/*****************************************************************************/
471/* */
472/* The basic mesh data structures */
473/* */
474/* There are three: vertices, triangles, and subsegments (abbreviated */
475/* `subseg'). These three data structures, linked by pointers, comprise */
476/* the mesh. A vertex simply represents a mesh vertex and its properties. */
477/* A triangle is a triangle. A subsegment is a special data structure used */
478/* to represent an impenetrable edge of the mesh (perhaps on the outer */
479/* boundary, on the boundary of a hole, or part of an internal boundary */
480/* separating two triangulated regions). Subsegments represent boundaries, */
481/* defined by the user, that triangles may not lie across. */
482/* */
483/* A triangle consists of a list of three vertices, a list of three */
484/* adjoining triangles, a list of three adjoining subsegments (when */
485/* segments exist), an arbitrary number of optional user-defined */
486/* floating-point attributes, and an optional area constraint. The latter */
487/* is an upper bound on the permissible area of each triangle in a region, */
488/* used for mesh refinement. */
489/* */
490/* For a triangle on a boundary of the mesh, some or all of the neighboring */
491/* triangles may not be present. For a triangle in the interior of the */
492/* mesh, often no neighboring subsegments are present. Such absent */
493/* triangles and subsegments are never represented by NULL pointers; they */
494/* are represented by two special records: `dummytri', the triangle that */
495/* fills "outer space", and `dummysub', the omnipresent subsegment. */
496/* `dummytri' and `dummysub' are used for several reasons; for instance, */
497/* they can be dereferenced and their contents examined without violating */
498/* protected memory. */
499/* */
500/* However, it is important to understand that a triangle includes other */
501/* information as well. The pointers to adjoining vertices, triangles, and */
502/* subsegments are ordered in a way that indicates their geometric relation */
503/* to each other. Furthermore, each of these pointers contains orientation */
504/* information. Each pointer to an adjoining triangle indicates which face */
505/* of that triangle is contacted. Similarly, each pointer to an adjoining */
506/* subsegment indicates which side of that subsegment is contacted, and how */
507/* the subsegment is oriented relative to the triangle. */
508/* */
509/* The data structure representing a subsegment may be thought to be */
510/* abutting the edge of one or two triangle data structures: either */
511/* sandwiched between two triangles, or resting against one triangle on an */
512/* exterior boundary or hole boundary. */
513/* */
514/* A subsegment consists of a list of four vertices--the vertices of the */
515/* subsegment, and the vertices of the segment it is a part of--a list of */
516/* two adjoining subsegments, and a list of two adjoining triangles. One */
517/* of the two adjoining triangles may not be present (though there should */
518/* always be one), and neighboring subsegments might not be present. */
519/* Subsegments also store a user-defined integer "boundary marker". */
520/* Typically, this integer is used to indicate what boundary conditions are */
521/* to be applied at that location in a finite element simulation. */
522/* */
523/* Like triangles, subsegments maintain information about the relative */
524/* orientation of neighboring objects. */
525/* */
526/* Vertices are relatively simple. A vertex is a list of floating-point */
527/* numbers, starting with the x, and y coordinates, followed by an */
528/* arbitrary number of optional user-defined floating-point attributes, */
529/* followed by an integer boundary marker. During the segment insertion */
530/* phase, there is also a pointer from each vertex to a triangle that may */
531/* contain it. Each pointer is not always correct, but when one is, it */
532/* speeds up segment insertion. These pointers are assigned values once */
533/* at the beginning of the segment insertion phase, and are not used or */
534/* updated except during this phase. Edge flipping during segment */
535/* insertion will render some of them incorrect. Hence, don't rely upon */
536/* them for anything. */
537/* */
538/* Other than the exception mentioned above, vertices have no information */
539/* about what triangles, subfacets, or subsegments they are linked to. */
540/* */
541/*****************************************************************************/
542
543/*****************************************************************************/
544/* */
545/* Handles */
546/* */
547/* The oriented triangle (`otri') and oriented subsegment (`osub') data */
548/* structures defined below do not themselves store any part of the mesh. */
549/* The mesh itself is made of `triangle's, `subseg's, and `vertex's. */
550/* */
551/* Oriented triangles and oriented subsegments will usually be referred to */
552/* as "handles." A handle is essentially a pointer into the mesh; it */
553/* allows you to "hold" one particular part of the mesh. Handles are used */
554/* to specify the regions in which one is traversing and modifying the mesh.*/
555/* A single `triangle' may be held by many handles, or none at all. (The */
556/* latter case is not a memory leak, because the triangle is still */
557/* connected to other triangles in the mesh.) */
558/* */
559/* An `otri' is a handle that holds a triangle. It holds a specific edge */
560/* of the triangle. An `osub' is a handle that holds a subsegment. It */
561/* holds either the left or right side of the subsegment. */
562/* */
563/* Navigation about the mesh is accomplished through a set of mesh */
564/* manipulation primitives, further below. Many of these primitives take */
565/* a handle and produce a new handle that holds the mesh near the first */
566/* handle. Other primitives take two handles and glue the corresponding */
567/* parts of the mesh together. The orientation of the handles is */
568/* important. For instance, when two triangles are glued together by the */
569/* bond() primitive, they are glued at the edges on which the handles lie. */
570/* */
571/* Because vertices have no information about which triangles they are */
572/* attached to, I commonly represent a vertex by use of a handle whose */
573/* origin is the vertex. A single handle can simultaneously represent a */
574/* triangle, an edge, and a vertex. */
575/* */
576/*****************************************************************************/
577
578/* The triangle data structure. Each triangle contains three pointers to */
579/* adjoining triangles, plus three pointers to vertices, plus three */
580/* pointers to subsegments (declared below; these pointers are usually */
581/* `dummysub'). It may or may not also contain user-defined attributes */
582/* and/or a floating-point "area constraint." It may also contain extra */
583/* pointers for nodes, when the user asks for high-order elements. */
584/* Because the size and structure of a `triangle' is not decided until */
585/* runtime, I haven't simply declared the type `triangle' as a struct. */
586
587typedef REAL **triangle; /* Really: typedef triangle *triangle */
588
589/* An oriented triangle: includes a pointer to a triangle and orientation. */
590/* The orientation denotes an edge of the triangle. Hence, there are */
591/* three possible orientations. By convention, each edge always points */
592/* counterclockwise about the corresponding triangle. */
593
594struct otri {
595 triangle *tri;
596 int orient; /* Ranges from 0 to 2. */
597};
598
599/* The subsegment data structure. Each subsegment contains two pointers to */
600/* adjoining subsegments, plus four pointers to vertices, plus two */
601/* pointers to adjoining triangles, plus one boundary marker, plus one */
602/* segment number. */
603
604typedef REAL **subseg; /* Really: typedef subseg *subseg */
605
606/* An oriented subsegment: includes a pointer to a subsegment and an */
607/* orientation. The orientation denotes a side of the edge. Hence, there */
608/* are two possible orientations. By convention, the edge is always */
609/* directed so that the "side" denoted is the right side of the edge. */
610
611struct osub {
612 subseg *ss;
613 int ssorient; /* Ranges from 0 to 1. */
614};
615
616/* The vertex data structure. Each vertex is actually an array of REALs. */
617/* The number of REALs is unknown until runtime. An integer boundary */
618/* marker, and sometimes a pointer to a triangle, is appended after the */
619/* REALs. */
620
621typedef REAL *vertex;
622
623/* A queue used to store encroached subsegments. Each subsegment's vertices */
624/* are stored so that we can check whether a subsegment is still the same. */
625
626struct badsubseg {
627 subseg encsubseg; /* An encroached subsegment. */
628 vertex subsegorg, subsegdest; /* Its two vertices. */
629};
630
631/* A queue used to store bad triangles. The key is the square of the cosine */
632/* of the smallest angle of the triangle. Each triangle's vertices are */
633/* stored so that one can check whether a triangle is still the same. */
634
635struct badtriang {
636 triangle poortri; /* A skinny or too-large triangle. */
637 REAL key; /* cos^2 of smallest (apical) angle. */
638 vertex triangorg, triangdest, triangapex; /* Its three vertices. */
639 struct badtriang *nexttriang; /* Pointer to next bad triangle. */
640};
641
642/* A stack of triangles flipped during the most recent vertex insertion. */
643/* The stack is used to undo the vertex insertion if the vertex encroaches */
644/* upon a subsegment. */
645
647 triangle flippedtri; /* A recently flipped triangle. */
648 struct flipstacker* prevflip; /* Previous flip in the stack. */
649};
650
651/* A node in a heap used to store events for the sweepline Delaunay */
652/* algorithm. Nodes do not point directly to their parents or children in */
653/* the heap. Instead, each node knows its position in the heap, and can */
654/* look up its parent and children in a separate array. The `eventptr' */
655/* points either to a `vertex' or to a triangle (in encoded format, so */
656/* that an orientation is included). In the latter case, the origin of */
657/* the oriented triangle is the apex of a "circle event" of the sweepline */
658/* algorithm. To distinguish site events from circle events, all circle */
659/* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */
660
661struct event {
662 REAL xkey, ykey; /* Coordinates of the event. */
663 VOID *eventptr; /* Can be a vertex or the location of a circle event. */
664 int heapposition; /* Marks this event's position in the heap. */
665};
666
667/* A node in the splay tree. Each node holds an oriented ghost triangle */
668/* that represents a boundary edge of the growing triangulation. When a */
669/* circle event covers two boundary edges with a triangle, so that they */
670/* are no longer boundary edges, those edges are not immediately deleted */
671/* from the tree; rather, they are lazily deleted when they are next */
672/* encountered. (Since only a random sample of boundary edges are kept */
673/* in the tree, lazy deletion is faster.) `keydest' is used to verify */
674/* that a triangle is still the same as when it entered the splay tree; if */
675/* it has been rotated (due to a circle event), it no longer represents a */
676/* boundary edge and should be deleted. */
677
678struct splaynode {
679 struct otri keyedge; /* Lprev of an edge on the front. */
680 vertex keydest; /* Used to verify that splay node is still live. */
681 struct splaynode *lchild, *rchild; /* Children in splay tree. */
682};
683
684/* A type used to allocate memory. firstblock is the first block of items. */
685/* nowblock is the block from which items are currently being allocated. */
686/* nextitem points to the next slab of free memory for an item. */
687/* deaditemstack is the head of a linked list (stack) of deallocated items */
688/* that can be recycled. unallocateditems is the number of items that */
689/* remain to be allocated from nowblock. */
690/* */
691/* Traversal is the process of walking through the entire list of items, and */
692/* is separate from allocation. Note that a traversal will visit items on */
693/* the "deaditemstack" stack as well as live items. pathblock points to */
694/* the block currently being traversed. pathitem points to the next item */
695/* to be traversed. pathitemsleft is the number of items that remain to */
696/* be traversed in pathblock. */
697/* */
698/* alignbytes determines how new records should be aligned in memory. */
699/* itembytes is the length of a record in bytes (after rounding up). */
700/* itemsperblock is the number of items allocated at once in a single */
701/* block. itemsfirstblock is the number of items in the first block, */
702/* which can vary from the others. items is the number of currently */
703/* allocated items. maxitems is the maximum number of items that have */
704/* been allocated at once; it is the current number of items plus the */
705/* number of records kept on deaditemstack. */
706
708 VOID **firstblock, **nowblock;
709 VOID *nextitem;
710 VOID *deaditemstack;
711 VOID **pathblock;
712 VOID* pathitem;
713 int alignbytes;
714 int itembytes;
715 int itemsperblock;
716 int itemsfirstblock;
717 long items, maxitems;
718 int unallocateditems;
719 int pathitemsleft;
720};
721
722
723/* Global constants. */
724
725REAL splitter; /* Used to split REAL factors for exact multiplication. */
726REAL epsilon; /* Floating-point machine epsilon. */
727REAL resulterrbound;
728REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
729REAL iccerrboundA, iccerrboundB, iccerrboundC;
730REAL o3derrboundA, o3derrboundB, o3derrboundC;
731
732/* Random number seed is not constant, but I've made it global anyway. */
733
734unsigned long randomseed; /* Current random number seed. */
735
736
737/* Mesh data structure. Triangle operates on only one mesh, but the mesh */
738/* structure is used (instead of global variables) to allow reentrancy. */
739
740struct mesh {
741
742/* Variables used to allocate memory for triangles, subsegments, vertices, */
743/* viri (triangles being eaten), encroached segments, bad (skinny or too */
744/* large) triangles, and splay tree nodes. */
745
746 struct memorypool triangles;
747 struct memorypool subsegs;
748 struct memorypool vertices;
749 struct memorypool viri;
750 struct memorypool badsubsegs;
751 struct memorypool badtriangles;
752 struct memorypool flipstackers;
753 struct memorypool splaynodes;
754
755/* Variables that maintain the bad triangle queues. The queues are */
756/* ordered from 4095 (highest priority) to 0 (lowest priority). */
757
758 struct badtriang *queuefront[4096];
759 struct badtriang *queuetail[4096];
760 int nextnonemptyq[4096];
761 int firstnonemptyq;
762
763/* Variable that maintains the stack of recently flipped triangles. */
764
765 struct flipstacker *lastflip;
766
767/* Other variables. */
768
769 REAL xmin, xmax, ymin, ymax; /* x and y bounds. */
770 REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */
771 int invertices; /* Number of input vertices. */
772 int inelements; /* Number of input triangles. */
773 int insegments; /* Number of input segments. */
774 int holes; /* Number of input holes. */
775 int regions; /* Number of input regions. */
776 int undeads; /* Number of input vertices that don't appear in the mesh. */
777 long edges; /* Number of output edges. */
778 int mesh_dim; /* Dimension (ought to be 2). */
779 int nextras; /* Number of attributes per vertex. */
780 int eextras; /* Number of attributes per triangle. */
781 long hullsize; /* Number of edges in convex hull. */
782 int steinerleft; /* Number of Steiner points not yet used. */
783 int vertexmarkindex; /* Index to find boundary marker of a vertex. */
784 int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */
785 int highorderindex; /* Index to find extra nodes for high-order elements. */
786 int elemattribindex; /* Index to find attributes of a triangle. */
787 int areaboundindex; /* Index to find area bound of a triangle. */
788 int checksegments; /* Are there segments in the triangulation yet? */
789 int checkquality; /* Has quality triangulation begun yet? */
790 int readnodefile; /* Has a .node file been read? */
791 long samples; /* Number of random samples for point location. */
792
793 long incirclecount; /* Number of incircle tests performed. */
794 long counterclockcount; /* Number of counterclockwise tests performed. */
795 long orient3dcount; /* Number of 3D orientation tests performed. */
796 long hyperbolacount; /* Number of right-of-hyperbola tests performed. */
797 long circumcentercount; /* Number of circumcenter calculations performed. */
798 long circletopcount; /* Number of circle top calculations performed. */
799
800/* Triangular bounding box vertices. */
801
802 vertex infvertex1, infvertex2, infvertex3;
803
804/* Pointer to the `triangle' that occupies all of "outer space." */
805
806 triangle *dummytri;
807 triangle *dummytribase; /* Keep base address so we can free() it later. */
808
809/* Pointer to the omnipresent subsegment. Referenced by any triangle or */
810/* subsegment that isn't really connected to a subsegment at that */
811/* location. */
812
813 subseg *dummysub;
814 subseg *dummysubbase; /* Keep base address so we can free() it later. */
815
816/* Pointer to a recently visited triangle. Improves point location if */
817/* proximate vertices are inserted sequentially. */
818
819 struct otri recenttri;
820
821}; /* End of `struct mesh'. */
822
823
824/* Data structure for command line switches and file names. This structure */
825/* is used (instead of global variables) to allow reentrancy. */
826
827struct behavior {
828
829/* Switches for the triangulator. */
830/* poly: -p switch. refine: -r switch. */
831/* quality: -q switch. */
832/* minangle: minimum angle bound, specified after -q switch. */
833/* goodangle: cosine squared of minangle. */
834/* offconstant: constant used to place off-center Steiner points. */
835/* vararea: -a switch without number. */
836/* fixedarea: -a switch with number. */
837/* maxarea: maximum area bound, specified after -a switch. */
838/* usertest: -u switch. */
839/* regionattrib: -A switch. convex: -c switch. */
840/* weighted: 1 for -w switch, 2 for -W switch. jettison: -j switch */
841/* firstnumber: inverse of -z switch. All items are numbered starting */
842/* from `firstnumber'. */
843/* edgesout: -e switch. voronoi: -v switch. */
844/* neighbors: -n switch. geomview: -g switch. */
845/* nobound: -B switch. nopolywritten: -P switch. */
846/* nonodewritten: -N switch. noelewritten: -E switch. */
847/* noiterationnum: -I switch. noholes: -O switch. */
848/* noexact: -X switch. */
849/* order: element order, specified after -o switch. */
850/* nobisect: count of how often -Y switch is selected. */
851/* steiner: maximum number of Steiner points, specified after -S switch. */
852/* incremental: -i switch. sweepline: -F switch. */
853/* dwyer: inverse of -l switch. */
854/* splitseg: -s switch. */
855/* conformdel: -D switch. docheck: -C switch. */
856/* quiet: -Q switch. verbose: count of how often -V switch is selected. */
857/* usesegments: -p, -r, -q, or -c switch; determines whether segments are */
858/* used at all. */
859/* */
860/* Read the instructions to find out the meaning of these switches. */
861
862 int poly, refine, quality, vararea, fixedarea, usertest;
863 int regionattrib, convex, weighted, jettison;
864 int firstnumber;
865 int edgesout, voronoi, neighbors, geomview;
866 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
867 int noholes, noexact, conformdel;
868 int incremental, sweepline, dwyer;
869 int splitseg;
870 int docheck;
871 int quiet, verbose;
872 int usesegments;
873 int order;
874 int nobisect;
875 int steiner;
876 REAL minangle, goodangle, offconstant;
877 REAL maxarea;
878
879/* Variables for file names. */
880
881#ifndef TRILIBRARY
882 char innodefilename[FILENAMESIZE];
883 char inelefilename[FILENAMESIZE];
884 char inpolyfilename[FILENAMESIZE];
885 char areafilename[FILENAMESIZE];
886 char outnodefilename[FILENAMESIZE];
887 char outelefilename[FILENAMESIZE];
888 char outpolyfilename[FILENAMESIZE];
889 char edgefilename[FILENAMESIZE];
890 char vnodefilename[FILENAMESIZE];
891 char vedgefilename[FILENAMESIZE];
892 char neighborfilename[FILENAMESIZE];
893 char offfilename[FILENAMESIZE];
894#endif /* not TRILIBRARY */
895
896}; /* End of `struct behavior'. */
897
898
899/*****************************************************************************/
900/* */
901/* Mesh manipulation primitives. Each triangle contains three pointers to */
902/* other triangles, with orientations. Each pointer points not to the */
903/* first byte of a triangle, but to one of the first three bytes of a */
904/* triangle. It is necessary to extract both the triangle itself and the */
905/* orientation. To save memory, I keep both pieces of information in one */
906/* pointer. To make this possible, I assume that all triangles are aligned */
907/* to four-byte boundaries. The decode() routine below decodes a pointer, */
908/* extracting an orientation (in the range 0 to 2) and a pointer to the */
909/* beginning of a triangle. The encode() routine compresses a pointer to a */
910/* triangle and an orientation into a single pointer. My assumptions that */
911/* triangles are four-byte-aligned and that the `unsigned long' type is */
912/* long enough to hold a pointer are two of the few kludges in this program.*/
913/* */
914/* Subsegments are manipulated similarly. A pointer to a subsegment */
915/* carries both an address and an orientation in the range 0 to 1. */
916/* */
917/* The other primitives take an oriented triangle or oriented subsegment, */
918/* and return an oriented triangle or oriented subsegment or vertex; or */
919/* they change the connections in the data structure. */
920/* */
921/* Below, triangles and subsegments are denoted by their vertices. The */
922/* triangle abc has origin (org) a, destination (dest) b, and apex (apex) */
923/* c. These vertices occur in counterclockwise order about the triangle. */
924/* The handle abc may simultaneously denote vertex a, edge ab, and triangle */
925/* abc. */
926/* */
927/* Similarly, the subsegment ab has origin (sorg) a and destination (sdest) */
928/* b. If ab is thought to be directed upward (with b directly above a), */
929/* then the handle ab is thought to grasp the right side of ab, and may */
930/* simultaneously denote vertex a and edge ab. */
931/* */
932/* An asterisk (*) denotes a vertex whose identity is unknown. */
933/* */
934/* Given this notation, a partial list of mesh manipulation primitives */
935/* follows. */
936/* */
937/* */
938/* For triangles: */
939/* */
940/* sym: Find the abutting triangle; same edge. */
941/* sym(abc) -> ba* */
942/* */
943/* lnext: Find the next edge (counterclockwise) of a triangle. */
944/* lnext(abc) -> bca */
945/* */
946/* lprev: Find the previous edge (clockwise) of a triangle. */
947/* lprev(abc) -> cab */
948/* */
949/* onext: Find the next edge counterclockwise with the same origin. */
950/* onext(abc) -> ac* */
951/* */
952/* oprev: Find the next edge clockwise with the same origin. */
953/* oprev(abc) -> a*b */
954/* */
955/* dnext: Find the next edge counterclockwise with the same destination. */
956/* dnext(abc) -> *ba */
957/* */
958/* dprev: Find the next edge clockwise with the same destination. */
959/* dprev(abc) -> cb* */
960/* */
961/* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */
962/* rnext(abc) -> *a* */
963/* */
964/* rprev: Find the previous edge (clockwise) of the adjacent triangle. */
965/* rprev(abc) -> b** */
966/* */
967/* org: Origin dest: Destination apex: Apex */
968/* org(abc) -> a dest(abc) -> b apex(abc) -> c */
969/* */
970/* bond: Bond two triangles together at the resepective handles. */
971/* bond(abc, bad) */
972/* */
973/* */
974/* For subsegments: */
975/* */
976/* ssym: Reverse the orientation of a subsegment. */
977/* ssym(ab) -> ba */
978/* */
979/* spivot: Find adjoining subsegment with the same origin. */
980/* spivot(ab) -> a* */
981/* */
982/* snext: Find next subsegment in sequence. */
983/* snext(ab) -> b* */
984/* */
985/* sorg: Origin sdest: Destination */
986/* sorg(ab) -> a sdest(ab) -> b */
987/* */
988/* sbond: Bond two subsegments together at the respective origins. */
989/* sbond(ab, ac) */
990/* */
991/* */
992/* For interacting tetrahedra and subfacets: */
993/* */
994/* tspivot: Find a subsegment abutting a triangle. */
995/* tspivot(abc) -> ba */
996/* */
997/* stpivot: Find a triangle abutting a subsegment. */
998/* stpivot(ab) -> ba* */
999/* */
1000/* tsbond: Bond a triangle to a subsegment. */
1001/* tsbond(abc, ba) */
1002/* */
1003/*****************************************************************************/
1004
1005/********* Mesh manipulation primitives begin here *********/
1009/* Fast lookup arrays to speed some of the mesh manipulation primitives. */
1010
1011int plus1mod3[3] = {1, 2, 0};
1012int minus1mod3[3] = {2, 0, 1};
1013
1014/********* Primitives for triangles *********/
1015/* */
1016/* */
1017
1018/* decode() converts a pointer to an oriented triangle. The orientation is */
1019/* extracted from the two least significant bits of the pointer. */
1020
1021#define decode(ptr, otri) \
1022 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
1023 (otri).tri = (triangle *) \
1024 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
1025
1026/* encode() compresses an oriented triangle into a single pointer. It */
1027/* relies on the assumption that all triangles are aligned to four-byte */
1028/* boundaries, so the two least significant bits of (otri).tri are zero. */
1029
1030#define encode(otri) \
1031 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
1032
1033/* The following handle manipulation primitives are all described by Guibas */
1034/* and Stolfi. However, Guibas and Stolfi use an edge-based data */
1035/* structure, whereas I use a triangle-based data structure. */
1036
1037/* sym() finds the abutting triangle, on the same edge. Note that the edge */
1038/* direction is necessarily reversed, because the handle specified by an */
1039/* oriented triangle is directed counterclockwise around the triangle. */
1040
1041#define sym(otri1, otri2) \
1042 ptr = (otri1).tri[(otri1).orient]; \
1043 decode(ptr, otri2);
1044
1045#define symself(otri) \
1046 ptr = (otri).tri[(otri).orient]; \
1047 decode(ptr, otri);
1048
1049/* lnext() finds the next edge (counterclockwise) of a triangle. */
1050
1051#define lnext(otri1, otri2) \
1052 (otri2).tri = (otri1).tri; \
1053 (otri2).orient = plus1mod3[(otri1).orient]
1054
1055#define lnextself(otri) \
1056 (otri).orient = plus1mod3[(otri).orient]
1057
1058/* lprev() finds the previous edge (clockwise) of a triangle. */
1059
1060#define lprev(otri1, otri2) \
1061 (otri2).tri = (otri1).tri; \
1062 (otri2).orient = minus1mod3[(otri1).orient]
1063
1064#define lprevself(otri) \
1065 (otri).orient = minus1mod3[(otri).orient]
1066
1067/* onext() spins counterclockwise around a vertex; that is, it finds the */
1068/* next edge with the same origin in the counterclockwise direction. This */
1069/* edge is part of a different triangle. */
1070
1071#define onext(otri1, otri2) \
1072 lprev(otri1, otri2); \
1073 symself(otri2);
1074
1075#define onextself(otri) \
1076 lprevself(otri); \
1077 symself(otri);
1078
1079/* oprev() spins clockwise around a vertex; that is, it finds the next edge */
1080/* with the same origin in the clockwise direction. This edge is part of */
1081/* a different triangle. */
1082
1083#define oprev(otri1, otri2) \
1084 sym(otri1, otri2); \
1085 lnextself(otri2);
1086
1087#define oprevself(otri) \
1088 symself(otri); \
1089 lnextself(otri);
1090
1091/* dnext() spins counterclockwise around a vertex; that is, it finds the */
1092/* next edge with the same destination in the counterclockwise direction. */
1093/* This edge is part of a different triangle. */
1094
1095#define dnext(otri1, otri2) \
1096 sym(otri1, otri2); \
1097 lprevself(otri2);
1098
1099#define dnextself(otri) \
1100 symself(otri); \
1101 lprevself(otri);
1102
1103/* dprev() spins clockwise around a vertex; that is, it finds the next edge */
1104/* with the same destination in the clockwise direction. This edge is */
1105/* part of a different triangle. */
1106
1107#define dprev(otri1, otri2) \
1108 lnext(otri1, otri2); \
1109 symself(otri2);
1110
1111#define dprevself(otri) \
1112 lnextself(otri); \
1113 symself(otri);
1114
1115/* rnext() moves one edge counterclockwise about the adjacent triangle. */
1116/* (It's best understood by reading Guibas and Stolfi. It involves */
1117/* changing triangles twice.) */
1118
1119#define rnext(otri1, otri2) \
1120 sym(otri1, otri2); \
1121 lnextself(otri2); \
1122 symself(otri2);
1123
1124#define rnextself(otri) \
1125 symself(otri); \
1126 lnextself(otri); \
1127 symself(otri);
1128
1129/* rprev() moves one edge clockwise about the adjacent triangle. */
1130/* (It's best understood by reading Guibas and Stolfi. It involves */
1131/* changing triangles twice.) */
1132
1133#define rprev(otri1, otri2) \
1134 sym(otri1, otri2); \
1135 lprevself(otri2); \
1136 symself(otri2);
1137
1138#define rprevself(otri) \
1139 symself(otri); \
1140 lprevself(otri); \
1141 symself(otri);
1142
1143/* These primitives determine or set the origin, destination, or apex of a */
1144/* triangle. */
1145
1146#define org(otri, vertexptr) \
1147 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
1148
1149#define dest(otri, vertexptr) \
1150 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
1151
1152#define apex(otri, vertexptr) \
1153 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
1154
1155#define setorg(otri, vertexptr) \
1156 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1157
1158#define setdest(otri, vertexptr) \
1159 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1160
1161#define setapex(otri, vertexptr) \
1162 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
1163
1164/* Bond two triangles together. */
1165
1166#define bond(otri1, otri2) \
1167 (otri1).tri[(otri1).orient] = encode(otri2); \
1168 (otri2).tri[(otri2).orient] = encode(otri1)
1169
1170/* Dissolve a bond (from one side). Note that the other triangle will still */
1171/* think it's connected to this triangle. Usually, however, the other */
1172/* triangle is being deleted entirely, or bonded to another triangle, so */
1173/* it doesn't matter. */
1174
1175#define dissolve(otri) \
1176 (otri).tri[(otri).orient] = (triangle) m->dummytri
1177
1178/* Copy an oriented triangle. */
1179
1180#define otricopy(otri1, otri2) \
1181 (otri2).tri = (otri1).tri; \
1182 (otri2).orient = (otri1).orient
1183
1184/* Test for equality of oriented triangles. */
1185
1186#define otriequal(otri1, otri2) \
1187 (((otri1).tri == (otri2).tri) && \
1188 ((otri1).orient == (otri2).orient))
1189
1190/* Primitives to infect or cure a triangle with the virus. These rely on */
1191/* the assumption that all subsegments are aligned to four-byte boundaries.*/
1192
1193#define infect(otri) \
1194 (otri).tri[6] = (triangle) \
1195 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
1196
1197#define uninfect(otri) \
1198 (otri).tri[6] = (triangle) \
1199 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
1200
1201/* Test a triangle for viral infection. */
1202
1203#define infected(otri) \
1204 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
1205
1206/* Check or set a triangle's attributes. */
1207
1208#define elemattribute(otri, attnum) \
1209 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
1210
1211#define setelemattribute(otri, attnum, value) \
1212 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
1213
1214/* Check or set a triangle's maximum area bound. */
1215
1216#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
1217
1218#define setareabound(otri, value) \
1219 ((REAL *) (otri).tri)[m->areaboundindex] = value
1220
1221/* Check or set a triangle's deallocation. Its second pointer is set to */
1222/* NULL to indicate that it is not allocated. (Its first pointer is used */
1223/* for the stack of dead items.) Its fourth pointer (its first vertex) */
1224/* is set to NULL in case a `badtriang' structure points to it. */
1225
1226#define deadtri(tria) ((tria)[1] == (triangle) NULL)
1227
1228#define killtri(tria) \
1229 (tria)[1] = (triangle) NULL; \
1230 (tria)[3] = (triangle) NULL
1231
1232/********* Primitives for subsegments *********/
1233/* */
1234/* */
1235
1236/* sdecode() converts a pointer to an oriented subsegment. The orientation */
1237/* is extracted from the least significant bit of the pointer. The two */
1238/* least significant bits (one for orientation, one for viral infection) */
1239/* are masked out to produce the real pointer. */
1240
1241#define sdecode(sptr, osub) \
1242 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
1243 (osub).ss = (subseg *) \
1244 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
1245
1246/* sencode() compresses an oriented subsegment into a single pointer. It */
1247/* relies on the assumption that all subsegments are aligned to two-byte */
1248/* boundaries, so the least significant bit of (osub).ss is zero. */
1249
1250#define sencode(osub) \
1251 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
1252
1253/* ssym() toggles the orientation of a subsegment. */
1254
1255#define ssym(osub1, osub2) \
1256 (osub2).ss = (osub1).ss; \
1257 (osub2).ssorient = 1 - (osub1).ssorient
1258
1259#define ssymself(osub) \
1260 (osub).ssorient = 1 - (osub).ssorient
1261
1262/* spivot() finds the other subsegment (from the same segment) that shares */
1263/* the same origin. */
1264
1265#define spivot(osub1, osub2) \
1266 sptr = (osub1).ss[(osub1).ssorient]; \
1267 sdecode(sptr, osub2)
1268
1269#define spivotself(osub) \
1270 sptr = (osub).ss[(osub).ssorient]; \
1271 sdecode(sptr, osub)
1272
1273/* snext() finds the next subsegment (from the same segment) in sequence; */
1274/* one whose origin is the input subsegment's destination. */
1275
1276#define snext(osub1, osub2) \
1277 sptr = (osub1).ss[1 - (osub1).ssorient]; \
1278 sdecode(sptr, osub2)
1279
1280#define snextself(osub) \
1281 sptr = (osub).ss[1 - (osub).ssorient]; \
1282 sdecode(sptr, osub)
1283
1284/* These primitives determine or set the origin or destination of a */
1285/* subsegment or the segment that includes it. */
1286
1287#define sorg(osub, vertexptr) \
1288 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
1289
1290#define sdest(osub, vertexptr) \
1291 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
1292
1293#define setsorg(osub, vertexptr) \
1294 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
1295
1296#define setsdest(osub, vertexptr) \
1297 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
1298
1299#define segorg(osub, vertexptr) \
1300 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
1301
1302#define segdest(osub, vertexptr) \
1303 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
1304
1305#define setsegorg(osub, vertexptr) \
1306 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
1307
1308#define setsegdest(osub, vertexptr) \
1309 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
1310
1311/* These primitives read or set a boundary marker. Boundary markers are */
1312/* used to hold user-defined tags for setting boundary conditions in */
1313/* finite element solvers. */
1314
1315#define mark(osub) (* (int *) ((osub).ss + 8))
1316
1317#define setmark(osub, value) \
1318 * (int *) ((osub).ss + 8) = value
1319
1320/* Bond two subsegments together. */
1321
1322#define sbond(osub1, osub2) \
1323 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
1324 (osub2).ss[(osub2).ssorient] = sencode(osub1)
1325
1326/* Dissolve a subsegment bond (from one side). Note that the other */
1327/* subsegment will still think it's connected to this subsegment. */
1328
1329#define sdissolve(osub) \
1330 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
1331
1332/* Copy a subsegment. */
1333
1334#define subsegcopy(osub1, osub2) \
1335 (osub2).ss = (osub1).ss; \
1336 (osub2).ssorient = (osub1).ssorient
1337
1338/* Test for equality of subsegments. */
1339
1340#define subsegequal(osub1, osub2) \
1341 (((osub1).ss == (osub2).ss) && \
1342 ((osub1).ssorient == (osub2).ssorient))
1343
1344/* Check or set a subsegment's deallocation. Its second pointer is set to */
1345/* NULL to indicate that it is not allocated. (Its first pointer is used */
1346/* for the stack of dead items.) Its third pointer (its first vertex) */
1347/* is set to NULL in case a `badsubseg' structure points to it. */
1348
1349#define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
1350
1351#define killsubseg(sub) \
1352 (sub)[1] = (subseg) NULL; \
1353 (sub)[2] = (subseg) NULL
1354
1355/********* Primitives for interacting triangles and subsegments *********/
1356/* */
1357/* */
1358
1359/* tspivot() finds a subsegment abutting a triangle. */
1360
1361#define tspivot(otri, osub) \
1362 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
1363 sdecode(sptr, osub)
1364
1365/* stpivot() finds a triangle abutting a subsegment. It requires that the */
1366/* variable `ptr' of type `triangle' be defined. */
1367
1368#define stpivot(osub, otri) \
1369 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
1370 decode(ptr, otri)
1371
1372/* Bond a triangle to a subsegment. */
1373
1374#define tsbond(otri, osub) \
1375 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
1376 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
1377
1378/* Dissolve a bond (from the triangle side). */
1379
1380#define tsdissolve(otri) \
1381 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
1382
1383/* Dissolve a bond (from the subsegment side). */
1384
1385#define stdissolve(osub) \
1386 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
1387
1388/********* Primitives for vertices *********/
1389/* */
1390/* */
1391
1392#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
1393
1394#define setvertexmark(vx, value) \
1395 ((int *) (vx))[m->vertexmarkindex] = value
1396
1397#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
1398
1399#define setvertextype(vx, value) \
1400 ((int *) (vx))[m->vertexmarkindex + 1] = value
1401
1402#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
1403
1404#define setvertex2tri(vx, value) \
1405 ((triangle *) (vx))[m->vertex2triindex] = value
1406
1409/********* Mesh manipulation primitives end here *********/
1410
1411/********* User-defined triangle evaluation routine begins here *********/
1415/*****************************************************************************/
1416/* */
1417/* triunsuitable() Determine if a triangle is unsuitable, and thus must */
1418/* be further refined. */
1419/* */
1420/* You may write your own procedure that decides whether or not a selected */
1421/* triangle is too big (and needs to be refined). There are two ways to do */
1422/* this. */
1423/* */
1424/* (1) Modify the procedure `triunsuitable' below, then recompile */
1425/* Triangle. */
1426/* */
1427/* (2) Define the symbol EXTERNAL_TEST (either by adding the definition */
1428/* to this file, or by using the appropriate compiler switch). This way, */
1429/* you can compile triangle.c separately from your test. Write your own */
1430/* `triunsuitable' procedure in a separate C file (using the same prototype */
1431/* as below). Compile it and link the object code with triangle.o. */
1432/* */
1433/* This procedure returns 1 if the triangle is too large and should be */
1434/* refined; 0 otherwise. */
1435/* */
1436/*****************************************************************************/
1437
1438#ifdef EXTERNAL_TEST
1439
1440int triunsuitable();
1441
1442#else /* not EXTERNAL_TEST */
1443
1444#ifdef ANSI_DECLARATORS
1445int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
1446#else /* not ANSI_DECLARATORS */
1447int triunsuitable(triorg, tridest, triapex, area)
1448vertex triorg; /* The triangle's origin vertex. */
1449vertex tridest; /* The triangle's destination vertex. */
1450vertex triapex; /* The triangle's apex vertex. */
1451REAL area; /* The area of the triangle. */
1452#endif /* not ANSI_DECLARATORS */
1453
1454{
1455 REAL dxoa, dxda, dxod;
1456 REAL dyoa, dyda, dyod;
1457 REAL oalen, dalen, odlen;
1458 REAL maxlen;
1459
1460 dxoa = triorg[0] - triapex[0];
1461 dyoa = triorg[1] - triapex[1];
1462 dxda = tridest[0] - triapex[0];
1463 dyda = tridest[1] - triapex[1];
1464 dxod = triorg[0] - tridest[0];
1465 dyod = triorg[1] - tridest[1];
1466 /* Find the squares of the lengths of the triangle's three edges. */
1467 oalen = dxoa * dxoa + dyoa * dyoa;
1468 dalen = dxda * dxda + dyda * dyda;
1469 odlen = dxod * dxod + dyod * dyod;
1470 /* Find the square of the length of the longest edge. */
1471 maxlen = (dalen > oalen) ? dalen : oalen;
1472 maxlen = (odlen > maxlen) ? odlen : maxlen;
1473
1474 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
1475 return 1;
1476 } else {
1477 return 0;
1478 }
1479}
1480
1481#endif /* not EXTERNAL_TEST */
1482
1485/********* User-defined triangle evaluation routine ends here *********/
1486
1487/********* Memory allocation and program exit wrappers begin here *********/
1491#ifdef ANSI_DECLARATORS
1492void triexit(int status)
1493#else /* not ANSI_DECLARATORS */
1494void triexit(status)
1495int status;
1496#endif /* not ANSI_DECLARATORS */
1497
1498{
1499 exit(status);
1500}
1501
1502#ifdef ANSI_DECLARATORS
1503VOID *trimalloc(int size)
1504#else /* not ANSI_DECLARATORS */
1505VOID *trimalloc(size)
1506int size;
1507#endif /* not ANSI_DECLARATORS */
1508
1509{
1510 VOID *memptr;
1511
1512 memptr = (VOID *) malloc((unsigned int) size);
1513 if (memptr == (VOID *) NULL) {
1514 printf("Error: Out of memory.\n");
1515 triexit(1);
1516 }
1517 return(memptr);
1518}
1519
1520#ifdef ANSI_DECLARATORS
1521void trifree(VOID *memptr)
1522#else /* not ANSI_DECLARATORS */
1523void trifree(memptr)
1524VOID *memptr;
1525#endif /* not ANSI_DECLARATORS */
1526
1527{
1528 free(memptr);
1529}
1530
1533/********* Memory allocation and program exit wrappers end here *********/
1534
1535/********* User interaction routines begin here *********/
1539/*****************************************************************************/
1540/* */
1541/* syntax() Print list of command line switches. */
1542/* */
1543/*****************************************************************************/
1544
1545#ifndef TRILIBRARY
1546
1547void syntax()
1548{
1549#ifdef CDT_ONLY
1550#ifdef REDUCED
1551 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
1552#else /* not REDUCED */
1553 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
1554#endif /* not REDUCED */
1555#else /* not CDT_ONLY */
1556#ifdef REDUCED
1557 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
1558#else /* not REDUCED */
1559 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
1560#endif /* not REDUCED */
1561#endif /* not CDT_ONLY */
1562
1563 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
1564#ifndef CDT_ONLY
1565 printf(" -r Refines a previously generated mesh.\n");
1566 printf(
1567 " -q Quality mesh generation. A minimum angle may be specified.\n");
1568 printf(" -a Applies a maximum triangle area constraint.\n");
1569 printf(" -u Applies a user-defined triangle constraint.\n");
1570#endif /* not CDT_ONLY */
1571 printf(
1572 " -A Applies attributes to identify triangles in certain regions.\n");
1573 printf(" -c Encloses the convex hull with segments.\n");
1574#ifndef CDT_ONLY
1575 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
1576#endif /* not CDT_ONLY */
1577/*
1578 printf(" -w Weighted Delaunay triangulation.\n");
1579 printf(" -W Regular triangulation (lower hull of a height field).\n");
1580*/
1581 printf(" -j Jettison unused vertices from output .node file.\n");
1582 printf(" -e Generates an edge list.\n");
1583 printf(" -v Generates a Voronoi diagram.\n");
1584 printf(" -n Generates a list of triangle neighbors.\n");
1585 printf(" -g Generates an .off file for Geomview.\n");
1586 printf(" -B Suppresses output of boundary information.\n");
1587 printf(" -P Suppresses output of .poly file.\n");
1588 printf(" -N Suppresses output of .node file.\n");
1589 printf(" -E Suppresses output of .ele file.\n");
1590 printf(" -I Suppresses mesh iteration numbers.\n");
1591 printf(" -O Ignores holes in .poly file.\n");
1592 printf(" -X Suppresses use of exact arithmetic.\n");
1593 printf(" -z Numbers all items starting from zero (rather than one).\n");
1594 printf(" -o2 Generates second-order subparametric elements.\n");
1595#ifndef CDT_ONLY
1596 printf(" -Y Suppresses boundary segment splitting.\n");
1597 printf(" -S Specifies maximum number of added Steiner points.\n");
1598#endif /* not CDT_ONLY */
1599#ifndef REDUCED
1600 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
1601 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
1602#endif /* not REDUCED */
1603 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
1604#ifndef REDUCED
1605#ifndef CDT_ONLY
1606 printf(
1607 " -s Force segments into mesh by splitting (instead of using CDT).\n");
1608#endif /* not CDT_ONLY */
1609 printf(" -C Check consistency of final mesh.\n");
1610#endif /* not REDUCED */
1611 printf(" -Q Quiet: No terminal output except errors.\n");
1612 printf(" -V Verbose: Detailed information on what I'm doing.\n");
1613 printf(" -h Help: Detailed instructions for Triangle.\n");
1614 triexit(0);
1615}
1616
1617#endif /* not TRILIBRARY */
1618
1619/*****************************************************************************/
1620/* */
1621/* info() Print out complete instructions. */
1622/* */
1623/*****************************************************************************/
1624
1625#ifndef TRILIBRARY
1626
1627void info()
1628{
1629 printf("Triangle\n");
1630 printf(
1631"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
1632 printf("Version 1.6\n\n");
1633 printf(
1634"Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
1635 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
1636 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
1637 printf(
1638"Created as part of the Quake project (tools for earthquake simulation).\n");
1639 printf(
1640"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
1641 printf("There is no warranty whatsoever. Use at your own risk.\n");
1642#ifdef SINGLE
1643 printf("This executable is compiled for single precision arithmetic.\n\n\n");
1644#else /* not SINGLE */
1645 printf("This executable is compiled for double precision arithmetic.\n\n\n");
1646#endif /* not SINGLE */
1647 printf(
1648"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
1649 printf(
1650"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
1651 printf(
1652"high-quality triangular meshes. The latter can be generated with no small\n"
1653);
1654 printf(
1655"or large angles, and are thus suitable for finite element analysis. If no\n"
1656);
1657 printf(
1658"command line switch is specified, your .node input file is read, and the\n");
1659 printf(
1660"Delaunay triangulation is returned in .node and .ele output files. The\n");
1661 printf("command syntax is:\n\n");
1662 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
1663 printf(
1664"Underscores indicate that numbers may optionally follow certain switches.\n");
1665 printf(
1666"Do not leave any space between a switch and its numeric parameter.\n");
1667 printf(
1668"input_file must be a file with extension .node, or extension .poly if the\n");
1669 printf(
1670"-p switch is used. If -r is used, you must supply .node and .ele files,\n");
1671 printf(
1672"and possibly a .poly file and an .area file as well. The formats of these\n"
1673);
1674 printf("files are described below.\n\n");
1675 printf("Command Line Switches:\n\n");
1676 printf(
1677" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
1678);
1679 printf(
1680" vertices, segments, holes, regional attributes, and regional area\n");
1681 printf(
1682" constraints. Generates a constrained Delaunay triangulation (CDT)\n"
1683);
1684 printf(
1685" fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
1686 printf(
1687" constrained Delaunay triangulation (CCDT). If you want a truly\n");
1688 printf(
1689" Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
1690 printf(
1691" well. When -p is not used, Triangle reads a .node file by default.\n"
1692);
1693 printf(
1694" -r Refines a previously generated mesh. The mesh is read from a .node\n"
1695);
1696 printf(
1697" file and an .ele file. If -p is also used, a .poly file is read\n");
1698 printf(
1699" and used to constrain segments in the mesh. If -a is also used\n");
1700 printf(
1701" (with no number following), an .area file is read and used to\n");
1702 printf(
1703" impose area constraints on the mesh. Further details on refinement\n"
1704);
1705 printf(" appear below.\n");
1706 printf(
1707" -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
1708 printf(
1709" Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
1710);
1711 printf(
1712" ensure that all angles are between 20 and 140 degrees. An\n");
1713 printf(
1714" alternative bound on the minimum angle, replacing 20 degrees, may\n");
1715 printf(
1716" be specified after the `q'. The specified angle may include a\n");
1717 printf(
1718" decimal point, but not exponential notation. Note that a bound of\n"
1719);
1720 printf(
1721" theta degrees on the smallest angle also implies a bound of\n");
1722 printf(
1723" (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
1724);
1725 printf(
1726" degrees or smaller, Triangle is mathematically guaranteed to\n");
1727 printf(
1728" terminate (assuming infinite precision arithmetic--Triangle may\n");
1729 printf(
1730" fail to terminate if you run out of precision). In practice,\n");
1731 printf(
1732" Triangle often succeeds for minimum angles up to 34 degrees. For\n");
1733 printf(
1734" some meshes, however, you might need to reduce the minimum angle to\n"
1735);
1736 printf(
1737" avoid problems associated with insufficient floating-point\n");
1738 printf(" precision.\n");
1739 printf(
1740" -a Imposes a maximum triangle area. If a number follows the `a', no\n");
1741 printf(
1742" triangle is generated whose area is larger than that number. If no\n"
1743);
1744 printf(
1745" number is specified, an .area file (if -r is used) or .poly file\n");
1746 printf(
1747" (if -r is not used) specifies a set of maximum area constraints.\n");
1748 printf(
1749" An .area file contains a separate area constraint for each\n");
1750 printf(
1751" triangle, and is useful for refining a finite element mesh based on\n"
1752);
1753 printf(
1754" a posteriori error estimates. A .poly file can optionally contain\n"
1755);
1756 printf(
1757" an area constraint for each segment-bounded region, thereby\n");
1758 printf(
1759" controlling triangle densities in a first triangulation of a PSLG.\n"
1760);
1761 printf(
1762" You can impose both a fixed area constraint and a varying area\n");
1763 printf(
1764" constraint by invoking the -a switch twice, once with and once\n");
1765 printf(
1766" without a number following. Each area specified may include a\n");
1767 printf(" decimal point.\n");
1768 printf(
1769" -u Imposes a user-defined constraint on triangle size. There are two\n"
1770);
1771 printf(
1772" ways to use this feature. One is to edit the triunsuitable()\n");
1773 printf(
1774" procedure in triangle.c to encode any constraint you like, then\n");
1775 printf(
1776" recompile Triangle. The other is to compile triangle.c with the\n");
1777 printf(
1778" EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
1779 printf(
1780" link Triangle with a separate object file that implements\n");
1781 printf(
1782" triunsuitable(). In either case, the -u switch causes the user-\n");
1783 printf(" defined test to be applied to every triangle.\n");
1784 printf(
1785" -A Assigns an additional floating-point attribute to each triangle\n");
1786 printf(
1787" that identifies what segment-bounded region each triangle belongs\n");
1788 printf(
1789" to. Attributes are assigned to regions by the .poly file. If a\n");
1790 printf(
1791" region is not explicitly marked by the .poly file, triangles in\n");
1792 printf(
1793" that region are assigned an attribute of zero. The -A switch has\n");
1794 printf(
1795" an effect only when the -p switch is used and the -r switch is not.\n"
1796);
1797 printf(
1798" -c Creates segments on the convex hull of the triangulation. If you\n");
1799 printf(
1800" are triangulating a vertex set, this switch causes a .poly file to\n"
1801);
1802 printf(
1803" be written, containing all edges of the convex hull. If you are\n");
1804 printf(
1805" triangulating a PSLG, this switch specifies that the whole convex\n");
1806 printf(
1807" hull of the PSLG should be triangulated, regardless of what\n");
1808 printf(
1809" segments the PSLG has. If you do not use this switch when\n");
1810 printf(
1811" triangulating a PSLG, Triangle assumes that you have identified the\n"
1812);
1813 printf(
1814" region to be triangulated by surrounding it with segments of the\n");
1815 printf(
1816" input PSLG. Beware: if you are not careful, this switch can cause\n"
1817);
1818 printf(
1819" the introduction of an extremely thin angle between a PSLG segment\n"
1820);
1821 printf(
1822" and a convex hull segment, which can cause overrefinement (and\n");
1823 printf(
1824" possibly failure if Triangle runs out of precision). If you are\n");
1825 printf(
1826" refining a mesh, the -c switch works differently: it causes a\n");
1827 printf(
1828" .poly file to be written containing the boundary edges of the mesh\n"
1829);
1830 printf(" (useful if no .poly file was read).\n");
1831 printf(
1832" -D Conforming Delaunay triangulation: use this switch if you want to\n"
1833);
1834 printf(
1835" ensure that all the triangles in the mesh are Delaunay, and not\n");
1836 printf(
1837" merely constrained Delaunay; or if you want to ensure that all the\n"
1838);
1839 printf(
1840" Voronoi vertices lie within the triangulation. (Some finite volume\n"
1841);
1842 printf(
1843" methods have this requirement.) This switch invokes Ruppert's\n");
1844 printf(
1845" original algorithm, which splits every subsegment whose diametral\n");
1846 printf(
1847" circle is encroached. It usually increases the number of vertices\n"
1848);
1849 printf(" and triangles.\n");
1850 printf(
1851" -j Jettisons vertices that are not part of the final triangulation\n");
1852 printf(
1853" from the output .node file. By default, Triangle copies all\n");
1854 printf(
1855" vertices in the input .node file to the output .node file, in the\n");
1856 printf(
1857" same order, so their indices do not change. The -j switch prevents\n"
1858);
1859 printf(
1860" duplicated input vertices, or vertices `eaten' by holes, from\n");
1861 printf(
1862" appearing in the output .node file. Thus, if two input vertices\n");
1863 printf(
1864" have exactly the same coordinates, only the first appears in the\n");
1865 printf(
1866" output. If any vertices are jettisoned, the vertex numbering in\n");
1867 printf(
1868" the output .node file differs from that of the input .node file.\n");
1869 printf(
1870" -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
1871 printf(
1872" -v Outputs the Voronoi diagram associated with the triangulation.\n");
1873 printf(
1874" Does not attempt to detect degeneracies, so some Voronoi vertices\n");
1875 printf(
1876" may be duplicated. See the discussion of Voronoi diagrams below.\n");
1877 printf(
1878" -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
1879 printf(" triangle.\n");
1880 printf(
1881" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
1882);
1883 printf(" viewing with the Geometry Center's Geomview package.\n");
1884 printf(
1885" -B No boundary markers in the output .node, .poly, and .edge output\n");
1886 printf(
1887" files. See the detailed discussion of boundary markers below.\n");
1888 printf(
1889" -P No output .poly file. Saves disk space, but you lose the ability\n");
1890 printf(
1891" to maintain constraining segments on later refinements of the mesh.\n"
1892);
1893 printf(" -N No output .node file.\n");
1894 printf(" -E No output .ele file.\n");
1895 printf(
1896" -I No iteration numbers. Suppresses the output of .node and .poly\n");
1897 printf(
1898" files, so your input files won't be overwritten. (If your input is\n"
1899);
1900 printf(
1901" a .poly file only, a .node file is written.) Cannot be used with\n");
1902 printf(
1903" the -r switch, because that would overwrite your input .ele file.\n");
1904 printf(
1905" Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
1906 printf(
1907" using a .node file for input, because no .node file is written, so\n"
1908);
1909 printf(" there is no record of any added Steiner points.\n");
1910 printf(" -O No holes. Ignores the holes in the .poly file.\n");
1911 printf(
1912" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
1913);
1914 printf(
1915" arithmetic for certain tests if it thinks the inexact tests are not\n"
1916);
1917 printf(
1918" accurate enough. Exact arithmetic ensures the robustness of the\n");
1919 printf(
1920" triangulation algorithms, despite floating-point roundoff error.\n");
1921 printf(
1922" Disabling exact arithmetic with the -X switch causes a small\n");
1923 printf(
1924" improvement in speed and creates the possibility that Triangle will\n"
1925);
1926 printf(" fail to produce a valid mesh. Not recommended.\n");
1927 printf(
1928" -z Numbers all items starting from zero (rather than one). Note that\n"
1929);
1930 printf(
1931" this switch is normally overridden by the value used to number the\n"
1932);
1933 printf(
1934" first vertex of the input .node or .poly file. However, this\n");
1935 printf(
1936" switch is useful when calling Triangle from another program.\n");
1937 printf(
1938" -o2 Generates second-order subparametric elements with six nodes each.\n"
1939);
1940 printf(
1941" -Y No new vertices on the boundary. This switch is useful when the\n");
1942 printf(
1943" mesh boundary must be preserved so that it conforms to some\n");
1944 printf(
1945" adjacent mesh. Be forewarned that you will probably sacrifice much\n"
1946);
1947 printf(
1948" of the quality of the mesh; Triangle will try, but the resulting\n");
1949 printf(
1950" mesh may contain poorly shaped triangles. Works well if all the\n");
1951 printf(
1952" boundary vertices are closely spaced. Specify this switch twice\n");
1953 printf(
1954" (`-YY') to prevent all segment splitting, including internal\n");
1955 printf(" boundaries.\n");
1956 printf(
1957" -S Specifies the maximum number of Steiner points (vertices that are\n");
1958 printf(
1959" not in the input, but are added to meet the constraints on minimum\n"
1960);
1961 printf(
1962" angle and maximum area). The default is to allow an unlimited\n");
1963 printf(
1964" number. If you specify this switch with no number after it,\n");
1965 printf(
1966" the limit is set to zero. Triangle always adds vertices at segment\n"
1967);
1968 printf(
1969" intersections, even if it needs to use more vertices than the limit\n"
1970);
1971 printf(
1972" you set. When Triangle inserts segments by splitting (-s), it\n");
1973 printf(
1974" always adds enough vertices to ensure that all the segments of the\n"
1975);
1976 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
1977 printf(
1978" -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
1979 printf(
1980" construct a Delaunay triangulation. Try it if the divide-and-\n");
1981 printf(" conquer algorithm fails.\n");
1982 printf(
1983" -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
1984 printf(
1985" triangulation. Warning: does not use exact arithmetic for all\n");
1986 printf(" calculations. An exact result is not guaranteed.\n");
1987 printf(
1988" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
1989 printf(
1990" default, Triangle alternates between vertical and horizontal cuts,\n"
1991);
1992 printf(
1993" which usually improve the speed except with vertex sets that are\n");
1994 printf(
1995" small or short and wide. This switch is primarily of theoretical\n");
1996 printf(" interest.\n");
1997 printf(
1998" -s Specifies that segments should be forced into the triangulation by\n"
1999);
2000 printf(
2001" recursively splitting them at their midpoints, rather than by\n");
2002 printf(
2003" generating a constrained Delaunay triangulation. Segment splitting\n"
2004);
2005 printf(
2006" is true to Ruppert's original algorithm, but can create needlessly\n"
2007);
2008 printf(
2009" small triangles. This switch is primarily of theoretical interest.\n"
2010);
2011 printf(
2012" -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
2013);
2014 printf(
2015" checking, even if the -X switch is used. Useful if you suspect\n");
2016 printf(" Triangle is buggy.\n");
2017 printf(
2018" -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
2019 printf(" unless an error occurs.\n");
2020 printf(
2021" -V Verbose: Gives detailed information about what Triangle is doing.\n"
2022);
2023 printf(
2024" Add more `V's for increasing amount of detail. `-V' is most\n");
2025 printf(
2026" useful; itgives information on algorithmic progress and much more\n");
2027 printf(
2028" detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
2029 printf(
2030" prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
2031);
2032 printf(" information only a debugger could love.\n");
2033 printf(" -h Help: Displays these instructions.\n");
2034 printf("\n");
2035 printf("Definitions:\n");
2036 printf("\n");
2037 printf(
2038" A Delaunay triangulation of a vertex set is a triangulation whose\n");
2039 printf(
2040" vertices are the vertex set, that covers the convex hull of the vertex\n");
2041 printf(
2042" set. A Delaunay triangulation has the property that no vertex lies\n");
2043 printf(
2044" inside the circumscribing circle (circle that passes through all three\n");
2045 printf(" vertices) of any triangle in the triangulation.\n\n");
2046 printf(
2047" A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
2048 printf(
2049" polygonal cells (some of which may be unbounded, meaning infinitely\n");
2050 printf(
2051" large), where each cell is the set of points in the plane that are closer\n"
2052);
2053 printf(
2054" to some input vertex than to any other input vertex. The Voronoi diagram\n"
2055);
2056 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
2057 printf(
2058" A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
2059 printf(
2060" Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
2061);
2062 printf(
2063" Segments may intersect each other only at their endpoints. The file\n");
2064 printf(" format for PSLGs (.poly files) is described below.\n\n");
2065 printf(
2066" A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
2067 printf(
2068" Delaunay triangulation, but each PSLG segment is present as a single edge\n"
2069);
2070 printf(
2071" of the CDT. (A constrained Delaunay triangulation is not truly a\n");
2072 printf(
2073" Delaunay triangulation, because some of its triangles might not be\n");
2074 printf(
2075" Delaunay.) By definition, a CDT does not have any vertices other than\n");
2076 printf(
2077" those specified in the input PSLG. Depending on context, a CDT might\n");
2078 printf(
2079" cover the convex hull of the PSLG, or it might cover only a segment-\n");
2080 printf(" bounded region (e.g. a polygon).\n\n");
2081 printf(
2082" A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
2083);
2084 printf(
2085" each triangle is truly Delaunay, and each PSLG segment is represented by\n"
2086);
2087 printf(
2088" a linear contiguous sequence of edges of the triangulation. New vertices\n"
2089);
2090 printf(
2091" (not part of the PSLG) may appear, and each input segment may have been\n");
2092 printf(
2093" subdivided into shorter edges (subsegments) by these additional vertices.\n"
2094);
2095 printf(
2096" The new vertices are frequently necessary to maintain the Delaunay\n");
2097 printf(" property while ensuring that every segment is represented.\n\n");
2098 printf(
2099" A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
2100 printf(
2101" triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
2102 printf(" vertices may appear, and input segments may be subdivided into\n");
2103 printf(
2104" subsegments, but not to guarantee that segments are respected; rather, to\n"
2105);
2106 printf(
2107" improve the quality of the triangles. The high-quality meshes produced\n");
2108 printf(
2109" by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
2110 printf(" with the -D switch.\n\n");
2111 printf("File Formats:\n\n");
2112 printf(
2113" All files may contain comments prefixed by the character '#'. Vertices,\n"
2114);
2115 printf(
2116" triangles, edges, holes, and maximum area constraints must be numbered\n");
2117 printf(
2118" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
2119 printf(
2120" input files must be consistent; if the vertices are numbered from 1, so\n");
2121 printf(
2122" must be all other objects. Triangle automatically detects your choice\n");
2123 printf(
2124" while reading the .node (or .poly) file. (When calling Triangle from\n");
2125 printf(
2126" another program, use the -z switch if you wish to number objects from\n");
2127 printf(" zero.) Examples of these file formats are given below.\n\n");
2128 printf(" .node files:\n");
2129 printf(
2130" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2131);
2132 printf(
2133" <# of boundary markers (0 or 1)>\n"
2134);
2135 printf(
2136" Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2137 printf("\n");
2138 printf(
2139" The attributes, which are typically floating-point values of physical\n");
2140 printf(
2141" quantities (such as mass or conductivity) associated with the nodes of\n"
2142);
2143 printf(
2144" a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
2145);
2146 printf(
2147" -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
2148);
2149 printf(" has attributes assigned to it by linear interpolation.\n\n");
2150 printf(
2151" If the fourth entry of the first line is `1', the last column of the\n");
2152 printf(
2153" remainder of the file is assumed to contain boundary markers. Boundary\n"
2154);
2155 printf(
2156" markers are used to identify boundary vertices and vertices resting on\n"
2157);
2158 printf(
2159" PSLG segments; a complete description appears in a section below. The\n"
2160);
2161 printf(
2162" .node file produced by Triangle contains boundary markers in the last\n");
2163 printf(" column unless they are suppressed by the -B switch.\n\n");
2164 printf(" .ele files:\n");
2165 printf(
2166" First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
2167 printf(
2168" Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
2169 printf("\n");
2170 printf(
2171" Nodes are indices into the corresponding .node file. The first three\n");
2172 printf(
2173" nodes are the corner vertices, and are listed in counterclockwise order\n"
2174);
2175 printf(
2176" around each triangle. (The remaining nodes, if any, depend on the type\n"
2177);
2178 printf(" of finite element used.)\n\n");
2179 printf(
2180" The attributes are just like those of .node files. Because there is no\n"
2181);
2182 printf(
2183" simple mapping from input to output triangles, Triangle attempts to\n");
2184 printf(
2185" interpolate attributes, and may cause a lot of diffusion of attributes\n"
2186);
2187 printf(
2188" among nearby triangles as the triangulation is refined. Attributes do\n"
2189);
2190 printf(" not diffuse across segments, so attributes used to identify\n");
2191 printf(" segment-bounded regions remain intact.\n\n");
2192 printf(
2193" In .ele files produced by Triangle, each triangular element has three\n");
2194 printf(
2195" nodes (vertices) unless the -o2 switch is used, in which case\n");
2196 printf(
2197" subparametric quadratic elements with six nodes each are generated.\n");
2198 printf(
2199" The first three nodes are the corners in counterclockwise order, and\n");
2200 printf(
2201" the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
2202 printf(
2203" opposite the first, second, and third vertices, respectively.\n");
2204 printf("\n");
2205 printf(" .poly files:\n");
2206 printf(
2207" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2208);
2209 printf(
2210" <# of boundary markers (0 or 1)>\n"
2211);
2212 printf(
2213" Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2214 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
2215 printf(
2216" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
2217 printf(" One line: <# of holes>\n");
2218 printf(" Following lines: <hole #> <x> <y>\n");
2219 printf(
2220" Optional line: <# of regional attributes and/or area constraints>\n");
2221 printf(
2222" Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
2223 printf("\n");
2224 printf(
2225" A .poly file represents a PSLG, as well as some additional information.\n"
2226);
2227 printf(
2228" The first section lists all the vertices, and is identical to the\n");
2229 printf(
2230" format of .node files. <# of vertices> may be set to zero to indicate\n"
2231);
2232 printf(
2233" that the vertices are listed in a separate .node file; .poly files\n");
2234 printf(
2235" produced by Triangle always have this format. A vertex set represented\n"
2236);
2237 printf(
2238" this way has the advantage that it may easily be triangulated with or\n");
2239 printf(
2240" without segments (depending on whether the -p switch is invoked).\n");
2241 printf("\n");
2242 printf(
2243" The second section lists the segments. Segments are edges whose\n");
2244 printf(
2245" presence in the triangulation is enforced. (Depending on the choice of\n"
2246);
2247 printf(
2248" switches, segment might be subdivided into smaller edges). Each\n");
2249 printf(
2250" segment is specified by listing the indices of its two endpoints. This\n"
2251);
2252 printf(
2253" means that you must include its endpoints in the vertex list. Each\n");
2254 printf(" segment, like each point, may have a boundary marker.\n\n");
2255 printf(
2256" If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
2257);
2258 printf(
2259" Delaunay triangulation (CDT), in which each segment appears as a single\n"
2260);
2261 printf(
2262" edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
2263);
2264 printf(
2265" produces a conforming constrained Delaunay triangulation (CCDT), in\n");
2266 printf(
2267" which segments may be subdivided into smaller edges. If -D is\n");
2268 printf(
2269" selected, Triangle produces a conforming Delaunay triangulation, so\n");
2270 printf(
2271" that every triangle is Delaunay, and not just constrained Delaunay.\n");
2272 printf("\n");
2273 printf(
2274" The third section lists holes (and concavities, if -c is selected) in\n");
2275 printf(
2276" the triangulation. Holes are specified by identifying a point inside\n");
2277 printf(
2278" each hole. After the triangulation is formed, Triangle creates holes\n");
2279 printf(
2280" by eating triangles, spreading out from each hole point until its\n");
2281 printf(
2282" progress is blocked by segments in the PSLG. You must be careful to\n");
2283 printf(
2284" enclose each hole in segments, or your whole triangulation might be\n");
2285 printf(
2286" eaten away. If the two triangles abutting a segment are eaten, the\n");
2287 printf(
2288" segment itself is also eaten. Do not place a hole directly on a\n");
2289 printf(" segment; if you do, Triangle chooses one side of the segment\n");
2290 printf(" arbitrarily.\n\n");
2291 printf(
2292" The optional fourth section lists regional attributes (to be assigned\n");
2293 printf(
2294" to all triangles in a region) and regional constraints on the maximum\n");
2295 printf(
2296" triangle area. Triangle reads this section only if the -A switch is\n");
2297 printf(
2298" used or the -a switch is used without a number following it, and the -r\n"
2299);
2300 printf(
2301" switch is not used. Regional attributes and area constraints are\n");
2302 printf(
2303" propagated in the same manner as holes: you specify a point for each\n");
2304 printf(
2305" attribute and/or constraint, and the attribute and/or constraint\n");
2306 printf(
2307" affects the whole region (bounded by segments) containing the point.\n");
2308 printf(
2309" If two values are written on a line after the x and y coordinate, the\n");
2310 printf(
2311" first such value is assumed to be a regional attribute (but is only\n");
2312 printf(
2313" applied if the -A switch is selected), and the second value is assumed\n"
2314);
2315 printf(
2316" to be a regional area constraint (but is only applied if the -a switch\n"
2317);
2318 printf(
2319" is selected). You may specify just one value after the coordinates,\n");
2320 printf(
2321" which can serve as both an attribute and an area constraint, depending\n"
2322);
2323 printf(
2324" on the choice of switches. If you are using the -A and -a switches\n");
2325 printf(
2326" simultaneously and wish to assign an attribute to some region without\n");
2327 printf(" imposing an area constraint, use a negative maximum area.\n\n");
2328 printf(
2329" When a triangulation is created from a .poly file, you must either\n");
2330 printf(
2331" enclose the entire region to be triangulated in PSLG segments, or\n");
2332 printf(
2333" use the -c switch, which automatically creates extra segments that\n");
2334 printf(
2335" enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
2336);
2337 printf(
2338" Triangle eats all triangles that are not enclosed by segments; if you\n");
2339 printf(
2340" are not careful, your whole triangulation may be eaten away. If you do\n"
2341);
2342 printf(
2343" use the -c switch, you can still produce concavities by the appropriate\n"
2344);
2345 printf(
2346" placement of holes just inside the boundary of the convex hull.\n");
2347 printf("\n");
2348 printf(
2349" An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
2350 printf(
2351" upon segments (except, of course, the endpoints of each segment). You\n"
2352);
2353 printf(
2354" aren't required to make your .poly files ideal, but you should be aware\n"
2355);
2356 printf(
2357" of what can go wrong. Segment intersections are relatively safe--\n");
2358 printf(
2359" Triangle calculates the intersection points for you and adds them to\n");
2360 printf(
2361" the triangulation--as long as your machine's floating-point precision\n");
2362 printf(
2363" doesn't become a problem. You are tempting the fates if you have three\n"
2364);
2365 printf(
2366" segments that cross at the same location, and expect Triangle to figure\n"
2367);
2368 printf(
2369" out where the intersection point is. Thanks to floating-point roundoff\n"
2370);
2371 printf(
2372" error, Triangle will probably decide that the three segments intersect\n"
2373);
2374 printf(
2375" at three different points, and you will find a minuscule triangle in\n");
2376 printf(
2377" your output--unless Triangle tries to refine the tiny triangle, uses\n");
2378 printf(
2379" up the last bit of machine precision, and fails to terminate at all.\n");
2380 printf(
2381" You're better off putting the intersection point in the input files,\n");
2382 printf(
2383" and manually breaking up each segment into two. Similarly, if you\n");
2384 printf(
2385" place a vertex at the middle of a segment, and hope that Triangle will\n"
2386);
2387 printf(
2388" break up the segment at that vertex, you might get lucky. On the other\n"
2389);
2390 printf(
2391" hand, Triangle might decide that the vertex doesn't lie precisely on\n");
2392 printf(
2393" the segment, and you'll have a needle-sharp triangle in your output--or\n"
2394);
2395 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
2396 printf("\n");
2397 printf(
2398" When Triangle reads a .poly file, it also writes a .poly file, which\n");
2399 printf(
2400" includes all the subsegments--the edges that are parts of input\n");
2401 printf(
2402" segments. If the -c switch is used, the output .poly file also\n");
2403 printf(
2404" includes all of the edges on the convex hull. Hence, the output .poly\n"
2405);
2406 printf(
2407" file is useful for finding edges associated with input segments and for\n"
2408);
2409 printf(
2410" setting boundary conditions in finite element simulations. Moreover,\n");
2411 printf(
2412" you will need the output .poly file if you plan to refine the output\n");
2413 printf(
2414" mesh, and don't want segments to be missing in later triangulations.\n");
2415 printf("\n");
2416 printf(" .area files:\n");
2417 printf(" First line: <# of triangles>\n");
2418 printf(" Following lines: <triangle #> <maximum area>\n");
2419 printf("\n");
2420 printf(
2421" An .area file associates with each triangle a maximum area that is used\n"
2422);
2423 printf(
2424" for mesh refinement. As with other file formats, every triangle must\n");
2425 printf(
2426" be represented, and the triangles must be numbered consecutively. A\n");
2427 printf(
2428" triangle may be left unconstrained by assigning it a negative maximum\n");
2429 printf(" area.\n\n");
2430 printf(" .edge files:\n");
2431 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
2432 printf(
2433" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
2434 printf("\n");
2435 printf(
2436" Endpoints are indices into the corresponding .node file. Triangle can\n"
2437);
2438 printf(
2439" produce .edge files (use the -e switch), but cannot read them. The\n");
2440 printf(
2441" optional column of boundary markers is suppressed by the -B switch.\n");
2442 printf("\n");
2443 printf(
2444" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
2445 printf(
2446" infinite ray with only one endpoint. For these edges, a different\n");
2447 printf(" format is used:\n\n");
2448 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
2449 printf(
2450" The `direction' is a floating-point vector that indicates the direction\n"
2451);
2452 printf(" of the infinite ray.\n\n");
2453 printf(" .neigh files:\n");
2454 printf(
2455" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
2456);
2457 printf(
2458" Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
2459 printf("\n");
2460 printf(
2461" Neighbors are indices into the corresponding .ele file. An index of -1\n"
2462);
2463 printf(
2464" indicates no neighbor (because the triangle is on an exterior\n");
2465 printf(
2466" boundary). The first neighbor of triangle i is opposite the first\n");
2467 printf(" corner of triangle i, and so on.\n\n");
2468 printf(
2469" Triangle can produce .neigh files (use the -n switch), but cannot read\n"
2470);
2471 printf(" them.\n\n");
2472 printf("Boundary Markers:\n\n");
2473 printf(
2474" Boundary markers are tags used mainly to identify which output vertices\n");
2475 printf(
2476" and edges are associated with which PSLG segment, and to identify which\n");
2477 printf(
2478" vertices and edges occur on a boundary of the triangulation. A common\n");
2479 printf(
2480" use is to determine where boundary conditions should be applied to a\n");
2481 printf(
2482" finite element mesh. You can prevent boundary markers from being written\n"
2483);
2484 printf(" into files produced by Triangle by using the -B switch.\n\n");
2485 printf(
2486" The boundary marker associated with each segment in an output .poly file\n"
2487);
2488 printf(" and each edge in an output .edge file is chosen as follows:\n");
2489 printf(
2490" - If an output edge is part or all of a PSLG segment with a nonzero\n");
2491 printf(
2492" boundary marker, then the edge is assigned the same marker.\n");
2493 printf(
2494" - Otherwise, if the edge lies on a boundary of the triangulation\n");
2495 printf(
2496" (even the boundary of a hole), then the edge is assigned the marker\n");
2497 printf(" one (1).\n");
2498 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
2499 printf(
2500" The boundary marker associated with each vertex in an output .node file\n");
2501 printf(" is chosen as follows:\n");
2502 printf(
2503" - If a vertex is assigned a nonzero boundary marker in the input file,\n"
2504);
2505 printf(
2506" then it is assigned the same marker in the output .node file.\n");
2507 printf(
2508" - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
2509 printf(
2510" endpoint of the segment) with a nonzero boundary marker, then the\n");
2511 printf(
2512" vertex is assigned the same marker. If the vertex lies on several\n");
2513 printf(" such segments, one of the markers is chosen arbitrarily.\n");
2514 printf(
2515" - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
2516 printf(" then the vertex is assigned the marker one (1).\n");
2517 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
2518 printf("\n");
2519 printf(
2520" If you want Triangle to determine for you which vertices and edges are on\n"
2521);
2522 printf(
2523" the boundary, assign them the boundary marker zero (or use no markers at\n"
2524);
2525 printf(
2526" all) in your input files. In the output files, all boundary vertices,\n");
2527 printf(" edges, and segments will be assigned the value one.\n\n");
2528 printf("Triangulation Iteration Numbers:\n\n");
2529 printf(
2530" Because Triangle can read and refine its own triangulations, input\n");
2531 printf(
2532" and output files have iteration numbers. For instance, Triangle might\n");
2533 printf(
2534" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
2535 printf(
2536" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
2537 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
2538 printf(
2539" their iteration number is zero; hence, Triangle might read the file\n");
2540 printf(
2541" points.node, triangulate it, and produce the files points.1.node and\n");
2542 printf(" points.1.ele.\n\n");
2543 printf(
2544" Iteration numbers allow you to create a sequence of successively finer\n");
2545 printf(
2546" meshes suitable for multigrid methods. They also allow you to produce a\n"
2547);
2548 printf(
2549" sequence of meshes using error estimate-driven mesh refinement.\n");
2550 printf("\n");
2551 printf(
2552" If you're not using refinement or quality meshing, and you don't like\n");
2553 printf(
2554" iteration numbers, use the -I switch to disable them. This switch also\n");
2555 printf(
2556" disables output of .node and .poly files to prevent your input files from\n"
2557);
2558 printf(
2559" being overwritten. (If the input is a .poly file that contains its own\n");
2560 printf(
2561" points, a .node file is written. This can be quite convenient for\n");
2562 printf(" computing CDTs or quality meshes.)\n\n");
2563 printf("Examples of How to Use Triangle:\n\n");
2564 printf(
2565" `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
2566);
2567 printf(
2568" triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
2569 printf(
2570" to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
2571 printf(
2572" instead. (No additional .node file is needed, so none is written.)\n");
2573 printf("\n");
2574 printf(
2575" `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
2576 printf(
2577" object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
2578);
2579 printf(
2580" its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
2581);
2582 printf(
2583" The segments are copied to object.2.poly, and all edges are written to\n");
2584 printf(" object.2.edge.\n\n");
2585 printf(
2586" `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
2587);
2588 printf(
2589" object.node), generates a mesh whose angles are all between 31.5 and 117\n"
2590);
2591 printf(
2592" degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
2593);
2594 printf(
2595" mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
2596 printf(" into multiple subsegments; these are written to object.1.poly.\n");
2597 printf("\n");
2598 printf(
2599" Here is a sample file `box.poly' describing a square with a square hole:\n"
2600);
2601 printf("\n");
2602 printf(
2603" # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
2604);
2605 printf(" 8 2 0 1\n");
2606 printf(" # Outer box has these vertices:\n");
2607 printf(" 1 0 0 0\n");
2608 printf(" 2 0 3 0\n");
2609 printf(" 3 3 0 0\n");
2610 printf(" 4 3 3 33 # A special marker for this vertex.\n");
2611 printf(" # Inner square has these vertices:\n");
2612 printf(" 5 1 1 0\n");
2613 printf(" 6 1 2 0\n");
2614 printf(" 7 2 1 0\n");
2615 printf(" 8 2 2 0\n");
2616 printf(" # Five segments with boundary markers.\n");
2617 printf(" 5 1\n");
2618 printf(" 1 1 2 5 # Left side of outer box.\n");
2619 printf(" # Square hole has these segments:\n");
2620 printf(" 2 5 7 0\n");
2621 printf(" 3 7 8 0\n");
2622 printf(" 4 8 6 10\n");
2623 printf(" 5 6 5 0\n");
2624 printf(" # One hole in the middle of the inner square.\n");
2625 printf(" 1\n");
2626 printf(" 1 1.5 1.5\n");
2627 printf("\n");
2628 printf(
2629" Note that some segments are missing from the outer square, so you must\n");
2630 printf(
2631" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
2632);
2633 printf(
2634" file `box.1.node', with twelve vertices. The last four vertices were\n");
2635 printf(
2636" added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
2637 printf(
2638" from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
2639 printf(
2640" other vertices but 4 have been marked to indicate that they lie on a\n");
2641 printf(" boundary.\n\n");
2642 printf(" 12 2 0 1\n");
2643 printf(" 1 0 0 5\n");
2644 printf(" 2 0 3 5\n");
2645 printf(" 3 3 0 1\n");
2646 printf(" 4 3 3 33\n");
2647 printf(" 5 1 1 1\n");
2648 printf(" 6 1 2 10\n");
2649 printf(" 7 2 1 1\n");
2650 printf(" 8 2 2 10\n");
2651 printf(" 9 0 1.5 5\n");
2652 printf(" 10 1.5 0 1\n");
2653 printf(" 11 3 1.5 1\n");
2654 printf(" 12 1.5 3 1\n");
2655 printf(" # Generated by triangle -pqc box.poly\n");
2656 printf("\n");
2657 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
2658 printf("\n");
2659 printf(" 12 3 0\n");
2660 printf(" 1 5 6 9\n");
2661 printf(" 2 10 3 7\n");
2662 printf(" 3 6 8 12\n");
2663 printf(" 4 9 1 5\n");
2664 printf(" 5 6 2 9\n");
2665 printf(" 6 7 3 11\n");
2666 printf(" 7 11 4 8\n");
2667 printf(" 8 7 5 10\n");
2668 printf(" 9 12 2 6\n");
2669 printf(" 10 8 7 11\n");
2670 printf(" 11 5 1 10\n");
2671 printf(" 12 8 4 12\n");
2672 printf(" # Generated by triangle -pqc box.poly\n\n");
2673 printf(
2674" Here is the output file `box.1.poly'. Note that segments have been added\n"
2675);
2676 printf(
2677" to represent the convex hull, and some segments have been subdivided by\n");
2678 printf(
2679" newly added vertices. Note also that <# of vertices> is set to zero to\n");
2680 printf(" indicate that the vertices should be read from the .node file.\n");
2681 printf("\n");
2682 printf(" 0 2 0 1\n");
2683 printf(" 12 1\n");
2684 printf(" 1 1 9 5\n");
2685 printf(" 2 5 7 1\n");
2686 printf(" 3 8 7 1\n");
2687 printf(" 4 6 8 10\n");
2688 printf(" 5 5 6 1\n");
2689 printf(" 6 3 10 1\n");
2690 printf(" 7 4 11 1\n");
2691 printf(" 8 2 12 1\n");
2692 printf(" 9 9 2 5\n");
2693 printf(" 10 10 1 1\n");
2694 printf(" 11 11 3 1\n");
2695 printf(" 12 12 4 1\n");
2696 printf(" 1\n");
2697 printf(" 1 1.5 1.5\n");
2698 printf(" # Generated by triangle -pqc box.poly\n");
2699 printf("\n");
2700 printf("Refinement and Area Constraints:\n");
2701 printf("\n");
2702 printf(
2703" The -r switch causes a mesh (.node and .ele files) to be read and\n");
2704 printf(
2705" refined. If the -p switch is also used, a .poly file is read and used to\n"
2706);
2707 printf(
2708" specify edges that are constrained and cannot be eliminated (although\n");
2709 printf(
2710" they can be subdivided into smaller edges) by the refinement process.\n");
2711 printf("\n");
2712 printf(
2713" When you refine a mesh, you generally want to impose tighter constraints.\n"
2714);
2715 printf(
2716" One way to accomplish this is to use -q with a larger angle, or -a\n");
2717 printf(
2718" followed by a smaller area than you used to generate the mesh you are\n");
2719 printf(
2720" refining. Another way to do this is to create an .area file, which\n");
2721 printf(
2722" specifies a maximum area for each triangle, and use the -a switch\n");
2723 printf(
2724" (without a number following). Each triangle's area constraint is applied\n"
2725);
2726 printf(
2727" to that triangle. Area constraints tend to diffuse as the mesh is\n");
2728 printf(
2729" refined, so if there are large variations in area constraint between\n");
2730 printf(
2731" adjacent triangles, you may not get the results you want. In that case,\n"
2732);
2733 printf(
2734" consider instead using the -u switch and writing a C procedure that\n");
2735 printf(" determines which triangles are too large.\n\n");
2736 printf(
2737" If you are refining a mesh composed of linear (three-node) elements, the\n"
2738);
2739 printf(
2740" output mesh contains all the nodes present in the input mesh, in the same\n"
2741);
2742 printf(
2743" order, with new nodes added at the end of the .node file. However, the\n");
2744 printf(
2745" refinement is not hierarchical: there is no guarantee that each output\n");
2746 printf(
2747" element is contained in a single input element. Often, an output element\n"
2748);
2749 printf(
2750" can overlap two or three input elements, and some input edges are not\n");
2751 printf(
2752" present in the output mesh. Hence, a sequence of refined meshes forms a\n"
2753);
2754 printf(
2755" hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
2756 printf(
2757" mesh of higher-order elements, the hierarchical property applies only to\n"
2758);
2759 printf(
2760" the nodes at the corners of an element; the midpoint nodes on each edge\n");
2761 printf(" are discarded before the mesh is refined.\n\n");
2762 printf(
2763" Maximum area constraints in .poly files operate differently from those in\n"
2764);
2765 printf(
2766" .area files. A maximum area in a .poly file applies to the whole\n");
2767 printf(
2768" (segment-bounded) region in which a point falls, whereas a maximum area\n");
2769 printf(
2770" in an .area file applies to only one triangle. Area constraints in .poly\n"
2771);
2772 printf(
2773" files are used only when a mesh is first generated, whereas area\n");
2774 printf(
2775" constraints in .area files are used only to refine an existing mesh, and\n"
2776);
2777 printf(
2778" are typically based on a posteriori error estimates resulting from a\n");
2779 printf(" finite element simulation on that mesh.\n\n");
2780 printf(
2781" `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
2782 printf(
2783" refines the triangulation to enforce a 25 degree minimum angle, and then\n"
2784);
2785 printf(
2786" writes the refined triangulation to object.2.node and object.2.ele.\n");
2787 printf("\n");
2788 printf(
2789" `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
2790);
2791 printf(
2792" After reconstructing the mesh and its subsegments, Triangle refines the\n");
2793 printf(
2794" mesh so that no triangle has area greater than 6.2, and furthermore the\n");
2795 printf(
2796" triangles satisfy the maximum area constraints in z.3.area. No angle\n");
2797 printf(
2798" bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
2799);
2800 printf(" z.4.poly.\n\n");
2801 printf(
2802" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
2803 printf(
2804" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
2805 printf(" suitable for multigrid.\n\n");
2806 printf("Convex Hulls and Mesh Boundaries:\n\n");
2807 printf(
2808" If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
2809 printf(
2810" hull as a by-product in the output .poly file if you use the -c switch.\n");
2811 printf(
2812" There are faster algorithms for finding a two-dimensional convex hull\n");
2813 printf(" than triangulation, of course, but this one comes for free.\n\n");
2814 printf(
2815" If the input is an unconstrained mesh (you are using the -r switch but\n");
2816 printf(
2817" not the -p switch), Triangle produces a list of its boundary edges\n");
2818 printf(
2819" (including hole boundaries) as a by-product when you use the -c switch.\n");
2820 printf(
2821" If you also use the -p switch, the output .poly file contains all the\n");
2822 printf(" segments from the input .poly file as well.\n\n");
2823 printf("Voronoi Diagrams:\n\n");
2824 printf(
2825" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
2826 printf(
2827" .v.edge. For example, `triangle -v points' reads points.node, produces\n");
2828 printf(
2829" its Delaunay triangulation in points.1.node and points.1.ele, and\n");
2830 printf(
2831" produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
2832);
2833 printf(
2834" .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
2835 printf(
2836" file contains a list of all Voronoi edges, some of which may be infinite\n"
2837);
2838 printf(
2839" rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
2840 printf(" vertices through Triangle, if so desired.)\n\n");
2841 printf(
2842" This implementation does not use exact arithmetic to compute the Voronoi\n"
2843);
2844 printf(
2845" vertices, and does not check whether neighboring vertices are identical.\n"
2846);
2847 printf(
2848" Be forewarned that if the Delaunay triangulation is degenerate or\n");
2849 printf(
2850" near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
2851 printf(" crossing edges.\n\n");
2852 printf(
2853" The result is a valid Voronoi diagram only if Triangle's output is a true\n"
2854);
2855 printf(
2856" Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
2857 printf(
2858" may contain crossing edges and other pathology) if the output is a CDT or\n"
2859);
2860 printf(
2861" CCDT, or if it has holes or concavities. If the triangulated domain is\n");
2862 printf(
2863" convex and has no holes, you can use -D switch to force Triangle to\n");
2864 printf(
2865" construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
2866 printf(" Voronoi diagram will be valid.\n\n");
2867 printf("Mesh Topology:\n\n");
2868 printf(
2869" You may wish to know which triangles are adjacent to a certain Delaunay\n");
2870 printf(
2871" edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
2872 printf(
2873" Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
2874 printf(
2875" each other. All of this information can be found by cross-referencing\n");
2876 printf(
2877" output files with the recollection that the Delaunay triangulation and\n");
2878 printf(" the Voronoi diagram are planar duals.\n\n");
2879 printf(
2880" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
2881 printf(
2882" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
2883 printf(
2884" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
2885 printf(
2886" vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
2887 printf(" of vertex k of the corresponding .node file.\n\n");
2888 printf(
2889" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
2890 printf(
2891" vertices of the corresponding Voronoi edge. If the endpoints of a\n");
2892 printf(
2893" Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
2894);
2895 printf(
2896" and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
2897);
2898 printf(
2899" respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
2900);
2901 printf(
2902" at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
2903);
2904 printf(
2905" a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
2906);
2907 printf(
2908" adjoin the right and left sides of the corresponding Voronoi edge,\n");
2909 printf(
2910" respectively. To find which Voronoi cells are adjacent to each other,\n");
2911 printf(" just read the list of Delaunay edges.\n\n");
2912 printf(
2913" Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
2914);
2915 printf(
2916" but you can reconstructed it straightforwardly. For instance, to find\n");
2917 printf(
2918" all the edges of Voronoi cell 1, search the output .edge file for every\n");
2919 printf(
2920" edge that has input vertex 1 as an endpoint. The corresponding dual\n");
2921 printf(
2922" edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
2923 printf("\n");
2924 printf(
2925" For each Voronoi vertex, the .neigh file gives a list of the three\n");
2926 printf(
2927" Voronoi vertices attached to it. You might find this more convenient\n");
2928 printf(" than the .v.edge file.\n\n");
2929 printf("Quadratic Elements:\n\n");
2930 printf(
2931" Triangle generates meshes with subparametric quadratic elements if the\n");
2932 printf(
2933" -o2 switch is specified. Quadratic elements have six nodes per element,\n"
2934);
2935 printf(
2936" rather than three. `Subparametric' means that the edges of the triangles\n"
2937);
2938 printf(
2939" are always straight, so that subparametric quadratic elements are\n");
2940 printf(
2941" geometrically identical to linear elements, even though they can be used\n"
2942);
2943 printf(
2944" with quadratic interpolating functions. The three extra nodes of an\n");
2945 printf(
2946" element fall at the midpoints of the three edges, with the fourth, fifth,\n"
2947);
2948 printf(
2949" and sixth nodes appearing opposite the first, second, and third corners\n");
2950 printf(" respectively.\n\n");
2951 printf("Domains with Small Angles:\n\n");
2952 printf(
2953" If two input segments adjoin each other at a small angle, clearly the -q\n"
2954);
2955 printf(
2956" switch cannot remove the small angle. Moreover, Triangle may have no\n");
2957 printf(
2958" choice but to generate additional triangles whose smallest angles are\n");
2959 printf(
2960" smaller than the specified bound. However, these triangles only appear\n");
2961 printf(
2962" between input segments separated by small angles. Moreover, if you\n");
2963 printf(
2964" request a minimum angle of theta degrees, Triangle will generally produce\n"
2965);
2966 printf(
2967" no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
2968);
2969 printf(" the minimum angle.\n\n");
2970 printf("Statistics:\n\n");
2971 printf(
2972" After generating a mesh, Triangle prints a count of entities in the\n");
2973 printf(
2974" output mesh, including the number of vertices, triangles, edges, exterior\n"
2975);
2976 printf(
2977" boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
2978 printf(
2979" including hole boundaries), interior boundary edges (i.e. subsegments of\n"
2980);
2981 printf(
2982" input segments not on the boundary), and total subsegments. If you've\n");
2983 printf(
2984" forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
2985);
2986 printf(
2987" with the -rNEP switches to read the mesh and print the statistics without\n"
2988);
2989 printf(
2990" writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
2991 printf("\n");
2992 printf(
2993" The -V switch produces extended statistics, including a rough estimate\n");
2994 printf(
2995" of memory use, the number of calls to geometric predicates, and\n");
2996 printf(
2997" histograms of the angles and the aspect ratios of the triangles in the\n");
2998 printf(" mesh.\n\n");
2999 printf("Exact Arithmetic:\n\n");
3000 printf(
3001" Triangle uses adaptive exact arithmetic to perform what computational\n");
3002 printf(
3003" geometers call the `orientation' and `incircle' tests. If the floating-\n"
3004);
3005 printf(
3006" point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
3007 printf(
3008" most workstations do), and does not use extended precision internal\n");
3009 printf(
3010" floating-point registers, then your output is guaranteed to be an\n");
3011 printf(
3012" absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
3013);
3014 printf(
3015" error notwithstanding. The word `adaptive' implies that these arithmetic\n"
3016);
3017 printf(
3018" routines compute the result only to the precision necessary to guarantee\n"
3019);
3020 printf(
3021" correctness, so they are usually nearly as fast as their approximate\n");
3022 printf(" counterparts.\n\n");
3023 printf(
3024" May CPUs, including Intel x86 processors, have extended precision\n");
3025 printf(
3026" floating-point registers. These must be reconfigured so their precision\n"
3027);
3028 printf(
3029" is reduced to memory precision. Triangle does this if it is compiled\n");
3030 printf(" correctly. See the makefile for details.\n\n");
3031 printf(
3032" The exact tests can be disabled with the -X switch. On most inputs, this\n"
3033);
3034 printf(
3035" switch reduces the computation time by about eight percent--it's not\n");
3036 printf(
3037" worth the risk. There are rare difficult inputs (having many collinear\n");
3038 printf(
3039" and cocircular vertices), however, for which the difference in speed\n");
3040 printf(
3041" could be a factor of two. Be forewarned that these are precisely the\n");
3042 printf(
3043" inputs most likely to cause errors if you use the -X switch. Hence, the\n"
3044);
3045 printf(" -X switch is not recommended.\n\n");
3046 printf(
3047" Unfortunately, the exact tests don't solve every numerical problem.\n");
3048 printf(
3049" Exact arithmetic is not used to compute the positions of new vertices,\n");
3050 printf(
3051" because the bit complexity of vertex coordinates would grow without\n");
3052 printf(
3053" bound. Hence, segment intersections aren't computed exactly; in very\n");
3054 printf(
3055" unusual cases, roundoff error in computing an intersection point might\n");
3056 printf(
3057" actually lead to an inverted triangle and an invalid triangulation.\n");
3058 printf(
3059" (This is one reason to specify your own intersection points in your .poly\n"
3060);
3061 printf(
3062" files.) Similarly, exact arithmetic is not used to compute the vertices\n"
3063);
3064 printf(" of the Voronoi diagram.\n\n");
3065 printf(
3066" Another pair of problems not solved by the exact arithmetic routines is\n");
3067 printf(
3068" underflow and overflow. If Triangle is compiled for double precision\n");
3069 printf(
3070" arithmetic, I believe that Triangle's geometric predicates work correctly\n"
3071);
3072 printf(
3073" if the exponent of every input coordinate falls in the range [-148, 201].\n"
3074);
3075 printf(
3076" Underflow can silently prevent the orientation and incircle tests from\n");
3077 printf(
3078" being performed exactly, while overflow typically causes a floating\n");
3079 printf(" exception.\n\n");
3080 printf("Calling Triangle from Another Program:\n\n");
3081 printf(" Read the file triangle.h for details.\n\n");
3082 printf("Troubleshooting:\n\n");
3083 printf(" Please read this section before mailing me bugs.\n\n");
3084 printf(" `My output mesh has no triangles!'\n\n");
3085 printf(
3086" If you're using a PSLG, you've probably failed to specify a proper set\n"
3087);
3088 printf(
3089" of bounding segments, or forgotten to use the -c switch. Or you may\n");
3090 printf(
3091" have placed a hole badly, thereby eating all your triangles. To test\n");
3092 printf(" these possibilities, try again with the -c and -O switches.\n");
3093 printf(
3094" Alternatively, all your input vertices may be collinear, in which case\n"
3095);
3096 printf(" you can hardly expect to triangulate them.\n\n");
3097 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
3098 printf(
3099" Bad things can happen when triangles get so small that the distance\n");
3100 printf(
3101" between their vertices isn't much larger than the precision of your\n");
3102 printf(
3103" machine's arithmetic. If you've compiled Triangle for single-precision\n"
3104);
3105 printf(
3106" arithmetic, you might do better by recompiling it for double-precision.\n"
3107);
3108 printf(
3109" Then again, you might just have to settle for more lenient constraints\n"
3110);
3111 printf(
3112" on the minimum angle and the maximum area than you had planned.\n");
3113 printf("\n");
3114 printf(
3115" You can minimize precision problems by ensuring that the origin lies\n");
3116 printf(
3117" inside your vertex set, or even inside the densest part of your\n");
3118 printf(
3119" mesh. If you're triangulating an object whose x-coordinates all fall\n");
3120 printf(
3121" between 6247133 and 6247134, you're not leaving much floating-point\n");
3122 printf(" precision for Triangle to work with.\n\n");
3123 printf(
3124" Precision problems can occur covertly if the input PSLG contains two\n");
3125 printf(
3126" segments that meet (or intersect) at an extremely small angle, or if\n");
3127 printf(
3128" such an angle is introduced by the -c switch. If you don't realize\n");
3129 printf(
3130" that a tiny angle is being formed, you might never discover why\n");
3131 printf(
3132" Triangle is crashing. To check for this possibility, use the -S switch\n"
3133);
3134 printf(
3135" (with an appropriate limit on the number of Steiner points, found by\n");
3136 printf(
3137" trial-and-error) to stop Triangle early, and view the output .poly file\n"
3138);
3139 printf(
3140" with Show Me (described below). Look carefully for regions where dense\n"
3141);
3142 printf(
3143" clusters of vertices are forming and for small angles between segments.\n"
3144);
3145 printf(
3146" Zoom in closely, as such segments might look like a single segment from\n"
3147);
3148 printf(" a distance.\n\n");
3149 printf(
3150" If some of the input values are too large, Triangle may suffer a\n");
3151 printf(
3152" floating exception due to overflow when attempting to perform an\n");
3153 printf(
3154" orientation or incircle test. (Read the section on exact arithmetic\n");
3155 printf(
3156" above.) Again, I recommend compiling Triangle for double (rather\n");
3157 printf(" than single) precision arithmetic.\n\n");
3158 printf(
3159" Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
3160 printf(
3161" -u) with an input that is not segment-bounded--that is, if your input\n");
3162 printf(
3163" is a vertex set, or you're using the -c switch. If the convex hull of\n"
3164);
3165 printf(
3166" your input vertices has collinear vertices on its boundary, an input\n");
3167 printf(
3168" vertex that you think lies on the convex hull might actually lie just\n");
3169 printf(
3170" inside the convex hull. If so, the vertex and the nearby convex hull\n");
3171 printf(
3172" edge form an extremely thin triangle. When Triangle tries to refine\n");
3173 printf(
3174" the mesh to enforce angle and area constraints, Triangle might generate\n"
3175);
3176 printf(
3177" extremely tiny triangles, or it might fail because of insufficient\n");
3178 printf(" floating-point precision.\n\n");
3179 printf(
3180" `The numbering of the output vertices doesn't match the input vertices.'\n"
3181);
3182 printf("\n");
3183 printf(
3184" You may have had duplicate input vertices, or you may have eaten some\n");
3185 printf(
3186" of your input vertices with a hole, or by placing them outside the area\n"
3187);
3188 printf(
3189" enclosed by segments. In any case, you can solve the problem by not\n");
3190 printf(" using the -j switch.\n\n");
3191 printf(
3192" `Triangle executes without incident, but when I look at the resulting\n");
3193 printf(
3194" mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
3195 printf("\n");
3196 printf(
3197" If you select the -X switch, Triangle occasionally makes mistakes due\n");
3198 printf(
3199" to floating-point roundoff error. Although these errors are rare,\n");
3200 printf(
3201" don't use the -X switch. If you still have problems, please report the\n"
3202);
3203 printf(" bug.\n\n");
3204 printf(
3205" `Triangle executes without incident, but when I look at the resulting\n");
3206 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
3207 printf(" inconsistencies.'\n");
3208 printf("\n");
3209 printf(
3210" If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
3211);
3212 printf(
3213" diagram if the domain you are triangulating is convex and free of\n");
3214 printf(
3215" holes, and you use the -D switch to construct a conforming Delaunay\n");
3216 printf(" triangulation (instead of a CDT or CCDT).\n\n");
3217 printf(
3218" Strange things can happen if you've taken liberties with your PSLG. Do\n");
3219 printf(
3220" you have a vertex lying in the middle of a segment? Triangle sometimes\n");
3221 printf(
3222" copes poorly with that sort of thing. Do you want to lay out a collinear\n"
3223);
3224 printf(
3225" row of evenly spaced, segment-connected vertices? Have you simply\n");
3226 printf(
3227" defined one long segment connecting the leftmost vertex to the rightmost\n"
3228);
3229 printf(
3230" vertex, and a bunch of vertices lying along it? This method occasionally\n"
3231);
3232 printf(
3233" works, especially with horizontal and vertical lines, but often it\n");
3234 printf(
3235" doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
3236);
3237 printf(" separate segment. If you don't like it, tough.\n\n");
3238 printf(
3239" Furthermore, if you have segments that intersect other than at their\n");
3240 printf(
3241" endpoints, try not to let the intersections fall extremely close to PSLG\n"
3242);
3243 printf(" vertices or each other.\n\n");
3244 printf(
3245" If you have problems refining a triangulation not produced by Triangle:\n");
3246 printf(
3247" Are you sure the triangulation is geometrically valid? Is it formatted\n");
3248 printf(
3249" correctly for Triangle? Are the triangles all listed so the first three\n"
3250);
3251 printf(
3252" vertices are their corners in counterclockwise order? Are all of the\n");
3253 printf(
3254" triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
3255);
3256 printf(" assumes that it starts with a CDT.\n\n");
3257 printf("Show Me:\n\n");
3258 printf(
3259" Triangle comes with a separate program named `Show Me', whose primary\n");
3260 printf(
3261" purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
3262);
3263 printf(
3264" purpose is to check the validity of your input files, and do so more\n");
3265 printf(
3266" thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
3267 printf(
3268" you have the X Windows system. Sorry, Microsoft Windows users.\n");
3269 printf("\n");
3270 printf("Triangle on the Web:\n");
3271 printf("\n");
3272 printf(" To see an illustrated version of these instructions, check out\n");
3273 printf("\n");
3274 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
3275 printf("\n");
3276 printf("A Brief Plea:\n");
3277 printf("\n");
3278 printf(
3279" If you use Triangle, and especially if you use it to accomplish real\n");
3280 printf(
3281" work, I would like very much to hear from you. A short letter or email\n");
3282 printf(
3283" (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
3284);
3285 printf(
3286" to me. The more people I know are using this program, the more easily I\n"
3287);
3288 printf(
3289" can justify spending time on improvements, which in turn will benefit\n");
3290 printf(
3291" you. Also, I can put you on a list to receive email whenever a new\n");
3292 printf(" version of Triangle is available.\n\n");
3293 printf(
3294" If you use a mesh generated by Triangle in a publication, please include\n"
3295);
3296 printf(
3297" an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
3298);
3299 printf(
3300" If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
3301 printf(
3302" ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
3303 printf(
3304" Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
3305 printf(
3306" Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
3307 printf(
3308" Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
3309 printf(
3310" Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
3311);
3312 printf(" Geometry.)'\n\n");
3313 printf("Research credit:\n\n");
3314 printf(
3315" Of course, I can take credit for only a fraction of the ideas that made\n");
3316 printf(
3317" this mesh generator possible. Triangle owes its existence to the efforts\n"
3318);
3319 printf(
3320" of many fine computational geometers and other researchers, including\n");
3321 printf(
3322" Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
3323);
3324 printf(
3325" Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
3326 printf(
3327" Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
3328 printf(
3329" Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
3330 printf(
3331" Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
3332);
3333 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
3334 printf(
3335" Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
3336 printf(" source code for references.\n\n");
3337 triexit(0);
3338}
3339
3340#endif /* not TRILIBRARY */
3341
3342/*****************************************************************************/
3343/* */
3344/* internalerror() Ask the user to send me the defective product. Exit. */
3345/* */
3346/*****************************************************************************/
3347
3348void internalerror()
3349{
3350 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
3351 printf(" Include the message above, your input data set, and the exact\n");
3352 printf(" command line you used to run Triangle.\n");
3353 triexit(1);
3354}
3355
3356/*****************************************************************************/
3357/* */
3358/* parsecommandline() Read the command line, identify switches, and set */
3359/* up options and file names. */
3360/* */
3361/*****************************************************************************/
3362
3363#ifdef ANSI_DECLARATORS
3364void parsecommandline(int argc, char **argv, struct behavior *b)
3365#else /* not ANSI_DECLARATORS */
3366void parsecommandline(argc, argv, b)
3367int argc;
3368char **argv;
3369struct behavior *b;
3370#endif /* not ANSI_DECLARATORS */
3371
3372{
3373#ifdef TRILIBRARY
3374#define STARTINDEX 0
3375#else /* not TRILIBRARY */
3376#define STARTINDEX 1
3377 int increment;
3378 int meshnumber;
3379#endif /* not TRILIBRARY */
3380 int i, j, k;
3381 char workstring[FILENAMESIZE];
3382
3383 b->poly = b->refine = b->quality = 0;
3384 b->vararea = b->fixedarea = b->usertest = 0;
3385 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
3386 b->firstnumber = 1;
3387 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
3388 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
3389 b->noiterationnum = 0;
3390 b->noholes = b->noexact = 0;
3391 b->incremental = b->sweepline = 0;
3392 b->dwyer = 1;
3393 b->splitseg = 0;
3394 b->docheck = 0;
3395 b->nobisect = 0;
3396 b->conformdel = 0;
3397 b->steiner = -1;
3398 b->order = 1;
3399 b->minangle = 0.0;
3400 b->maxarea = -1.0;
3401 b->quiet = b->verbose = 0;
3402#ifndef TRILIBRARY
3403 b->innodefilename[0] = '\0';
3404#endif /* not TRILIBRARY */
3405
3406 for (i = STARTINDEX; i < argc; i++) {
3407#ifndef TRILIBRARY
3408 if (argv[i][0] == '-') {
3409#endif /* not TRILIBRARY */
3410 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
3411 if (argv[i][j] == 'p') {
3412 b->poly = 1;
3413 }
3414#ifndef CDT_ONLY
3415 if (argv[i][j] == 'r') {
3416 b->refine = 1;
3417 }
3418 if (argv[i][j] == 'q') {
3419 b->quality = 1;
3420 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3421 (argv[i][j + 1] == '.')) {
3422 k = 0;
3423 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3424 (argv[i][j + 1] == '.')) {
3425 j++;
3426 workstring[k] = argv[i][j];
3427 k++;
3428 }
3429 workstring[k] = '\0';
3430 b->minangle = (REAL) strtod(workstring, (char **) NULL);
3431 } else {
3432 b->minangle = 20.0;
3433 }
3434 }
3435 if (argv[i][j] == 'a') {
3436 b->quality = 1;
3437 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3438 (argv[i][j + 1] == '.')) {
3439 b->fixedarea = 1;
3440 k = 0;
3441 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
3442 (argv[i][j + 1] == '.')) {
3443 j++;
3444 workstring[k] = argv[i][j];
3445 k++;
3446 }
3447 workstring[k] = '\0';
3448 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
3449 if (b->maxarea <= 0.0) {
3450 printf("Error: Maximum area must be greater than zero.\n");
3451 triexit(1);
3452 }
3453 } else {
3454 b->vararea = 1;
3455 }
3456 }
3457 if (argv[i][j] == 'u') {
3458 b->quality = 1;
3459 b->usertest = 1;
3460 }
3461#endif /* not CDT_ONLY */
3462 if (argv[i][j] == 'A') {
3463 b->regionattrib = 1;
3464 }
3465 if (argv[i][j] == 'c') {
3466 b->convex = 1;
3467 }
3468 if (argv[i][j] == 'w') {
3469 b->weighted = 1;
3470 }
3471 if (argv[i][j] == 'W') {
3472 b->weighted = 2;
3473 }
3474 if (argv[i][j] == 'j') {
3475 b->jettison = 1;
3476 }
3477 if (argv[i][j] == 'z') {
3478 b->firstnumber = 0;
3479 }
3480 if (argv[i][j] == 'e') {
3481 b->edgesout = 1;
3482 }
3483 if (argv[i][j] == 'v') {
3484 b->voronoi = 1;
3485 }
3486 if (argv[i][j] == 'n') {
3487 b->neighbors = 1;
3488 }
3489 if (argv[i][j] == 'g') {
3490 b->geomview = 1;
3491 }
3492 if (argv[i][j] == 'B') {
3493 b->nobound = 1;
3494 }
3495 if (argv[i][j] == 'P') {
3496 b->nopolywritten = 1;
3497 }
3498 if (argv[i][j] == 'N') {
3499 b->nonodewritten = 1;
3500 }
3501 if (argv[i][j] == 'E') {
3502 b->noelewritten = 1;
3503 }
3504#ifndef TRILIBRARY
3505 if (argv[i][j] == 'I') {
3506 b->noiterationnum = 1;
3507 }
3508#endif /* not TRILIBRARY */
3509 if (argv[i][j] == 'O') {
3510 b->noholes = 1;
3511 }
3512 if (argv[i][j] == 'X') {
3513 b->noexact = 1;
3514 }
3515 if (argv[i][j] == 'o') {
3516 if (argv[i][j + 1] == '2') {
3517 j++;
3518 b->order = 2;
3519 }
3520 }
3521#ifndef CDT_ONLY
3522 if (argv[i][j] == 'Y') {
3523 b->nobisect++;
3524 }
3525 if (argv[i][j] == 'S') {
3526 b->steiner = 0;
3527 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
3528 j++;
3529 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
3530 }
3531 }
3532#endif /* not CDT_ONLY */
3533#ifndef REDUCED
3534 if (argv[i][j] == 'i') {
3535 b->incremental = 1;
3536 }
3537 if (argv[i][j] == 'F') {
3538 b->sweepline = 1;
3539 }
3540#endif /* not REDUCED */
3541 if (argv[i][j] == 'l') {
3542 b->dwyer = 0;
3543 }
3544#ifndef REDUCED
3545#ifndef CDT_ONLY
3546 if (argv[i][j] == 's') {
3547 b->splitseg = 1;
3548 }
3549 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
3550 b->quality = 1;
3551 b->conformdel = 1;
3552 }
3553#endif /* not CDT_ONLY */
3554 if (argv[i][j] == 'C') {
3555 b->docheck = 1;
3556 }
3557#endif /* not REDUCED */
3558 if (argv[i][j] == 'Q') {
3559 b->quiet = 1;
3560 }
3561 if (argv[i][j] == 'V') {
3562 b->verbose++;
3563 }
3564#ifndef TRILIBRARY
3565 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
3566 (argv[i][j] == '?')) {
3567 info();
3568 }
3569#endif /* not TRILIBRARY */
3570 }
3571#ifndef TRILIBRARY
3572 } else {
3573 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
3574 b->innodefilename[FILENAMESIZE - 1] = '\0';
3575 }
3576#endif /* not TRILIBRARY */
3577 }
3578#ifndef TRILIBRARY
3579 if (b->innodefilename[0] == '\0') {
3580 syntax();
3581 }
3582 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
3583 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3584 }
3585 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
3586 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3587 b->poly = 1;
3588 }
3589#ifndef CDT_ONLY
3590 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
3591 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
3592 b->refine = 1;
3593 }
3594 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
3595 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
3596 b->refine = 1;
3597 b->quality = 1;
3598 b->vararea = 1;
3599 }
3600#endif /* not CDT_ONLY */
3601#endif /* not TRILIBRARY */
3602 b->usesegments = b->poly || b->refine || b->quality || b->convex;
3603 b->goodangle = cos(b->minangle * PI / 180.0);
3604 if (b->goodangle == 1.0) {
3605 b->offconstant = 0.0;
3606 } else {
3607 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
3608 }
3609 b->goodangle *= b->goodangle;
3610 if (b->refine && b->noiterationnum) {
3611 printf(
3612 "Error: You cannot use the -I switch when refining a triangulation.\n");
3613 triexit(1);
3614 }
3615 /* Be careful not to allocate space for element area constraints that */
3616 /* will never be assigned any value (other than the default -1.0). */
3617 if (!b->refine && !b->poly) {
3618 b->vararea = 0;
3619 }
3620 /* Be careful not to add an extra attribute to each element unless the */
3621 /* input supports it (PSLG in, but not refining a preexisting mesh). */
3622 if (b->refine || !b->poly) {
3623 b->regionattrib = 0;
3624 }
3625 /* Regular/weighted triangulations are incompatible with PSLGs */
3626 /* and meshing. */
3627 if (b->weighted && (b->poly || b->quality)) {
3628 b->weighted = 0;
3629 if (!b->quiet) {
3630 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
3631 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
3632 );
3633 }
3634 }
3635 if (b->jettison && b->nonodewritten && !b->quiet) {
3636 printf("Warning: -j and -N switches are somewhat incompatible.\n");
3637 printf(" If any vertices are jettisoned, you will need the output\n");
3638 printf(" .node file to reconstruct the new node indices.");
3639 }
3640
3641#ifndef TRILIBRARY
3642 strcpy(b->inpolyfilename, b->innodefilename);
3643 strcpy(b->inelefilename, b->innodefilename);
3644 strcpy(b->areafilename, b->innodefilename);
3645 increment = 0;
3646 strcpy(workstring, b->innodefilename);
3647 j = 1;
3648 while (workstring[j] != '\0') {
3649 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
3650 increment = j + 1;
3651 }
3652 j++;
3653 }
3654 meshnumber = 0;
3655 if (increment > 0) {
3656 j = increment;
3657 do {
3658 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
3659 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
3660 } else {
3661 increment = 0;
3662 }
3663 j++;
3664 } while (workstring[j] != '\0');
3665 }
3666 if (b->noiterationnum) {
3667 strcpy(b->outnodefilename, b->innodefilename);
3668 strcpy(b->outelefilename, b->innodefilename);
3669 strcpy(b->edgefilename, b->innodefilename);
3670 strcpy(b->vnodefilename, b->innodefilename);
3671 strcpy(b->vedgefilename, b->innodefilename);
3672 strcpy(b->neighborfilename, b->innodefilename);
3673 strcpy(b->offfilename, b->innodefilename);
3674 strcat(b->outnodefilename, ".node");
3675 strcat(b->outelefilename, ".ele");
3676 strcat(b->edgefilename, ".edge");
3677 strcat(b->vnodefilename, ".v.node");
3678 strcat(b->vedgefilename, ".v.edge");
3679 strcat(b->neighborfilename, ".neigh");
3680 strcat(b->offfilename, ".off");
3681 } else if (increment == 0) {
3682 strcpy(b->outnodefilename, b->innodefilename);
3683 strcpy(b->outpolyfilename, b->innodefilename);
3684 strcpy(b->outelefilename, b->innodefilename);
3685 strcpy(b->edgefilename, b->innodefilename);
3686 strcpy(b->vnodefilename, b->innodefilename);
3687 strcpy(b->vedgefilename, b->innodefilename);
3688 strcpy(b->neighborfilename, b->innodefilename);
3689 strcpy(b->offfilename, b->innodefilename);
3690 strcat(b->outnodefilename, ".1.node");
3691 strcat(b->outpolyfilename, ".1.poly");
3692 strcat(b->outelefilename, ".1.ele");
3693 strcat(b->edgefilename, ".1.edge");
3694 strcat(b->vnodefilename, ".1.v.node");
3695 strcat(b->vedgefilename, ".1.v.edge");
3696 strcat(b->neighborfilename, ".1.neigh");
3697 strcat(b->offfilename, ".1.off");
3698 } else {
3699 workstring[increment] = '%';
3700 workstring[increment + 1] = 'd';
3701 workstring[increment + 2] = '\0';
3702 sprintf(b->outnodefilename, workstring, meshnumber + 1);
3703 strcpy(b->outpolyfilename, b->outnodefilename);
3704 strcpy(b->outelefilename, b->outnodefilename);
3705 strcpy(b->edgefilename, b->outnodefilename);
3706 strcpy(b->vnodefilename, b->outnodefilename);
3707 strcpy(b->vedgefilename, b->outnodefilename);
3708 strcpy(b->neighborfilename, b->outnodefilename);
3709 strcpy(b->offfilename, b->outnodefilename);
3710 strcat(b->outnodefilename, ".node");
3711 strcat(b->outpolyfilename, ".poly");
3712 strcat(b->outelefilename, ".ele");
3713 strcat(b->edgefilename, ".edge");
3714 strcat(b->vnodefilename, ".v.node");
3715 strcat(b->vedgefilename, ".v.edge");
3716 strcat(b->neighborfilename, ".neigh");
3717 strcat(b->offfilename, ".off");
3718 }
3719 strcat(b->innodefilename, ".node");
3720 strcat(b->inpolyfilename, ".poly");
3721 strcat(b->inelefilename, ".ele");
3722 strcat(b->areafilename, ".area");
3723#endif /* not TRILIBRARY */
3724}
3725
3728/********* User interaction routines begin here *********/
3729
3730/********* Debugging routines begin here *********/
3734/*****************************************************************************/
3735/* */
3736/* printtriangle() Print out the details of an oriented triangle. */
3737/* */
3738/* I originally wrote this procedure to simplify debugging; it can be */
3739/* called directly from the debugger, and presents information about an */
3740/* oriented triangle in digestible form. It's also used when the */
3741/* highest level of verbosity (`-VVV') is specified. */
3742/* */
3743/*****************************************************************************/
3744
3745#ifdef ANSI_DECLARATORS
3746void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
3747#else /* not ANSI_DECLARATORS */
3748void printtriangle(m, b, t)
3749struct mesh *m;
3750struct behavior *b;
3751struct otri *t;
3752#endif /* not ANSI_DECLARATORS */
3753
3754{
3755 struct otri printtri;
3756 struct osub printsh;
3757 vertex printvertex;
3758
3759 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
3760 t->orient);
3761 decode(t->tri[0], printtri);
3762 if (printtri.tri == m->dummytri) {
3763 printf(" [0] = Outer space\n");
3764 } else {
3765 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
3766 printtri.orient);
3767 }
3768 decode(t->tri[1], printtri);
3769 if (printtri.tri == m->dummytri) {
3770 printf(" [1] = Outer space\n");
3771 } else {
3772 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
3773 printtri.orient);
3774 }
3775 decode(t->tri[2], printtri);
3776 if (printtri.tri == m->dummytri) {
3777 printf(" [2] = Outer space\n");
3778 } else {
3779 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
3780 printtri.orient);
3781 }
3782
3783 org(*t, printvertex);
3784 if (printvertex == (vertex) NULL)
3785 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
3786 else
3787 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
3788 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
3789 printvertex[0], printvertex[1]);
3790 dest(*t, printvertex);
3791 if (printvertex == (vertex) NULL)
3792 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
3793 else
3794 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
3795 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
3796 printvertex[0], printvertex[1]);
3797 apex(*t, printvertex);
3798 if (printvertex == (vertex) NULL)
3799 printf(" Apex [%d] = NULL\n", t->orient + 3);
3800 else
3801 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
3802 t->orient + 3, (unsigned long) printvertex,
3803 printvertex[0], printvertex[1]);
3804
3805 if (b->usesegments) {
3806 sdecode(t->tri[6], printsh);
3807 if (printsh.ss != m->dummysub) {
3808 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
3809 printsh.ssorient);
3810 }
3811 sdecode(t->tri[7], printsh);
3812 if (printsh.ss != m->dummysub) {
3813 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
3814 printsh.ssorient);
3815 }
3816 sdecode(t->tri[8], printsh);
3817 if (printsh.ss != m->dummysub) {
3818 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
3819 printsh.ssorient);
3820 }
3821 }
3822
3823 if (b->vararea) {
3824 printf(" Area constraint: %.4g\n", areabound(*t));
3825 }
3826}
3827
3828/*****************************************************************************/
3829/* */
3830/* printsubseg() Print out the details of an oriented subsegment. */
3831/* */
3832/* I originally wrote this procedure to simplify debugging; it can be */
3833/* called directly from the debugger, and presents information about an */
3834/* oriented subsegment in digestible form. It's also used when the highest */
3835/* level of verbosity (`-VVV') is specified. */
3836/* */
3837/*****************************************************************************/
3838
3839#ifdef ANSI_DECLARATORS
3840void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
3841#else /* not ANSI_DECLARATORS */
3842void printsubseg(m, b, s)
3843struct mesh *m;
3844struct behavior *b;
3845struct osub *s;
3846#endif /* not ANSI_DECLARATORS */
3847
3848{
3849 struct osub printsh;
3850 struct otri printtri;
3851 vertex printvertex;
3852
3853 printf("subsegment x%lx with orientation %d and mark %d:\n",
3854 (unsigned long) s->ss, s->ssorient, mark(*s));
3855 sdecode(s->ss[0], printsh);
3856 if (printsh.ss == m->dummysub) {
3857 printf(" [0] = No subsegment\n");
3858 } else {
3859 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
3860 printsh.ssorient);
3861 }
3862 sdecode(s->ss[1], printsh);
3863 if (printsh.ss == m->dummysub) {
3864 printf(" [1] = No subsegment\n");
3865 } else {
3866 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
3867 printsh.ssorient);
3868 }
3869
3870 sorg(*s, printvertex);
3871 if (printvertex == (vertex) NULL)
3872 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
3873 else
3874 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
3875 2 + s->ssorient, (unsigned long) printvertex,
3876 printvertex[0], printvertex[1]);
3877 sdest(*s, printvertex);
3878 if (printvertex == (vertex) NULL)
3879 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
3880 else
3881 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
3882 3 - s->ssorient, (unsigned long) printvertex,
3883 printvertex[0], printvertex[1]);
3884
3885 decode(s->ss[6], printtri);
3886 if (printtri.tri == m->dummytri) {
3887 printf(" [6] = Outer space\n");
3888 } else {
3889 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
3890 printtri.orient);
3891 }
3892 decode(s->ss[7], printtri);
3893 if (printtri.tri == m->dummytri) {
3894 printf(" [7] = Outer space\n");
3895 } else {
3896 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
3897 printtri.orient);
3898 }
3899
3900 segorg(*s, printvertex);
3901 if (printvertex == (vertex) NULL)
3902 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
3903 else
3904 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
3905 4 + s->ssorient, (unsigned long) printvertex,
3906 printvertex[0], printvertex[1]);
3907 segdest(*s, printvertex);
3908 if (printvertex == (vertex) NULL)
3909 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
3910 else
3911 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
3912 5 - s->ssorient, (unsigned long) printvertex,
3913 printvertex[0], printvertex[1]);
3914}
3915
3918/********* Debugging routines end here *********/
3919
3920/********* Memory management routines begin here *********/
3924/*****************************************************************************/
3925/* */
3926/* poolzero() Set all of a pool's fields to zero. */
3927/* */
3928/* This procedure should never be called on a pool that has any memory */
3929/* allocated to it, as that memory would leak. */
3930/* */
3931/*****************************************************************************/
3932
3933#ifdef ANSI_DECLARATORS
3934void poolzero(struct memorypool* pool)
3935#else /* not ANSI_DECLARATORS */
3936void poolzero(pool)
3937struct memorypool* pool;
3938#endif /* not ANSI_DECLARATORS */
3939
3940{
3941 pool->firstblock = (VOID **) NULL;
3942 pool->nowblock = (VOID **) NULL;
3943 pool->nextitem = (VOID *) NULL;
3944 pool->deaditemstack = (VOID *) NULL;
3945 pool->pathblock = (VOID **) NULL;
3946 pool->pathitem = (VOID *) NULL;
3947 pool->alignbytes = 0;
3948 pool->itembytes = 0;
3949 pool->itemsperblock = 0;
3950 pool->itemsfirstblock = 0;
3951 pool->items = 0;
3952 pool->maxitems = 0;
3953 pool->unallocateditems = 0;
3954 pool->pathitemsleft = 0;
3955}
3956
3957/*****************************************************************************/
3958/* */
3959/* poolrestart() Deallocate all items in a pool. */
3960/* */
3961/* The pool is returned to its starting state, except that no memory is */
3962/* freed to the operating system. Rather, the previously allocated blocks */
3963/* are ready to be reused. */
3964/* */
3965/*****************************************************************************/
3966
3967#ifdef ANSI_DECLARATORS
3968void poolrestart(struct memorypool* pool)
3969#else /* not ANSI_DECLARATORS */
3970void poolrestart(pool)
3971struct memorypool* pool;
3972#endif /* not ANSI_DECLARATORS */
3973
3974{
3975 unsigned long alignptr;
3976
3977 pool->items = 0;
3978 pool->maxitems = 0;
3979
3980 /* Set the currently active block. */
3981 pool->nowblock = pool->firstblock;
3982 /* Find the first item in the pool. Increment by the size of (VOID *). */
3983 alignptr = (unsigned long) (pool->nowblock + 1);
3984 /* Align the item on an `alignbytes'-byte boundary. */
3985 pool->nextitem = (VOID *)
3986 (alignptr + (unsigned long) pool->alignbytes -
3987 (alignptr % (unsigned long) pool->alignbytes));
3988 /* There are lots of unallocated items left in this block. */
3989 pool->unallocateditems = pool->itemsfirstblock;
3990 /* The stack of deallocated items is empty. */
3991 pool->deaditemstack = (VOID *) NULL;
3992}
3993
3994/*****************************************************************************/
3995/* */
3996/* poolinit() Initialize a pool of memory for allocation of items. */
3997/* */
3998/* This routine initializes the machinery for allocating items. A `pool' */
3999/* is created whose records have size at least `bytecount'. Items will be */
4000/* allocated in `itemcount'-item blocks. Each item is assumed to be a */
4001/* collection of words, and either pointers or floating-point values are */
4002/* assumed to be the "primary" word type. (The "primary" word type is used */
4003/* to determine alignment of items.) If `alignment' isn't zero, all items */
4004/* will be `alignment'-byte aligned in memory. `alignment' must be either */
4005/* a multiple or a factor of the primary word size; powers of two are safe. */
4006/* `alignment' is normally used to create a few unused bits at the bottom */
4007/* of each item's pointer, in which information may be stored. */
4008/* */
4009/* Don't change this routine unless you understand it. */
4010/* */
4011/*****************************************************************************/
4012
4013#ifdef ANSI_DECLARATORS
4014void poolinit(struct memorypool* pool, int bytecount, int itemcount,
4015 int firstitemcount, unsigned alignment)
4016#else /* not ANSI_DECLARATORS */
4017void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
4018struct memorypool* pool;
4019int bytecount;
4020int itemcount;
4021int firstitemcount;
4022unsigned alignment;
4023#endif /* not ANSI_DECLARATORS */
4024
4025{
4026 /* Find the proper alignment, which must be at least as large as: */
4027 /* - The parameter `alignment'. */
4028 /* - sizeof(VOID *), so the stack of dead items can be maintained */
4029 /* without unaligned accesses. */
4030 if (alignment > sizeof(VOID *)) {
4031 pool->alignbytes = alignment;
4032 } else {
4033 pool->alignbytes = sizeof(VOID *);
4034 }
4035 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
4036 pool->alignbytes;
4037 pool->itemsperblock = itemcount;
4038 if (firstitemcount == 0) {
4039 pool->itemsfirstblock = itemcount;
4040 } else {
4041 pool->itemsfirstblock = firstitemcount;
4042 }
4043
4044 /* Allocate a block of items. Space for `itemsfirstblock' items and one */
4045 /* pointer (to point to the next block) are allocated, as well as space */
4046 /* to ensure alignment of the items. */
4047 pool->firstblock = (VOID **)
4048 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
4049 pool->alignbytes);
4050 /* Set the next block pointer to NULL. */
4051 *(pool->firstblock) = (VOID *) NULL;
4052 poolrestart(pool);
4053}
4054
4055/*****************************************************************************/
4056/* */
4057/* pooldeinit() Free to the operating system all memory taken by a pool. */
4058/* */
4059/*****************************************************************************/
4060
4061#ifdef ANSI_DECLARATORS
4062void pooldeinit(struct memorypool* pool)
4063#else /* not ANSI_DECLARATORS */
4064void pooldeinit(pool)
4065struct memorypool* pool;
4066#endif /* not ANSI_DECLARATORS */
4067
4068{
4069 while (pool->firstblock != (VOID **) NULL) {
4070 pool->nowblock = (VOID **) *(pool->firstblock);
4071 trifree((VOID *) pool->firstblock);
4072 pool->firstblock = pool->nowblock;
4073 }
4074}
4075
4076/*****************************************************************************/
4077/* */
4078/* poolalloc() Allocate space for an item. */
4079/* */
4080/*****************************************************************************/
4081
4082#ifdef ANSI_DECLARATORS
4083VOID* poolalloc(struct memorypool* pool)
4084#else /* not ANSI_DECLARATORS */
4085VOID* poolalloc(pool)
4086struct memorypool* pool;
4087#endif /* not ANSI_DECLARATORS */
4088
4089{
4090 VOID *newitem;
4091 VOID **newblock;
4092 unsigned long alignptr;
4093
4094 /* First check the linked list of dead items. If the list is not */
4095 /* empty, allocate an item from the list rather than a fresh one. */
4096 if (pool->deaditemstack != (VOID *) NULL) {
4097 newitem = pool->deaditemstack; /* Take first item in list. */
4098 pool->deaditemstack = * (VOID **) pool->deaditemstack;
4099 } else {
4100 /* Check if there are any free items left in the current block. */
4101 if (pool->unallocateditems == 0) {
4102 /* Check if another block must be allocated. */
4103 if (*(pool->nowblock) == (VOID *) NULL) {
4104 /* Allocate a new block of items, pointed to by the previous block. */
4105 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
4106 (int) sizeof(VOID *) +
4107 pool->alignbytes);
4108 *(pool->nowblock) = (VOID *) newblock;
4109 /* The next block pointer is NULL. */
4110 *newblock = (VOID *) NULL;
4111 }
4112
4113 /* Move to the new block. */
4114 pool->nowblock = (VOID **) *(pool->nowblock);
4115 /* Find the first item in the block. */
4116 /* Increment by the size of (VOID *). */
4117 alignptr = (unsigned long) (pool->nowblock + 1);
4118 /* Align the item on an `alignbytes'-byte boundary. */
4119 pool->nextitem = (VOID *)
4120 (alignptr + (unsigned long) pool->alignbytes -
4121 (alignptr % (unsigned long) pool->alignbytes));
4122 /* There are lots of unallocated items left in this block. */
4123 pool->unallocateditems = pool->itemsperblock;
4124 }
4125
4126 /* Allocate a new item. */
4127 newitem = pool->nextitem;
4128 /* Advance `nextitem' pointer to next free item in block. */
4129 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
4130 pool->unallocateditems--;
4131 pool->maxitems++;
4132 }
4133 pool->items++;
4134 return newitem;
4135}
4136
4137/*****************************************************************************/
4138/* */
4139/* pooldealloc() Deallocate space for an item. */
4140/* */
4141/* The deallocated space is stored in a queue for later reuse. */
4142/* */
4143/*****************************************************************************/
4144
4145#ifdef ANSI_DECLARATORS
4146void pooldealloc(struct memorypool* pool, VOID *dyingitem)
4147#else /* not ANSI_DECLARATORS */
4148void pooldealloc(pool, dyingitem)
4149struct memorypool* pool;
4150VOID *dyingitem;
4151#endif /* not ANSI_DECLARATORS */
4152
4153{
4154 /* Push freshly killed item onto stack. */
4155 *((VOID **) dyingitem) = pool->deaditemstack;
4156 pool->deaditemstack = dyingitem;
4157 pool->items--;
4158}
4159
4160/*****************************************************************************/
4161/* */
4162/* traversalinit() Prepare to traverse the entire list of items. */
4163/* */
4164/* This routine is used in conjunction with traverse(). */
4165/* */
4166/*****************************************************************************/
4167
4168#ifdef ANSI_DECLARATORS
4169void traversalinit(struct memorypool* pool)
4170#else /* not ANSI_DECLARATORS */
4171void traversalinit(pool)
4172struct memorypool* pool;
4173#endif /* not ANSI_DECLARATORS */
4174
4175{
4176 unsigned long alignptr;
4177
4178 /* Begin the traversal in the first block. */
4179 pool->pathblock = pool->firstblock;
4180 /* Find the first item in the block. Increment by the size of (VOID *). */
4181 alignptr = (unsigned long) (pool->pathblock + 1);
4182 /* Align with item on an `alignbytes'-byte boundary. */
4183 pool->pathitem = (VOID *)
4184 (alignptr + (unsigned long) pool->alignbytes -
4185 (alignptr % (unsigned long) pool->alignbytes));
4186 /* Set the number of items left in the current block. */
4187 pool->pathitemsleft = pool->itemsfirstblock;
4188}
4189
4190/*****************************************************************************/
4191/* */
4192/* traverse() Find the next item in the list. */
4193/* */
4194/* This routine is used in conjunction with traversalinit(). Be forewarned */
4195/* that this routine successively returns all items in the list, including */
4196/* deallocated ones on the deaditemqueue. It's up to you to figure out */
4197/* which ones are actually dead. Why? I don't want to allocate extra */
4198/* space just to demarcate dead items. It can usually be done more */
4199/* space-efficiently by a routine that knows something about the structure */
4200/* of the item. */
4201/* */
4202/*****************************************************************************/
4203
4204#ifdef ANSI_DECLARATORS
4205VOID *traverse(struct memorypool* pool)
4206#else /* not ANSI_DECLARATORS */
4207VOID *traverse(pool)
4208struct memorypool* pool;
4209#endif /* not ANSI_DECLARATORS */
4210
4211{
4212 VOID *newitem;
4213 unsigned long alignptr;
4214
4215 /* Stop upon exhausting the list of items. */
4216 if (pool->pathitem == pool->nextitem) {
4217 return (VOID *) NULL;
4218 }
4219
4220 /* Check whether any untraversed items remain in the current block. */
4221 if (pool->pathitemsleft == 0) {
4222 /* Find the next block. */
4223 pool->pathblock = (VOID **) *(pool->pathblock);
4224 /* Find the first item in the block. Increment by the size of (VOID *). */
4225 alignptr = (unsigned long) (pool->pathblock + 1);
4226 /* Align with item on an `alignbytes'-byte boundary. */
4227 pool->pathitem = (VOID *)
4228 (alignptr + (unsigned long) pool->alignbytes -
4229 (alignptr % (unsigned long) pool->alignbytes));
4230 /* Set the number of items left in the current block. */
4231 pool->pathitemsleft = pool->itemsperblock;
4232 }
4233
4234 newitem = pool->pathitem;
4235 /* Find the next item in the block. */
4236 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
4237 pool->pathitemsleft--;
4238 return newitem;
4239}
4240
4241/*****************************************************************************/
4242/* */
4243/* dummyinit() Initialize the triangle that fills "outer space" and the */
4244/* omnipresent subsegment. */
4245/* */
4246/* The triangle that fills "outer space," called `dummytri', is pointed to */
4247/* by every triangle and subsegment on a boundary (be it outer or inner) of */
4248/* the triangulation. Also, `dummytri' points to one of the triangles on */
4249/* the convex hull (until the holes and concavities are carved), making it */
4250/* possible to find a starting triangle for point location. */
4251/* */
4252/* The omnipresent subsegment, `dummysub', is pointed to by every triangle */
4253/* or subsegment that doesn't have a full complement of real subsegments */
4254/* to point to. */
4255/* */
4256/* `dummytri' and `dummysub' are generally required to fulfill only a few */
4257/* invariants: their vertices must remain NULL and `dummytri' must always */
4258/* be bonded (at offset zero) to some triangle on the convex hull of the */
4259/* mesh, via a boundary edge. Otherwise, the connections of `dummytri' and */
4260/* `dummysub' may change willy-nilly. This makes it possible to avoid */
4261/* writing a good deal of special-case code (in the edge flip, for example) */
4262/* for dealing with the boundary of the mesh, places where no subsegment is */
4263/* present, and so forth. Other entities are frequently bonded to */
4264/* `dummytri' and `dummysub' as if they were real mesh entities, with no */
4265/* harm done. */
4266/* */
4267/*****************************************************************************/
4268
4269#ifdef ANSI_DECLARATORS
4270void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
4271 int subsegbytes)
4272#else /* not ANSI_DECLARATORS */
4273void dummyinit(m, b, trianglebytes, subsegbytes)
4274struct mesh *m;
4275struct behavior *b;
4276int trianglebytes;
4277int subsegbytes;
4278#endif /* not ANSI_DECLARATORS */
4279
4280{
4281 unsigned long alignptr;
4282
4283 /* Set up `dummytri', the `triangle' that occupies "outer space." */
4284 m->dummytribase = (triangle *) trimalloc(trianglebytes +
4285 m->triangles.alignbytes);
4286 /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
4287 alignptr = (unsigned long) m->dummytribase;
4288 m->dummytri = (triangle *)
4289 (alignptr + (unsigned long) m->triangles.alignbytes -
4290 (alignptr % (unsigned long) m->triangles.alignbytes));
4291 /* Initialize the three adjoining triangles to be "outer space." These */
4292 /* will eventually be changed by various bonding operations, but their */
4293 /* values don't really matter, as long as they can legally be */
4294 /* dereferenced. */
4295 m->dummytri[0] = (triangle) m->dummytri;
4296 m->dummytri[1] = (triangle) m->dummytri;
4297 m->dummytri[2] = (triangle) m->dummytri;
4298 /* Three NULL vertices. */
4299 m->dummytri[3] = (triangle) NULL;
4300 m->dummytri[4] = (triangle) NULL;
4301 m->dummytri[5] = (triangle) NULL;
4302
4303 if (b->usesegments) {
4304 /* Set up `dummysub', the omnipresent subsegment pointed to by any */
4305 /* triangle side or subsegment end that isn't attached to a real */
4306 /* subsegment. */
4307 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
4308 m->subsegs.alignbytes);
4309 /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
4310 alignptr = (unsigned long) m->dummysubbase;
4311 m->dummysub = (subseg *)
4312 (alignptr + (unsigned long) m->subsegs.alignbytes -
4313 (alignptr % (unsigned long) m->subsegs.alignbytes));
4314 /* Initialize the two adjoining subsegments to be the omnipresent */
4315 /* subsegment. These will eventually be changed by various bonding */
4316 /* operations, but their values don't really matter, as long as they */
4317 /* can legally be dereferenced. */
4318 m->dummysub[0] = (subseg) m->dummysub;
4319 m->dummysub[1] = (subseg) m->dummysub;
4320 /* Four NULL vertices. */
4321 m->dummysub[2] = (subseg) NULL;
4322 m->dummysub[3] = (subseg) NULL;
4323 m->dummysub[4] = (subseg) NULL;
4324 m->dummysub[5] = (subseg) NULL;
4325 /* Initialize the two adjoining triangles to be "outer space." */
4326 m->dummysub[6] = (subseg) m->dummytri;
4327 m->dummysub[7] = (subseg) m->dummytri;
4328 /* Set the boundary marker to zero. */
4329 * (int *) (m->dummysub + 8) = 0;
4330
4331 /* Initialize the three adjoining subsegments of `dummytri' to be */
4332 /* the omnipresent subsegment. */
4333 m->dummytri[6] = (triangle) m->dummysub;
4334 m->dummytri[7] = (triangle) m->dummysub;
4335 m->dummytri[8] = (triangle) m->dummysub;
4336 }
4337}
4338
4339/*****************************************************************************/
4340/* */
4341/* initializevertexpool() Calculate the size of the vertex data structure */
4342/* and initialize its memory pool. */
4343/* */
4344/* This routine also computes the `vertexmarkindex' and `vertex2triindex' */
4345/* indices used to find values within each vertex. */
4346/* */
4347/*****************************************************************************/
4348
4349#ifdef ANSI_DECLARATORS
4350void initializevertexpool(struct mesh *m, struct behavior *b)
4351#else /* not ANSI_DECLARATORS */
4352void initializevertexpool(m, b)
4353struct mesh *m;
4354struct behavior *b;
4355#endif /* not ANSI_DECLARATORS */
4356
4357{
4358 int vertexsize;
4359
4360 /* The index within each vertex at which the boundary marker is found, */
4361 /* followed by the vertex type. Ensure the vertex marker is aligned to */
4362 /* a sizeof(int)-byte address. */
4363 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
4364 sizeof(int) - 1) /
4365 sizeof(int);
4366 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
4367 if (b->poly) {
4368 /* The index within each vertex at which a triangle pointer is found. */
4369 /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
4370 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
4371 sizeof(triangle);
4372 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
4373 }
4374
4375 /* Initialize the pool of vertices. */
4376 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
4377 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
4378 sizeof(REAL));
4379}
4380
4381/*****************************************************************************/
4382/* */
4383/* initializetrisubpools() Calculate the sizes of the triangle and */
4384/* subsegment data structures and initialize */
4385/* their memory pools. */
4386/* */
4387/* This routine also computes the `highorderindex', `elemattribindex', and */
4388/* `areaboundindex' indices used to find values within each triangle. */
4389/* */
4390/*****************************************************************************/
4391
4392#ifdef ANSI_DECLARATORS
4393void initializetrisubpools(struct mesh *m, struct behavior *b)
4394#else /* not ANSI_DECLARATORS */
4395void initializetrisubpools(m, b)
4396struct mesh *m;
4397struct behavior *b;
4398#endif /* not ANSI_DECLARATORS */
4399
4400{
4401 unsigned trisize;
4402
4403 /* The index within each triangle at which the extra nodes (above three) */
4404 /* associated with high order elements are found. There are three */
4405 /* pointers to other triangles, three pointers to corners, and possibly */
4406 /* three pointers to subsegments before the extra nodes. */
4407 m->highorderindex = 6 + (b->usesegments * 3);
4408 /* The number of bytes occupied by a triangle. */
4409 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
4410 sizeof(triangle);
4411 /* The index within each triangle at which its attributes are found, */
4412 /* where the index is measured in REALs. */
4413 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
4414 /* The index within each triangle at which the maximum area constraint */
4415 /* is found, where the index is measured in REALs. Note that if the */
4416 /* `regionattrib' flag is set, an additional attribute will be added. */
4417 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
4418 /* If triangle attributes or an area bound are needed, increase the number */
4419 /* of bytes occupied by a triangle. */
4420 if (b->vararea) {
4421 trisize = (m->areaboundindex + 1) * sizeof(REAL);
4422 } else if (m->eextras + b->regionattrib > 0) {
4423 trisize = m->areaboundindex * sizeof(REAL);
4424 }
4425 /* If a Voronoi diagram or triangle neighbor graph is requested, make */
4426 /* sure there's room to store an integer index in each triangle. This */
4427 /* integer index can occupy the same space as the subsegment pointers */
4428 /* or attributes or area constraint or extra nodes. */
4429 if ((b->voronoi || b->neighbors) &&
4430 (trisize < 6 * sizeof(triangle) + sizeof(int))) {
4431 trisize = 6 * sizeof(triangle) + sizeof(int);
4432 }
4433
4434 /* Having determined the memory size of a triangle, initialize the pool. */
4435 poolinit(&m->triangles, trisize, TRIPERBLOCK,
4436 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
4437 TRIPERBLOCK, 4);
4438
4439 if (b->usesegments) {
4440 /* Initialize the pool of subsegments. Take into account all eight */
4441 /* pointers and one boundary marker. */
4442 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
4443 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
4444
4445 /* Initialize the "outer space" triangle and omnipresent subsegment. */
4446 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
4447 } else {
4448 /* Initialize the "outer space" triangle. */
4449 dummyinit(m, b, m->triangles.itembytes, 0);
4450 }
4451}
4452
4453/*****************************************************************************/
4454/* */
4455/* triangledealloc() Deallocate space for a triangle, marking it dead. */
4456/* */
4457/*****************************************************************************/
4458
4459#ifdef ANSI_DECLARATORS
4460void triangledealloc(struct mesh *m, triangle *dyingtriangle)
4461#else /* not ANSI_DECLARATORS */
4462void triangledealloc(m, dyingtriangle)
4463struct mesh *m;
4464triangle *dyingtriangle;
4465#endif /* not ANSI_DECLARATORS */
4466
4467{
4468 /* Mark the triangle as dead. This makes it possible to detect dead */
4469 /* triangles when traversing the list of all triangles. */
4470 killtri(dyingtriangle);
4471 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
4472}
4473
4474/*****************************************************************************/
4475/* */
4476/* triangletraverse() Traverse the triangles, skipping dead ones. */
4477/* */
4478/*****************************************************************************/
4479
4480#ifdef ANSI_DECLARATORS
4481triangle *triangletraverse(struct mesh *m)
4482#else /* not ANSI_DECLARATORS */
4483triangle *triangletraverse(m)
4484struct mesh *m;
4485#endif /* not ANSI_DECLARATORS */
4486
4487{
4488 triangle *newtriangle;
4489
4490 do {
4491 newtriangle = (triangle *) traverse(&m->triangles);
4492 if (newtriangle == (triangle *) NULL) {
4493 return (triangle *) NULL;
4494 }
4495 } while (deadtri(newtriangle)); /* Skip dead ones. */
4496 return newtriangle;
4497}
4498
4499/*****************************************************************************/
4500/* */
4501/* subsegdealloc() Deallocate space for a subsegment, marking it dead. */
4502/* */
4503/*****************************************************************************/
4504
4505#ifdef ANSI_DECLARATORS
4506void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
4507#else /* not ANSI_DECLARATORS */
4508void subsegdealloc(m, dyingsubseg)
4509struct mesh *m;
4510subseg *dyingsubseg;
4511#endif /* not ANSI_DECLARATORS */
4512
4513{
4514 /* Mark the subsegment as dead. This makes it possible to detect dead */
4515 /* subsegments when traversing the list of all subsegments. */
4516 killsubseg(dyingsubseg);
4517 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
4518}
4519
4520/*****************************************************************************/
4521/* */
4522/* subsegtraverse() Traverse the subsegments, skipping dead ones. */
4523/* */
4524/*****************************************************************************/
4525
4526#ifdef ANSI_DECLARATORS
4527subseg *subsegtraverse(struct mesh *m)
4528#else /* not ANSI_DECLARATORS */
4529subseg *subsegtraverse(m)
4530struct mesh *m;
4531#endif /* not ANSI_DECLARATORS */
4532
4533{
4534 subseg *newsubseg;
4535
4536 do {
4537 newsubseg = (subseg *) traverse(&m->subsegs);
4538 if (newsubseg == (subseg *) NULL) {
4539 return (subseg *) NULL;
4540 }
4541 } while (deadsubseg(newsubseg)); /* Skip dead ones. */
4542 return newsubseg;
4543}
4544
4545/*****************************************************************************/
4546/* */
4547/* vertexdealloc() Deallocate space for a vertex, marking it dead. */
4548/* */
4549/*****************************************************************************/
4550
4551#ifdef ANSI_DECLARATORS
4552void vertexdealloc(struct mesh *m, vertex dyingvertex)
4553#else /* not ANSI_DECLARATORS */
4554void vertexdealloc(m, dyingvertex)
4555struct mesh *m;
4556vertex dyingvertex;
4557#endif /* not ANSI_DECLARATORS */
4558
4559{
4560 /* Mark the vertex as dead. This makes it possible to detect dead */
4561 /* vertices when traversing the list of all vertices. */
4562 setvertextype(dyingvertex, DEADVERTEX);
4563 pooldealloc(&m->vertices, (VOID *) dyingvertex);
4564}
4565
4566/*****************************************************************************/
4567/* */
4568/* vertextraverse() Traverse the vertices, skipping dead ones. */
4569/* */
4570/*****************************************************************************/
4571
4572#ifdef ANSI_DECLARATORS
4573vertex vertextraverse(struct mesh *m)
4574#else /* not ANSI_DECLARATORS */
4575vertex vertextraverse(m)
4576struct mesh *m;
4577#endif /* not ANSI_DECLARATORS */
4578
4579{
4580 vertex newvertex;
4581
4582 do {
4583 newvertex = (vertex) traverse(&m->vertices);
4584 if (newvertex == (vertex) NULL) {
4585 return (vertex) NULL;
4586 }
4587 } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */
4588 return newvertex;
4589}
4590
4591/*****************************************************************************/
4592/* */
4593/* badsubsegdealloc() Deallocate space for a bad subsegment, marking it */
4594/* dead. */
4595/* */
4596/*****************************************************************************/
4597
4598#ifndef CDT_ONLY
4599
4600#ifdef ANSI_DECLARATORS
4601void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
4602#else /* not ANSI_DECLARATORS */
4603void badsubsegdealloc(m, dyingseg)
4604struct mesh *m;
4605struct badsubseg *dyingseg;
4606#endif /* not ANSI_DECLARATORS */
4607
4608{
4609 /* Set subsegment's origin to NULL. This makes it possible to detect dead */
4610 /* badsubsegs when traversing the list of all badsubsegs . */
4611 dyingseg->subsegorg = (vertex) NULL;
4612 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
4613}
4614
4615#endif /* not CDT_ONLY */
4616
4617/*****************************************************************************/
4618/* */
4619/* badsubsegtraverse() Traverse the bad subsegments, skipping dead ones. */
4620/* */
4621/*****************************************************************************/
4622
4623#ifndef CDT_ONLY
4624
4625#ifdef ANSI_DECLARATORS
4626struct badsubseg *badsubsegtraverse(struct mesh *m)
4627#else /* not ANSI_DECLARATORS */
4628struct badsubseg *badsubsegtraverse(m)
4629struct mesh *m;
4630#endif /* not ANSI_DECLARATORS */
4631
4632{
4633 struct badsubseg *newseg;
4634
4635 do {
4636 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
4637 if (newseg == (struct badsubseg *) NULL) {
4638 return (struct badsubseg *) NULL;
4639 }
4640 } while (newseg->subsegorg == (vertex) NULL); /* Skip dead ones. */
4641 return newseg;
4642}
4643
4644#endif /* not CDT_ONLY */
4645
4646/*****************************************************************************/
4647/* */
4648/* getvertex() Get a specific vertex, by number, from the list. */
4649/* */
4650/* The first vertex is number 'firstnumber'. */
4651/* */
4652/* Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */
4653/* is large). I don't care to take the trouble to make it work in constant */
4654/* time. */
4655/* */
4656/*****************************************************************************/
4657
4658#ifdef ANSI_DECLARATORS
4659vertex getvertex(struct mesh *m, struct behavior *b, int number)
4660#else /* not ANSI_DECLARATORS */
4661vertex getvertex(m, b, number)
4662struct mesh *m;
4663struct behavior *b;
4664int number;
4665#endif /* not ANSI_DECLARATORS */
4666
4667{
4668 VOID **getblock;
4669 char *foundvertex;
4670 unsigned long alignptr;
4671 int current;
4672
4673 getblock = m->vertices.firstblock;
4674 current = b->firstnumber;
4675
4676 /* Find the right block. */
4677 if (current + m->vertices.itemsfirstblock <= number) {
4678 getblock = (VOID **) *getblock;
4679 current += m->vertices.itemsfirstblock;
4680 while (current + m->vertices.itemsperblock <= number) {
4681 getblock = (VOID **) *getblock;
4682 current += m->vertices.itemsperblock;
4683 }
4684 }
4685
4686 /* Now find the right vertex. */
4687 alignptr = (unsigned long) (getblock + 1);
4688 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
4689 (alignptr % (unsigned long) m->vertices.alignbytes));
4690 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
4691}
4692
4693/*****************************************************************************/
4694/* */
4695/* triangledeinit() Free all remaining allocated memory. */
4696/* */
4697/*****************************************************************************/
4698
4699#ifdef ANSI_DECLARATORS
4700void triangledeinit(struct mesh *m, struct behavior *b)
4701#else /* not ANSI_DECLARATORS */
4702void triangledeinit(m, b)
4703struct mesh *m;
4704struct behavior *b;
4705#endif /* not ANSI_DECLARATORS */
4706
4707{
4708 pooldeinit(&m->triangles);
4709 trifree((VOID *) m->dummytribase);
4710 if (b->usesegments) {
4711 pooldeinit(&m->subsegs);
4712 trifree((VOID *) m->dummysubbase);
4713 }
4714 pooldeinit(&m->vertices);
4715#ifndef CDT_ONLY
4716 if (b->quality) {
4717 pooldeinit(&m->badsubsegs);
4718 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
4719 pooldeinit(&m->badtriangles);
4720 pooldeinit(&m->flipstackers);
4721 }
4722 }
4723#endif /* not CDT_ONLY */
4724}
4725
4728/********* Memory management routines end here *********/
4729
4730/********* Constructors begin here *********/
4734/*****************************************************************************/
4735/* */
4736/* maketriangle() Create a new triangle with orientation zero. */
4737/* */
4738/*****************************************************************************/
4739
4740#ifdef ANSI_DECLARATORS
4741void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
4742#else /* not ANSI_DECLARATORS */
4743void maketriangle(m, b, newotri)
4744struct mesh *m;
4745struct behavior *b;
4746struct otri *newotri;
4747#endif /* not ANSI_DECLARATORS */
4748
4749{
4750 int i;
4751
4752 newotri->tri = (triangle *) poolalloc(&m->triangles);
4753 /* Initialize the three adjoining triangles to be "outer space". */
4754 newotri->tri[0] = (triangle) m->dummytri;
4755 newotri->tri[1] = (triangle) m->dummytri;
4756 newotri->tri[2] = (triangle) m->dummytri;
4757 /* Three NULL vertices. */
4758 newotri->tri[3] = (triangle) NULL;
4759 newotri->tri[4] = (triangle) NULL;
4760 newotri->tri[5] = (triangle) NULL;
4761 if (b->usesegments) {
4762 /* Initialize the three adjoining subsegments to be the omnipresent */
4763 /* subsegment. */
4764 newotri->tri[6] = (triangle) m->dummysub;
4765 newotri->tri[7] = (triangle) m->dummysub;
4766 newotri->tri[8] = (triangle) m->dummysub;
4767 }
4768 for (i = 0; i < m->eextras; i++) {
4769 setelemattribute(*newotri, i, 0.0);
4770 }
4771 if (b->vararea) {
4772 setareabound(*newotri, -1.0);
4773 }
4774
4775 newotri->orient = 0;
4776}
4777
4778/*****************************************************************************/
4779/* */
4780/* makesubseg() Create a new subsegment with orientation zero. */
4781/* */
4782/*****************************************************************************/
4783
4784#ifdef ANSI_DECLARATORS
4785void makesubseg(struct mesh *m, struct osub *newsubseg)
4786#else /* not ANSI_DECLARATORS */
4787void makesubseg(m, newsubseg)
4788struct mesh *m;
4789struct osub *newsubseg;
4790#endif /* not ANSI_DECLARATORS */
4791
4792{
4793 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
4794 /* Initialize the two adjoining subsegments to be the omnipresent */
4795 /* subsegment. */
4796 newsubseg->ss[0] = (subseg) m->dummysub;
4797 newsubseg->ss[1] = (subseg) m->dummysub;
4798 /* Four NULL vertices. */
4799 newsubseg->ss[2] = (subseg) NULL;
4800 newsubseg->ss[3] = (subseg) NULL;
4801 newsubseg->ss[4] = (subseg) NULL;
4802 newsubseg->ss[5] = (subseg) NULL;
4803 /* Initialize the two adjoining triangles to be "outer space." */
4804 newsubseg->ss[6] = (subseg) m->dummytri;
4805 newsubseg->ss[7] = (subseg) m->dummytri;
4806 /* Set the boundary marker to zero. */
4807 setmark(*newsubseg, 0);
4808
4809 newsubseg->ssorient = 0;
4810}
4811
4814/********* Constructors end here *********/
4815
4816/********* Geometric primitives begin here *********/
4820/* The adaptive exact arithmetic geometric predicates implemented herein are */
4821/* described in detail in my paper, "Adaptive Precision Floating-Point */
4822/* Arithmetic and Fast Robust Geometric Predicates." See the header for a */
4823/* full citation. */
4824
4825/* Which of the following two methods of finding the absolute values is */
4826/* fastest is compiler-dependent. A few compilers can inline and optimize */
4827/* the fabs() call; but most will incur the overhead of a function call, */
4828/* which is disastrously slow. A faster way on IEEE machines might be to */
4829/* mask the appropriate bit, but that's difficult to do in C without */
4830/* forcing the value to be stored to memory (rather than be kept in the */
4831/* register to which the optimizer assigned it). */
4832
4833#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
4834/* #define Absolute(a) fabs(a) */
4835
4836/* Many of the operations are broken up into two pieces, a main part that */
4837/* performs an approximate operation, and a "tail" that computes the */
4838/* roundoff error of that operation. */
4839/* */
4840/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */
4841/* Split(), and Two_Product() are all implemented as described in the */
4842/* reference. Each of these macros requires certain variables to be */
4843/* defined in the calling routine. The variables `bvirt', `c', `abig', */
4844/* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */
4845/* they store the result of an operation that may incur roundoff error. */
4846/* The input parameter `x' (or the highest numbered `x_' parameter) must */
4847/* also be declared `INEXACT'. */
4848
4849#define Fast_Two_Sum_Tail(a, b, x, y) \
4850 bvirt = x - a; \
4851 y = b - bvirt
4852
4853#define Fast_Two_Sum(a, b, x, y) \
4854 x = (REAL) (a + b); \
4855 Fast_Two_Sum_Tail(a, b, x, y)
4856
4857#define Two_Sum_Tail(a, b, x, y) \
4858 bvirt = (REAL) (x - a); \
4859 avirt = x - bvirt; \
4860 bround = b - bvirt; \
4861 around = a - avirt; \
4862 y = around + bround
4863
4864#define Two_Sum(a, b, x, y) \
4865 x = (REAL) (a + b); \
4866 Two_Sum_Tail(a, b, x, y)
4867
4868#define Two_Diff_Tail(a, b, x, y) \
4869 bvirt = (REAL) (a - x); \
4870 avirt = x + bvirt; \
4871 bround = bvirt - b; \
4872 around = a - avirt; \
4873 y = around + bround
4874
4875#define Two_Diff(a, b, x, y) \
4876 x = (REAL) (a - b); \
4877 Two_Diff_Tail(a, b, x, y)
4878
4879#define Split(a, ahi, alo) \
4880 c = (REAL) (splitter * a); \
4881 abig = (REAL) (c - a); \
4882 ahi = c - abig; \
4883 alo = a - ahi
4884
4885#define Two_Product_Tail(a, b, x, y) \
4886 Split(a, ahi, alo); \
4887 Split(b, bhi, blo); \
4888 err1 = x - (ahi * bhi); \
4889 err2 = err1 - (alo * bhi); \
4890 err3 = err2 - (ahi * blo); \
4891 y = (alo * blo) - err3
4892
4893#define Two_Product(a, b, x, y) \
4894 x = (REAL) (a * b); \
4895 Two_Product_Tail(a, b, x, y)
4896
4897/* Two_Product_Presplit() is Two_Product() where one of the inputs has */
4898/* already been split. Avoids redundant splitting. */
4899
4900#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
4901 x = (REAL) (a * b); \
4902 Split(a, ahi, alo); \
4903 err1 = x - (ahi * bhi); \
4904 err2 = err1 - (alo * bhi); \
4905 err3 = err2 - (ahi * blo); \
4906 y = (alo * blo) - err3
4907
4908/* Square() can be done more quickly than Two_Product(). */
4909
4910#define Square_Tail(a, x, y) \
4911 Split(a, ahi, alo); \
4912 err1 = x - (ahi * ahi); \
4913 err3 = err1 - ((ahi + ahi) * alo); \
4914 y = (alo * alo) - err3
4915
4916#define Square(a, x, y) \
4917 x = (REAL) (a * a); \
4918 Square_Tail(a, x, y)
4919
4920/* Macros for summing expansions of various fixed lengths. These are all */
4921/* unrolled versions of Expansion_Sum(). */
4922
4923#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
4924 Two_Sum(a0, b , _i, x0); \
4925 Two_Sum(a1, _i, x2, x1)
4926
4927#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
4928 Two_Diff(a0, b , _i, x0); \
4929 Two_Sum( a1, _i, x2, x1)
4930
4931#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
4932 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
4933 Two_One_Sum(_j, _0, b1, x3, x2, x1)
4934
4935#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
4936 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
4937 Two_One_Diff(_j, _0, b1, x3, x2, x1)
4938
4939/* Macro for multiplying a two-component expansion by a single component. */
4940
4941#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
4942 Split(b, bhi, blo); \
4943 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
4944 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
4945 Two_Sum(_i, _0, _k, x1); \
4946 Fast_Two_Sum(_j, _k, x3, x2)
4947
4948/*****************************************************************************/
4949/* */
4950/* exactinit() Initialize the variables used for exact arithmetic. */
4951/* */
4952/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
4953/* floating-point arithmetic. `epsilon' bounds the relative roundoff */
4954/* error. It is used for floating-point error analysis. */
4955/* */
4956/* `splitter' is used to split floating-point numbers into two half- */
4957/* length significands for exact multiplication. */
4958/* */
4959/* I imagine that a highly optimizing compiler might be too smart for its */
4960/* own good, and somehow cause this routine to fail, if it pretends that */
4961/* floating-point arithmetic is too much like real arithmetic. */
4962/* */
4963/* Don't change this routine unless you fully understand it. */
4964/* */
4965/*****************************************************************************/
4966
4967void exactinit()
4968{
4969 REAL half;
4970 REAL check, lastcheck;
4971 int every_other;
4972#ifdef LINUX
4973 int cword;
4974#endif /* LINUX */
4975
4976#ifdef CPU86
4977#ifdef SINGLE
4978 _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */
4979#else /* not SINGLE */
4980 _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */
4981#endif /* not SINGLE */
4982#endif /* CPU86 */
4983#ifdef LINUX
4984#ifdef SINGLE
4985 /* cword = 4223; */
4986 cword = 4210; /* set FPU control word for single precision */
4987#else /* not SINGLE */
4988 /* cword = 4735; */
4989 cword = 4722; /* set FPU control word for double precision */
4990#endif /* not SINGLE */
4991 _FPU_SETCW(cword);
4992#endif /* LINUX */
4993
4994 every_other = 1;
4995 half = 0.5;
4996 epsilon = 1.0;
4997 splitter = 1.0;
4998 check = 1.0;
4999 /* Repeatedly divide `epsilon' by two until it is too small to add to */
5000 /* one without causing roundoff. (Also check if the sum is equal to */
5001 /* the previous sum, for machines that round up instead of using exact */
5002 /* rounding. Not that these routines will work on such machines.) */
5003 do {
5004 lastcheck = check;
5005 epsilon *= half;
5006 if (every_other) {
5007 splitter *= 2.0;
5008 }
5009 every_other = !every_other;
5010 check = 1.0 + epsilon;
5011 } while ((check != 1.0) && (check != lastcheck));
5012 splitter += 1.0;
5013 /* Error bounds for orientation and incircle tests. */
5014 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
5015 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
5016 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
5017 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
5018 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
5019 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
5020 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
5021 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
5022 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
5023 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
5024}
5025
5026/*****************************************************************************/
5027/* */
5028/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
5029/* components from the output expansion. */
5030/* */
5031/* Sets h = e + f. See my Robust Predicates paper for details. */
5032/* */
5033/* If round-to-even is used (as with IEEE 754), maintains the strongly */
5034/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
5035/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
5036/* properties. */
5037/* */
5038/*****************************************************************************/
5039
5040#ifdef ANSI_DECLARATORS
5041int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
5042#else /* not ANSI_DECLARATORS */
5043int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */
5044int elen;
5045REAL *e;
5046int flen;
5047REAL *f;
5048REAL *h;
5049#endif /* not ANSI_DECLARATORS */
5050
5051{
5052 REAL Q;
5053 INEXACT REAL Qnew;
5054 INEXACT REAL hh;
5055 INEXACT REAL bvirt;
5056 REAL avirt, bround, around;
5057 int eindex, findex, hindex;
5058 REAL enow, fnow;
5059
5060 enow = e[0];
5061 fnow = f[0];
5062 eindex = findex = 0;
5063 if ((fnow > enow) == (fnow > -enow)) {
5064 Q = enow;
5065 enow = e[++eindex];
5066 } else {
5067 Q = fnow;
5068 fnow = f[++findex];
5069 }
5070 hindex = 0;
5071 if ((eindex < elen) && (findex < flen)) {
5072 if ((fnow > enow) == (fnow > -enow)) {
5073 Fast_Two_Sum(enow, Q, Qnew, hh);
5074 enow = e[++eindex];
5075 } else {
5076 Fast_Two_Sum(fnow, Q, Qnew, hh);
5077 fnow = f[++findex];
5078 }
5079 Q = Qnew;
5080 if (hh != 0.0) {
5081 h[hindex++] = hh;
5082 }
5083 while ((eindex < elen) && (findex < flen)) {
5084 if ((fnow > enow) == (fnow > -enow)) {
5085 Two_Sum(Q, enow, Qnew, hh);
5086 enow = e[++eindex];
5087 } else {
5088 Two_Sum(Q, fnow, Qnew, hh);
5089 fnow = f[++findex];
5090 }
5091 Q = Qnew;
5092 if (hh != 0.0) {
5093 h[hindex++] = hh;
5094 }
5095 }
5096 }
5097 while (eindex < elen) {
5098 Two_Sum(Q, enow, Qnew, hh);
5099 enow = e[++eindex];
5100 Q = Qnew;
5101 if (hh != 0.0) {
5102 h[hindex++] = hh;
5103 }
5104 }
5105 while (findex < flen) {
5106 Two_Sum(Q, fnow, Qnew, hh);
5107 fnow = f[++findex];
5108 Q = Qnew;
5109 if (hh != 0.0) {
5110 h[hindex++] = hh;
5111 }
5112 }
5113 if ((Q != 0.0) || (hindex == 0)) {
5114 h[hindex++] = Q;
5115 }
5116 return hindex;
5117}
5118
5119/*****************************************************************************/
5120/* */
5121/* scale_expansion_zeroelim() Multiply an expansion by a scalar, */
5122/* eliminating zero components from the */
5123/* output expansion. */
5124/* */
5125/* Sets h = be. See my Robust Predicates paper for details. */
5126/* */
5127/* Maintains the nonoverlapping property. If round-to-even is used (as */
5128/* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
5129/* properties as well. (That is, if e has one of these properties, so */
5130/* will h.) */
5131/* */
5132/*****************************************************************************/
5133
5134#ifdef ANSI_DECLARATORS
5135int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
5136#else /* not ANSI_DECLARATORS */
5137int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */
5138int elen;
5139REAL *e;
5140REAL b;
5141REAL *h;
5142#endif /* not ANSI_DECLARATORS */
5143
5144{
5145 INEXACT REAL Q, sum;
5146 REAL hh;
5147 INEXACT REAL product1;
5148 REAL product0;
5149 int eindex, hindex;
5150 REAL enow;
5151 INEXACT REAL bvirt;
5152 REAL avirt, bround, around;
5153 INEXACT REAL c;
5154 INEXACT REAL abig;
5155 REAL ahi, alo, bhi, blo;
5156 REAL err1, err2, err3;
5157
5158 Split(b, bhi, blo);
5159 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
5160 hindex = 0;
5161 if (hh != 0) {
5162 h[hindex++] = hh;
5163 }
5164 for (eindex = 1; eindex < elen; eindex++) {
5165 enow = e[eindex];
5166 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
5167 Two_Sum(Q, product0, sum, hh);
5168 if (hh != 0) {
5169 h[hindex++] = hh;
5170 }
5171 Fast_Two_Sum(product1, sum, Q, hh);
5172 if (hh != 0) {
5173 h[hindex++] = hh;
5174 }
5175 }
5176 if ((Q != 0.0) || (hindex == 0)) {
5177 h[hindex++] = Q;
5178 }
5179 return hindex;
5180}
5181
5182/*****************************************************************************/
5183/* */
5184/* estimate() Produce a one-word estimate of an expansion's value. */
5185/* */
5186/* See my Robust Predicates paper for details. */
5187/* */
5188/*****************************************************************************/
5189
5190#ifdef ANSI_DECLARATORS
5191REAL estimate(int elen, REAL *e)
5192#else /* not ANSI_DECLARATORS */
5193REAL estimate(elen, e)
5194int elen;
5195REAL *e;
5196#endif /* not ANSI_DECLARATORS */
5197
5198{
5199 REAL Q;
5200 int eindex;
5201
5202 Q = e[0];
5203 for (eindex = 1; eindex < elen; eindex++) {
5204 Q += e[eindex];
5205 }
5206 return Q;
5207}
5208
5209/*****************************************************************************/
5210/* */
5211/* counterclockwise() Return a positive value if the points pa, pb, and */
5212/* pc occur in counterclockwise order; a negative */
5213/* value if they occur in clockwise order; and zero */
5214/* if they are collinear. The result is also a rough */
5215/* approximation of twice the signed area of the */
5216/* triangle defined by the three points. */
5217/* */
5218/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5219/* result returned is the determinant of a matrix. This determinant is */
5220/* computed adaptively, in the sense that exact arithmetic is used only to */
5221/* the degree it is needed to ensure that the returned value has the */
5222/* correct sign. Hence, this function is usually quite fast, but will run */
5223/* more slowly when the input points are collinear or nearly so. */
5224/* */
5225/* See my Robust Predicates paper for details. */
5226/* */
5227/*****************************************************************************/
5228
5229#ifdef ANSI_DECLARATORS
5230REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
5231#else /* not ANSI_DECLARATORS */
5232REAL counterclockwiseadapt(pa, pb, pc, detsum)
5233vertex pa;
5234vertex pb;
5235vertex pc;
5236REAL detsum;
5237#endif /* not ANSI_DECLARATORS */
5238
5239{
5240 INEXACT REAL acx, acy, bcx, bcy;
5241 REAL acxtail, acytail, bcxtail, bcytail;
5242 INEXACT REAL detleft, detright;
5243 REAL detlefttail, detrighttail;
5244 REAL det, errbound;
5245 REAL B[4], C1[8], C2[12], D[16];
5246 INEXACT REAL B3;
5247 int C1length, C2length, Dlength;
5248 REAL u[4];
5249 INEXACT REAL u3;
5250 INEXACT REAL s1, t1;
5251 REAL s0, t0;
5252
5253 INEXACT REAL bvirt;
5254 REAL avirt, bround, around;
5255 INEXACT REAL c;
5256 INEXACT REAL abig;
5257 REAL ahi, alo, bhi, blo;
5258 REAL err1, err2, err3;
5259 INEXACT REAL _i, _j;
5260 REAL _0;
5261
5262 acx = (REAL) (pa[0] - pc[0]);
5263 bcx = (REAL) (pb[0] - pc[0]);
5264 acy = (REAL) (pa[1] - pc[1]);
5265 bcy = (REAL) (pb[1] - pc[1]);
5266
5267 Two_Product(acx, bcy, detleft, detlefttail);
5268 Two_Product(acy, bcx, detright, detrighttail);
5269
5270 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
5271 B3, B[2], B[1], B[0]);
5272 B[3] = B3;
5273
5274 det = estimate(4, B);
5275 errbound = ccwerrboundB * detsum;
5276 if ((det >= errbound) || (-det >= errbound)) {
5277 return det;
5278 }
5279
5280 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
5281 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
5282 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
5283 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
5284
5285 if ((acxtail == 0.0) && (acytail == 0.0)
5286 && (bcxtail == 0.0) && (bcytail == 0.0)) {
5287 return det;
5288 }
5289
5290 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
5291 det += (acx * bcytail + bcy * acxtail)
5292 - (acy * bcxtail + bcx * acytail);
5293 if ((det >= errbound) || (-det >= errbound)) {
5294 return det;
5295 }
5296
5297 Two_Product(acxtail, bcy, s1, s0);
5298 Two_Product(acytail, bcx, t1, t0);
5299 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5300 u[3] = u3;
5301 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
5302
5303 Two_Product(acx, bcytail, s1, s0);
5304 Two_Product(acy, bcxtail, t1, t0);
5305 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5306 u[3] = u3;
5307 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
5308
5309 Two_Product(acxtail, bcytail, s1, s0);
5310 Two_Product(acytail, bcxtail, t1, t0);
5311 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
5312 u[3] = u3;
5313 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
5314
5315 return(D[Dlength - 1]);
5316}
5317
5318#ifdef ANSI_DECLARATORS
5319REAL counterclockwise(struct mesh *m, struct behavior *b,
5320 vertex pa, vertex pb, vertex pc)
5321#else /* not ANSI_DECLARATORS */
5322REAL counterclockwise(m, b, pa, pb, pc)
5323struct mesh *m;
5324struct behavior *b;
5325vertex pa;
5326vertex pb;
5327vertex pc;
5328#endif /* not ANSI_DECLARATORS */
5329
5330{
5331 REAL detleft, detright, det;
5332 REAL detsum, errbound;
5333
5334 m->counterclockcount++;
5335
5336 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
5337 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
5338 det = detleft - detright;
5339
5340 if (b->noexact) {
5341 return det;
5342 }
5343
5344 if (detleft > 0.0) {
5345 if (detright <= 0.0) {
5346 return det;
5347 } else {
5348 detsum = detleft + detright;
5349 }
5350 } else if (detleft < 0.0) {
5351 if (detright >= 0.0) {
5352 return det;
5353 } else {
5354 detsum = -detleft - detright;
5355 }
5356 } else {
5357 return det;
5358 }
5359
5360 errbound = ccwerrboundA * detsum;
5361 if ((det >= errbound) || (-det >= errbound)) {
5362 return det;
5363 }
5364
5365 return counterclockwiseadapt(pa, pb, pc, detsum);
5366}
5367
5368/*****************************************************************************/
5369/* */
5370/* incircle() Return a positive value if the point pd lies inside the */
5371/* circle passing through pa, pb, and pc; a negative value if */
5372/* it lies outside; and zero if the four points are cocircular.*/
5373/* The points pa, pb, and pc must be in counterclockwise */
5374/* order, or the sign of the result will be reversed. */
5375/* */
5376/* Uses exact arithmetic if necessary to ensure a correct answer. The */
5377/* result returned is the determinant of a matrix. This determinant is */
5378/* computed adaptively, in the sense that exact arithmetic is used only to */
5379/* the degree it is needed to ensure that the returned value has the */
5380/* correct sign. Hence, this function is usually quite fast, but will run */
5381/* more slowly when the input points are cocircular or nearly so. */
5382/* */
5383/* See my Robust Predicates paper for details. */
5384/* */
5385/*****************************************************************************/
5386
5387#ifdef ANSI_DECLARATORS
5388REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
5389#else /* not ANSI_DECLARATORS */
5390REAL incircleadapt(pa, pb, pc, pd, permanent)
5391vertex pa;
5392vertex pb;
5393vertex pc;
5394vertex pd;
5395REAL permanent;
5396#endif /* not ANSI_DECLARATORS */
5397
5398{
5399 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
5400 REAL det, errbound;
5401
5402 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5403 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5404 REAL bc[4], ca[4], ab[4];
5405 INEXACT REAL bc3, ca3, ab3;
5406 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
5407 int axbclen, axxbclen, aybclen, ayybclen, alen;
5408 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
5409 int bxcalen, bxxcalen, bycalen, byycalen, blen;
5410 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
5411 int cxablen, cxxablen, cyablen, cyyablen, clen;
5412 REAL abdet[64];
5413 int ablen;
5414 REAL fin1[1152], fin2[1152];
5415 REAL *finnow, *finother, *finswap;
5416 int finlength;
5417
5418 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
5419 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
5420 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
5421 REAL aa[4], bb[4], cc[4];
5422 INEXACT REAL aa3, bb3, cc3;
5423 INEXACT REAL ti1, tj1;
5424 REAL ti0, tj0;
5425 REAL u[4], v[4];
5426 INEXACT REAL u3, v3;
5427 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
5428 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
5429 int temp8len, temp16alen, temp16blen, temp16clen;
5430 int temp32alen, temp32blen, temp48len, temp64len;
5431 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
5432 int axtbblen, axtcclen, aytbblen, aytcclen;
5433 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
5434 int bxtaalen, bxtcclen, bytaalen, bytcclen;
5435 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
5436 int cxtaalen, cxtbblen, cytaalen, cytbblen;
5437 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
5438 int axtbclen=0, aytbclen=0, bxtcalen=0, bytcalen=0, cxtablen=0, cytablen=0;
5439 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
5440 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
5441 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
5442 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
5443 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
5444 REAL abt[8], bct[8], cat[8];
5445 int abtlen, bctlen, catlen;
5446 REAL abtt[4], bctt[4], catt[4];
5447 int abttlen, bcttlen, cattlen;
5448 INEXACT REAL abtt3, bctt3, catt3;
5449 REAL negate;
5450
5451 INEXACT REAL bvirt;
5452 REAL avirt, bround, around;
5453 INEXACT REAL c;
5454 INEXACT REAL abig;
5455 REAL ahi, alo, bhi, blo;
5456 REAL err1, err2, err3;
5457 INEXACT REAL _i, _j;
5458 REAL _0;
5459
5460 adx = (REAL) (pa[0] - pd[0]);
5461 bdx = (REAL) (pb[0] - pd[0]);
5462 cdx = (REAL) (pc[0] - pd[0]);
5463 ady = (REAL) (pa[1] - pd[1]);
5464 bdy = (REAL) (pb[1] - pd[1]);
5465 cdy = (REAL) (pc[1] - pd[1]);
5466
5467 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
5468 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
5469 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
5470 bc[3] = bc3;
5471 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
5472 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
5473 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
5474 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
5475 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
5476
5477 Two_Product(cdx, ady, cdxady1, cdxady0);
5478 Two_Product(adx, cdy, adxcdy1, adxcdy0);
5479 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
5480 ca[3] = ca3;
5481 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
5482 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
5483 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
5484 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
5485 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
5486
5487 Two_Product(adx, bdy, adxbdy1, adxbdy0);
5488 Two_Product(bdx, ady, bdxady1, bdxady0);
5489 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
5490 ab[3] = ab3;
5491 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
5492 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
5493 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
5494 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
5495 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
5496
5497 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
5498 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
5499
5500 det = estimate(finlength, fin1);
5501 errbound = iccerrboundB * permanent;
5502 if ((det >= errbound) || (-det >= errbound)) {
5503 return det;
5504 }
5505
5506 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
5507 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
5508 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
5509 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
5510 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
5511 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
5512 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
5513 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
5514 return det;
5515 }
5516
5517 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
5518 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
5519 - (bdy * cdxtail + cdx * bdytail))
5520 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
5521 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
5522 - (cdy * adxtail + adx * cdytail))
5523 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
5524 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
5525 - (ady * bdxtail + bdx * adytail))
5526 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
5527 if ((det >= errbound) || (-det >= errbound)) {
5528 return det;
5529 }
5530
5531 finnow = fin1;
5532 finother = fin2;
5533
5534 if ((bdxtail != 0.0) || (bdytail != 0.0)
5535 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5536 Square(adx, adxadx1, adxadx0);
5537 Square(ady, adyady1, adyady0);
5538 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
5539 aa[3] = aa3;
5540 }
5541 if ((cdxtail != 0.0) || (cdytail != 0.0)
5542 || (adxtail != 0.0) || (adytail != 0.0)) {
5543 Square(bdx, bdxbdx1, bdxbdx0);
5544 Square(bdy, bdybdy1, bdybdy0);
5545 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
5546 bb[3] = bb3;
5547 }
5548 if ((adxtail != 0.0) || (adytail != 0.0)
5549 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5550 Square(cdx, cdxcdx1, cdxcdx0);
5551 Square(cdy, cdycdy1, cdycdy0);
5552 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
5553 cc[3] = cc3;
5554 }
5555
5556 if (adxtail != 0.0) {
5557 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
5558 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
5559 temp16a);
5560
5561 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
5562 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
5563
5564 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
5565 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
5566
5567 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5568 temp16blen, temp16b, temp32a);
5569 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5570 temp32alen, temp32a, temp48);
5571 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5572 temp48, finother);
5573 finswap = finnow; finnow = finother; finother = finswap;
5574 }
5575 if (adytail != 0.0) {
5576 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
5577 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
5578 temp16a);
5579
5580 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
5581 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
5582
5583 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
5584 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
5585
5586 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5587 temp16blen, temp16b, temp32a);
5588 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5589 temp32alen, temp32a, temp48);
5590 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5591 temp48, finother);
5592 finswap = finnow; finnow = finother; finother = finswap;
5593 }
5594 if (bdxtail != 0.0) {
5595 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
5596 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
5597 temp16a);
5598
5599 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
5600 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
5601
5602 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
5603 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
5604
5605 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5606 temp16blen, temp16b, temp32a);
5607 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5608 temp32alen, temp32a, temp48);
5609 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5610 temp48, finother);
5611 finswap = finnow; finnow = finother; finother = finswap;
5612 }
5613 if (bdytail != 0.0) {
5614 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
5615 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
5616 temp16a);
5617
5618 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
5619 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
5620
5621 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
5622 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
5623
5624 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5625 temp16blen, temp16b, temp32a);
5626 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5627 temp32alen, temp32a, temp48);
5628 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5629 temp48, finother);
5630 finswap = finnow; finnow = finother; finother = finswap;
5631 }
5632 if (cdxtail != 0.0) {
5633 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
5634 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
5635 temp16a);
5636
5637 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
5638 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
5639
5640 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
5641 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
5642
5643 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5644 temp16blen, temp16b, temp32a);
5645 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5646 temp32alen, temp32a, temp48);
5647 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5648 temp48, finother);
5649 finswap = finnow; finnow = finother; finother = finswap;
5650 }
5651 if (cdytail != 0.0) {
5652 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
5653 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
5654 temp16a);
5655
5656 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
5657 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
5658
5659 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
5660 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
5661
5662 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5663 temp16blen, temp16b, temp32a);
5664 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
5665 temp32alen, temp32a, temp48);
5666 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5667 temp48, finother);
5668 finswap = finnow; finnow = finother; finother = finswap;
5669 }
5670
5671 if ((adxtail != 0.0) || (adytail != 0.0)) {
5672 if ((bdxtail != 0.0) || (bdytail != 0.0)
5673 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5674 Two_Product(bdxtail, cdy, ti1, ti0);
5675 Two_Product(bdx, cdytail, tj1, tj0);
5676 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5677 u[3] = u3;
5678 negate = -bdy;
5679 Two_Product(cdxtail, negate, ti1, ti0);
5680 negate = -bdytail;
5681 Two_Product(cdx, negate, tj1, tj0);
5682 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5683 v[3] = v3;
5684 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
5685
5686 Two_Product(bdxtail, cdytail, ti1, ti0);
5687 Two_Product(cdxtail, bdytail, tj1, tj0);
5688 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
5689 bctt[3] = bctt3;
5690 bcttlen = 4;
5691 } else {
5692 bct[0] = 0.0;
5693 bctlen = 1;
5694 bctt[0] = 0.0;
5695 bcttlen = 1;
5696 }
5697
5698 if (adxtail != 0.0) {
5699 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
5700 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
5701 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
5702 temp32a);
5703 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5704 temp32alen, temp32a, temp48);
5705 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5706 temp48, finother);
5707 finswap = finnow; finnow = finother; finother = finswap;
5708 if (bdytail != 0.0) {
5709 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
5710 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
5711 temp16a);
5712 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5713 temp16a, finother);
5714 finswap = finnow; finnow = finother; finother = finswap;
5715 }
5716 if (cdytail != 0.0) {
5717 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
5718 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
5719 temp16a);
5720 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5721 temp16a, finother);
5722 finswap = finnow; finnow = finother; finother = finswap;
5723 }
5724
5725 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
5726 temp32a);
5727 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
5728 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
5729 temp16a);
5730 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
5731 temp16b);
5732 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5733 temp16blen, temp16b, temp32b);
5734 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5735 temp32blen, temp32b, temp64);
5736 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5737 temp64, finother);
5738 finswap = finnow; finnow = finother; finother = finswap;
5739 }
5740 if (adytail != 0.0) {
5741 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
5742 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
5743 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
5744 temp32a);
5745 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5746 temp32alen, temp32a, temp48);
5747 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5748 temp48, finother);
5749 finswap = finnow; finnow = finother; finother = finswap;
5750
5751
5752 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
5753 temp32a);
5754 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
5755 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
5756 temp16a);
5757 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
5758 temp16b);
5759 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5760 temp16blen, temp16b, temp32b);
5761 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5762 temp32blen, temp32b, temp64);
5763 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5764 temp64, finother);
5765 finswap = finnow; finnow = finother; finother = finswap;
5766 }
5767 }
5768 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
5769 if ((cdxtail != 0.0) || (cdytail != 0.0)
5770 || (adxtail != 0.0) || (adytail != 0.0)) {
5771 Two_Product(cdxtail, ady, ti1, ti0);
5772 Two_Product(cdx, adytail, tj1, tj0);
5773 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5774 u[3] = u3;
5775 negate = -cdy;
5776 Two_Product(adxtail, negate, ti1, ti0);
5777 negate = -cdytail;
5778 Two_Product(adx, negate, tj1, tj0);
5779 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5780 v[3] = v3;
5781 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
5782
5783 Two_Product(cdxtail, adytail, ti1, ti0);
5784 Two_Product(adxtail, cdytail, tj1, tj0);
5785 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
5786 catt[3] = catt3;
5787 cattlen = 4;
5788 } else {
5789 cat[0] = 0.0;
5790 catlen = 1;
5791 catt[0] = 0.0;
5792 cattlen = 1;
5793 }
5794
5795 if (bdxtail != 0.0) {
5796 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
5797 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
5798 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
5799 temp32a);
5800 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5801 temp32alen, temp32a, temp48);
5802 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5803 temp48, finother);
5804 finswap = finnow; finnow = finother; finother = finswap;
5805 if (cdytail != 0.0) {
5806 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
5807 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
5808 temp16a);
5809 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5810 temp16a, finother);
5811 finswap = finnow; finnow = finother; finother = finswap;
5812 }
5813 if (adytail != 0.0) {
5814 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
5815 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
5816 temp16a);
5817 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5818 temp16a, finother);
5819 finswap = finnow; finnow = finother; finother = finswap;
5820 }
5821
5822 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
5823 temp32a);
5824 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
5825 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
5826 temp16a);
5827 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
5828 temp16b);
5829 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5830 temp16blen, temp16b, temp32b);
5831 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5832 temp32blen, temp32b, temp64);
5833 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5834 temp64, finother);
5835 finswap = finnow; finnow = finother; finother = finswap;
5836 }
5837 if (bdytail != 0.0) {
5838 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
5839 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
5840 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
5841 temp32a);
5842 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5843 temp32alen, temp32a, temp48);
5844 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5845 temp48, finother);
5846 finswap = finnow; finnow = finother; finother = finswap;
5847
5848
5849 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
5850 temp32a);
5851 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
5852 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
5853 temp16a);
5854 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
5855 temp16b);
5856 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5857 temp16blen, temp16b, temp32b);
5858 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5859 temp32blen, temp32b, temp64);
5860 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5861 temp64, finother);
5862 finswap = finnow; finnow = finother; finother = finswap;
5863 }
5864 }
5865 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
5866 if ((adxtail != 0.0) || (adytail != 0.0)
5867 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5868 Two_Product(adxtail, bdy, ti1, ti0);
5869 Two_Product(adx, bdytail, tj1, tj0);
5870 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5871 u[3] = u3;
5872 negate = -ady;
5873 Two_Product(bdxtail, negate, ti1, ti0);
5874 negate = -adytail;
5875 Two_Product(bdx, negate, tj1, tj0);
5876 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
5877 v[3] = v3;
5878 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
5879
5880 Two_Product(adxtail, bdytail, ti1, ti0);
5881 Two_Product(bdxtail, adytail, tj1, tj0);
5882 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
5883 abtt[3] = abtt3;
5884 abttlen = 4;
5885 } else {
5886 abt[0] = 0.0;
5887 abtlen = 1;
5888 abtt[0] = 0.0;
5889 abttlen = 1;
5890 }
5891
5892 if (cdxtail != 0.0) {
5893 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
5894 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
5895 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
5896 temp32a);
5897 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5898 temp32alen, temp32a, temp48);
5899 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5900 temp48, finother);
5901 finswap = finnow; finnow = finother; finother = finswap;
5902 if (adytail != 0.0) {
5903 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
5904 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
5905 temp16a);
5906 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5907 temp16a, finother);
5908 finswap = finnow; finnow = finother; finother = finswap;
5909 }
5910 if (bdytail != 0.0) {
5911 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
5912 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
5913 temp16a);
5914 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
5915 temp16a, finother);
5916 finswap = finnow; finnow = finother; finother = finswap;
5917 }
5918
5919 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
5920 temp32a);
5921 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
5922 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
5923 temp16a);
5924 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
5925 temp16b);
5926 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5927 temp16blen, temp16b, temp32b);
5928 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5929 temp32blen, temp32b, temp64);
5930 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5931 temp64, finother);
5932 finswap = finnow; finnow = finother; finother = finswap;
5933 }
5934 if (cdytail != 0.0) {
5935 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
5936 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
5937 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
5938 temp32a);
5939 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5940 temp32alen, temp32a, temp48);
5941 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
5942 temp48, finother);
5943 finswap = finnow; finnow = finother; finother = finswap;
5944
5945
5946 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
5947 temp32a);
5948 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
5949 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
5950 temp16a);
5951 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
5952 temp16b);
5953 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
5954 temp16blen, temp16b, temp32b);
5955 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
5956 temp32blen, temp32b, temp64);
5957 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
5958 temp64, finother);
5959 finswap = finnow; finnow = finother; finother = finswap;
5960 }
5961 }
5962
5963 return finnow[finlength - 1];
5964}
5965
5966#ifdef ANSI_DECLARATORS
5967REAL incircle(struct mesh *m, struct behavior *b,
5968 vertex pa, vertex pb, vertex pc, vertex pd)
5969#else /* not ANSI_DECLARATORS */
5970REAL incircle(m, b, pa, pb, pc, pd)
5971struct mesh *m;
5972struct behavior *b;
5973vertex pa;
5974vertex pb;
5975vertex pc;
5976vertex pd;
5977#endif /* not ANSI_DECLARATORS */
5978
5979{
5980 REAL adx, bdx, cdx, ady, bdy, cdy;
5981 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
5982 REAL alift, blift, clift;
5983 REAL det;
5984 REAL permanent, errbound;
5985
5986 m->incirclecount++;
5987
5988 adx = pa[0] - pd[0];
5989 bdx = pb[0] - pd[0];
5990 cdx = pc[0] - pd[0];
5991 ady = pa[1] - pd[1];
5992 bdy = pb[1] - pd[1];
5993 cdy = pc[1] - pd[1];
5994
5995 bdxcdy = bdx * cdy;
5996 cdxbdy = cdx * bdy;
5997 alift = adx * adx + ady * ady;
5998
5999 cdxady = cdx * ady;
6000 adxcdy = adx * cdy;
6001 blift = bdx * bdx + bdy * bdy;
6002
6003 adxbdy = adx * bdy;
6004 bdxady = bdx * ady;
6005 clift = cdx * cdx + cdy * cdy;
6006
6007 det = alift * (bdxcdy - cdxbdy)
6008 + blift * (cdxady - adxcdy)
6009 + clift * (adxbdy - bdxady);
6010
6011 if (b->noexact) {
6012 return det;
6013 }
6014
6015 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
6016 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
6017 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
6018 errbound = iccerrboundA * permanent;
6019 if ((det > errbound) || (-det > errbound)) {
6020 return det;
6021 }
6022
6023 return incircleadapt(pa, pb, pc, pd, permanent);
6024}
6025
6026/*****************************************************************************/
6027/* */
6028/* orient3d() Return a positive value if the point pd lies below the */
6029/* plane passing through pa, pb, and pc; "below" is defined so */
6030/* that pa, pb, and pc appear in counterclockwise order when */
6031/* viewed from above the plane. Returns a negative value if */
6032/* pd lies above the plane. Returns zero if the points are */
6033/* coplanar. The result is also a rough approximation of six */
6034/* times the signed volume of the tetrahedron defined by the */
6035/* four points. */
6036/* */
6037/* Uses exact arithmetic if necessary to ensure a correct answer. The */
6038/* result returned is the determinant of a matrix. This determinant is */
6039/* computed adaptively, in the sense that exact arithmetic is used only to */
6040/* the degree it is needed to ensure that the returned value has the */
6041/* correct sign. Hence, this function is usually quite fast, but will run */
6042/* more slowly when the input points are coplanar or nearly so. */
6043/* */
6044/* See my Robust Predicates paper for details. */
6045/* */
6046/*****************************************************************************/
6047
6048#ifdef ANSI_DECLARATORS
6049REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
6050 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
6051 REAL permanent)
6052#else /* not ANSI_DECLARATORS */
6053REAL orient3dadapt(pa, pb, pc, pd,
6054 aheight, bheight, cheight, dheight, permanent)
6055vertex pa;
6056vertex pb;
6057vertex pc;
6058vertex pd;
6059REAL aheight;
6060REAL bheight;
6061REAL cheight;
6062REAL dheight;
6063REAL permanent;
6064#endif /* not ANSI_DECLARATORS */
6065
6066{
6067 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6068 REAL det, errbound;
6069
6070 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
6071 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
6072 REAL bc[4], ca[4], ab[4];
6073 INEXACT REAL bc3, ca3, ab3;
6074 REAL adet[8], bdet[8], cdet[8];
6075 int alen, blen, clen;
6076 REAL abdet[16];
6077 int ablen;
6078 REAL *finnow, *finother, *finswap;
6079 REAL fin1[192], fin2[192];
6080 int finlength;
6081
6082 REAL adxtail, bdxtail, cdxtail;
6083 REAL adytail, bdytail, cdytail;
6084 REAL adheighttail, bdheighttail, cdheighttail;
6085 INEXACT REAL at_blarge, at_clarge;
6086 INEXACT REAL bt_clarge, bt_alarge;
6087 INEXACT REAL ct_alarge, ct_blarge;
6088 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
6089 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
6090 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
6091 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
6092 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
6093 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
6094 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
6095 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
6096 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
6097 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
6098 REAL bct[8], cat[8], abt[8];
6099 int bctlen, catlen, abtlen;
6100 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
6101 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
6102 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
6103 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
6104 REAL u[4], v[12], w[16];
6105 INEXACT REAL u3;
6106 int vlength, wlength;
6107 REAL negate;
6108
6109 INEXACT REAL bvirt;
6110 REAL avirt, bround, around;
6111 INEXACT REAL c;
6112 INEXACT REAL abig;
6113 REAL ahi, alo, bhi, blo;
6114 REAL err1, err2, err3;
6115 INEXACT REAL _i, _j, _k;
6116 REAL _0;
6117
6118 adx = (REAL) (pa[0] - pd[0]);
6119 bdx = (REAL) (pb[0] - pd[0]);
6120 cdx = (REAL) (pc[0] - pd[0]);
6121 ady = (REAL) (pa[1] - pd[1]);
6122 bdy = (REAL) (pb[1] - pd[1]);
6123 cdy = (REAL) (pc[1] - pd[1]);
6124 adheight = (REAL) (aheight - dheight);
6125 bdheight = (REAL) (bheight - dheight);
6126 cdheight = (REAL) (cheight - dheight);
6127
6128 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
6129 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
6130 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
6131 bc[3] = bc3;
6132 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
6133
6134 Two_Product(cdx, ady, cdxady1, cdxady0);
6135 Two_Product(adx, cdy, adxcdy1, adxcdy0);
6136 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
6137 ca[3] = ca3;
6138 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
6139
6140 Two_Product(adx, bdy, adxbdy1, adxbdy0);
6141 Two_Product(bdx, ady, bdxady1, bdxady0);
6142 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
6143 ab[3] = ab3;
6144 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
6145
6146 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
6147 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
6148
6149 det = estimate(finlength, fin1);
6150 errbound = o3derrboundB * permanent;
6151 if ((det >= errbound) || (-det >= errbound)) {
6152 return det;
6153 }
6154
6155 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
6156 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
6157 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
6158 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
6159 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
6160 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
6161 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
6162 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
6163 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
6164
6165 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
6166 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
6167 (adheighttail == 0.0) &&
6168 (bdheighttail == 0.0) &&
6169 (cdheighttail == 0.0)) {
6170 return det;
6171 }
6172
6173 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
6174 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
6175 (bdy * cdxtail + cdx * bdytail)) +
6176 adheighttail * (bdx * cdy - bdy * cdx)) +
6177 (bdheight * ((cdx * adytail + ady * cdxtail) -
6178 (cdy * adxtail + adx * cdytail)) +
6179 bdheighttail * (cdx * ady - cdy * adx)) +
6180 (cdheight * ((adx * bdytail + bdy * adxtail) -
6181 (ady * bdxtail + bdx * adytail)) +
6182 cdheighttail * (adx * bdy - ady * bdx));
6183 if ((det >= errbound) || (-det >= errbound)) {
6184 return det;
6185 }
6186
6187 finnow = fin1;
6188 finother = fin2;
6189
6190 if (adxtail == 0.0) {
6191 if (adytail == 0.0) {
6192 at_b[0] = 0.0;
6193 at_blen = 1;
6194 at_c[0] = 0.0;
6195 at_clen = 1;
6196 } else {
6197 negate = -adytail;
6198 Two_Product(negate, bdx, at_blarge, at_b[0]);
6199 at_b[1] = at_blarge;
6200 at_blen = 2;
6201 Two_Product(adytail, cdx, at_clarge, at_c[0]);
6202 at_c[1] = at_clarge;
6203 at_clen = 2;
6204 }
6205 } else {
6206 if (adytail == 0.0) {
6207 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
6208 at_b[1] = at_blarge;
6209 at_blen = 2;
6210 negate = -adxtail;
6211 Two_Product(negate, cdy, at_clarge, at_c[0]);
6212 at_c[1] = at_clarge;
6213 at_clen = 2;
6214 } else {
6215 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
6216 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
6217 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
6218 at_blarge, at_b[2], at_b[1], at_b[0]);
6219 at_b[3] = at_blarge;
6220 at_blen = 4;
6221 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
6222 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
6223 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
6224 at_clarge, at_c[2], at_c[1], at_c[0]);
6225 at_c[3] = at_clarge;
6226 at_clen = 4;
6227 }
6228 }
6229 if (bdxtail == 0.0) {
6230 if (bdytail == 0.0) {
6231 bt_c[0] = 0.0;
6232 bt_clen = 1;
6233 bt_a[0] = 0.0;
6234 bt_alen = 1;
6235 } else {
6236 negate = -bdytail;
6237 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
6238 bt_c[1] = bt_clarge;
6239 bt_clen = 2;
6240 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
6241 bt_a[1] = bt_alarge;
6242 bt_alen = 2;
6243 }
6244 } else {
6245 if (bdytail == 0.0) {
6246 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
6247 bt_c[1] = bt_clarge;
6248 bt_clen = 2;
6249 negate = -bdxtail;
6250 Two_Product(negate, ady, bt_alarge, bt_a[0]);
6251 bt_a[1] = bt_alarge;
6252 bt_alen = 2;
6253 } else {
6254 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
6255 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
6256 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
6257 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
6258 bt_c[3] = bt_clarge;
6259 bt_clen = 4;
6260 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
6261 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
6262 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
6263 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
6264 bt_a[3] = bt_alarge;
6265 bt_alen = 4;
6266 }
6267 }
6268 if (cdxtail == 0.0) {
6269 if (cdytail == 0.0) {
6270 ct_a[0] = 0.0;
6271 ct_alen = 1;
6272 ct_b[0] = 0.0;
6273 ct_blen = 1;
6274 } else {
6275 negate = -cdytail;
6276 Two_Product(negate, adx, ct_alarge, ct_a[0]);
6277 ct_a[1] = ct_alarge;
6278 ct_alen = 2;
6279 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
6280 ct_b[1] = ct_blarge;
6281 ct_blen = 2;
6282 }
6283 } else {
6284 if (cdytail == 0.0) {
6285 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
6286 ct_a[1] = ct_alarge;
6287 ct_alen = 2;
6288 negate = -cdxtail;
6289 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
6290 ct_b[1] = ct_blarge;
6291 ct_blen = 2;
6292 } else {
6293 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
6294 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
6295 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
6296 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
6297 ct_a[3] = ct_alarge;
6298 ct_alen = 4;
6299 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
6300 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
6301 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
6302 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
6303 ct_b[3] = ct_blarge;
6304 ct_blen = 4;
6305 }
6306 }
6307
6308 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
6309 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
6310 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6311 finother);
6312 finswap = finnow; finnow = finother; finother = finswap;
6313
6314 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
6315 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
6316 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6317 finother);
6318 finswap = finnow; finnow = finother; finother = finswap;
6319
6320 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
6321 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
6322 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6323 finother);
6324 finswap = finnow; finnow = finother; finother = finswap;
6325
6326 if (adheighttail != 0.0) {
6327 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
6328 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6329 finother);
6330 finswap = finnow; finnow = finother; finother = finswap;
6331 }
6332 if (bdheighttail != 0.0) {
6333 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
6334 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6335 finother);
6336 finswap = finnow; finnow = finother; finother = finswap;
6337 }
6338 if (cdheighttail != 0.0) {
6339 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
6340 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
6341 finother);
6342 finswap = finnow; finnow = finother; finother = finswap;
6343 }
6344
6345 if (adxtail != 0.0) {
6346 if (bdytail != 0.0) {
6347 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
6348 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
6349 u[3] = u3;
6350 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6351 finother);
6352 finswap = finnow; finnow = finother; finother = finswap;
6353 if (cdheighttail != 0.0) {
6354 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
6355 u3, u[2], u[1], u[0]);
6356 u[3] = u3;
6357 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6358 finother);
6359 finswap = finnow; finnow = finother; finother = finswap;
6360 }
6361 }
6362 if (cdytail != 0.0) {
6363 negate = -adxtail;
6364 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
6365 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
6366 u[3] = u3;
6367 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6368 finother);
6369 finswap = finnow; finnow = finother; finother = finswap;
6370 if (bdheighttail != 0.0) {
6371 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
6372 u3, u[2], u[1], u[0]);
6373 u[3] = u3;
6374 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6375 finother);
6376 finswap = finnow; finnow = finother; finother = finswap;
6377 }
6378 }
6379 }
6380 if (bdxtail != 0.0) {
6381 if (cdytail != 0.0) {
6382 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
6383 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
6384 u[3] = u3;
6385 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6386 finother);
6387 finswap = finnow; finnow = finother; finother = finswap;
6388 if (adheighttail != 0.0) {
6389 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
6390 u3, u[2], u[1], u[0]);
6391 u[3] = u3;
6392 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6393 finother);
6394 finswap = finnow; finnow = finother; finother = finswap;
6395 }
6396 }
6397 if (adytail != 0.0) {
6398 negate = -bdxtail;
6399 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
6400 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
6401 u[3] = u3;
6402 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6403 finother);
6404 finswap = finnow; finnow = finother; finother = finswap;
6405 if (cdheighttail != 0.0) {
6406 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
6407 u3, u[2], u[1], u[0]);
6408 u[3] = u3;
6409 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6410 finother);
6411 finswap = finnow; finnow = finother; finother = finswap;
6412 }
6413 }
6414 }
6415 if (cdxtail != 0.0) {
6416 if (adytail != 0.0) {
6417 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
6418 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
6419 u[3] = u3;
6420 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6421 finother);
6422 finswap = finnow; finnow = finother; finother = finswap;
6423 if (bdheighttail != 0.0) {
6424 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
6425 u3, u[2], u[1], u[0]);
6426 u[3] = u3;
6427 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6428 finother);
6429 finswap = finnow; finnow = finother; finother = finswap;
6430 }
6431 }
6432 if (bdytail != 0.0) {
6433 negate = -cdxtail;
6434 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
6435 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
6436 u[3] = u3;
6437 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6438 finother);
6439 finswap = finnow; finnow = finother; finother = finswap;
6440 if (adheighttail != 0.0) {
6441 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
6442 u3, u[2], u[1], u[0]);
6443 u[3] = u3;
6444 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
6445 finother);
6446 finswap = finnow; finnow = finother; finother = finswap;
6447 }
6448 }
6449 }
6450
6451 if (adheighttail != 0.0) {
6452 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
6453 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6454 finother);
6455 finswap = finnow; finnow = finother; finother = finswap;
6456 }
6457 if (bdheighttail != 0.0) {
6458 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
6459 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6460 finother);
6461 finswap = finnow; finnow = finother; finother = finswap;
6462 }
6463 if (cdheighttail != 0.0) {
6464 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
6465 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
6466 finother);
6467 finswap = finnow; finnow = finother; finother = finswap;
6468 }
6469
6470 return finnow[finlength - 1];
6471}
6472
6473#ifdef ANSI_DECLARATORS
6474REAL orient3d(struct mesh *m, struct behavior *b,
6475 vertex pa, vertex pb, vertex pc, vertex pd,
6476 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
6477#else /* not ANSI_DECLARATORS */
6478REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
6479struct mesh *m;
6480struct behavior *b;
6481vertex pa;
6482vertex pb;
6483vertex pc;
6484vertex pd;
6485REAL aheight;
6486REAL bheight;
6487REAL cheight;
6488REAL dheight;
6489#endif /* not ANSI_DECLARATORS */
6490
6491{
6492 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6493 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
6494 REAL det;
6495 REAL permanent, errbound;
6496
6497 m->orient3dcount++;
6498
6499 adx = pa[0] - pd[0];
6500 bdx = pb[0] - pd[0];
6501 cdx = pc[0] - pd[0];
6502 ady = pa[1] - pd[1];
6503 bdy = pb[1] - pd[1];
6504 cdy = pc[1] - pd[1];
6505 adheight = aheight - dheight;
6506 bdheight = bheight - dheight;
6507 cdheight = cheight - dheight;
6508
6509 bdxcdy = bdx * cdy;
6510 cdxbdy = cdx * bdy;
6511
6512 cdxady = cdx * ady;
6513 adxcdy = adx * cdy;
6514
6515 adxbdy = adx * bdy;
6516 bdxady = bdx * ady;
6517
6518 det = adheight * (bdxcdy - cdxbdy)
6519 + bdheight * (cdxady - adxcdy)
6520 + cdheight * (adxbdy - bdxady);
6521
6522 if (b->noexact) {
6523 return det;
6524 }
6525
6526 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
6527 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
6528 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
6529 errbound = o3derrboundA * permanent;
6530 if ((det > errbound) || (-det > errbound)) {
6531 return det;
6532 }
6533
6534 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
6535 permanent);
6536}
6537
6538/*****************************************************************************/
6539/* */
6540/* nonregular() Return a positive value if the point pd is incompatible */
6541/* with the circle or plane passing through pa, pb, and pc */
6542/* (meaning that pd is inside the circle or below the */
6543/* plane); a negative value if it is compatible; and zero if */
6544/* the four points are cocircular/coplanar. The points pa, */
6545/* pb, and pc must be in counterclockwise order, or the sign */
6546/* of the result will be reversed. */
6547/* */
6548/* If the -w switch is used, the points are lifted onto the parabolic */
6549/* lifting map, then they are dropped according to their weights, then the */
6550/* 3D orientation test is applied. If the -W switch is used, the points' */
6551/* heights are already provided, so the 3D orientation test is applied */
6552/* directly. If neither switch is used, the incircle test is applied. */
6553/* */
6554/*****************************************************************************/
6555
6556#ifdef ANSI_DECLARATORS
6557REAL nonregular(struct mesh *m, struct behavior *b,
6558 vertex pa, vertex pb, vertex pc, vertex pd)
6559#else /* not ANSI_DECLARATORS */
6560REAL nonregular(m, b, pa, pb, pc, pd)
6561struct mesh *m;
6562struct behavior *b;
6563vertex pa;
6564vertex pb;
6565vertex pc;
6566vertex pd;
6567#endif /* not ANSI_DECLARATORS */
6568
6569{
6570 if (b->weighted == 0) {
6571 return incircle(m, b, pa, pb, pc, pd);
6572 } else if (b->weighted == 1) {
6573 return orient3d(m, b, pa, pb, pc, pd,
6574 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
6575 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
6576 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
6577 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
6578 } else {
6579 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
6580 }
6581}
6582
6583/*****************************************************************************/
6584/* */
6585/* findcircumcenter() Find the circumcenter of a triangle. */
6586/* */
6587/* The result is returned both in terms of x-y coordinates and xi-eta */
6588/* (barycentric) coordinates. The xi-eta coordinate system is defined in */
6589/* terms of the triangle: the origin of the triangle is the origin of the */
6590/* coordinate system; the destination of the triangle is one unit along the */
6591/* xi axis; and the apex of the triangle is one unit along the eta axis. */
6592/* This procedure also returns the square of the length of the triangle's */
6593/* shortest edge. */
6594/* */
6595/*****************************************************************************/
6596
6597#ifdef ANSI_DECLARATORS
6598void findcircumcenter(struct mesh *m, struct behavior *b,
6599 vertex torg, vertex tdest, vertex tapex,
6600 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
6601#else /* not ANSI_DECLARATORS */
6602void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
6603 offcenter)
6604struct mesh *m;
6605struct behavior *b;
6606vertex torg;
6607vertex tdest;
6608vertex tapex;
6609vertex circumcenter;
6610REAL *xi;
6611REAL *eta;
6612int offcenter;
6613#endif /* not ANSI_DECLARATORS */
6614
6615{
6616 REAL xdo, ydo, xao, yao;
6617 REAL dodist, aodist, dadist;
6618 REAL denominator;
6619 REAL dx, dy, dxoff, dyoff;
6620
6621 m->circumcentercount++;
6622
6623 /* Compute the circumcenter of the triangle. */
6624 xdo = tdest[0] - torg[0];
6625 ydo = tdest[1] - torg[1];
6626 xao = tapex[0] - torg[0];
6627 yao = tapex[1] - torg[1];
6628 dodist = xdo * xdo + ydo * ydo;
6629 aodist = xao * xao + yao * yao;
6630 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
6631 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
6632 if (b->noexact) {
6633 denominator = 0.5 / (xdo * yao - xao * ydo);
6634 } else {
6635 /* Use the counterclockwise() routine to ensure a positive (and */
6636 /* reasonably accurate) result, avoiding any possibility of */
6637 /* division by zero. */
6638 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
6639 /* Don't count the above as an orientation test. */
6640 m->counterclockcount--;
6641 }
6642 dx = (yao * dodist - ydo * aodist) * denominator;
6643 dy = (xdo * aodist - xao * dodist) * denominator;
6644
6645 /* Find the (squared) length of the triangle's shortest edge. This */
6646 /* serves as a conservative estimate of the insertion radius of the */
6647 /* circumcenter's parent. The estimate is used to ensure that */
6648 /* the algorithm terminates even if very small angles appear in */
6649 /* the input PSLG. */
6650 if ((dodist < aodist) && (dodist < dadist)) {
6651 if (offcenter && (b->offconstant > 0.0)) {
6652 /* Find the position of the off-center, as described by Alper Ungor. */
6653 dxoff = 0.5 * xdo - b->offconstant * ydo;
6654 dyoff = 0.5 * ydo + b->offconstant * xdo;
6655 /* If the off-center is closer to the origin than the */
6656 /* circumcenter, use the off-center instead. */
6657 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6658 dx = dxoff;
6659 dy = dyoff;
6660 }
6661 }
6662 } else if (aodist < dadist) {
6663 if (offcenter && (b->offconstant > 0.0)) {
6664 dxoff = 0.5 * xao + b->offconstant * yao;
6665 dyoff = 0.5 * yao - b->offconstant * xao;
6666 /* If the off-center is closer to the origin than the */
6667 /* circumcenter, use the off-center instead. */
6668 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6669 dx = dxoff;
6670 dy = dyoff;
6671 }
6672 }
6673 } else {
6674 if (offcenter && (b->offconstant > 0.0)) {
6675 dxoff = 0.5 * (tapex[0] - tdest[0]) -
6676 b->offconstant * (tapex[1] - tdest[1]);
6677 dyoff = 0.5 * (tapex[1] - tdest[1]) +
6678 b->offconstant * (tapex[0] - tdest[0]);
6679 /* If the off-center is closer to the destination than the */
6680 /* circumcenter, use the off-center instead. */
6681 if (dxoff * dxoff + dyoff * dyoff <
6682 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
6683 dx = xdo + dxoff;
6684 dy = ydo + dyoff;
6685 }
6686 }
6687 }
6688
6689 circumcenter[0] = torg[0] + dx;
6690 circumcenter[1] = torg[1] + dy;
6691
6692 /* To interpolate vertex attributes for the new vertex inserted at */
6693 /* the circumcenter, define a coordinate system with a xi-axis, */
6694 /* directed from the triangle's origin to its destination, and */
6695 /* an eta-axis, directed from its origin to its apex. */
6696 /* Calculate the xi and eta coordinates of the circumcenter. */
6697 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
6698 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
6699}
6700
6703/********* Geometric primitives end here *********/
6704
6705/*****************************************************************************/
6706/* */
6707/* triangleinit() Initialize some variables. */
6708/* */
6709/*****************************************************************************/
6710
6711#ifdef ANSI_DECLARATORS
6712void triangleinit(struct mesh *m)
6713#else /* not ANSI_DECLARATORS */
6714void triangleinit(m)
6715struct mesh *m;
6716#endif /* not ANSI_DECLARATORS */
6717
6718{
6719 poolzero(&m->vertices);
6720 poolzero(&m->triangles);
6721 poolzero(&m->subsegs);
6722 poolzero(&m->viri);
6723 poolzero(&m->badsubsegs);
6724 poolzero(&m->badtriangles);
6725 poolzero(&m->flipstackers);
6726 poolzero(&m->splaynodes);
6727
6728 m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */
6729 m->undeads = 0; /* No eliminated input vertices yet. */
6730 m->samples = 1; /* Point location should take at least one sample. */
6731 m->checksegments = 0; /* There are no segments in the triangulation yet. */
6732 m->checkquality = 0; /* The quality triangulation stage has not begun. */
6733 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
6734 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
6735 randomseed = 1;
6736
6737 exactinit(); /* Initialize exact arithmetic constants. */
6738}
6739
6740/*****************************************************************************/
6741/* */
6742/* randomnation() Generate a random number between 0 and `choices' - 1. */
6743/* */
6744/* This is a simple linear congruential random number generator. Hence, it */
6745/* is a bad random number generator, but good enough for most randomized */
6746/* geometric algorithms. */
6747/* */
6748/*****************************************************************************/
6749
6750#ifdef ANSI_DECLARATORS
6751unsigned long randomnation(unsigned int choices)
6752#else /* not ANSI_DECLARATORS */
6753unsigned long randomnation(choices)
6754unsigned int choices;
6755#endif /* not ANSI_DECLARATORS */
6756
6757{
6758 randomseed = (randomseed * 1366l + 150889l) % 714025l;
6759 return randomseed / (714025l / choices + 1);
6760}
6761
6762/********* Mesh quality testing routines begin here *********/
6766/*****************************************************************************/
6767/* */
6768/* checkmesh() Test the mesh for topological consistency. */
6769/* */
6770/*****************************************************************************/
6771
6772#ifndef REDUCED
6773
6774#ifdef ANSI_DECLARATORS
6775void checkmesh(struct mesh *m, struct behavior *b)
6776#else /* not ANSI_DECLARATORS */
6777void checkmesh(m, b)
6778struct mesh *m;
6779struct behavior *b;
6780#endif /* not ANSI_DECLARATORS */
6781
6782{
6783 struct otri triangleloop;
6784 struct otri oppotri, oppooppotri;
6785 vertex triorg, tridest, triapex;
6786 vertex oppoorg, oppodest;
6787 int horrors;
6788 int saveexact;
6789 triangle ptr; /* Temporary variable used by sym(). */
6790
6791 /* Temporarily turn on exact arithmetic if it's off. */
6792 saveexact = b->noexact;
6793 b->noexact = 0;
6794 if (!b->quiet) {
6795 printf(" Checking consistency of mesh...\n");
6796 }
6797 horrors = 0;
6798 /* Run through the list of triangles, checking each one. */
6799 traversalinit(&m->triangles);
6800 triangleloop.tri = triangletraverse(m);
6801 while (triangleloop.tri != (triangle *) NULL) {
6802 /* Check all three edges of the triangle. */
6803 for (triangleloop.orient = 0; triangleloop.orient < 3;
6804 triangleloop.orient++) {
6805 org(triangleloop, triorg);
6806 dest(triangleloop, tridest);
6807 if (triangleloop.orient == 0) { /* Only test for inversion once. */
6808 /* Test if the triangle is flat or inverted. */
6809 apex(triangleloop, triapex);
6810 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
6811 printf(" !! !! Inverted ");
6812 printtriangle(m, b, &triangleloop);
6813 horrors++;
6814 }
6815 }
6816 /* Find the neighboring triangle on this edge. */
6817 sym(triangleloop, oppotri);
6818 if (oppotri.tri != m->dummytri) {
6819 /* Check that the triangle's neighbor knows it's a neighbor. */
6820 sym(oppotri, oppooppotri);
6821 if ((triangleloop.tri != oppooppotri.tri)
6822 || (triangleloop.orient != oppooppotri.orient)) {
6823 printf(" !! !! Asymmetric triangle-triangle bond:\n");
6824 if (triangleloop.tri == oppooppotri.tri) {
6825 printf(" (Right triangle, wrong orientation)\n");
6826 }
6827 printf(" First ");
6828 printtriangle(m, b, &triangleloop);
6829 printf(" Second (nonreciprocating) ");
6830 printtriangle(m, b, &oppotri);
6831 horrors++;
6832 }
6833 /* Check that both triangles agree on the identities */
6834 /* of their shared vertices. */
6835 org(oppotri, oppoorg);
6836 dest(oppotri, oppodest);
6837 if ((triorg != oppodest) || (tridest != oppoorg)) {
6838 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
6839 );
6840 printf(" First mismatched ");
6841 printtriangle(m, b, &triangleloop);
6842 printf(" Second mismatched ");
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(" In my studied opinion, the mesh appears to be consistent.\n");
6853 }
6854 } else if (horrors == 1) {
6855 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
6856 } else {
6857 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
6858 }
6859 /* Restore the status of exact arithmetic. */
6860 b->noexact = saveexact;
6861}
6862
6863#endif /* not REDUCED */
6864
6865/*****************************************************************************/
6866/* */
6867/* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */
6868/* */
6869/*****************************************************************************/
6870
6871#ifndef REDUCED
6872
6873#ifdef ANSI_DECLARATORS
6874void checkdelaunay(struct mesh *m, struct behavior *b)
6875#else /* not ANSI_DECLARATORS */
6876void checkdelaunay(m, b)
6877struct mesh *m;
6878struct behavior *b;
6879#endif /* not ANSI_DECLARATORS */
6880
6881{
6882 struct otri triangleloop;
6883 struct otri oppotri;
6884 struct osub opposubseg;
6885 vertex triorg, tridest, triapex;
6886 vertex oppoapex;
6887 int shouldbedelaunay;
6888 int horrors;
6889 int saveexact;
6890 triangle ptr; /* Temporary variable used by sym(). */
6891 subseg sptr; /* Temporary variable used by tspivot(). */
6892
6893 /* Temporarily turn on exact arithmetic if it's off. */
6894 saveexact = b->noexact;
6895 b->noexact = 0;
6896 if (!b->quiet) {
6897 printf(" Checking Delaunay property of mesh...\n");
6898 }
6899 horrors = 0;
6900 /* Run through the list of triangles, checking each one. */
6901 traversalinit(&m->triangles);
6902 triangleloop.tri = triangletraverse(m);
6903 while (triangleloop.tri != (triangle *) NULL) {
6904 /* Check all three edges of the triangle. */
6905 for (triangleloop.orient = 0; triangleloop.orient < 3;
6906 triangleloop.orient++) {
6907 org(triangleloop, triorg);
6908 dest(triangleloop, tridest);
6909 apex(triangleloop, triapex);
6910 sym(triangleloop, oppotri);
6911 apex(oppotri, oppoapex);
6912 /* Only test that the edge is locally Delaunay if there is an */
6913 /* adjoining triangle whose pointer is larger (to ensure that */
6914 /* each pair isn't tested twice). */
6915 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
6916 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
6917 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
6918 (triorg != m->infvertex3) &&
6919 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
6920 (tridest != m->infvertex3) &&
6921 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
6922 (triapex != m->infvertex3) &&
6923 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
6924 (oppoapex != m->infvertex3);
6925 if (m->checksegments && shouldbedelaunay) {
6926 /* If a subsegment separates the triangles, then the edge is */
6927 /* constrained, so no local Delaunay test should be done. */
6928 tspivot(triangleloop, opposubseg);
6929 if (opposubseg.ss != m->dummysub){
6930 shouldbedelaunay = 0;
6931 }
6932 }
6933 if (shouldbedelaunay) {
6934 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
6935 if (!b->weighted) {
6936 printf(" !! !! Non-Delaunay pair of triangles:\n");
6937 printf(" First non-Delaunay ");
6938 printtriangle(m, b, &triangleloop);
6939 printf(" Second non-Delaunay ");
6940 } else {
6941 printf(" !! !! Non-regular pair of triangles:\n");
6942 printf(" First non-regular ");
6943 printtriangle(m, b, &triangleloop);
6944 printf(" Second non-regular ");
6945 }
6946 printtriangle(m, b, &oppotri);
6947 horrors++;
6948 }
6949 }
6950 }
6951 triangleloop.tri = triangletraverse(m);
6952 }
6953 if (horrors == 0) {
6954 if (!b->quiet) {
6955 printf(
6956 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
6957 }
6958 } else if (horrors == 1) {
6959 printf(
6960 " !! !! !! !! Precisely one terrifying transgression identified.\n");
6961 } else {
6962 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
6963 }
6964 /* Restore the status of exact arithmetic. */
6965 b->noexact = saveexact;
6966}
6967
6968#endif /* not REDUCED */
6969
6970/*****************************************************************************/
6971/* */
6972/* enqueuebadtriang() Add a bad triangle data structure to the end of a */
6973/* queue. */
6974/* */
6975/* The queue is actually a set of 4096 queues. I use multiple queues to */
6976/* give priority to smaller angles. I originally implemented a heap, but */
6977/* the queues are faster by a larger margin than I'd suspected. */
6978/* */
6979/*****************************************************************************/
6980
6981#ifndef CDT_ONLY
6982
6983#ifdef ANSI_DECLARATORS
6984void enqueuebadtriang(struct mesh *m, struct behavior *b,
6985 struct badtriang *badtri)
6986#else /* not ANSI_DECLARATORS */
6987void enqueuebadtriang(m, b, badtri)
6988struct mesh *m;
6989struct behavior *b;
6990struct badtriang *badtri;
6991#endif /* not ANSI_DECLARATORS */
6992
6993{
6994 REAL length, multiplier;
6995 int exponent, expincrement;
6996 int queuenumber;
6997 int posexponent;
6998 int i;
6999
7000 if (b->verbose > 2) {
7001 printf(" Queueing bad triangle:\n");
7002 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7003 badtri->triangorg[0], badtri->triangorg[1],
7004 badtri->triangdest[0], badtri->triangdest[1],
7005 badtri->triangapex[0], badtri->triangapex[1]);
7006 }
7007
7008 /* Determine the appropriate queue to put the bad triangle into. */
7009 /* Recall that the key is the square of its shortest edge length. */
7010 if (badtri->key >= 1.0) {
7011 length = badtri->key;
7012 posexponent = 1;
7013 } else {
7014 /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */
7015 /* fact and use the reciprocal of `badtri->key', which is > 1.0. */
7016 length = 1.0 / badtri->key;
7017 posexponent = 0;
7018 }
7019 /* `length' is approximately 2.0 to what exponent? The following code */
7020 /* determines the answer in time logarithmic in the exponent. */
7021 exponent = 0;
7022 while (length > 2.0) {
7023 /* Find an approximation by repeated squaring of two. */
7024 expincrement = 1;
7025 multiplier = 0.5;
7026 while (length * multiplier * multiplier > 1.0) {
7027 expincrement *= 2;
7028 multiplier *= multiplier;
7029 }
7030 /* Reduce the value of `length', then iterate if necessary. */
7031 exponent += expincrement;
7032 length *= multiplier;
7033 }
7034 /* `length' is approximately squareroot(2.0) to what exponent? */
7035 exponent = 2 * exponent + (length > SQUAREROOTTWO);
7036 /* `exponent' is now in the range 0...2047 for IEEE double precision. */
7037 /* Choose a queue in the range 0...4095. The shortest edges have the */
7038 /* highest priority (queue 4095). */
7039 if (posexponent) {
7040 queuenumber = 2047 - exponent;
7041 } else {
7042 queuenumber = 2048 + exponent;
7043 }
7044
7045 /* Are we inserting into an empty queue? */
7046 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
7047 /* Yes, we are inserting into an empty queue. */
7048 /* Will this become the highest-priority queue? */
7049 if (queuenumber > m->firstnonemptyq) {
7050 /* Yes, this is the highest-priority queue. */
7051 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
7052 m->firstnonemptyq = queuenumber;
7053 } else {
7054 /* No, this is not the highest-priority queue. */
7055 /* Find the queue with next higher priority. */
7056 i = queuenumber + 1;
7057 while (m->queuefront[i] == (struct badtriang *) NULL) {
7058 i++;
7059 }
7060 /* Mark the newly nonempty queue as following a higher-priority queue. */
7061 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
7062 m->nextnonemptyq[i] = queuenumber;
7063 }
7064 /* Put the bad triangle at the beginning of the (empty) queue. */
7065 m->queuefront[queuenumber] = badtri;
7066 } else {
7067 /* Add the bad triangle to the end of an already nonempty queue. */
7068 m->queuetail[queuenumber]->nexttriang = badtri;
7069 }
7070 /* Maintain a pointer to the last triangle of the queue. */
7071 m->queuetail[queuenumber] = badtri;
7072 /* Newly enqueued bad triangle has no successor in the queue. */
7073 badtri->nexttriang = (struct badtriang *) NULL;
7074}
7075
7076#endif /* not CDT_ONLY */
7077
7078/*****************************************************************************/
7079/* */
7080/* enqueuebadtri() Add a bad triangle to the end of a queue. */
7081/* */
7082/* Allocates a badtriang data structure for the triangle, then passes it to */
7083/* enqueuebadtriang(). */
7084/* */
7085/*****************************************************************************/
7086
7087#ifndef CDT_ONLY
7088
7089#ifdef ANSI_DECLARATORS
7090void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
7091 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
7092#else /* not ANSI_DECLARATORS */
7093void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
7094struct mesh *m;
7095struct behavior *b;
7096struct otri *enqtri;
7097REAL minedge;
7098vertex enqapex;
7099vertex enqorg;
7100vertex enqdest;
7101#endif /* not ANSI_DECLARATORS */
7102
7103{
7104 struct badtriang *newbad;
7105
7106 /* Allocate space for the bad triangle. */
7107 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
7108 newbad->poortri = encode(*enqtri);
7109 newbad->key = minedge;
7110 newbad->triangapex = enqapex;
7111 newbad->triangorg = enqorg;
7112 newbad->triangdest = enqdest;
7113 enqueuebadtriang(m, b, newbad);
7114}
7115
7116#endif /* not CDT_ONLY */
7117
7118/*****************************************************************************/
7119/* */
7120/* dequeuebadtriang() Remove a triangle from the front of the queue. */
7121/* */
7122/*****************************************************************************/
7123
7124#ifndef CDT_ONLY
7125
7126#ifdef ANSI_DECLARATORS
7127struct badtriang *dequeuebadtriang(struct mesh *m)
7128#else /* not ANSI_DECLARATORS */
7129struct badtriang *dequeuebadtriang(m)
7130struct mesh *m;
7131#endif /* not ANSI_DECLARATORS */
7132
7133{
7134 struct badtriang *result;
7135
7136 /* If no queues are nonempty, return NULL. */
7137 if (m->firstnonemptyq < 0) {
7138 return (struct badtriang *) NULL;
7139 }
7140 /* Find the first triangle of the highest-priority queue. */
7141 result = m->queuefront[m->firstnonemptyq];
7142 /* Remove the triangle from the queue. */
7143 m->queuefront[m->firstnonemptyq] = result->nexttriang;
7144 /* If this queue is now empty, note the new highest-priority */
7145 /* nonempty queue. */
7146 if (result == m->queuetail[m->firstnonemptyq]) {
7147 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
7148 }
7149 return result;
7150}
7151
7152#endif /* not CDT_ONLY */
7153
7154/*****************************************************************************/
7155/* */
7156/* checkseg4encroach() Check a subsegment to see if it is encroached; add */
7157/* it to the list if it is. */
7158/* */
7159/* A subsegment is encroached if there is a vertex in its diametral lens. */
7160/* For Ruppert's algorithm (-D switch), the "diametral lens" is the */
7161/* diametral circle. For Chew's algorithm (default), the diametral lens is */
7162/* just big enough to enclose two isosceles triangles whose bases are the */
7163/* subsegment. Each of the two isosceles triangles has two angles equal */
7164/* to `b->minangle'. */
7165/* */
7166/* Chew's algorithm does not require diametral lenses at all--but they save */
7167/* time. Any vertex inside a subsegment's diametral lens implies that the */
7168/* triangle adjoining the subsegment will be too skinny, so it's only a */
7169/* matter of time before the encroaching vertex is deleted by Chew's */
7170/* algorithm. It's faster to simply not insert the doomed vertex in the */
7171/* first place, which is why I use diametral lenses with Chew's algorithm. */
7172/* */
7173/* Returns a nonzero value if the subsegment is encroached. */
7174/* */
7175/*****************************************************************************/
7176
7177#ifndef CDT_ONLY
7178
7179#ifdef ANSI_DECLARATORS
7180int checkseg4encroach(struct mesh *m, struct behavior *b,
7181 struct osub *testsubseg)
7182#else /* not ANSI_DECLARATORS */
7183int checkseg4encroach(m, b, testsubseg)
7184struct mesh *m;
7185struct behavior *b;
7186struct osub *testsubseg;
7187#endif /* not ANSI_DECLARATORS */
7188
7189{
7190 struct otri neighbortri;
7191 struct osub testsym;
7192 struct badsubseg *encroachedseg;
7193 REAL dotproduct;
7194 int encroached;
7195 int sides;
7196 vertex eorg, edest, eapex;
7197 triangle ptr; /* Temporary variable used by stpivot(). */
7198
7199 encroached = 0;
7200 sides = 0;
7201
7202 sorg(*testsubseg, eorg);
7203 sdest(*testsubseg, edest);
7204 /* Check one neighbor of the subsegment. */
7205 stpivot(*testsubseg, neighbortri);
7206 /* Does the neighbor exist, or is this a boundary edge? */
7207 if (neighbortri.tri != m->dummytri) {
7208 sides++;
7209 /* Find a vertex opposite this subsegment. */
7210 apex(neighbortri, eapex);
7211 /* Check whether the apex is in the diametral lens of the subsegment */
7212 /* (the diametral circle if `conformdel' is set). A dot product */
7213 /* of two sides of the triangle is used to check whether the angle */
7214 /* at the apex is greater than (180 - 2 `minangle') degrees (for */
7215 /* lenses; 90 degrees for diametral circles). */
7216 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7217 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7218 if (dotproduct < 0.0) {
7219 if (b->conformdel ||
7220 (dotproduct * dotproduct >=
7221 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7222 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7223 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7224 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7225 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7226 encroached = 1;
7227 }
7228 }
7229 }
7230 /* Check the other neighbor of the subsegment. */
7231 ssym(*testsubseg, testsym);
7232 stpivot(testsym, neighbortri);
7233 /* Does the neighbor exist, or is this a boundary edge? */
7234 if (neighbortri.tri != m->dummytri) {
7235 sides++;
7236 /* Find the other vertex opposite this subsegment. */
7237 apex(neighbortri, eapex);
7238 /* Check whether the apex is in the diametral lens of the subsegment */
7239 /* (or the diametral circle, if `conformdel' is set). */
7240 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7241 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7242 if (dotproduct < 0.0) {
7243 if (b->conformdel ||
7244 (dotproduct * dotproduct >=
7245 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
7246 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7247 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7248 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7249 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7250 encroached += 2;
7251 }
7252 }
7253 }
7254
7255 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
7256 if (b->verbose > 2) {
7257 printf(
7258 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
7259 eorg[0], eorg[1], edest[0], edest[1]);
7260 }
7261 /* Add the subsegment to the list of encroached subsegments. */
7262 /* Be sure to get the orientation right. */
7263 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
7264 if (encroached == 1) {
7265 encroachedseg->encsubseg = sencode(*testsubseg);
7266 encroachedseg->subsegorg = eorg;
7267 encroachedseg->subsegdest = edest;
7268 } else {
7269 encroachedseg->encsubseg = sencode(testsym);
7270 encroachedseg->subsegorg = edest;
7271 encroachedseg->subsegdest = eorg;
7272 }
7273 }
7274
7275 return encroached;
7276}
7277
7278#endif /* not CDT_ONLY */
7279
7280/*****************************************************************************/
7281/* */
7282/* testtriangle() Test a triangle for quality and size. */
7283/* */
7284/* Tests a triangle to see if it satisfies the minimum angle condition and */
7285/* the maximum area condition. Triangles that aren't up to spec are added */
7286/* to the bad triangle queue. */
7287/* */
7288/*****************************************************************************/
7289
7290#ifndef CDT_ONLY
7291
7292#ifdef ANSI_DECLARATORS
7293void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
7294#else /* not ANSI_DECLARATORS */
7295void testtriangle(m, b, testtri)
7296struct mesh *m;
7297struct behavior *b;
7298struct otri *testtri;
7299#endif /* not ANSI_DECLARATORS */
7300
7301{
7302 struct otri tri1, tri2;
7303 struct osub testsub;
7304 vertex torg, tdest, tapex;
7305 vertex base1, base2;
7306 vertex org1, dest1, org2, dest2;
7307 vertex joinvertex;
7308 REAL dxod, dyod, dxda, dyda, dxao, dyao;
7309 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
7310 REAL apexlen, orglen, destlen, minedge;
7311 REAL angle;
7312 REAL area;
7313 REAL dist1, dist2;
7314 subseg sptr; /* Temporary variable used by tspivot(). */
7315 triangle ptr; /* Temporary variable used by oprev() and dnext(). */
7316
7317 org(*testtri, torg);
7318 dest(*testtri, tdest);
7319 apex(*testtri, tapex);
7320 dxod = torg[0] - tdest[0];
7321 dyod = torg[1] - tdest[1];
7322 dxda = tdest[0] - tapex[0];
7323 dyda = tdest[1] - tapex[1];
7324 dxao = tapex[0] - torg[0];
7325 dyao = tapex[1] - torg[1];
7326 dxod2 = dxod * dxod;
7327 dyod2 = dyod * dyod;
7328 dxda2 = dxda * dxda;
7329 dyda2 = dyda * dyda;
7330 dxao2 = dxao * dxao;
7331 dyao2 = dyao * dyao;
7332 /* Find the lengths of the triangle's three edges. */
7333 apexlen = dxod2 + dyod2;
7334 orglen = dxda2 + dyda2;
7335 destlen = dxao2 + dyao2;
7336
7337 if ((apexlen < orglen) && (apexlen < destlen)) {
7338 /* The edge opposite the apex is shortest. */
7339 minedge = apexlen;
7340 /* Find the square of the cosine of the angle at the apex. */
7341 angle = dxda * dxao + dyda * dyao;
7342 angle = angle * angle / (orglen * destlen);
7343 base1 = torg;
7344 base2 = tdest;
7345 otricopy(*testtri, tri1);
7346 } else if (orglen < destlen) {
7347 /* The edge opposite the origin is shortest. */
7348 minedge = orglen;
7349 /* Find the square of the cosine of the angle at the origin. */
7350 angle = dxod * dxao + dyod * dyao;
7351 angle = angle * angle / (apexlen * destlen);
7352 base1 = tdest;
7353 base2 = tapex;
7354 lnext(*testtri, tri1);
7355 } else {
7356 /* The edge opposite the destination is shortest. */
7357 minedge = destlen;
7358 /* Find the square of the cosine of the angle at the destination. */
7359 angle = dxod * dxda + dyod * dyda;
7360 angle = angle * angle / (apexlen * orglen);
7361 base1 = tapex;
7362 base2 = torg;
7363 lprev(*testtri, tri1);
7364 }
7365
7366 if (b->vararea || b->fixedarea || b->usertest) {
7367 /* Check whether the area is larger than permitted. */
7368 area = 0.5 * (dxod * dyda - dyod * dxda);
7369 if (b->fixedarea && (area > b->maxarea)) {
7370 /* Add this triangle to the list of bad triangles. */
7371 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7372 return;
7373 }
7374
7375 /* Nonpositive area constraints are treated as unconstrained. */
7376 if ((b->vararea) && (area > areabound(*testtri)) &&
7377 (areabound(*testtri) > 0.0)) {
7378 /* Add this triangle to the list of bad triangles. */
7379 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7380 return;
7381 }
7382
7383 if (b->usertest) {
7384 /* Check whether the user thinks this triangle is too large. */
7385 if (triunsuitable(torg, tdest, tapex, area)) {
7386 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7387 return;
7388 }
7389 }
7390 }
7391
7392 /* Check whether the angle is smaller than permitted. */
7393 if (angle > b->goodangle) {
7394 /* Use the rules of Miller, Pav, and Walkington to decide that certain */
7395 /* triangles should not be split, even if they have bad angles. */
7396 /* A skinny triangle is not split if its shortest edge subtends a */
7397 /* small input angle, and both endpoints of the edge lie on a */
7398 /* concentric circular shell. For convenience, I make a small */
7399 /* adjustment to that rule: I check if the endpoints of the edge */
7400 /* both lie in segment interiors, equidistant from the apex where */
7401 /* the two segments meet. */
7402 /* First, check if both points lie in segment interiors. */
7403 if ((vertextype(base1) == SEGMENTVERTEX) &&
7404 (vertextype(base2) == SEGMENTVERTEX)) {
7405 /* Check if both points lie in a common segment. If they do, the */
7406 /* skinny triangle is enqueued to be split as usual. */
7407 tspivot(tri1, testsub);
7408 if (testsub.ss == m->dummysub) {
7409 /* No common segment. Find a subsegment that contains `torg'. */
7410 otricopy(tri1, tri2);
7411 do {
7412 oprevself(tri1);
7413 tspivot(tri1, testsub);
7414 } while (testsub.ss == m->dummysub);
7415 /* Find the endpoints of the containing segment. */
7416 segorg(testsub, org1);
7417 segdest(testsub, dest1);
7418 /* Find a subsegment that contains `tdest'. */
7419 do {
7420 dnextself(tri2);
7421 tspivot(tri2, testsub);
7422 } while (testsub.ss == m->dummysub);
7423 /* Find the endpoints of the containing segment. */
7424 segorg(testsub, org2);
7425 segdest(testsub, dest2);
7426 /* Check if the two containing segments have an endpoint in common. */
7427 joinvertex = (vertex) NULL;
7428 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
7429 joinvertex = dest1;
7430 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
7431 joinvertex = org1;
7432 }
7433 if (joinvertex != (vertex) NULL) {
7434 /* Compute the distance from the common endpoint (of the two */
7435 /* segments) to each of the endpoints of the shortest edge. */
7436 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
7437 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
7438 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
7439 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
7440 /* If the two distances are equal, don't split the triangle. */
7441 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
7442 /* Return now to avoid enqueueing the bad triangle. */
7443 return;
7444 }
7445 }
7446 }
7447 }
7448
7449 /* Add this triangle to the list of bad triangles. */
7450 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
7451 }
7452}
7453
7454#endif /* not CDT_ONLY */
7455
7458/********* Mesh quality testing routines end here *********/
7459
7460/********* Point location routines begin here *********/
7464/*****************************************************************************/
7465/* */
7466/* makevertexmap() Construct a mapping from vertices to triangles to */
7467/* improve the speed of point location for segment */
7468/* insertion. */
7469/* */
7470/* Traverses all the triangles, and provides each corner of each triangle */
7471/* with a pointer to that triangle. Of course, pointers will be */
7472/* overwritten by other pointers because (almost) each vertex is a corner */
7473/* of several triangles, but in the end every vertex will point to some */
7474/* triangle that contains it. */
7475/* */
7476/*****************************************************************************/
7477
7478#ifdef ANSI_DECLARATORS
7479void makevertexmap(struct mesh *m, struct behavior *b)
7480#else /* not ANSI_DECLARATORS */
7481void makevertexmap(m, b)
7482struct mesh *m;
7483struct behavior *b;
7484#endif /* not ANSI_DECLARATORS */
7485
7486{
7487 struct otri triangleloop;
7488 vertex triorg;
7489
7490 if (b->verbose) {
7491 printf(" Constructing mapping from vertices to triangles.\n");
7492 }
7493 traversalinit(&m->triangles);
7494 triangleloop.tri = triangletraverse(m);
7495 while (triangleloop.tri != (triangle *) NULL) {
7496 /* Check all three vertices of the triangle. */
7497 for (triangleloop.orient = 0; triangleloop.orient < 3;
7498 triangleloop.orient++) {
7499 org(triangleloop, triorg);
7500 setvertex2tri(triorg, encode(triangleloop));
7501 }
7502 triangleloop.tri = triangletraverse(m);
7503 }
7504}
7505
7506/*****************************************************************************/
7507/* */
7508/* preciselocate() Find a triangle or edge containing a given point. */
7509/* */
7510/* Begins its search from `searchtri'. It is important that `searchtri' */
7511/* be a handle with the property that `searchpoint' is strictly to the left */
7512/* of the edge denoted by `searchtri', or is collinear with that edge and */
7513/* does not intersect that edge. (In particular, `searchpoint' should not */
7514/* be the origin or destination of that edge.) */
7515/* */
7516/* These conditions are imposed because preciselocate() is normally used in */
7517/* one of two situations: */
7518/* */
7519/* (1) To try to find the location to insert a new point. Normally, we */
7520/* know an edge that the point is strictly to the left of. In the */
7521/* incremental Delaunay algorithm, that edge is a bounding box edge. */
7522/* In Ruppert's Delaunay refinement algorithm for quality meshing, */
7523/* that edge is the shortest edge of the triangle whose circumcenter */
7524/* is being inserted. */
7525/* */
7526/* (2) To try to find an existing point. In this case, any edge on the */
7527/* convex hull is a good starting edge. You must screen out the */
7528/* possibility that the vertex sought is an endpoint of the starting */
7529/* edge before you call preciselocate(). */
7530/* */
7531/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7532/* */
7533/* This implementation differs from that given by Guibas and Stolfi. It */
7534/* walks from triangle to triangle, crossing an edge only if `searchpoint' */
7535/* is on the other side of the line containing that edge. After entering */
7536/* a triangle, there are two edges by which one can leave that triangle. */
7537/* If both edges are valid (`searchpoint' is on the other side of both */
7538/* edges), one of the two is chosen by drawing a line perpendicular to */
7539/* the entry edge (whose endpoints are `forg' and `fdest') passing through */
7540/* `fapex'. Depending on which side of this perpendicular `searchpoint' */
7541/* falls on, an exit edge is chosen. */
7542/* */
7543/* This implementation is empirically faster than the Guibas and Stolfi */
7544/* point location routine (which I originally used), which tends to spiral */
7545/* in toward its target. */
7546/* */
7547/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7548/* is a handle whose origin is the existing vertex. */
7549/* */
7550/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7551/* handle whose primary edge is the edge on which the point lies. */
7552/* */
7553/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7554/* `searchtri' is a handle on the triangle that contains the point. */
7555/* */
7556/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7557/* handle whose primary edge the point is to the right of. This might */
7558/* occur when the circumcenter of a triangle falls just slightly outside */
7559/* the mesh due to floating-point roundoff error. It also occurs when */
7560/* seeking a hole or region point that a foolish user has placed outside */
7561/* the mesh. */
7562/* */
7563/* If `stopatsubsegment' is nonzero, the search will stop if it tries to */
7564/* walk through a subsegment, and will return OUTSIDE. */
7565/* */
7566/* WARNING: This routine is designed for convex triangulations, and will */
7567/* not generally work after the holes and concavities have been carved. */
7568/* However, it can still be used to find the circumcenter of a triangle, as */
7569/* long as the search is begun from the triangle in question. */
7570/* */
7571/*****************************************************************************/
7572
7573#ifdef ANSI_DECLARATORS
7574enum locateresult preciselocate(struct mesh *m, struct behavior *b,
7575 vertex searchpoint, struct otri *searchtri,
7576 int stopatsubsegment)
7577#else /* not ANSI_DECLARATORS */
7578enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
7579struct mesh *m;
7580struct behavior *b;
7581vertex searchpoint;
7582struct otri *searchtri;
7583int stopatsubsegment;
7584#endif /* not ANSI_DECLARATORS */
7585
7586{
7587 struct otri backtracktri;
7588 struct osub checkedge;
7589 vertex forg, fdest, fapex;
7590 REAL orgorient, destorient;
7591 int moveleft;
7592 triangle ptr; /* Temporary variable used by sym(). */
7593 subseg sptr; /* Temporary variable used by tspivot(). */
7594
7595 if (b->verbose > 2) {
7596 printf(" Searching for point (%.12g, %.12g).\n",
7597 searchpoint[0], searchpoint[1]);
7598 }
7599 /* Where are we? */
7600 org(*searchtri, forg);
7601 dest(*searchtri, fdest);
7602 apex(*searchtri, fapex);
7603 while (1) {
7604 if (b->verbose > 2) {
7605 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7606 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
7607 }
7608 /* Check whether the apex is the point we seek. */
7609 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
7610 lprevself(*searchtri);
7611 return ONVERTEX;
7612 }
7613 /* Does the point lie on the other side of the line defined by the */
7614 /* triangle edge opposite the triangle's destination? */
7615 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
7616 /* Does the point lie on the other side of the line defined by the */
7617 /* triangle edge opposite the triangle's origin? */
7618 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
7619 if (destorient > 0.0) {
7620 if (orgorient > 0.0) {
7621 /* Move left if the inner product of (fapex - searchpoint) and */
7622 /* (fdest - forg) is positive. This is equivalent to drawing */
7623 /* a line perpendicular to the line (forg, fdest) and passing */
7624 /* through `fapex', and determining which side of this line */
7625 /* `searchpoint' falls on. */
7626 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
7627 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
7628 } else {
7629 moveleft = 1;
7630 }
7631 } else {
7632 if (orgorient > 0.0) {
7633 moveleft = 0;
7634 } else {
7635 /* The point we seek must be on the boundary of or inside this */
7636 /* triangle. */
7637 if (destorient == 0.0) {
7638 lprevself(*searchtri);
7639 return ONEDGE;
7640 }
7641 if (orgorient == 0.0) {
7642 lnextself(*searchtri);
7643 return ONEDGE;
7644 }
7645 return INTRIANGLE;
7646 }
7647 }
7648
7649 /* Move to another triangle. Leave a trace `backtracktri' in case */
7650 /* floating-point roundoff or some such bogey causes us to walk */
7651 /* off a boundary of the triangulation. */
7652 if (moveleft) {
7653 lprev(*searchtri, backtracktri);
7654 fdest = fapex;
7655 } else {
7656 lnext(*searchtri, backtracktri);
7657 forg = fapex;
7658 }
7659 sym(backtracktri, *searchtri);
7660
7661 if (m->checksegments && stopatsubsegment) {
7662 /* Check for walking through a subsegment. */
7663 tspivot(backtracktri, checkedge);
7664 if (checkedge.ss != m->dummysub) {
7665 /* Go back to the last triangle. */
7666 otricopy(backtracktri, *searchtri);
7667 return OUTSIDE;
7668 }
7669 }
7670 /* Check for walking right out of the triangulation. */
7671 if (searchtri->tri == m->dummytri) {
7672 /* Go back to the last triangle. */
7673 otricopy(backtracktri, *searchtri);
7674 return OUTSIDE;
7675 }
7676
7677 apex(*searchtri, fapex);
7678 }
7679}
7680
7681/*****************************************************************************/
7682/* */
7683/* locate() Find a triangle or edge containing a given point. */
7684/* */
7685/* Searching begins from one of: the input `searchtri', a recently */
7686/* encountered triangle `recenttri', or from a triangle chosen from a */
7687/* random sample. The choice is made by determining which triangle's */
7688/* origin is closest to the point we are searching for. Normally, */
7689/* `searchtri' should be a handle on the convex hull of the triangulation. */
7690/* */
7691/* Details on the random sampling method can be found in the Mucke, Saias, */
7692/* and Zhu paper cited in the header of this code. */
7693/* */
7694/* On completion, `searchtri' is a triangle that contains `searchpoint'. */
7695/* */
7696/* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
7697/* is a handle whose origin is the existing vertex. */
7698/* */
7699/* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
7700/* handle whose primary edge is the edge on which the point lies. */
7701/* */
7702/* Returns INTRIANGLE if the point lies strictly within a triangle. */
7703/* `searchtri' is a handle on the triangle that contains the point. */
7704/* */
7705/* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
7706/* handle whose primary edge the point is to the right of. This might */
7707/* occur when the circumcenter of a triangle falls just slightly outside */
7708/* the mesh due to floating-point roundoff error. It also occurs when */
7709/* seeking a hole or region point that a foolish user has placed outside */
7710/* the mesh. */
7711/* */
7712/* WARNING: This routine is designed for convex triangulations, and will */
7713/* not generally work after the holes and concavities have been carved. */
7714/* */
7715/*****************************************************************************/
7716
7717#ifdef ANSI_DECLARATORS
7718enum locateresult locate(struct mesh *m, struct behavior *b,
7719 vertex searchpoint, struct otri *searchtri)
7720#else /* not ANSI_DECLARATORS */
7721enum locateresult locate(m, b, searchpoint, searchtri)
7722struct mesh *m;
7723struct behavior *b;
7724vertex searchpoint;
7725struct otri *searchtri;
7726#endif /* not ANSI_DECLARATORS */
7727
7728{
7729 VOID **sampleblock;
7730 char *firsttri;
7731 struct otri sampletri;
7732 vertex torg, tdest;
7733 unsigned long alignptr;
7734 REAL searchdist, dist;
7735 REAL ahead;
7736 long samplesperblock, totalsamplesleft, samplesleft;
7737 long population, totalpopulation;
7738 triangle ptr; /* Temporary variable used by sym(). */
7739
7740 if (b->verbose > 2) {
7741 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
7742 searchpoint[0], searchpoint[1]);
7743 }
7744 /* Record the distance from the suggested starting triangle to the */
7745 /* point we seek. */
7746 org(*searchtri, torg);
7747 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7748 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7749 if (b->verbose > 2) {
7750 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
7751 torg[0], torg[1]);
7752 }
7753
7754 /* If a recently encountered triangle has been recorded and has not been */
7755 /* deallocated, test it as a good starting point. */
7756 if (m->recenttri.tri != (triangle *) NULL) {
7757 if (!deadtri(m->recenttri.tri)) {
7758 org(m->recenttri, torg);
7759 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7760 otricopy(m->recenttri, *searchtri);
7761 return ONVERTEX;
7762 }
7763 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7764 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7765 if (dist < searchdist) {
7766 otricopy(m->recenttri, *searchtri);
7767 searchdist = dist;
7768 if (b->verbose > 2) {
7769 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
7770 torg[0], torg[1]);
7771 }
7772 }
7773 }
7774 }
7775
7776 /* The number of random samples taken is proportional to the cube root of */
7777 /* the number of triangles in the mesh. The next bit of code assumes */
7778 /* that the number of triangles increases monotonically (or at least */
7779 /* doesn't decrease enough to matter). */
7780 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
7781 m->triangles.items) {
7782 m->samples++;
7783 }
7784
7785 /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */
7786 /* from each block of triangles (except the first)--until we meet the */
7787 /* sample quota. The ceiling means that blocks at the end might be */
7788 /* neglected, but I don't care. */
7789 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
7790 /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */
7791 /* from the first block of triangles. */
7792 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
7793 m->triangles.maxitems + 1;
7794 totalsamplesleft = m->samples;
7795 population = m->triangles.itemsfirstblock;
7796 totalpopulation = m->triangles.maxitems;
7797 sampleblock = m->triangles.firstblock;
7798 sampletri.orient = 0;
7799 while (totalsamplesleft > 0) {
7800 /* If we're in the last block, `population' needs to be corrected. */
7801 if (population > totalpopulation) {
7802 population = totalpopulation;
7803 }
7804 /* Find a pointer to the first triangle in the block. */
7805 alignptr = (unsigned long) (sampleblock + 1);
7806 firsttri = (char *) (alignptr +
7807 (unsigned long) m->triangles.alignbytes -
7808 (alignptr %
7809 (unsigned long) m->triangles.alignbytes));
7810
7811 /* Choose `samplesleft' randomly sampled triangles in this block. */
7812 do {
7813 sampletri.tri = (triangle *) (firsttri +
7814 (randomnation((unsigned int) population) *
7815 m->triangles.itembytes));
7816 if (!deadtri(sampletri.tri)) {
7817 org(sampletri, torg);
7818 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7819 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7820 if (dist < searchdist) {
7821 otricopy(sampletri, *searchtri);
7822 searchdist = dist;
7823 if (b->verbose > 2) {
7824 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
7825 torg[0], torg[1]);
7826 }
7827 }
7828 }
7829
7830 samplesleft--;
7831 totalsamplesleft--;
7832 } while ((samplesleft > 0) && (totalsamplesleft > 0));
7833
7834 if (totalsamplesleft > 0) {
7835 sampleblock = (VOID **) *sampleblock;
7836 samplesleft = samplesperblock;
7837 totalpopulation -= population;
7838 population = TRIPERBLOCK;
7839 }
7840 }
7841
7842 /* Where are we? */
7843 org(*searchtri, torg);
7844 dest(*searchtri, tdest);
7845 /* Check the starting triangle's vertices. */
7846 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7847 return ONVERTEX;
7848 }
7849 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
7850 lnextself(*searchtri);
7851 return ONVERTEX;
7852 }
7853 /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
7854 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
7855 if (ahead < 0.0) {
7856 /* Turn around so that `searchpoint' is to the left of the */
7857 /* edge specified by `searchtri'. */
7858 symself(*searchtri);
7859 } else if (ahead == 0.0) {
7860 /* Check if `searchpoint' is between `torg' and `tdest'. */
7861 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
7862 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
7863 return ONEDGE;
7864 }
7865 }
7866 return preciselocate(m, b, searchpoint, searchtri, 0);
7867}
7868
7871/********* Point location routines end here *********/
7872
7873/********* Mesh transformation routines begin here *********/
7877/*****************************************************************************/
7878/* */
7879/* insertsubseg() Create a new subsegment and insert it between two */
7880/* triangles. */
7881/* */
7882/* The new subsegment is inserted at the edge described by the handle */
7883/* `tri'. Its vertices are properly initialized. The marker `subsegmark' */
7884/* is applied to the subsegment and, if appropriate, its vertices. */
7885/* */
7886/*****************************************************************************/
7887
7888#ifdef ANSI_DECLARATORS
7889void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
7890 int subsegmark)
7891#else /* not ANSI_DECLARATORS */
7892void insertsubseg(m, b, tri, subsegmark)
7893struct mesh *m;
7894struct behavior *b;
7895struct otri *tri; /* Edge at which to insert the new subsegment. */
7896int subsegmark; /* Marker for the new subsegment. */
7897#endif /* not ANSI_DECLARATORS */
7898
7899{
7900 struct otri oppotri;
7901 struct osub newsubseg;
7902 vertex triorg, tridest;
7903 triangle ptr; /* Temporary variable used by sym(). */
7904 subseg sptr; /* Temporary variable used by tspivot(). */
7905
7906 org(*tri, triorg);
7907 dest(*tri, tridest);
7908 /* Mark vertices if possible. */
7909 if (vertexmark(triorg) == 0) {
7910 setvertexmark(triorg, subsegmark);
7911 }
7912 if (vertexmark(tridest) == 0) {
7913 setvertexmark(tridest, subsegmark);
7914 }
7915 /* Check if there's already a subsegment here. */
7916 tspivot(*tri, newsubseg);
7917 if (newsubseg.ss == m->dummysub) {
7918 /* Make new subsegment and initialize its vertices. */
7919 makesubseg(m, &newsubseg);
7920 setsorg(newsubseg, tridest);
7921 setsdest(newsubseg, triorg);
7922 setsegorg(newsubseg, tridest);
7923 setsegdest(newsubseg, triorg);
7924 /* Bond new subsegment to the two triangles it is sandwiched between. */
7925 /* Note that the facing triangle `oppotri' might be equal to */
7926 /* `dummytri' (outer space), but the new subsegment is bonded to it */
7927 /* all the same. */
7928 tsbond(*tri, newsubseg);
7929 sym(*tri, oppotri);
7930 ssymself(newsubseg);
7931 tsbond(oppotri, newsubseg);
7932 setmark(newsubseg, subsegmark);
7933 if (b->verbose > 2) {
7934 printf(" Inserting new ");
7935 printsubseg(m, b, &newsubseg);
7936 }
7937 } else {
7938 if (mark(newsubseg) == 0) {
7939 setmark(newsubseg, subsegmark);
7940 }
7941 }
7942}
7943
7944/*****************************************************************************/
7945/* */
7946/* Terminology */
7947/* */
7948/* A "local transformation" replaces a small set of triangles with another */
7949/* set of triangles. This may or may not involve inserting or deleting a */
7950/* vertex. */
7951/* */
7952/* The term "casing" is used to describe the set of triangles that are */
7953/* attached to the triangles being transformed, but are not transformed */
7954/* themselves. Think of the casing as a fixed hollow structure inside */
7955/* which all the action happens. A "casing" is only defined relative to */
7956/* a single transformation; each occurrence of a transformation will */
7957/* involve a different casing. */
7958/* */
7959/*****************************************************************************/
7960
7961/*****************************************************************************/
7962/* */
7963/* flip() Transform two triangles to two different triangles by flipping */
7964/* an edge counterclockwise within a quadrilateral. */
7965/* */
7966/* Imagine the original triangles, abc and bad, oriented so that the */
7967/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
7968/* and the vertex a on the right. The vertex c lies below the edge, and */
7969/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
7970/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
7971/* */
7972/* The triangles abc and bad are deleted and replaced by the triangles cdb */
7973/* and dca. The triangles that represent abc and bad are NOT deallocated; */
7974/* they are reused for dca and cdb, respectively. Hence, any handles that */
7975/* may have held the original triangles are still valid, although not */
7976/* directed as they were before. */
7977/* */
7978/* Upon completion of this routine, the `flipedge' handle holds the edge */
7979/* dc of triangle dca, and is directed down, from vertex d to vertex c. */
7980/* (Hence, the two triangles have rotated counterclockwise.) */
7981/* */
7982/* WARNING: This transformation is geometrically valid only if the */
7983/* quadrilateral adbc is convex. Furthermore, this transformation is */
7984/* valid only if there is not a subsegment between the triangles abc and */
7985/* bad. This routine does not check either of these preconditions, and */
7986/* it is the responsibility of the calling routine to ensure that they are */
7987/* met. If they are not, the streets shall be filled with wailing and */
7988/* gnashing of teeth. */
7989/* */
7990/*****************************************************************************/
7991
7992#ifdef ANSI_DECLARATORS
7993void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
7994#else /* not ANSI_DECLARATORS */
7995void flip(m, b, flipedge)
7996struct mesh *m;
7997struct behavior *b;
7998struct otri *flipedge; /* Handle for the triangle abc. */
7999#endif /* not ANSI_DECLARATORS */
8000
8001{
8002 struct otri botleft, botright;
8003 struct otri topleft, topright;
8004 struct otri top;
8005 struct otri botlcasing, botrcasing;
8006 struct otri toplcasing, toprcasing;
8007 struct osub botlsubseg, botrsubseg;
8008 struct osub toplsubseg, toprsubseg;
8009 vertex leftvertex, rightvertex, botvertex;
8010 vertex farvertex;
8011 triangle ptr; /* Temporary variable used by sym(). */
8012 subseg sptr; /* Temporary variable used by tspivot(). */
8013
8014 /* Identify the vertices of the quadrilateral. */
8015 org(*flipedge, rightvertex);
8016 dest(*flipedge, leftvertex);
8017 apex(*flipedge, botvertex);
8018 sym(*flipedge, top);
8019#ifdef SELF_CHECK
8020 if (top.tri == m->dummytri) {
8021 printf("Internal error in flip(): Attempt to flip on boundary.\n");
8022 lnextself(*flipedge);
8023 return;
8024 }
8025 if (m->checksegments) {
8026 tspivot(*flipedge, toplsubseg);
8027 if (toplsubseg.ss != m->dummysub) {
8028 printf("Internal error in flip(): Attempt to flip a segment.\n");
8029 lnextself(*flipedge);
8030 return;
8031 }
8032 }
8033#endif /* SELF_CHECK */
8034 apex(top, farvertex);
8035
8036 /* Identify the casing of the quadrilateral. */
8037 lprev(top, topleft);
8038 sym(topleft, toplcasing);
8039 lnext(top, topright);
8040 sym(topright, toprcasing);
8041 lnext(*flipedge, botleft);
8042 sym(botleft, botlcasing);
8043 lprev(*flipedge, botright);
8044 sym(botright, botrcasing);
8045 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
8046 bond(topleft, botlcasing);
8047 bond(botleft, botrcasing);
8048 bond(botright, toprcasing);
8049 bond(topright, toplcasing);
8050
8051 if (m->checksegments) {
8052 /* Check for subsegments and rebond them to the quadrilateral. */
8053 tspivot(topleft, toplsubseg);
8054 tspivot(botleft, botlsubseg);
8055 tspivot(botright, botrsubseg);
8056 tspivot(topright, toprsubseg);
8057 if (toplsubseg.ss == m->dummysub) {
8058 tsdissolve(topright);
8059 } else {
8060 tsbond(topright, toplsubseg);
8061 }
8062 if (botlsubseg.ss == m->dummysub) {
8063 tsdissolve(topleft);
8064 } else {
8065 tsbond(topleft, botlsubseg);
8066 }
8067 if (botrsubseg.ss == m->dummysub) {
8068 tsdissolve(botleft);
8069 } else {
8070 tsbond(botleft, botrsubseg);
8071 }
8072 if (toprsubseg.ss == m->dummysub) {
8073 tsdissolve(botright);
8074 } else {
8075 tsbond(botright, toprsubseg);
8076 }
8077 }
8078
8079 /* New vertex assignments for the rotated quadrilateral. */
8080 setorg(*flipedge, farvertex);
8081 setdest(*flipedge, botvertex);
8082 setapex(*flipedge, rightvertex);
8083 setorg(top, botvertex);
8084 setdest(top, farvertex);
8085 setapex(top, leftvertex);
8086 if (b->verbose > 2) {
8087 printf(" Edge flip results in left ");
8088 printtriangle(m, b, &top);
8089 printf(" and right ");
8090 printtriangle(m, b, flipedge);
8091 }
8092}
8093
8094/*****************************************************************************/
8095/* */
8096/* unflip() Transform two triangles to two different triangles by */
8097/* flipping an edge clockwise within a quadrilateral. Reverses */
8098/* the flip() operation so that the data structures representing */
8099/* the triangles are back where they were before the flip(). */
8100/* */
8101/* Imagine the original triangles, abc and bad, oriented so that the */
8102/* shared edge ab lies in a horizontal plane, with the vertex b on the left */
8103/* and the vertex a on the right. The vertex c lies below the edge, and */
8104/* the vertex d lies above the edge. The `flipedge' handle holds the edge */
8105/* ab of triangle abc, and is directed left, from vertex a to vertex b. */
8106/* */
8107/* The triangles abc and bad are deleted and replaced by the triangles cdb */
8108/* and dca. The triangles that represent abc and bad are NOT deallocated; */
8109/* they are reused for cdb and dca, respectively. Hence, any handles that */
8110/* may have held the original triangles are still valid, although not */
8111/* directed as they were before. */
8112/* */
8113/* Upon completion of this routine, the `flipedge' handle holds the edge */
8114/* cd of triangle cdb, and is directed up, from vertex c to vertex d. */
8115/* (Hence, the two triangles have rotated clockwise.) */
8116/* */
8117/* WARNING: This transformation is geometrically valid only if the */
8118/* quadrilateral adbc is convex. Furthermore, this transformation is */
8119/* valid only if there is not a subsegment between the triangles abc and */
8120/* bad. This routine does not check either of these preconditions, and */
8121/* it is the responsibility of the calling routine to ensure that they are */
8122/* met. If they are not, the streets shall be filled with wailing and */
8123/* gnashing of teeth. */
8124/* */
8125/*****************************************************************************/
8126
8127#ifdef ANSI_DECLARATORS
8128void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
8129#else /* not ANSI_DECLARATORS */
8130void unflip(m, b, flipedge)
8131struct mesh *m;
8132struct behavior *b;
8133struct otri *flipedge; /* Handle for the triangle abc. */
8134#endif /* not ANSI_DECLARATORS */
8135
8136{
8137 struct otri botleft, botright;
8138 struct otri topleft, topright;
8139 struct otri top;
8140 struct otri botlcasing, botrcasing;
8141 struct otri toplcasing, toprcasing;
8142 struct osub botlsubseg, botrsubseg;
8143 struct osub toplsubseg, toprsubseg;
8144 vertex leftvertex, rightvertex, botvertex;
8145 vertex farvertex;
8146 triangle ptr; /* Temporary variable used by sym(). */
8147 subseg sptr; /* Temporary variable used by tspivot(). */
8148
8149 /* Identify the vertices of the quadrilateral. */
8150 org(*flipedge, rightvertex);
8151 dest(*flipedge, leftvertex);
8152 apex(*flipedge, botvertex);
8153 sym(*flipedge, top);
8154#ifdef SELF_CHECK
8155 if (top.tri == m->dummytri) {
8156 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
8157 lnextself(*flipedge);
8158 return;
8159 }
8160 if (m->checksegments) {
8161 tspivot(*flipedge, toplsubseg);
8162 if (toplsubseg.ss != m->dummysub) {
8163 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
8164 lnextself(*flipedge);
8165 return;
8166 }
8167 }
8168#endif /* SELF_CHECK */
8169 apex(top, farvertex);
8170
8171 /* Identify the casing of the quadrilateral. */
8172 lprev(top, topleft);
8173 sym(topleft, toplcasing);
8174 lnext(top, topright);
8175 sym(topright, toprcasing);
8176 lnext(*flipedge, botleft);
8177 sym(botleft, botlcasing);
8178 lprev(*flipedge, botright);
8179 sym(botright, botrcasing);
8180 /* Rotate the quadrilateral one-quarter turn clockwise. */
8181 bond(topleft, toprcasing);
8182 bond(botleft, toplcasing);
8183 bond(botright, botlcasing);
8184 bond(topright, botrcasing);
8185
8186 if (m->checksegments) {
8187 /* Check for subsegments and rebond them to the quadrilateral. */
8188 tspivot(topleft, toplsubseg);
8189 tspivot(botleft, botlsubseg);
8190 tspivot(botright, botrsubseg);
8191 tspivot(topright, toprsubseg);
8192 if (toplsubseg.ss == m->dummysub) {
8193 tsdissolve(botleft);
8194 } else {
8195 tsbond(botleft, toplsubseg);
8196 }
8197 if (botlsubseg.ss == m->dummysub) {
8198 tsdissolve(botright);
8199 } else {
8200 tsbond(botright, botlsubseg);
8201 }
8202 if (botrsubseg.ss == m->dummysub) {
8203 tsdissolve(topright);
8204 } else {
8205 tsbond(topright, botrsubseg);
8206 }
8207 if (toprsubseg.ss == m->dummysub) {
8208 tsdissolve(topleft);
8209 } else {
8210 tsbond(topleft, toprsubseg);
8211 }
8212 }
8213
8214 /* New vertex assignments for the rotated quadrilateral. */
8215 setorg(*flipedge, botvertex);
8216 setdest(*flipedge, farvertex);
8217 setapex(*flipedge, leftvertex);
8218 setorg(top, farvertex);
8219 setdest(top, botvertex);
8220 setapex(top, rightvertex);
8221 if (b->verbose > 2) {
8222 printf(" Edge unflip results in left ");
8223 printtriangle(m, b, flipedge);
8224 printf(" and right ");
8225 printtriangle(m, b, &top);
8226 }
8227}
8228
8229/*****************************************************************************/
8230/* */
8231/* insertvertex() Insert a vertex into a Delaunay triangulation, */
8232/* performing flips as necessary to maintain the Delaunay */
8233/* property. */
8234/* */
8235/* The point `insertvertex' is located. If `searchtri.tri' is not NULL, */
8236/* the search for the containing triangle begins from `searchtri'. If */
8237/* `searchtri.tri' is NULL, a full point location procedure is called. */
8238/* If `insertvertex' is found inside a triangle, the triangle is split into */
8239/* three; if `insertvertex' lies on an edge, the edge is split in two, */
8240/* thereby splitting the two adjacent triangles into four. Edge flips are */
8241/* used to restore the Delaunay property. If `insertvertex' lies on an */
8242/* existing vertex, no action is taken, and the value DUPLICATEVERTEX is */
8243/* returned. On return, `searchtri' is set to a handle whose origin is the */
8244/* existing vertex. */
8245/* */
8246/* Normally, the parameter `splitseg' is set to NULL, implying that no */
8247/* subsegment should be split. In this case, if `insertvertex' is found to */
8248/* lie on a segment, no action is taken, and the value VIOLATINGVERTEX is */
8249/* returned. On return, `searchtri' is set to a handle whose primary edge */
8250/* is the violated subsegment. */
8251/* */
8252/* If the calling routine wishes to split a subsegment by inserting a */
8253/* vertex in it, the parameter `splitseg' should be that subsegment. In */
8254/* this case, `searchtri' MUST be the triangle handle reached by pivoting */
8255/* from that subsegment; no point location is done. */
8256/* */
8257/* `segmentflaws' and `triflaws' are flags that indicate whether or not */
8258/* there should be checks for the creation of encroached subsegments or bad */
8259/* quality triangles. If a newly inserted vertex encroaches upon */
8260/* subsegments, these subsegments are added to the list of subsegments to */
8261/* be split if `segmentflaws' is set. If bad triangles are created, these */
8262/* are added to the queue if `triflaws' is set. */
8263/* */
8264/* If a duplicate vertex or violated segment does not prevent the vertex */
8265/* from being inserted, the return value will be ENCROACHINGVERTEX if the */
8266/* vertex encroaches upon a subsegment (and checking is enabled), or */
8267/* SUCCESSFULVERTEX otherwise. In either case, `searchtri' is set to a */
8268/* handle whose origin is the newly inserted vertex. */
8269/* */
8270/* insertvertex() does not use flip() for reasons of speed; some */
8271/* information can be reused from edge flip to edge flip, like the */
8272/* locations of subsegments. */
8273/* */
8274/*****************************************************************************/
8275
8276#ifdef ANSI_DECLARATORS
8277enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
8278 vertex newvertex, struct otri *searchtri,
8279 struct osub *splitseg,
8280 int segmentflaws, int triflaws)
8281#else /* not ANSI_DECLARATORS */
8282enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
8283 segmentflaws, triflaws)
8284struct mesh *m;
8285struct behavior *b;
8286vertex newvertex;
8287struct otri *searchtri;
8288struct osub *splitseg;
8289int segmentflaws;
8290int triflaws;
8291#endif /* not ANSI_DECLARATORS */
8292
8293{
8294 struct otri horiz;
8295 struct otri top;
8296 struct otri botleft, botright;
8297 struct otri topleft, topright;
8298 struct otri newbotleft, newbotright;
8299 struct otri newtopright;
8300 struct otri botlcasing, botrcasing;
8301 struct otri toplcasing={NULL, 0}, toprcasing={NULL, 0};
8302 struct otri testtri;
8303 struct osub botlsubseg, botrsubseg;
8304 struct osub toplsubseg, toprsubseg;
8305 struct osub brokensubseg;
8306 struct osub checksubseg;
8307 struct osub rightsubseg;
8308 struct osub newsubseg;
8309 struct badsubseg *encroached;
8310 struct flipstacker *newflip;
8311 vertex first;
8312 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
8313 vertex segmentorg, segmentdest;
8314 REAL attrib;
8315 REAL area;
8316 enum insertvertexresult success;
8317 enum locateresult intersect;
8318 int doflip;
8319 int mirrorflag;
8320 int enq;
8321 int i;
8322 triangle ptr; /* Temporary variable used by sym(). */
8323 subseg sptr; /* Temporary variable used by spivot() and tspivot(). */
8324
8325 if (b->verbose > 1) {
8326 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
8327 }
8328
8329 if (splitseg == (struct osub *) NULL) {
8330 /* Find the location of the vertex to be inserted. Check if a good */
8331 /* starting triangle has already been provided by the caller. */
8332 if (searchtri->tri == m->dummytri) {
8333 /* Find a boundary triangle. */
8334 horiz.tri = m->dummytri;
8335 horiz.orient = 0;
8336 symself(horiz);
8337 /* Search for a triangle containing `newvertex'. */
8338 intersect = locate(m, b, newvertex, &horiz);
8339 } else {
8340 /* Start searching from the triangle provided by the caller. */
8341 otricopy(*searchtri, horiz);
8342 intersect = preciselocate(m, b, newvertex, &horiz, 1);
8343 }
8344 } else {
8345 /* The calling routine provides the subsegment in which */
8346 /* the vertex is inserted. */
8347 otricopy(*searchtri, horiz);
8348 intersect = ONEDGE;
8349 }
8350
8351 if (intersect == ONVERTEX) {
8352 /* There's already a vertex there. Return in `searchtri' a triangle */
8353 /* whose origin is the existing vertex. */
8354 otricopy(horiz, *searchtri);
8355 otricopy(horiz, m->recenttri);
8356 return DUPLICATEVERTEX;
8357 }
8358 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
8359 /* The vertex falls on an edge or boundary. */
8360 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
8361 /* Check whether the vertex falls on a subsegment. */
8362 tspivot(horiz, brokensubseg);
8363 if (brokensubseg.ss != m->dummysub) {
8364 /* The vertex falls on a subsegment, and hence will not be inserted. */
8365 if (segmentflaws) {
8366 enq = b->nobisect != 2;
8367 if (enq && (b->nobisect == 1)) {
8368 /* This subsegment may be split only if it is an */
8369 /* internal boundary. */
8370 sym(horiz, testtri);
8371 enq = testtri.tri != m->dummytri;
8372 }
8373 if (enq) {
8374 /* Add the subsegment to the list of encroached subsegments. */
8375 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
8376 encroached->encsubseg = sencode(brokensubseg);
8377 sorg(brokensubseg, encroached->subsegorg);
8378 sdest(brokensubseg, encroached->subsegdest);
8379 if (b->verbose > 2) {
8380 printf(
8381 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
8382 encroached->subsegorg[0], encroached->subsegorg[1],
8383 encroached->subsegdest[0], encroached->subsegdest[1]);
8384 }
8385 }
8386 }
8387 /* Return a handle whose primary edge contains the vertex, */
8388 /* which has not been inserted. */
8389 otricopy(horiz, *searchtri);
8390 otricopy(horiz, m->recenttri);
8391 return VIOLATINGVERTEX;
8392 }
8393 }
8394
8395 /* Insert the vertex on an edge, dividing one triangle into two (if */
8396 /* the edge lies on a boundary) or two triangles into four. */
8397 lprev(horiz, botright);
8398 sym(botright, botrcasing);
8399 sym(horiz, topright);
8400 /* Is there a second triangle? (Or does this edge lie on a boundary?) */
8401 mirrorflag = topright.tri != m->dummytri;
8402 if (mirrorflag) {
8403 lnextself(topright);
8404 sym(topright, toprcasing);
8405 maketriangle(m, b, &newtopright);
8406 } else {
8407 /* Splitting a boundary edge increases the number of boundary edges. */
8408 m->hullsize++;
8409 }
8410 maketriangle(m, b, &newbotright);
8411
8412 /* Set the vertices of changed and new triangles. */
8413 org(horiz, rightvertex);
8414 dest(horiz, leftvertex);
8415 apex(horiz, botvertex);
8416 setorg(newbotright, botvertex);
8417 setdest(newbotright, rightvertex);
8418 setapex(newbotright, newvertex);
8419 setorg(horiz, newvertex);
8420 for (i = 0; i < m->eextras; i++) {
8421 /* Set the element attributes of a new triangle. */
8422 setelemattribute(newbotright, i, elemattribute(botright, i));
8423 }
8424 if (b->vararea) {
8425 /* Set the area constraint of a new triangle. */
8426 setareabound(newbotright, areabound(botright));
8427 }
8428 if (mirrorflag) {
8429 dest(topright, topvertex);
8430 setorg(newtopright, rightvertex);
8431 setdest(newtopright, topvertex);
8432 setapex(newtopright, newvertex);
8433 setorg(topright, newvertex);
8434 for (i = 0; i < m->eextras; i++) {
8435 /* Set the element attributes of another new triangle. */
8436 setelemattribute(newtopright, i, elemattribute(topright, i));
8437 }
8438 if (b->vararea) {
8439 /* Set the area constraint of another new triangle. */
8440 setareabound(newtopright, areabound(topright));
8441 }
8442 }
8443
8444 /* There may be subsegments that need to be bonded */
8445 /* to the new triangle(s). */
8446 if (m->checksegments) {
8447 tspivot(botright, botrsubseg);
8448 if (botrsubseg.ss != m->dummysub) {
8449 tsdissolve(botright);
8450 tsbond(newbotright, botrsubseg);
8451 }
8452 if (mirrorflag) {
8453 tspivot(topright, toprsubseg);
8454 if (toprsubseg.ss != m->dummysub) {
8455 tsdissolve(topright);
8456 tsbond(newtopright, toprsubseg);
8457 }
8458 }
8459 }
8460
8461 /* Bond the new triangle(s) to the surrounding triangles. */
8462 bond(newbotright, botrcasing);
8463 lprevself(newbotright);
8464 bond(newbotright, botright);
8465 lprevself(newbotright);
8466 if (mirrorflag) {
8467 bond(newtopright, toprcasing);
8468 lnextself(newtopright);
8469 bond(newtopright, topright);
8470 lnextself(newtopright);
8471 bond(newtopright, newbotright);
8472 }
8473
8474 if (splitseg != (struct osub *) NULL) {
8475 /* Split the subsegment into two. */
8476 setsdest(*splitseg, newvertex);
8477 segorg(*splitseg, segmentorg);
8478 segdest(*splitseg, segmentdest);
8479 ssymself(*splitseg);
8480 spivot(*splitseg, rightsubseg);
8481 insertsubseg(m, b, &newbotright, mark(*splitseg));
8482 tspivot(newbotright, newsubseg);
8483 setsegorg(newsubseg, segmentorg);
8484 setsegdest(newsubseg, segmentdest);
8485 sbond(*splitseg, newsubseg);
8486 ssymself(newsubseg);
8487 sbond(newsubseg, rightsubseg);
8488 ssymself(*splitseg);
8489 /* Transfer the subsegment's boundary marker to the vertex */
8490 /* if required. */
8491 if (vertexmark(newvertex) == 0) {
8492 setvertexmark(newvertex, mark(*splitseg));
8493 }
8494 }
8495
8496 if (m->checkquality) {
8497 poolrestart(&m->flipstackers);
8498 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8499 m->lastflip->flippedtri = encode(horiz);
8500 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
8501 }
8502
8503#ifdef SELF_CHECK
8504 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
8505 printf("Internal error in insertvertex():\n");
8506 printf(
8507 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
8508 }
8509 if (mirrorflag) {
8510 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
8511 printf("Internal error in insertvertex():\n");
8512 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
8513 }
8514 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
8515 printf("Internal error in insertvertex():\n");
8516 printf(
8517 " Clockwise triangle after edge vertex insertion (top right).\n");
8518 }
8519 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
8520 printf("Internal error in insertvertex():\n");
8521 printf(
8522 " Clockwise triangle after edge vertex insertion (top left).\n");
8523 }
8524 }
8525 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
8526 printf("Internal error in insertvertex():\n");
8527 printf(
8528 " Clockwise triangle after edge vertex insertion (bottom left).\n");
8529 }
8530 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
8531 printf("Internal error in insertvertex():\n");
8532 printf(
8533 " Clockwise triangle after edge vertex insertion (bottom right).\n");
8534 }
8535#endif /* SELF_CHECK */
8536 if (b->verbose > 2) {
8537 printf(" Updating bottom left ");
8538 printtriangle(m, b, &botright);
8539 if (mirrorflag) {
8540 printf(" Updating top left ");
8541 printtriangle(m, b, &topright);
8542 printf(" Creating top right ");
8543 printtriangle(m, b, &newtopright);
8544 }
8545 printf(" Creating bottom right ");
8546 printtriangle(m, b, &newbotright);
8547 }
8548
8549 /* Position `horiz' on the first edge to check for */
8550 /* the Delaunay property. */
8551 lnextself(horiz);
8552 } else {
8553 /* Insert the vertex in a triangle, splitting it into three. */
8554 lnext(horiz, botleft);
8555 lprev(horiz, botright);
8556 sym(botleft, botlcasing);
8557 sym(botright, botrcasing);
8558 maketriangle(m, b, &newbotleft);
8559 maketriangle(m, b, &newbotright);
8560
8561 /* Set the vertices of changed and new triangles. */
8562 org(horiz, rightvertex);
8563 dest(horiz, leftvertex);
8564 apex(horiz, botvertex);
8565 setorg(newbotleft, leftvertex);
8566 setdest(newbotleft, botvertex);
8567 setapex(newbotleft, newvertex);
8568 setorg(newbotright, botvertex);
8569 setdest(newbotright, rightvertex);
8570 setapex(newbotright, newvertex);
8571 setapex(horiz, newvertex);
8572 for (i = 0; i < m->eextras; i++) {
8573 /* Set the element attributes of the new triangles. */
8574 attrib = elemattribute(horiz, i);
8575 setelemattribute(newbotleft, i, attrib);
8576 setelemattribute(newbotright, i, attrib);
8577 }
8578 if (b->vararea) {
8579 /* Set the area constraint of the new triangles. */
8580 area = areabound(horiz);
8581 setareabound(newbotleft, area);
8582 setareabound(newbotright, area);
8583 }
8584
8585 /* There may be subsegments that need to be bonded */
8586 /* to the new triangles. */
8587 if (m->checksegments) {
8588 tspivot(botleft, botlsubseg);
8589 if (botlsubseg.ss != m->dummysub) {
8590 tsdissolve(botleft);
8591 tsbond(newbotleft, botlsubseg);
8592 }
8593 tspivot(botright, botrsubseg);
8594 if (botrsubseg.ss != m->dummysub) {
8595 tsdissolve(botright);
8596 tsbond(newbotright, botrsubseg);
8597 }
8598 }
8599
8600 /* Bond the new triangles to the surrounding triangles. */
8601 bond(newbotleft, botlcasing);
8602 bond(newbotright, botrcasing);
8603 lnextself(newbotleft);
8604 lprevself(newbotright);
8605 bond(newbotleft, newbotright);
8606 lnextself(newbotleft);
8607 bond(botleft, newbotleft);
8608 lprevself(newbotright);
8609 bond(botright, newbotright);
8610
8611 if (m->checkquality) {
8612 poolrestart(&m->flipstackers);
8613 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8614 m->lastflip->flippedtri = encode(horiz);
8615 m->lastflip->prevflip = (struct flipstacker *) NULL;
8616 }
8617
8618#ifdef SELF_CHECK
8619 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
8620 printf("Internal error in insertvertex():\n");
8621 printf(" Clockwise triangle prior to vertex insertion.\n");
8622 }
8623 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
8624 printf("Internal error in insertvertex():\n");
8625 printf(" Clockwise triangle after vertex insertion (top).\n");
8626 }
8627 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
8628 printf("Internal error in insertvertex():\n");
8629 printf(" Clockwise triangle after vertex insertion (left).\n");
8630 }
8631 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
8632 printf("Internal error in insertvertex():\n");
8633 printf(" Clockwise triangle after vertex insertion (right).\n");
8634 }
8635#endif /* SELF_CHECK */
8636 if (b->verbose > 2) {
8637 printf(" Updating top ");
8638 printtriangle(m, b, &horiz);
8639 printf(" Creating left ");
8640 printtriangle(m, b, &newbotleft);
8641 printf(" Creating right ");
8642 printtriangle(m, b, &newbotright);
8643 }
8644 }
8645
8646 /* The insertion is successful by default, unless an encroached */
8647 /* subsegment is found. */
8648 success = SUCCESSFULVERTEX;
8649 /* Circle around the newly inserted vertex, checking each edge opposite */
8650 /* it for the Delaunay property. Non-Delaunay edges are flipped. */
8651 /* `horiz' is always the edge being checked. `first' marks where to */
8652 /* stop circling. */
8653 org(horiz, first);
8654 rightvertex = first;
8655 dest(horiz, leftvertex);
8656 /* Circle until finished. */
8657 while (1) {
8658 /* By default, the edge will be flipped. */
8659 doflip = 1;
8660
8661 if (m->checksegments) {
8662 /* Check for a subsegment, which cannot be flipped. */
8663 tspivot(horiz, checksubseg);
8664 if (checksubseg.ss != m->dummysub) {
8665 /* The edge is a subsegment and cannot be flipped. */
8666 doflip = 0;
8667#ifndef CDT_ONLY
8668 if (segmentflaws) {
8669 /* Does the new vertex encroach upon this subsegment? */
8670 if (checkseg4encroach(m, b, &checksubseg)) {
8671 success = ENCROACHINGVERTEX;
8672 }
8673 }
8674#endif /* not CDT_ONLY */
8675 }
8676 }
8677
8678 if (doflip) {
8679 /* Check if the edge is a boundary edge. */
8680 sym(horiz, top);
8681 if (top.tri == m->dummytri) {
8682 /* The edge is a boundary edge and cannot be flipped. */
8683 doflip = 0;
8684 } else {
8685 /* Find the vertex on the other side of the edge. */
8686 apex(top, farvertex);
8687 /* In the incremental Delaunay triangulation algorithm, any of */
8688 /* `leftvertex', `rightvertex', and `farvertex' could be vertices */
8689 /* of the triangular bounding box. These vertices must be */
8690 /* treated as if they are infinitely distant, even though their */
8691 /* "coordinates" are not. */
8692 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
8693 (leftvertex == m->infvertex3)) {
8694 /* `leftvertex' is infinitely distant. Check the convexity of */
8695 /* the boundary of the triangulation. 'farvertex' might be */
8696 /* infinite as well, but trust me, this same condition should */
8697 /* be applied. */
8698 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
8699 > 0.0;
8700 } else if ((rightvertex == m->infvertex1) ||
8701 (rightvertex == m->infvertex2) ||
8702 (rightvertex == m->infvertex3)) {
8703 /* `rightvertex' is infinitely distant. Check the convexity of */
8704 /* the boundary of the triangulation. 'farvertex' might be */
8705 /* infinite as well, but trust me, this same condition should */
8706 /* be applied. */
8707 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
8708 > 0.0;
8709 } else if ((farvertex == m->infvertex1) ||
8710 (farvertex == m->infvertex2) ||
8711 (farvertex == m->infvertex3)) {
8712 /* `farvertex' is infinitely distant and cannot be inside */
8713 /* the circumcircle of the triangle `horiz'. */
8714 doflip = 0;
8715 } else {
8716 /* Test whether the edge is locally Delaunay. */
8717 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
8718 farvertex) > 0.0;
8719 }
8720 if (doflip) {
8721 /* We made it! Flip the edge `horiz' by rotating its containing */
8722 /* quadrilateral (the two triangles adjacent to `horiz'). */
8723 /* Identify the casing of the quadrilateral. */
8724 lprev(top, topleft);
8725 sym(topleft, toplcasing);
8726 lnext(top, topright);
8727 sym(topright, toprcasing);
8728 lnext(horiz, botleft);
8729 sym(botleft, botlcasing);
8730 lprev(horiz, botright);
8731 sym(botright, botrcasing);
8732 /* Rotate the quadrilateral one-quarter turn counterclockwise. */
8733 bond(topleft, botlcasing);
8734 bond(botleft, botrcasing);
8735 bond(botright, toprcasing);
8736 bond(topright, toplcasing);
8737 if (m->checksegments) {
8738 /* Check for subsegments and rebond them to the quadrilateral. */
8739 tspivot(topleft, toplsubseg);
8740 tspivot(botleft, botlsubseg);
8741 tspivot(botright, botrsubseg);
8742 tspivot(topright, toprsubseg);
8743 if (toplsubseg.ss == m->dummysub) {
8744 tsdissolve(topright);
8745 } else {
8746 tsbond(topright, toplsubseg);
8747 }
8748 if (botlsubseg.ss == m->dummysub) {
8749 tsdissolve(topleft);
8750 } else {
8751 tsbond(topleft, botlsubseg);
8752 }
8753 if (botrsubseg.ss == m->dummysub) {
8754 tsdissolve(botleft);
8755 } else {
8756 tsbond(botleft, botrsubseg);
8757 }
8758 if (toprsubseg.ss == m->dummysub) {
8759 tsdissolve(botright);
8760 } else {
8761 tsbond(botright, toprsubseg);
8762 }
8763 }
8764 /* New vertex assignments for the rotated quadrilateral. */
8765 setorg(horiz, farvertex);
8766 setdest(horiz, newvertex);
8767 setapex(horiz, rightvertex);
8768 setorg(top, newvertex);
8769 setdest(top, farvertex);
8770 setapex(top, leftvertex);
8771 for (i = 0; i < m->eextras; i++) {
8772 /* Take the average of the two triangles' attributes. */
8773 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
8774 setelemattribute(top, i, attrib);
8775 setelemattribute(horiz, i, attrib);
8776 }
8777 if (b->vararea) {
8778 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
8779 area = -1.0;
8780 } else {
8781 /* Take the average of the two triangles' area constraints. */
8782 /* This prevents small area constraints from migrating a */
8783 /* long, long way from their original location due to flips. */
8784 area = 0.5 * (areabound(top) + areabound(horiz));
8785 }
8786 setareabound(top, area);
8787 setareabound(horiz, area);
8788 }
8789
8790 if (m->checkquality) {
8791 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
8792 newflip->flippedtri = encode(horiz);
8793 newflip->prevflip = m->lastflip;
8794 m->lastflip = newflip;
8795 }
8796
8797#ifdef SELF_CHECK
8798 if (newvertex != (vertex) NULL) {
8799 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
8800 0.0) {
8801 printf("Internal error in insertvertex():\n");
8802 printf(" Clockwise triangle prior to edge flip (bottom).\n");
8803 }
8804 /* The following test has been removed because constrainededge() */
8805 /* sometimes generates inverted triangles that insertvertex() */
8806 /* removes. */
8807/*
8808 if (counterclockwise(m, b, rightvertex, farvertex, leftvertex) <
8809 0.0) {
8810 printf("Internal error in insertvertex():\n");
8811 printf(" Clockwise triangle prior to edge flip (top).\n");
8812 }
8813*/
8814 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
8815 0.0) {
8816 printf("Internal error in insertvertex():\n");
8817 printf(" Clockwise triangle after edge flip (left).\n");
8818 }
8819 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
8820 0.0) {
8821 printf("Internal error in insertvertex():\n");
8822 printf(" Clockwise triangle after edge flip (right).\n");
8823 }
8824 }
8825#endif /* SELF_CHECK */
8826 if (b->verbose > 2) {
8827 printf(" Edge flip results in left ");
8828 lnextself(topleft);
8829 printtriangle(m, b, &topleft);
8830 printf(" and right ");
8831 printtriangle(m, b, &horiz);
8832 }
8833 /* On the next iterations, consider the two edges that were */
8834 /* exposed (this is, are now visible to the newly inserted */
8835 /* vertex) by the edge flip. */
8836 lprevself(horiz);
8837 leftvertex = farvertex;
8838 }
8839 }
8840 }
8841 if (!doflip) {
8842 /* The handle `horiz' is accepted as locally Delaunay. */
8843#ifndef CDT_ONLY
8844 if (triflaws) {
8845 /* Check the triangle `horiz' for quality. */
8846 testtriangle(m, b, &horiz);
8847 }
8848#endif /* not CDT_ONLY */
8849 /* Look for the next edge around the newly inserted vertex. */
8850 lnextself(horiz);
8851 sym(horiz, testtri);
8852 /* Check for finishing a complete revolution about the new vertex, or */
8853 /* falling outside of the triangulation. The latter will happen */
8854 /* when a vertex is inserted at a boundary. */
8855 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
8856 /* We're done. Return a triangle whose origin is the new vertex. */
8857 lnext(horiz, *searchtri);
8858 lnext(horiz, m->recenttri);
8859 return success;
8860 }
8861 /* Finish finding the next edge around the newly inserted vertex. */
8862 lnext(testtri, horiz);
8863 rightvertex = leftvertex;
8864 dest(horiz, leftvertex);
8865 }
8866 }
8867}
8868
8869/*****************************************************************************/
8870/* */
8871/* triangulatepolygon() Find the Delaunay triangulation of a polygon that */
8872/* has a certain "nice" shape. This includes the */
8873/* polygons that result from deletion of a vertex or */
8874/* insertion of a segment. */
8875/* */
8876/* This is a conceptually difficult routine. The starting assumption is */
8877/* that we have a polygon with n sides. n - 1 of these sides are currently */
8878/* represented as edges in the mesh. One side, called the "base", need not */
8879/* be. */
8880/* */
8881/* Inside the polygon is a structure I call a "fan", consisting of n - 1 */
8882/* triangles that share a common origin. For each of these triangles, the */
8883/* edge opposite the origin is one of the sides of the polygon. The */
8884/* primary edge of each triangle is the edge directed from the origin to */
8885/* the destination; note that this is not the same edge that is a side of */
8886/* the polygon. `firstedge' is the primary edge of the first triangle. */
8887/* From there, the triangles follow in counterclockwise order about the */
8888/* polygon, until `lastedge', the primary edge of the last triangle. */
8889/* `firstedge' and `lastedge' are probably connected to other triangles */
8890/* beyond the extremes of the fan, but their identity is not important, as */
8891/* long as the fan remains connected to them. */
8892/* */
8893/* Imagine the polygon oriented so that its base is at the bottom. This */
8894/* puts `firstedge' on the far right, and `lastedge' on the far left. */
8895/* The right vertex of the base is the destination of `firstedge', and the */
8896/* left vertex of the base is the apex of `lastedge'. */
8897/* */
8898/* The challenge now is to find the right sequence of edge flips to */
8899/* transform the fan into a Delaunay triangulation of the polygon. Each */
8900/* edge flip effectively removes one triangle from the fan, committing it */
8901/* to the polygon. The resulting polygon has one fewer edge. If `doflip' */
8902/* is set, the final flip will be performed, resulting in a fan of one */
8903/* (useless?) triangle. If `doflip' is not set, the final flip is not */
8904/* performed, resulting in a fan of two triangles, and an unfinished */
8905/* triangular polygon that is not yet filled out with a single triangle. */
8906/* On completion of the routine, `lastedge' is the last remaining triangle, */
8907/* or the leftmost of the last two. */
8908/* */
8909/* Although the flips are performed in the order described above, the */
8910/* decisions about what flips to perform are made in precisely the reverse */
8911/* order. The recursive triangulatepolygon() procedure makes a decision, */
8912/* uses up to two recursive calls to triangulate the "subproblems" */
8913/* (polygons with fewer edges), and then performs an edge flip. */
8914/* */
8915/* The "decision" it makes is which vertex of the polygon should be */
8916/* connected to the base. This decision is made by testing every possible */
8917/* vertex. Once the best vertex is found, the two edges that connect this */
8918/* vertex to the base become the bases for two smaller polygons. These */
8919/* are triangulated recursively. Unfortunately, this approach can take */
8920/* O(n^2) time not only in the worst case, but in many common cases. It's */
8921/* rarely a big deal for vertex deletion, where n is rarely larger than */
8922/* ten, but it could be a big deal for segment insertion, especially if */
8923/* there's a lot of long segments that each cut many triangles. I ought to */
8924/* code a faster algorithm some day. */
8925/* */
8926/* The `edgecount' parameter is the number of sides of the polygon, */
8927/* including its base. `triflaws' is a flag that determines whether the */
8928/* new triangles should be tested for quality, and enqueued if they are */
8929/* bad. */
8930/* */
8931/*****************************************************************************/
8932
8933#ifdef ANSI_DECLARATORS
8934void triangulatepolygon(struct mesh *m, struct behavior *b,
8935 struct otri *firstedge, struct otri *lastedge,
8936 int edgecount, int doflip, int triflaws)
8937#else /* not ANSI_DECLARATORS */
8938void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
8939struct mesh *m;
8940struct behavior *b;
8941struct otri *firstedge;
8942struct otri *lastedge;
8943int edgecount;
8944int doflip;
8945int triflaws;
8946#endif /* not ANSI_DECLARATORS */
8947
8948{
8949 struct otri testtri;
8950 struct otri besttri;
8951 struct otri tempedge;
8952 vertex leftbasevertex, rightbasevertex;
8953 vertex testvertex;
8954 vertex bestvertex;
8955 int bestnumber;
8956 int i;
8957 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
8958
8959 /* Identify the base vertices. */
8960 apex(*lastedge, leftbasevertex);
8961 dest(*firstedge, rightbasevertex);
8962 if (b->verbose > 2) {
8963 printf(" Triangulating interior polygon at edge\n");
8964 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
8965 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
8966 }
8967 /* Find the best vertex to connect the base to. */
8968 onext(*firstedge, besttri);
8969 dest(besttri, bestvertex);
8970 otricopy(besttri, testtri);
8971 bestnumber = 1;
8972 for (i = 2; i <= edgecount - 2; i++) {
8973 onextself(testtri);
8974 dest(testtri, testvertex);
8975 /* Is this a better vertex? */
8976 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
8977 testvertex) > 0.0) {
8978 otricopy(testtri, besttri);
8979 bestvertex = testvertex;
8980 bestnumber = i;
8981 }
8982 }
8983 if (b->verbose > 2) {
8984 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
8985 bestvertex[1]);
8986 }
8987 if (bestnumber > 1) {
8988 /* Recursively triangulate the smaller polygon on the right. */
8989 oprev(besttri, tempedge);
8990 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
8991 triflaws);
8992 }
8993 if (bestnumber < edgecount - 2) {
8994 /* Recursively triangulate the smaller polygon on the left. */
8995 sym(besttri, tempedge);
8996 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
8997 triflaws);
8998 /* Find `besttri' again; it may have been lost to edge flips. */
8999 sym(tempedge, besttri);
9000 }
9001 if (doflip) {
9002 /* Do one final edge flip. */
9003 flip(m, b, &besttri);
9004#ifndef CDT_ONLY
9005 if (triflaws) {
9006 /* Check the quality of the newly committed triangle. */
9007 sym(besttri, testtri);
9008 testtriangle(m, b, &testtri);
9009 }
9010#endif /* not CDT_ONLY */
9011 }
9012 /* Return the base triangle. */
9013 otricopy(besttri, *lastedge);
9014}
9015
9016/*****************************************************************************/
9017/* */
9018/* deletevertex() Delete a vertex from a Delaunay triangulation, ensuring */
9019/* that the triangulation remains Delaunay. */
9020/* */
9021/* The origin of `deltri' is deleted. The union of the triangles adjacent */
9022/* to this vertex is a polygon, for which the Delaunay triangulation is */
9023/* found. Two triangles are removed from the mesh. */
9024/* */
9025/* Only interior vertices that do not lie on segments or boundaries may be */
9026/* deleted. */
9027/* */
9028/*****************************************************************************/
9029
9030#ifndef CDT_ONLY
9031
9032#ifdef ANSI_DECLARATORS
9033void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
9034#else /* not ANSI_DECLARATORS */
9035void deletevertex(m, b, deltri)
9036struct mesh *m;
9037struct behavior *b;
9038struct otri *deltri;
9039#endif /* not ANSI_DECLARATORS */
9040
9041{
9042 struct otri countingtri;
9043 struct otri firstedge, lastedge;
9044 struct otri deltriright;
9045 struct otri lefttri, righttri;
9046 struct otri leftcasing, rightcasing;
9047 struct osub leftsubseg, rightsubseg;
9048 vertex delvertex;
9049 vertex neworg;
9050 int edgecount;
9051 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
9052 subseg sptr; /* Temporary variable used by tspivot(). */
9053
9054 org(*deltri, delvertex);
9055 if (b->verbose > 1) {
9056 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
9057 }
9058 vertexdealloc(m, delvertex);
9059
9060 /* Count the degree of the vertex being deleted. */
9061 onext(*deltri, countingtri);
9062 edgecount = 1;
9063 while (!otriequal(*deltri, countingtri)) {
9064#ifdef SELF_CHECK
9065 if (countingtri.tri == m->dummytri) {
9066 printf("Internal error in deletevertex():\n");
9067 printf(" Attempt to delete boundary vertex.\n");
9068 internalerror();
9069 }
9070#endif /* SELF_CHECK */
9071 edgecount++;
9072 onextself(countingtri);
9073 }
9074
9075#ifdef SELF_CHECK
9076 if (edgecount < 3) {
9077 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
9078 edgecount);
9079 internalerror();
9080 }
9081#endif /* SELF_CHECK */
9082 if (edgecount > 3) {
9083 /* Triangulate the polygon defined by the union of all triangles */
9084 /* adjacent to the vertex being deleted. Check the quality of */
9085 /* the resulting triangles. */
9086 onext(*deltri, firstedge);
9087 oprev(*deltri, lastedge);
9088 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
9089 !b->nobisect);
9090 }
9091 /* Splice out two triangles. */
9092 lprev(*deltri, deltriright);
9093 dnext(*deltri, lefttri);
9094 sym(lefttri, leftcasing);
9095 oprev(deltriright, righttri);
9096 sym(righttri, rightcasing);
9097 bond(*deltri, leftcasing);
9098 bond(deltriright, rightcasing);
9099 tspivot(lefttri, leftsubseg);
9100 if (leftsubseg.ss != m->dummysub) {
9101 tsbond(*deltri, leftsubseg);
9102 }
9103 tspivot(righttri, rightsubseg);
9104 if (rightsubseg.ss != m->dummysub) {
9105 tsbond(deltriright, rightsubseg);
9106 }
9107
9108 /* Set the new origin of `deltri' and check its quality. */
9109 org(lefttri, neworg);
9110 setorg(*deltri, neworg);
9111 if (!b->nobisect) {
9112 testtriangle(m, b, deltri);
9113 }
9114
9115 /* Delete the two spliced-out triangles. */
9116 triangledealloc(m, lefttri.tri);
9117 triangledealloc(m, righttri.tri);
9118}
9119
9120#endif /* not CDT_ONLY */
9121
9122/*****************************************************************************/
9123/* */
9124/* undovertex() Undo the most recent vertex insertion. */
9125/* */
9126/* Walks through the list of transformations (flips and a vertex insertion) */
9127/* in the reverse of the order in which they were done, and undoes them. */
9128/* The inserted vertex is removed from the triangulation and deallocated. */
9129/* Two triangles (possibly just one) are also deallocated. */
9130/* */
9131/*****************************************************************************/
9132
9133#ifndef CDT_ONLY
9134
9135#ifdef ANSI_DECLARATORS
9136void undovertex(struct mesh *m, struct behavior *b)
9137#else /* not ANSI_DECLARATORS */
9138void undovertex(m, b)
9139struct mesh *m;
9140struct behavior *b;
9141#endif /* not ANSI_DECLARATORS */
9142
9143{
9144 struct otri fliptri;
9145 struct otri botleft, botright, topright;
9146 struct otri botlcasing, botrcasing, toprcasing;
9147 struct otri gluetri;
9148 struct osub botlsubseg, botrsubseg, toprsubseg;
9149 vertex botvertex, rightvertex;
9150 triangle ptr; /* Temporary variable used by sym(). */
9151 subseg sptr; /* Temporary variable used by tspivot(). */
9152
9153 /* Walk through the list of transformations (flips and a vertex insertion) */
9154 /* in the reverse of the order in which they were done, and undo them. */
9155 while (m->lastflip != (struct flipstacker *) NULL) {
9156 /* Find a triangle involved in the last unreversed transformation. */
9157 decode(m->lastflip->flippedtri, fliptri);
9158
9159 /* We are reversing one of three transformations: a trisection of one */
9160 /* triangle into three (by inserting a vertex in the triangle), a */
9161 /* bisection of two triangles into four (by inserting a vertex in an */
9162 /* edge), or an edge flip. */
9163 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
9164 /* Restore a triangle that was split into three triangles, */
9165 /* so it is again one triangle. */
9166 dprev(fliptri, botleft);
9167 lnextself(botleft);
9168 onext(fliptri, botright);
9169 lprevself(botright);
9170 sym(botleft, botlcasing);
9171 sym(botright, botrcasing);
9172 dest(botleft, botvertex);
9173
9174 setapex(fliptri, botvertex);
9175 lnextself(fliptri);
9176 bond(fliptri, botlcasing);
9177 tspivot(botleft, botlsubseg);
9178 tsbond(fliptri, botlsubseg);
9179 lnextself(fliptri);
9180 bond(fliptri, botrcasing);
9181 tspivot(botright, botrsubseg);
9182 tsbond(fliptri, botrsubseg);
9183
9184 /* Delete the two spliced-out triangles. */
9185 triangledealloc(m, botleft.tri);
9186 triangledealloc(m, botright.tri);
9187 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
9188 /* Restore two triangles that were split into four triangles, */
9189 /* so they are again two triangles. */
9190 lprev(fliptri, gluetri);
9191 sym(gluetri, botright);
9192 lnextself(botright);
9193 sym(botright, botrcasing);
9194 dest(botright, rightvertex);
9195
9196 setorg(fliptri, rightvertex);
9197 bond(gluetri, botrcasing);
9198 tspivot(botright, botrsubseg);
9199 tsbond(gluetri, botrsubseg);
9200
9201 /* Delete the spliced-out triangle. */
9202 triangledealloc(m, botright.tri);
9203
9204 sym(fliptri, gluetri);
9205 if (gluetri.tri != m->dummytri) {
9206 lnextself(gluetri);
9207 dnext(gluetri, topright);
9208 sym(topright, toprcasing);
9209
9210 setorg(gluetri, rightvertex);
9211 bond(gluetri, toprcasing);
9212 tspivot(topright, toprsubseg);
9213 tsbond(gluetri, toprsubseg);
9214
9215 /* Delete the spliced-out triangle. */
9216 triangledealloc(m, topright.tri);
9217 }
9218
9219 /* This is the end of the list, sneakily encoded. */
9220 m->lastflip->prevflip = (struct flipstacker *) NULL;
9221 } else {
9222 /* Undo an edge flip. */
9223 unflip(m, b, &fliptri);
9224 }
9225
9226 /* Go on and process the next transformation. */
9227 m->lastflip = m->lastflip->prevflip;
9228 }
9229}
9230
9231#endif /* not CDT_ONLY */
9232
9235/********* Mesh transformation routines end here *********/
9236
9237/********* Divide-and-conquer Delaunay triangulation begins here *********/
9241/*****************************************************************************/
9242/* */
9243/* The divide-and-conquer bounding box */
9244/* */
9245/* I originally implemented the divide-and-conquer and incremental Delaunay */
9246/* triangulations using the edge-based data structure presented by Guibas */
9247/* and Stolfi. Switching to a triangle-based data structure doubled the */
9248/* speed. However, I had to think of a few extra tricks to maintain the */
9249/* elegance of the original algorithms. */
9250/* */
9251/* The "bounding box" used by my variant of the divide-and-conquer */
9252/* algorithm uses one triangle for each edge of the convex hull of the */
9253/* triangulation. These bounding triangles all share a common apical */
9254/* vertex, which is represented by NULL and which represents nothing. */
9255/* The bounding triangles are linked in a circular fan about this NULL */
9256/* vertex, and the edges on the convex hull of the triangulation appear */
9257/* opposite the NULL vertex. You might find it easiest to imagine that */
9258/* the NULL vertex is a point in 3D space behind the center of the */
9259/* triangulation, and that the bounding triangles form a sort of cone. */
9260/* */
9261/* This bounding box makes it easy to represent degenerate cases. For */
9262/* instance, the triangulation of two vertices is a single edge. This edge */
9263/* is represented by two bounding box triangles, one on each "side" of the */
9264/* edge. These triangles are also linked together in a fan about the NULL */
9265/* vertex. */
9266/* */
9267/* The bounding box also makes it easy to traverse the convex hull, as the */
9268/* divide-and-conquer algorithm needs to do. */
9269/* */
9270/*****************************************************************************/
9271
9272/*****************************************************************************/
9273/* */
9274/* vertexsort() Sort an array of vertices by x-coordinate, using the */
9275/* y-coordinate as a secondary key. */
9276/* */
9277/* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */
9278/* the usual quicksort mistakes. */
9279/* */
9280/*****************************************************************************/
9281
9282#ifdef ANSI_DECLARATORS
9283void vertexsort(vertex *sortarray, int arraysize)
9284#else /* not ANSI_DECLARATORS */
9285void vertexsort(sortarray, arraysize)
9286vertex *sortarray;
9287int arraysize;
9288#endif /* not ANSI_DECLARATORS */
9289
9290{
9291 int left, right;
9292 int pivot;
9293 REAL pivotx, pivoty;
9294 vertex temp;
9295
9296 if (arraysize == 2) {
9297 /* Recursive base case. */
9298 if ((sortarray[0][0] > sortarray[1][0]) ||
9299 ((sortarray[0][0] == sortarray[1][0]) &&
9300 (sortarray[0][1] > sortarray[1][1]))) {
9301 temp = sortarray[1];
9302 sortarray[1] = sortarray[0];
9303 sortarray[0] = temp;
9304 }
9305 return;
9306 }
9307 /* Choose a random pivot to split the array. */
9308 pivot = (int) randomnation((unsigned int) arraysize);
9309 pivotx = sortarray[pivot][0];
9310 pivoty = sortarray[pivot][1];
9311 /* Split the array. */
9312 left = -1;
9313 right = arraysize;
9314 while (left < right) {
9315 /* Search for a vertex whose x-coordinate is too large for the left. */
9316 do {
9317 left++;
9318 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
9319 ((sortarray[left][0] == pivotx) &&
9320 (sortarray[left][1] < pivoty))));
9321 /* Search for a vertex whose x-coordinate is too small for the right. */
9322 do {
9323 right--;
9324 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
9325 ((sortarray[right][0] == pivotx) &&
9326 (sortarray[right][1] > pivoty))));
9327 if (left < right) {
9328 /* Swap the left and right vertices. */
9329 temp = sortarray[left];
9330 sortarray[left] = sortarray[right];
9331 sortarray[right] = temp;
9332 }
9333 }
9334 if (left > 1) {
9335 /* Recursively sort the left subset. */
9336 vertexsort(sortarray, left);
9337 }
9338 if (right < arraysize - 2) {
9339 /* Recursively sort the right subset. */
9340 vertexsort(&sortarray[right + 1], arraysize - right - 1);
9341 }
9342}
9343
9344/*****************************************************************************/
9345/* */
9346/* vertexmedian() An order statistic algorithm, almost. Shuffles an */
9347/* array of vertices so that the first `median' vertices */
9348/* occur lexicographically before the remaining vertices. */
9349/* */
9350/* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */
9351/* if axis == 1. Very similar to the vertexsort() procedure, but runs in */
9352/* randomized linear time. */
9353/* */
9354/*****************************************************************************/
9355
9356#ifdef ANSI_DECLARATORS
9357void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
9358#else /* not ANSI_DECLARATORS */
9359void vertexmedian(sortarray, arraysize, median, axis)
9360vertex *sortarray;
9361int arraysize;
9362int median;
9363int axis;
9364#endif /* not ANSI_DECLARATORS */
9365
9366{
9367 int left, right;
9368 int pivot;
9369 REAL pivot1, pivot2;
9370 vertex temp;
9371
9372 if (arraysize == 2) {
9373 /* Recursive base case. */
9374 if ((sortarray[0][axis] > sortarray[1][axis]) ||
9375 ((sortarray[0][axis] == sortarray[1][axis]) &&
9376 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
9377 temp = sortarray[1];
9378 sortarray[1] = sortarray[0];
9379 sortarray[0] = temp;
9380 }
9381 return;
9382 }
9383 /* Choose a random pivot to split the array. */
9384 pivot = (int) randomnation((unsigned int) arraysize);
9385 pivot1 = sortarray[pivot][axis];
9386 pivot2 = sortarray[pivot][1 - axis];
9387 /* Split the array. */
9388 left = -1;
9389 right = arraysize;
9390 while (left < right) {
9391 /* Search for a vertex whose x-coordinate is too large for the left. */
9392 do {
9393 left++;
9394 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
9395 ((sortarray[left][axis] == pivot1) &&
9396 (sortarray[left][1 - axis] < pivot2))));
9397 /* Search for a vertex whose x-coordinate is too small for the right. */
9398 do {
9399 right--;
9400 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
9401 ((sortarray[right][axis] == pivot1) &&
9402 (sortarray[right][1 - axis] > pivot2))));
9403 if (left < right) {
9404 /* Swap the left and right vertices. */
9405 temp = sortarray[left];
9406 sortarray[left] = sortarray[right];
9407 sortarray[right] = temp;
9408 }
9409 }
9410 /* Unlike in vertexsort(), at most one of the following */
9411 /* conditionals is true. */
9412 if (left > median) {
9413 /* Recursively shuffle the left subset. */
9414 vertexmedian(sortarray, left, median, axis);
9415 }
9416 if (right < median - 1) {
9417 /* Recursively shuffle the right subset. */
9418 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
9419 median - right - 1, axis);
9420 }
9421}
9422
9423/*****************************************************************************/
9424/* */
9425/* alternateaxes() Sorts the vertices as appropriate for the divide-and- */
9426/* conquer algorithm with alternating cuts. */
9427/* */
9428/* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */
9429/* For the base case, subsets containing only two or three vertices are */
9430/* always sorted by x-coordinate. */
9431/* */
9432/*****************************************************************************/
9433
9434#ifdef ANSI_DECLARATORS
9435void alternateaxes(vertex *sortarray, int arraysize, int axis)
9436#else /* not ANSI_DECLARATORS */
9437void alternateaxes(sortarray, arraysize, axis)
9438vertex *sortarray;
9439int arraysize;
9440int axis;
9441#endif /* not ANSI_DECLARATORS */
9442
9443{
9444 int divider;
9445
9446 divider = arraysize >> 1;
9447 if (arraysize <= 3) {
9448 /* Recursive base case: subsets of two or three vertices will be */
9449 /* handled specially, and should always be sorted by x-coordinate. */
9450 axis = 0;
9451 }
9452 /* Partition with a horizontal or vertical cut. */
9453 vertexmedian(sortarray, arraysize, divider, axis);
9454 /* Recursively partition the subsets with a cross cut. */
9455 if (arraysize - divider >= 2) {
9456 if (divider >= 2) {
9457 alternateaxes(sortarray, divider, 1 - axis);
9458 }
9459 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
9460 }
9461}
9462
9463/*****************************************************************************/
9464/* */
9465/* mergehulls() Merge two adjacent Delaunay triangulations into a */
9466/* single Delaunay triangulation. */
9467/* */
9468/* This is similar to the algorithm given by Guibas and Stolfi, but uses */
9469/* a triangle-based, rather than edge-based, data structure. */
9470/* */
9471/* The algorithm walks up the gap between the two triangulations, knitting */
9472/* them together. As they are merged, some of their bounding triangles */
9473/* are converted into real triangles of the triangulation. The procedure */
9474/* pulls each hull's bounding triangles apart, then knits them together */
9475/* like the teeth of two gears. The Delaunay property determines, at each */
9476/* step, whether the next "tooth" is a bounding triangle of the left hull */
9477/* or the right. When a bounding triangle becomes real, its apex is */
9478/* changed from NULL to a real vertex. */
9479/* */
9480/* Only two new triangles need to be allocated. These become new bounding */
9481/* triangles at the top and bottom of the seam. They are used to connect */
9482/* the remaining bounding triangles (those that have not been converted */
9483/* into real triangles) into a single fan. */
9484/* */
9485/* On entry, `farleft' and `innerleft' are bounding triangles of the left */
9486/* triangulation. The origin of `farleft' is the leftmost vertex, and */
9487/* the destination of `innerleft' is the rightmost vertex of the */
9488/* triangulation. Similarly, `innerright' and `farright' are bounding */
9489/* triangles of the right triangulation. The origin of `innerright' and */
9490/* destination of `farright' are the leftmost and rightmost vertices. */
9491/* */
9492/* On completion, the origin of `farleft' is the leftmost vertex of the */
9493/* merged triangulation, and the destination of `farright' is the rightmost */
9494/* vertex. */
9495/* */
9496/*****************************************************************************/
9497
9498#ifdef ANSI_DECLARATORS
9499void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
9500 struct otri *innerleft, struct otri *innerright,
9501 struct otri *farright, int axis)
9502#else /* not ANSI_DECLARATORS */
9503void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
9504struct mesh *m;
9505struct behavior *b;
9506struct otri *farleft;
9507struct otri *innerleft;
9508struct otri *innerright;
9509struct otri *farright;
9510int axis;
9511#endif /* not ANSI_DECLARATORS */
9512
9513{
9514 struct otri leftcand, rightcand;
9515 struct otri baseedge;
9516 struct otri nextedge;
9517 struct otri sidecasing, topcasing, outercasing;
9518 struct otri checkedge;
9519 vertex innerleftdest;
9520 vertex innerrightorg;
9521 vertex innerleftapex, innerrightapex;
9522 vertex farleftpt, farrightpt;
9523 vertex farleftapex, farrightapex;
9524 vertex lowerleft, lowerright;
9525 vertex upperleft, upperright;
9526 vertex nextapex;
9527 vertex checkvertex;
9528 int changemade;
9529 int badedge;
9530 int leftfinished, rightfinished;
9531 triangle ptr; /* Temporary variable used by sym(). */
9532
9533 dest(*innerleft, innerleftdest);
9534 apex(*innerleft, innerleftapex);
9535 org(*innerright, innerrightorg);
9536 apex(*innerright, innerrightapex);
9537 /* Special treatment for horizontal cuts. */
9538 if (b->dwyer && (axis == 1)) {
9539 org(*farleft, farleftpt);
9540 apex(*farleft, farleftapex);
9541 dest(*farright, farrightpt);
9542 apex(*farright, farrightapex);
9543 /* The pointers to the extremal vertices are shifted to point to the */
9544 /* topmost and bottommost vertex of each hull, rather than the */
9545 /* leftmost and rightmost vertices. */
9546 while (farleftapex[1] < farleftpt[1]) {
9547 lnextself(*farleft);
9548 symself(*farleft);
9549 farleftpt = farleftapex;
9550 apex(*farleft, farleftapex);
9551 }
9552 sym(*innerleft, checkedge);
9553 apex(checkedge, checkvertex);
9554 while (checkvertex[1] > innerleftdest[1]) {
9555 lnext(checkedge, *innerleft);
9556 innerleftapex = innerleftdest;
9557 innerleftdest = checkvertex;
9558 sym(*innerleft, checkedge);
9559 apex(checkedge, checkvertex);
9560 }
9561 while (innerrightapex[1] < innerrightorg[1]) {
9562 lnextself(*innerright);
9563 symself(*innerright);
9564 innerrightorg = innerrightapex;
9565 apex(*innerright, innerrightapex);
9566 }
9567 sym(*farright, checkedge);
9568 apex(checkedge, checkvertex);
9569 while (checkvertex[1] > farrightpt[1]) {
9570 lnext(checkedge, *farright);
9571 farrightapex = farrightpt;
9572 farrightpt = checkvertex;
9573 sym(*farright, checkedge);
9574 apex(checkedge, checkvertex);
9575 }
9576 }
9577 /* Find a line tangent to and below both hulls. */
9578 do {
9579 changemade = 0;
9580 /* Make innerleftdest the "bottommost" vertex of the left hull. */
9581 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
9582 0.0) {
9583 lprevself(*innerleft);
9584 symself(*innerleft);
9585 innerleftdest = innerleftapex;
9586 apex(*innerleft, innerleftapex);
9587 changemade = 1;
9588 }
9589 /* Make innerrightorg the "bottommost" vertex of the right hull. */
9590 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
9591 0.0) {
9592 lnextself(*innerright);
9593 symself(*innerright);
9594 innerrightorg = innerrightapex;
9595 apex(*innerright, innerrightapex);
9596 changemade = 1;
9597 }
9598 } while (changemade);
9599 /* Find the two candidates to be the next "gear tooth." */
9600 sym(*innerleft, leftcand);
9601 sym(*innerright, rightcand);
9602 /* Create the bottom new bounding triangle. */
9603 maketriangle(m, b, &baseedge);
9604 /* Connect it to the bounding boxes of the left and right triangulations. */
9605 bond(baseedge, *innerleft);
9606 lnextself(baseedge);
9607 bond(baseedge, *innerright);
9608 lnextself(baseedge);
9609 setorg(baseedge, innerrightorg);
9610 setdest(baseedge, innerleftdest);
9611 /* Apex is intentionally left NULL. */
9612 if (b->verbose > 2) {
9613 printf(" Creating base bounding ");
9614 printtriangle(m, b, &baseedge);
9615 }
9616 /* Fix the extreme triangles if necessary. */
9617 org(*farleft, farleftpt);
9618 if (innerleftdest == farleftpt) {
9619 lnext(baseedge, *farleft);
9620 }
9621 dest(*farright, farrightpt);
9622 if (innerrightorg == farrightpt) {
9623 lprev(baseedge, *farright);
9624 }
9625 /* The vertices of the current knitting edge. */
9626 lowerleft = innerleftdest;
9627 lowerright = innerrightorg;
9628 /* The candidate vertices for knitting. */
9629 apex(leftcand, upperleft);
9630 apex(rightcand, upperright);
9631 /* Walk up the gap between the two triangulations, knitting them together. */
9632 while (1) {
9633 /* Have we reached the top? (This isn't quite the right question, */
9634 /* because even though the left triangulation might seem finished now, */
9635 /* moving up on the right triangulation might reveal a new vertex of */
9636 /* the left triangulation. And vice-versa.) */
9637 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
9638 0.0;
9639 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
9640 <= 0.0;
9641 if (leftfinished && rightfinished) {
9642 /* Create the top new bounding triangle. */
9643 maketriangle(m, b, &nextedge);
9644 setorg(nextedge, lowerleft);
9645 setdest(nextedge, lowerright);
9646 /* Apex is intentionally left NULL. */
9647 /* Connect it to the bounding boxes of the two triangulations. */
9648 bond(nextedge, baseedge);
9649 lnextself(nextedge);
9650 bond(nextedge, rightcand);
9651 lnextself(nextedge);
9652 bond(nextedge, leftcand);
9653 if (b->verbose > 2) {
9654 printf(" Creating top bounding ");
9655 printtriangle(m, b, &nextedge);
9656 }
9657 /* Special treatment for horizontal cuts. */
9658 if (b->dwyer && (axis == 1)) {
9659 org(*farleft, farleftpt);
9660 apex(*farleft, farleftapex);
9661 dest(*farright, farrightpt);
9662 apex(*farright, farrightapex);
9663 sym(*farleft, checkedge);
9664 apex(checkedge, checkvertex);
9665 /* The pointers to the extremal vertices are restored to the */
9666 /* leftmost and rightmost vertices (rather than topmost and */
9667 /* bottommost). */
9668 while (checkvertex[0] < farleftpt[0]) {
9669 lprev(checkedge, *farleft);
9670 farleftapex = farleftpt;
9671 farleftpt = checkvertex;
9672 sym(*farleft, checkedge);
9673 apex(checkedge, checkvertex);
9674 }
9675 while (farrightapex[0] > farrightpt[0]) {
9676 lprevself(*farright);
9677 symself(*farright);
9678 farrightpt = farrightapex;
9679 apex(*farright, farrightapex);
9680 }
9681 }
9682 return;
9683 }
9684 /* Consider eliminating edges from the left triangulation. */
9685 if (!leftfinished) {
9686 /* What vertex would be exposed if an edge were deleted? */
9687 lprev(leftcand, nextedge);
9688 symself(nextedge);
9689 apex(nextedge, nextapex);
9690 /* If nextapex is NULL, then no vertex would be exposed; the */
9691 /* triangulation would have been eaten right through. */
9692 if (nextapex != (vertex) NULL) {
9693 /* Check whether the edge is Delaunay. */
9694 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
9695 0.0;
9696 while (badedge) {
9697 /* Eliminate the edge with an edge flip. As a result, the */
9698 /* left triangulation will have one more boundary triangle. */
9699 lnextself(nextedge);
9700 sym(nextedge, topcasing);
9701 lnextself(nextedge);
9702 sym(nextedge, sidecasing);
9703 bond(nextedge, topcasing);
9704 bond(leftcand, sidecasing);
9705 lnextself(leftcand);
9706 sym(leftcand, outercasing);
9707 lprevself(nextedge);
9708 bond(nextedge, outercasing);
9709 /* Correct the vertices to reflect the edge flip. */
9710 setorg(leftcand, lowerleft);
9711 setdest(leftcand, NULL);
9712 setapex(leftcand, nextapex);
9713 setorg(nextedge, NULL);
9714 setdest(nextedge, upperleft);
9715 setapex(nextedge, nextapex);
9716 /* Consider the newly exposed vertex. */
9717 upperleft = nextapex;
9718 /* What vertex would be exposed if another edge were deleted? */
9719 otricopy(sidecasing, nextedge);
9720 apex(nextedge, nextapex);
9721 if (nextapex != (vertex) NULL) {
9722 /* Check whether the edge is Delaunay. */
9723 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
9724 nextapex) > 0.0;
9725 } else {
9726 /* Avoid eating right through the triangulation. */
9727 badedge = 0;
9728 }
9729 }
9730 }
9731 }
9732 /* Consider eliminating edges from the right triangulation. */
9733 if (!rightfinished) {
9734 /* What vertex would be exposed if an edge were deleted? */
9735 lnext(rightcand, nextedge);
9736 symself(nextedge);
9737 apex(nextedge, nextapex);
9738 /* If nextapex is NULL, then no vertex would be exposed; the */
9739 /* triangulation would have been eaten right through. */
9740 if (nextapex != (vertex) NULL) {
9741 /* Check whether the edge is Delaunay. */
9742 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
9743 0.0;
9744 while (badedge) {
9745 /* Eliminate the edge with an edge flip. As a result, the */
9746 /* right triangulation will have one more boundary triangle. */
9747 lprevself(nextedge);
9748 sym(nextedge, topcasing);
9749 lprevself(nextedge);
9750 sym(nextedge, sidecasing);
9751 bond(nextedge, topcasing);
9752 bond(rightcand, sidecasing);
9753 lprevself(rightcand);
9754 sym(rightcand, outercasing);
9755 lnextself(nextedge);
9756 bond(nextedge, outercasing);
9757 /* Correct the vertices to reflect the edge flip. */
9758 setorg(rightcand, NULL);
9759 setdest(rightcand, lowerright);
9760 setapex(rightcand, nextapex);
9761 setorg(nextedge, upperright);
9762 setdest(nextedge, NULL);
9763 setapex(nextedge, nextapex);
9764 /* Consider the newly exposed vertex. */
9765 upperright = nextapex;
9766 /* What vertex would be exposed if another edge were deleted? */
9767 otricopy(sidecasing, nextedge);
9768 apex(nextedge, nextapex);
9769 if (nextapex != (vertex) NULL) {
9770 /* Check whether the edge is Delaunay. */
9771 badedge = incircle(m, b, lowerleft, lowerright, upperright,
9772 nextapex) > 0.0;
9773 } else {
9774 /* Avoid eating right through the triangulation. */
9775 badedge = 0;
9776 }
9777 }
9778 }
9779 }
9780 if (leftfinished || (!rightfinished &&
9781 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
9782 0.0))) {
9783 /* Knit the triangulations, adding an edge from `lowerleft' */
9784 /* to `upperright'. */
9785 bond(baseedge, rightcand);
9786 lprev(rightcand, baseedge);
9787 setdest(baseedge, lowerleft);
9788 lowerright = upperright;
9789 sym(baseedge, rightcand);
9790 apex(rightcand, upperright);
9791 } else {
9792 /* Knit the triangulations, adding an edge from `upperleft' */
9793 /* to `lowerright'. */
9794 bond(baseedge, leftcand);
9795 lnext(leftcand, baseedge);
9796 setorg(baseedge, lowerright);
9797 lowerleft = upperleft;
9798 sym(baseedge, leftcand);
9799 apex(leftcand, upperleft);
9800 }
9801 if (b->verbose > 2) {
9802 printf(" Connecting ");
9803 printtriangle(m, b, &baseedge);
9804 }
9805 }
9806}
9807
9808/*****************************************************************************/
9809/* */
9810/* divconqrecurse() Recursively form a Delaunay triangulation by the */
9811/* divide-and-conquer method. */
9812/* */
9813/* Recursively breaks down the problem into smaller pieces, which are */
9814/* knitted together by mergehulls(). The base cases (problems of two or */
9815/* three vertices) are handled specially here. */
9816/* */
9817/* On completion, `farleft' and `farright' are bounding triangles such that */
9818/* the origin of `farleft' is the leftmost vertex (breaking ties by */
9819/* choosing the highest leftmost vertex), and the destination of */
9820/* `farright' is the rightmost vertex (breaking ties by choosing the */
9821/* lowest rightmost vertex). */
9822/* */
9823/*****************************************************************************/
9824
9825#ifdef ANSI_DECLARATORS
9826void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
9827 int vertices, int axis,
9828 struct otri *farleft, struct otri *farright)
9829#else /* not ANSI_DECLARATORS */
9830void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
9831struct mesh *m;
9832struct behavior *b;
9833vertex *sortarray;
9834int vertices;
9835int axis;
9836struct otri *farleft;
9837struct otri *farright;
9838#endif /* not ANSI_DECLARATORS */
9839
9840{
9841 struct otri midtri, tri1, tri2, tri3;
9842 struct otri innerleft, innerright;
9843 REAL area;
9844 int divider;
9845
9846 if (b->verbose > 2) {
9847 printf(" Triangulating %d vertices.\n", vertices);
9848 }
9849 if (vertices == 2) {
9850 /* The triangulation of two vertices is an edge. An edge is */
9851 /* represented by two bounding triangles. */
9852 maketriangle(m, b, farleft);
9853 setorg(*farleft, sortarray[0]);
9854 setdest(*farleft, sortarray[1]);
9855 /* The apex is intentionally left NULL. */
9856 maketriangle(m, b, farright);
9857 setorg(*farright, sortarray[1]);
9858 setdest(*farright, sortarray[0]);
9859 /* The apex is intentionally left NULL. */
9860 bond(*farleft, *farright);
9861 lprevself(*farleft);
9862 lnextself(*farright);
9863 bond(*farleft, *farright);
9864 lprevself(*farleft);
9865 lnextself(*farright);
9866 bond(*farleft, *farright);
9867 if (b->verbose > 2) {
9868 printf(" Creating ");
9869 printtriangle(m, b, farleft);
9870 printf(" Creating ");
9871 printtriangle(m, b, farright);
9872 }
9873 /* Ensure that the origin of `farleft' is sortarray[0]. */
9874 lprev(*farright, *farleft);
9875 return;
9876 } else if (vertices == 3) {
9877 /* The triangulation of three vertices is either a triangle (with */
9878 /* three bounding triangles) or two edges (with four bounding */
9879 /* triangles). In either case, four triangles are created. */
9880 maketriangle(m, b, &midtri);
9881 maketriangle(m, b, &tri1);
9882 maketriangle(m, b, &tri2);
9883 maketriangle(m, b, &tri3);
9884 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
9885 if (area == 0.0) {
9886 /* Three collinear vertices; the triangulation is two edges. */
9887 setorg(midtri, sortarray[0]);
9888 setdest(midtri, sortarray[1]);
9889 setorg(tri1, sortarray[1]);
9890 setdest(tri1, sortarray[0]);
9891 setorg(tri2, sortarray[2]);
9892 setdest(tri2, sortarray[1]);
9893 setorg(tri3, sortarray[1]);
9894 setdest(tri3, sortarray[2]);
9895 /* All apices are intentionally left NULL. */
9896 bond(midtri, tri1);
9897 bond(tri2, tri3);
9898 lnextself(midtri);
9899 lprevself(tri1);
9900 lnextself(tri2);
9901 lprevself(tri3);
9902 bond(midtri, tri3);
9903 bond(tri1, tri2);
9904 lnextself(midtri);
9905 lprevself(tri1);
9906 lnextself(tri2);
9907 lprevself(tri3);
9908 bond(midtri, tri1);
9909 bond(tri2, tri3);
9910 /* Ensure that the origin of `farleft' is sortarray[0]. */
9911 otricopy(tri1, *farleft);
9912 /* Ensure that the destination of `farright' is sortarray[2]. */
9913 otricopy(tri2, *farright);
9914 } else {
9915 /* The three vertices are not collinear; the triangulation is one */
9916 /* triangle, namely `midtri'. */
9917 setorg(midtri, sortarray[0]);
9918 setdest(tri1, sortarray[0]);
9919 setorg(tri3, sortarray[0]);
9920 /* Apices of tri1, tri2, and tri3 are left NULL. */
9921 if (area > 0.0) {
9922 /* The vertices are in counterclockwise order. */
9923 setdest(midtri, sortarray[1]);
9924 setorg(tri1, sortarray[1]);
9925 setdest(tri2, sortarray[1]);
9926 setapex(midtri, sortarray[2]);
9927 setorg(tri2, sortarray[2]);
9928 setdest(tri3, sortarray[2]);
9929 } else {
9930 /* The vertices are in clockwise order. */
9931 setdest(midtri, sortarray[2]);
9932 setorg(tri1, sortarray[2]);
9933 setdest(tri2, sortarray[2]);
9934 setapex(midtri, sortarray[1]);
9935 setorg(tri2, sortarray[1]);
9936 setdest(tri3, sortarray[1]);
9937 }
9938 /* The topology does not depend on how the vertices are ordered. */
9939 bond(midtri, tri1);
9940 lnextself(midtri);
9941 bond(midtri, tri2);
9942 lnextself(midtri);
9943 bond(midtri, tri3);
9944 lprevself(tri1);
9945 lnextself(tri2);
9946 bond(tri1, tri2);
9947 lprevself(tri1);
9948 lprevself(tri3);
9949 bond(tri1, tri3);
9950 lnextself(tri2);
9951 lprevself(tri3);
9952 bond(tri2, tri3);
9953 /* Ensure that the origin of `farleft' is sortarray[0]. */
9954 otricopy(tri1, *farleft);
9955 /* Ensure that the destination of `farright' is sortarray[2]. */
9956 if (area > 0.0) {
9957 otricopy(tri2, *farright);
9958 } else {
9959 lnext(*farleft, *farright);
9960 }
9961 }
9962 if (b->verbose > 2) {
9963 printf(" Creating ");
9964 printtriangle(m, b, &midtri);
9965 printf(" Creating ");
9966 printtriangle(m, b, &tri1);
9967 printf(" Creating ");
9968 printtriangle(m, b, &tri2);
9969 printf(" Creating ");
9970 printtriangle(m, b, &tri3);
9971 }
9972 return;
9973 } else {
9974 /* Split the vertices in half. */
9975 divider = vertices >> 1;
9976 /* Recursively triangulate each half. */
9977 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
9978 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
9979 &innerright, farright);
9980 if (b->verbose > 1) {
9981 printf(" Joining triangulations with %d and %d vertices.\n", divider,
9982 vertices - divider);
9983 }
9984 /* Merge the two triangulations into one. */
9985 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
9986 }
9987}
9988
9989#ifdef ANSI_DECLARATORS
9990long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
9991#else /* not ANSI_DECLARATORS */
9992long removeghosts(m, b, startghost)
9993struct mesh *m;
9994struct behavior *b;
9995struct otri *startghost;
9996#endif /* not ANSI_DECLARATORS */
9997
9998{
9999 struct otri searchedge;
10000 struct otri dissolveedge;
10001 struct otri deadtriangle;
10002 vertex markorg;
10003 long hullsize;
10004 triangle ptr; /* Temporary variable used by sym(). */
10005
10006 if (b->verbose) {
10007 printf(" Removing ghost triangles.\n");
10008 }
10009 /* Find an edge on the convex hull to start point location from. */
10010 lprev(*startghost, searchedge);
10011 symself(searchedge);
10012 m->dummytri[0] = encode(searchedge);
10013 /* Remove the bounding box and count the convex hull edges. */
10014 otricopy(*startghost, dissolveedge);
10015 hullsize = 0;
10016 do {
10017 hullsize++;
10018 lnext(dissolveedge, deadtriangle);
10019 lprevself(dissolveedge);
10020 symself(dissolveedge);
10021 /* If no PSLG is involved, set the boundary markers of all the vertices */
10022 /* on the convex hull. If a PSLG is used, this step is done later. */
10023 if (!b->poly) {
10024 /* Watch out for the case where all the input vertices are collinear. */
10025 if (dissolveedge.tri != m->dummytri) {
10026 org(dissolveedge, markorg);
10027 if (vertexmark(markorg) == 0) {
10028 setvertexmark(markorg, 1);
10029 }
10030 }
10031 }
10032 /* Remove a bounding triangle from a convex hull triangle. */
10033 dissolve(dissolveedge);
10034 /* Find the next bounding triangle. */
10035 sym(deadtriangle, dissolveedge);
10036 /* Delete the bounding triangle. */
10037 triangledealloc(m, deadtriangle.tri);
10038 } while (!otriequal(dissolveedge, *startghost));
10039 return hullsize;
10040}
10041
10042/*****************************************************************************/
10043/* */
10044/* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */
10045/* conquer method. */
10046/* */
10047/* Sorts the vertices, calls a recursive procedure to triangulate them, and */
10048/* removes the bounding box, setting boundary markers as appropriate. */
10049/* */
10050/*****************************************************************************/
10051
10052#ifdef ANSI_DECLARATORS
10053long divconqdelaunay(struct mesh *m, struct behavior *b)
10054#else /* not ANSI_DECLARATORS */
10055long divconqdelaunay(m, b)
10056struct mesh *m;
10057struct behavior *b;
10058#endif /* not ANSI_DECLARATORS */
10059
10060{
10061 vertex *sortarray;
10062 struct otri hullleft, hullright;
10063 int divider;
10064 int i, j;
10065
10066 if (b->verbose) {
10067 printf(" Sorting vertices.\n");
10068 }
10069
10070 /* Allocate an array of pointers to vertices for sorting. */
10071 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
10072 traversalinit(&m->vertices);
10073 for (i = 0; i < m->invertices; i++) {
10074 sortarray[i] = vertextraverse(m);
10075 }
10076 /* Sort the vertices. */
10077 vertexsort(sortarray, m->invertices);
10078 /* Discard duplicate vertices, which can really mess up the algorithm. */
10079 i = 0;
10080 for (j = 1; j < m->invertices; j++) {
10081 if ((sortarray[i][0] == sortarray[j][0])
10082 && (sortarray[i][1] == sortarray[j][1])) {
10083 if (!b->quiet) {
10084 printf(
10085"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10086 sortarray[j][0], sortarray[j][1]);
10087 }
10088 setvertextype(sortarray[j], UNDEADVERTEX);
10089 m->undeads++;
10090 } else {
10091 i++;
10092 sortarray[i] = sortarray[j];
10093 }
10094 }
10095 i++;
10096 if (b->dwyer) {
10097 /* Re-sort the array of vertices to accommodate alternating cuts. */
10098 divider = i >> 1;
10099 if (i - divider >= 2) {
10100 if (divider >= 2) {
10101 alternateaxes(sortarray, divider, 1);
10102 }
10103 alternateaxes(&sortarray[divider], i - divider, 1);
10104 }
10105 }
10106
10107 if (b->verbose) {
10108 printf(" Forming triangulation.\n");
10109 }
10110
10111 /* Form the Delaunay triangulation. */
10112 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10113 trifree((VOID *) sortarray);
10114
10115 return removeghosts(m, b, &hullleft);
10116}
10117
10120/********* Divide-and-conquer Delaunay triangulation ends here *********/
10121
10122/********* Incremental Delaunay triangulation begins here *********/
10126/*****************************************************************************/
10127/* */
10128/* boundingbox() Form an "infinite" bounding triangle to insert vertices */
10129/* into. */
10130/* */
10131/* The vertices at "infinity" are assigned finite coordinates, which are */
10132/* used by the point location routines, but (mostly) ignored by the */
10133/* Delaunay edge flip routines. */
10134/* */
10135/*****************************************************************************/
10136
10137#ifndef REDUCED
10138
10139#ifdef ANSI_DECLARATORS
10140void boundingbox(struct mesh *m, struct behavior *b)
10141#else /* not ANSI_DECLARATORS */
10142void boundingbox(m, b)
10143struct mesh *m;
10144struct behavior *b;
10145#endif /* not ANSI_DECLARATORS */
10146
10147{
10148 struct otri inftri; /* Handle for the triangular bounding box. */
10149 REAL width;
10150
10151 if (b->verbose) {
10152 printf(" Creating triangular bounding box.\n");
10153 }
10154 /* Find the width (or height, whichever is larger) of the triangulation. */
10155 width = m->xmax - m->xmin;
10156 if (m->ymax - m->ymin > width) {
10157 width = m->ymax - m->ymin;
10158 }
10159 if (width == 0.0) {
10160 width = 1.0;
10161 }
10162 /* Create the vertices of the bounding box. */
10163 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10164 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10165 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10166 m->infvertex1[0] = m->xmin - 50.0 * width;
10167 m->infvertex1[1] = m->ymin - 40.0 * width;
10168 m->infvertex2[0] = m->xmax + 50.0 * width;
10169 m->infvertex2[1] = m->ymin - 40.0 * width;
10170 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10171 m->infvertex3[1] = m->ymax + 60.0 * width;
10172
10173 /* Create the bounding box. */
10174 maketriangle(m, b, &inftri);
10175 setorg(inftri, m->infvertex1);
10176 setdest(inftri, m->infvertex2);
10177 setapex(inftri, m->infvertex3);
10178 /* Link dummytri to the bounding box so we can always find an */
10179 /* edge to begin searching (point location) from. */
10180 m->dummytri[0] = (triangle) inftri.tri;
10181 if (b->verbose > 2) {
10182 printf(" Creating ");
10183 printtriangle(m, b, &inftri);
10184 }
10185}
10186
10187#endif /* not REDUCED */
10188
10189/*****************************************************************************/
10190/* */
10191/* removebox() Remove the "infinite" bounding triangle, setting boundary */
10192/* markers as appropriate. */
10193/* */
10194/* The triangular bounding box has three boundary triangles (one for each */
10195/* side of the bounding box), and a bunch of triangles fanning out from */
10196/* the three bounding box vertices (one triangle for each edge of the */
10197/* convex hull of the inner mesh). This routine removes these triangles. */
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 removebox(struct mesh *m, struct behavior *b)
10207#else /* not ANSI_DECLARATORS */
10208long removebox(m, b)
10209struct mesh *m;
10210struct behavior *b;
10211#endif /* not ANSI_DECLARATORS */
10212
10213{
10214 struct otri deadtriangle;
10215 struct otri searchedge;
10216 struct otri checkedge;
10217 struct otri nextedge, finaledge, dissolveedge;
10218 vertex markorg;
10219 long hullsize;
10220 triangle ptr; /* Temporary variable used by sym(). */
10221
10222 if (b->verbose) {
10223 printf(" Removing triangular bounding box.\n");
10224 }
10225 /* Find a boundary triangle. */
10226 nextedge.tri = m->dummytri;
10227 nextedge.orient = 0;
10228 symself(nextedge);
10229 /* Mark a place to stop. */
10230 lprev(nextedge, finaledge);
10231 lnextself(nextedge);
10232 symself(nextedge);
10233 /* Find a triangle (on the boundary of the vertex set) that isn't */
10234 /* a bounding box triangle. */
10235 lprev(nextedge, searchedge);
10236 symself(searchedge);
10237 /* Check whether nextedge is another boundary triangle */
10238 /* adjacent to the first one. */
10239 lnext(nextedge, checkedge);
10240 symself(checkedge);
10241 if (checkedge.tri == m->dummytri) {
10242 /* Go on to the next triangle. There are only three boundary */
10243 /* triangles, and this next triangle cannot be the third one, */
10244 /* so it's safe to stop here. */
10245 lprevself(searchedge);
10246 symself(searchedge);
10247 }
10248 /* Find a new boundary edge to search from, as the current search */
10249 /* edge lies on a bounding box triangle and will be deleted. */
10250 m->dummytri[0] = encode(searchedge);
10251 hullsize = -2l;
10252 while (!otriequal(nextedge, finaledge)) {
10253 hullsize++;
10254 lprev(nextedge, dissolveedge);
10255 symself(dissolveedge);
10256 /* If not using a PSLG, the vertices should be marked now. */
10257 /* (If using a PSLG, markhull() will do the job.) */
10258 if (!b->poly) {
10259 /* Be careful! One must check for the case where all the input */
10260 /* vertices are collinear, and thus all the triangles are part of */
10261 /* the bounding box. Otherwise, the setvertexmark() call below */
10262 /* will cause a bad pointer reference. */
10263 if (dissolveedge.tri != m->dummytri) {
10264 org(dissolveedge, markorg);
10265 if (vertexmark(markorg) == 0) {
10266 setvertexmark(markorg, 1);
10267 }
10268 }
10269 }
10270 /* Disconnect the bounding box triangle from the mesh triangle. */
10271 dissolve(dissolveedge);
10272 lnext(nextedge, deadtriangle);
10273 sym(deadtriangle, nextedge);
10274 /* Get rid of the bounding box triangle. */
10275 triangledealloc(m, deadtriangle.tri);
10276 /* Do we need to turn the corner? */
10277 if (nextedge.tri == m->dummytri) {
10278 /* Turn the corner. */
10279 otricopy(dissolveedge, nextedge);
10280 }
10281 }
10282 triangledealloc(m, finaledge.tri);
10283
10284 trifree((VOID *) m->infvertex1); /* Deallocate the bounding box vertices. */
10285 trifree((VOID *) m->infvertex2);
10286 trifree((VOID *) m->infvertex3);
10287
10288 return hullsize;
10289}
10290
10291#endif /* not REDUCED */
10292
10293/*****************************************************************************/
10294/* */
10295/* incrementaldelaunay() Form a Delaunay triangulation by incrementally */
10296/* inserting vertices. */
10297/* */
10298/* Returns the number of edges on the convex hull of the triangulation. */
10299/* */
10300/*****************************************************************************/
10301
10302#ifndef REDUCED
10303
10304#ifdef ANSI_DECLARATORS
10305long incrementaldelaunay(struct mesh *m, struct behavior *b)
10306#else /* not ANSI_DECLARATORS */
10307long incrementaldelaunay(m, b)
10308struct mesh *m;
10309struct behavior *b;
10310#endif /* not ANSI_DECLARATORS */
10311
10312{
10313 struct otri starttri;
10314 vertex vertexloop;
10315
10316 /* Create a triangular bounding box. */
10317 boundingbox(m, b);
10318 if (b->verbose) {
10319 printf(" Incrementally inserting vertices.\n");
10320 }
10321 traversalinit(&m->vertices);
10322 vertexloop = vertextraverse(m);
10323 while (vertexloop != (vertex) NULL) {
10324 starttri.tri = m->dummytri;
10325 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10326 == DUPLICATEVERTEX) {
10327 if (!b->quiet) {
10328 printf(
10329"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10330 vertexloop[0], vertexloop[1]);
10331 }
10332 setvertextype(vertexloop, UNDEADVERTEX);
10333 m->undeads++;
10334 }
10335 vertexloop = vertextraverse(m);
10336 }
10337 /* Remove the bounding box. */
10338 return removebox(m, b);
10339}
10340
10341#endif /* not REDUCED */
10342
10345/********* Incremental Delaunay triangulation ends here *********/
10346
10347/********* Sweepline Delaunay triangulation begins here *********/
10351#ifndef REDUCED
10352
10353#ifdef ANSI_DECLARATORS
10354void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10355#else /* not ANSI_DECLARATORS */
10356void eventheapinsert(heap, heapsize, newevent)
10357struct event **heap;
10358int heapsize;
10359struct event *newevent;
10360#endif /* not ANSI_DECLARATORS */
10361
10362{
10363 REAL eventx, eventy;
10364 int eventnum;
10365 int parent;
10366 int notdone;
10367
10368 eventx = newevent->xkey;
10369 eventy = newevent->ykey;
10370 eventnum = heapsize;
10371 notdone = eventnum > 0;
10372 while (notdone) {
10373 parent = (eventnum - 1) >> 1;
10374 if ((heap[parent]->ykey < eventy) ||
10375 ((heap[parent]->ykey == eventy)
10376 && (heap[parent]->xkey <= eventx))) {
10377 notdone = 0;
10378 } else {
10379 heap[eventnum] = heap[parent];
10380 heap[eventnum]->heapposition = eventnum;
10381
10382 eventnum = parent;
10383 notdone = eventnum > 0;
10384 }
10385 }
10386 heap[eventnum] = newevent;
10387 newevent->heapposition = eventnum;
10388}
10389
10390#endif /* not REDUCED */
10391
10392#ifndef REDUCED
10393
10394#ifdef ANSI_DECLARATORS
10395void eventheapify(struct event **heap, int heapsize, int eventnum)
10396#else /* not ANSI_DECLARATORS */
10397void eventheapify(heap, heapsize, eventnum)
10398struct event **heap;
10399int heapsize;
10400int eventnum;
10401#endif /* not ANSI_DECLARATORS */
10402
10403{
10404 struct event *thisevent;
10405 REAL eventx, eventy;
10406 int leftchild, rightchild;
10407 int smallest;
10408 int notdone;
10409
10410 thisevent = heap[eventnum];
10411 eventx = thisevent->xkey;
10412 eventy = thisevent->ykey;
10413 leftchild = 2 * eventnum + 1;
10414 notdone = leftchild < heapsize;
10415 while (notdone) {
10416 if ((heap[leftchild]->ykey < eventy) ||
10417 ((heap[leftchild]->ykey == eventy)
10418 && (heap[leftchild]->xkey < eventx))) {
10419 smallest = leftchild;
10420 } else {
10421 smallest = eventnum;
10422 }
10423 rightchild = leftchild + 1;
10424 if (rightchild < heapsize) {
10425 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10426 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10427 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10428 smallest = rightchild;
10429 }
10430 }
10431 if (smallest == eventnum) {
10432 notdone = 0;
10433 } else {
10434 heap[eventnum] = heap[smallest];
10435 heap[eventnum]->heapposition = eventnum;
10436 heap[smallest] = thisevent;
10437 thisevent->heapposition = smallest;
10438
10439 eventnum = smallest;
10440 leftchild = 2 * eventnum + 1;
10441 notdone = leftchild < heapsize;
10442 }
10443 }
10444}
10445
10446#endif /* not REDUCED */
10447
10448#ifndef REDUCED
10449
10450#ifdef ANSI_DECLARATORS
10451void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10452#else /* not ANSI_DECLARATORS */
10453void eventheapdelete(heap, heapsize, eventnum)
10454struct event **heap;
10455int heapsize;
10456int eventnum;
10457#endif /* not ANSI_DECLARATORS */
10458
10459{
10460 struct event *moveevent;
10461 REAL eventx, eventy;
10462 int parent;
10463 int notdone;
10464
10465 moveevent = heap[heapsize - 1];
10466 if (eventnum > 0) {
10467 eventx = moveevent->xkey;
10468 eventy = moveevent->ykey;
10469 do {
10470 parent = (eventnum - 1) >> 1;
10471 if ((heap[parent]->ykey < eventy) ||
10472 ((heap[parent]->ykey == eventy)
10473 && (heap[parent]->xkey <= eventx))) {
10474 notdone = 0;
10475 } else {
10476 heap[eventnum] = heap[parent];
10477 heap[eventnum]->heapposition = eventnum;
10478
10479 eventnum = parent;
10480 notdone = eventnum > 0;
10481 }
10482 } while (notdone);
10483 }
10484 heap[eventnum] = moveevent;
10485 moveevent->heapposition = eventnum;
10486 eventheapify(heap, heapsize - 1, eventnum);
10487}
10488
10489#endif /* not REDUCED */
10490
10491#ifndef REDUCED
10492
10493#ifdef ANSI_DECLARATORS
10494void createeventheap(struct mesh *m, struct event ***eventheap,
10495 struct event **events, struct event **freeevents)
10496#else /* not ANSI_DECLARATORS */
10497void createeventheap(m, eventheap, events, freeevents)
10498struct mesh *m;
10499struct event ***eventheap;
10500struct event **events;
10501struct event **freeevents;
10502#endif /* not ANSI_DECLARATORS */
10503
10504{
10505 vertex thisvertex;
10506 int maxevents;
10507 int i;
10508
10509 maxevents = (3 * m->invertices) / 2;
10510 *eventheap = (struct event **) trimalloc(maxevents *
10511 (int) sizeof(struct event *));
10512 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10513 traversalinit(&m->vertices);
10514 for (i = 0; i < m->invertices; i++) {
10515 thisvertex = vertextraverse(m);
10516 (*events)[i].eventptr = (VOID *) thisvertex;
10517 (*events)[i].xkey = thisvertex[0];
10518 (*events)[i].ykey = thisvertex[1];
10519 eventheapinsert(*eventheap, i, *events + i);
10520 }
10521 *freeevents = (struct event *) NULL;
10522 for (i = maxevents - 1; i >= m->invertices; i--) {
10523 (*events)[i].eventptr = (VOID *) *freeevents;
10524 *freeevents = *events + i;
10525 }
10526}
10527
10528#endif /* not REDUCED */
10529
10530#ifndef REDUCED
10531
10532#ifdef ANSI_DECLARATORS
10533int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10534#else /* not ANSI_DECLARATORS */
10535int rightofhyperbola(m, fronttri, newsite)
10536struct mesh *m;
10537struct otri *fronttri;
10538vertex newsite;
10539#endif /* not ANSI_DECLARATORS */
10540
10541{
10542 vertex leftvertex, rightvertex;
10543 REAL dxa, dya, dxb, dyb;
10544
10545 m->hyperbolacount++;
10546
10547 dest(*fronttri, leftvertex);
10548 apex(*fronttri, rightvertex);
10549 if ((leftvertex[1] < rightvertex[1]) ||
10550 ((leftvertex[1] == rightvertex[1]) &&
10551 (leftvertex[0] < rightvertex[0]))) {
10552 if (newsite[0] >= rightvertex[0]) {
10553 return 1;
10554 }
10555 } else {
10556 if (newsite[0] <= leftvertex[0]) {
10557 return 0;
10558 }
10559 }
10560 dxa = leftvertex[0] - newsite[0];
10561 dya = leftvertex[1] - newsite[1];
10562 dxb = rightvertex[0] - newsite[0];
10563 dyb = rightvertex[1] - newsite[1];
10564 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10565}
10566
10567#endif /* not REDUCED */
10568
10569#ifndef REDUCED
10570
10571#ifdef ANSI_DECLARATORS
10572REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10573#else /* not ANSI_DECLARATORS */
10574REAL circletop(m, pa, pb, pc, ccwabc)
10575struct mesh *m;
10576vertex pa;
10577vertex pb;
10578vertex pc;
10579REAL ccwabc;
10580#endif /* not ANSI_DECLARATORS */
10581
10582{
10583 REAL xac, yac, xbc, ybc, xab, yab;
10584 REAL aclen2, bclen2, ablen2;
10585
10586 m->circletopcount++;
10587
10588 xac = pa[0] - pc[0];
10589 yac = pa[1] - pc[1];
10590 xbc = pb[0] - pc[0];
10591 ybc = pb[1] - pc[1];
10592 xab = pa[0] - pb[0];
10593 yab = pa[1] - pb[1];
10594 aclen2 = xac * xac + yac * yac;
10595 bclen2 = xbc * xbc + ybc * ybc;
10596 ablen2 = xab * xab + yab * yab;
10597 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10598 / (2.0 * ccwabc);
10599}
10600
10601#endif /* not REDUCED */
10602
10603#ifndef REDUCED
10604
10605#ifdef ANSI_DECLARATORS
10606void check4deadevent(struct otri *checktri, struct event **freeevents,
10607 struct event **eventheap, int *heapsize)
10608#else /* not ANSI_DECLARATORS */
10609void check4deadevent(checktri, freeevents, eventheap, heapsize)
10610struct otri *checktri;
10611struct event **freeevents;
10612struct event **eventheap;
10613int *heapsize;
10614#endif /* not ANSI_DECLARATORS */
10615
10616{
10617 struct event *deadevent;
10618 vertex eventvertex;
10619 int eventnum;
10620
10621 org(*checktri, eventvertex);
10622 if (eventvertex != (vertex) NULL) {
10623 deadevent = (struct event *) eventvertex;
10624 eventnum = deadevent->heapposition;
10625 deadevent->eventptr = (VOID *) *freeevents;
10626 *freeevents = deadevent;
10627 eventheapdelete(eventheap, *heapsize, eventnum);
10628 (*heapsize)--;
10629 setorg(*checktri, NULL);
10630 }
10631}
10632
10633#endif /* not REDUCED */
10634
10635#ifndef REDUCED
10636
10637#ifdef ANSI_DECLARATORS
10638struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10639 vertex searchpoint, struct otri *searchtri)
10640#else /* not ANSI_DECLARATORS */
10641struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10642struct mesh *m;
10643struct splaynode *splaytree;
10644vertex searchpoint;
10645struct otri *searchtri;
10646#endif /* not ANSI_DECLARATORS */
10647
10648{
10649 struct splaynode *child, *grandchild;
10650 struct splaynode *lefttree, *righttree;
10651 struct splaynode *leftright;
10652 vertex checkvertex;
10653 int rightofroot, rightofchild;
10654
10655 if (splaytree == (struct splaynode *) NULL) {
10656 return (struct splaynode *) NULL;
10657 }
10658 dest(splaytree->keyedge, checkvertex);
10659 if (checkvertex == splaytree->keydest) {
10660 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10661 if (rightofroot) {
10662 otricopy(splaytree->keyedge, *searchtri);
10663 child = splaytree->rchild;
10664 } else {
10665 child = splaytree->lchild;
10666 }
10667 if (child == (struct splaynode *) NULL) {
10668 return splaytree;
10669 }
10670 dest(child->keyedge, checkvertex);
10671 if (checkvertex != child->keydest) {
10672 child = splay(m, child, searchpoint, searchtri);
10673 if (child == (struct splaynode *) NULL) {
10674 if (rightofroot) {
10675 splaytree->rchild = (struct splaynode *) NULL;
10676 } else {
10677 splaytree->lchild = (struct splaynode *) NULL;
10678 }
10679 return splaytree;
10680 }
10681 }
10682 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10683 if (rightofchild) {
10684 otricopy(child->keyedge, *searchtri);
10685 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10686 child->rchild = grandchild;
10687 } else {
10688 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10689 child->lchild = grandchild;
10690 }
10691 if (grandchild == (struct splaynode *) NULL) {
10692 if (rightofroot) {
10693 splaytree->rchild = child->lchild;
10694 child->lchild = splaytree;
10695 } else {
10696 splaytree->lchild = child->rchild;
10697 child->rchild = splaytree;
10698 }
10699 return child;
10700 }
10701 if (rightofchild) {
10702 if (rightofroot) {
10703 splaytree->rchild = child->lchild;
10704 child->lchild = splaytree;
10705 } else {
10706 splaytree->lchild = grandchild->rchild;
10707 grandchild->rchild = splaytree;
10708 }
10709 child->rchild = grandchild->lchild;
10710 grandchild->lchild = child;
10711 } else {
10712 if (rightofroot) {
10713 splaytree->rchild = grandchild->lchild;
10714 grandchild->lchild = splaytree;
10715 } else {
10716 splaytree->lchild = child->rchild;
10717 child->rchild = splaytree;
10718 }
10719 child->lchild = grandchild->rchild;
10720 grandchild->rchild = child;
10721 }
10722 return grandchild;
10723 } else {
10724 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10725 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10726
10727 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10728 if (lefttree == (struct splaynode *) NULL) {
10729 return righttree;
10730 } else if (righttree == (struct splaynode *) NULL) {
10731 return lefttree;
10732 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10733 lefttree->rchild = righttree->lchild;
10734 righttree->lchild = lefttree;
10735 return righttree;
10736 } else if (righttree->lchild == (struct splaynode *) NULL) {
10737 righttree->lchild = lefttree->rchild;
10738 lefttree->rchild = righttree;
10739 return lefttree;
10740 } else {
10741/* printf("Holy Toledo!!!\n"); */
10742 leftright = lefttree->rchild;
10743 while (leftright->rchild != (struct splaynode *) NULL) {
10744 leftright = leftright->rchild;
10745 }
10746 leftright->rchild = righttree;
10747 return lefttree;
10748 }
10749 }
10750}
10751
10752#endif /* not REDUCED */
10753
10754#ifndef REDUCED
10755
10756#ifdef ANSI_DECLARATORS
10757struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10758 struct otri *newkey, vertex searchpoint)
10759#else /* not ANSI_DECLARATORS */
10760struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10761struct mesh *m;
10762struct splaynode *splayroot;
10763struct otri *newkey;
10764vertex searchpoint;
10765#endif /* not ANSI_DECLARATORS */
10766
10767{
10768 struct splaynode *newsplaynode;
10769
10770 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10771 otricopy(*newkey, newsplaynode->keyedge);
10772 dest(*newkey, newsplaynode->keydest);
10773 if (splayroot == (struct splaynode *) NULL) {
10774 newsplaynode->lchild = (struct splaynode *) NULL;
10775 newsplaynode->rchild = (struct splaynode *) NULL;
10776 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10777 newsplaynode->lchild = splayroot;
10778 newsplaynode->rchild = splayroot->rchild;
10779 splayroot->rchild = (struct splaynode *) NULL;
10780 } else {
10781 newsplaynode->lchild = splayroot->lchild;
10782 newsplaynode->rchild = splayroot;
10783 splayroot->lchild = (struct splaynode *) NULL;
10784 }
10785 return newsplaynode;
10786}
10787
10788#endif /* not REDUCED */
10789
10790#ifndef REDUCED
10791
10792#ifdef ANSI_DECLARATORS
10793struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10794 struct splaynode *splayroot,
10795 struct otri *newkey,
10796 vertex pa, vertex pb, vertex pc, REAL topy)
10797#else /* not ANSI_DECLARATORS */
10798struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10799struct mesh *m;
10800struct behavior *b;
10801struct splaynode *splayroot;
10802struct otri *newkey;
10803vertex pa;
10804vertex pb;
10805vertex pc;
10806REAL topy;
10807#endif /* not ANSI_DECLARATORS */
10808
10809{
10810 REAL ccwabc;
10811 REAL xac, yac, xbc, ybc;
10812 REAL aclen2, bclen2;
10813 REAL searchpoint[2];
10814 struct otri dummytri;
10815
10816 ccwabc = counterclockwise(m, b, pa, pb, pc);
10817 xac = pa[0] - pc[0];
10818 yac = pa[1] - pc[1];
10819 xbc = pb[0] - pc[0];
10820 ybc = pb[1] - pc[1];
10821 aclen2 = xac * xac + yac * yac;
10822 bclen2 = xbc * xbc + ybc * ybc;
10823 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10824 searchpoint[1] = topy;
10825 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10826 newkey, (vertex) searchpoint);
10827}
10828
10829#endif /* not REDUCED */
10830
10831#ifndef REDUCED
10832
10833#ifdef ANSI_DECLARATORS
10834struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10835 struct otri *bottommost, vertex searchvertex,
10836 struct otri *searchtri, int *farright)
10837#else /* not ANSI_DECLARATORS */
10838struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10839 searchtri, farright)
10840struct mesh *m;
10841struct splaynode *splayroot;
10842struct otri *bottommost;
10843vertex searchvertex;
10844struct otri *searchtri;
10845int *farright;
10846#endif /* not ANSI_DECLARATORS */
10847
10848{
10849 int farrightflag;
10850 triangle ptr; /* Temporary variable used by onext(). */
10851
10852 otricopy(*bottommost, *searchtri);
10853 splayroot = splay(m, splayroot, searchvertex, searchtri);
10854
10855 farrightflag = 0;
10856 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10857 onextself(*searchtri);
10858 farrightflag = otriequal(*searchtri, *bottommost);
10859 }
10860 *farright = farrightflag;
10861 return splayroot;
10862}
10863
10864#endif /* not REDUCED */
10865
10866#ifndef REDUCED
10867
10868#ifdef ANSI_DECLARATORS
10869long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10870#else /* not ANSI_DECLARATORS */
10871long sweeplinedelaunay(m, b)
10872struct mesh *m;
10873struct behavior *b;
10874#endif /* not ANSI_DECLARATORS */
10875
10876{
10877 struct event **eventheap;
10878 struct event *events;
10879 struct event *freeevents;
10880 struct event *nextevent;
10881 struct event *newevent;
10882 struct splaynode *splayroot;
10883 struct otri bottommost;
10884 struct otri searchtri;
10885 struct otri fliptri;
10886 struct otri lefttri, righttri, farlefttri, farrighttri;
10887 struct otri inserttri;
10888 vertex firstvertex, secondvertex;
10889 vertex nextvertex, lastvertex;
10890 vertex connectvertex;
10891 vertex leftvertex, midvertex, rightvertex;
10892 REAL lefttest, righttest;
10893 int heapsize;
10894 int check4events, farrightflag;
10895 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
10896
10897 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10898 SPLAYNODEPERBLOCK, 0);
10899 splayroot = (struct splaynode *) NULL;
10900
10901 if (b->verbose) {
10902 printf(" Placing vertices in event heap.\n");
10903 }
10904 createeventheap(m, &eventheap, &events, &freeevents);
10905 heapsize = m->invertices;
10906
10907 if (b->verbose) {
10908 printf(" Forming triangulation.\n");
10909 }
10910 maketriangle(m, b, &lefttri);
10911 maketriangle(m, b, &righttri);
10912 bond(lefttri, righttri);
10913 lnextself(lefttri);
10914 lprevself(righttri);
10915 bond(lefttri, righttri);
10916 lnextself(lefttri);
10917 lprevself(righttri);
10918 bond(lefttri, righttri);
10919 firstvertex = (vertex) eventheap[0]->eventptr;
10920 eventheap[0]->eventptr = (VOID *) freeevents;
10921 freeevents = eventheap[0];
10922 eventheapdelete(eventheap, heapsize, 0);
10923 heapsize--;
10924 do {
10925 if (heapsize == 0) {
10926 printf("Error: Input vertices are all identical.\n");
10927 triexit(1);
10928 }
10929 secondvertex = (vertex) eventheap[0]->eventptr;
10930 eventheap[0]->eventptr = (VOID *) freeevents;
10931 freeevents = eventheap[0];
10932 eventheapdelete(eventheap, heapsize, 0);
10933 heapsize--;
10934 if ((firstvertex[0] == secondvertex[0]) &&
10935 (firstvertex[1] == secondvertex[1])) {
10936 if (!b->quiet) {
10937 printf(
10938"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10939 secondvertex[0], secondvertex[1]);
10940 }
10941 setvertextype(secondvertex, UNDEADVERTEX);
10942 m->undeads++;
10943 }
10944 } while ((firstvertex[0] == secondvertex[0]) &&
10945 (firstvertex[1] == secondvertex[1]));
10946 setorg(lefttri, firstvertex);
10947 setdest(lefttri, secondvertex);
10948 setorg(righttri, secondvertex);
10949 setdest(righttri, firstvertex);
10950 lprev(lefttri, bottommost);
10951 lastvertex = secondvertex;
10952 while (heapsize > 0) {
10953 nextevent = eventheap[0];
10954 eventheapdelete(eventheap, heapsize, 0);
10955 heapsize--;
10956 check4events = 1;
10957 if (nextevent->xkey < m->xmin) {
10958 decode(nextevent->eventptr, fliptri);
10959 oprev(fliptri, farlefttri);
10960 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10961 onext(fliptri, farrighttri);
10962 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10963
10964 if (otriequal(farlefttri, bottommost)) {
10965 lprev(fliptri, bottommost);
10966 }
10967 flip(m, b, &fliptri);
10968 setapex(fliptri, NULL);
10969 lprev(fliptri, lefttri);
10970 lnext(fliptri, righttri);
10971 sym(lefttri, farlefttri);
10972
10973 if (randomnation(SAMPLERATE) == 0) {
10974 symself(fliptri);
10975 dest(fliptri, leftvertex);
10976 apex(fliptri, midvertex);
10977 org(fliptri, rightvertex);
10978 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10979 midvertex, rightvertex, nextevent->ykey);
10980 }
10981 } else {
10982 nextvertex = (vertex) nextevent->eventptr;
10983 if ((nextvertex[0] == lastvertex[0]) &&
10984 (nextvertex[1] == lastvertex[1])) {
10985 if (!b->quiet) {
10986 printf(
10987"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10988 nextvertex[0], nextvertex[1]);
10989 }
10990 setvertextype(nextvertex, UNDEADVERTEX);
10991 m->undeads++;
10992 check4events = 0;
10993 } else {
10994 lastvertex = nextvertex;
10995
10996 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10997 &searchtri, &farrightflag);
10998/*
10999 otricopy(bottommost, searchtri);
11000 farrightflag = 0;
11001 while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) {
11002 onextself(searchtri);
11003 farrightflag = otriequal(searchtri, bottommost);
11004 }
11005*/
11006
11007 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
11008
11009 otricopy(searchtri, farrighttri);
11010 sym(searchtri, farlefttri);
11011 maketriangle(m, b, &lefttri);
11012 maketriangle(m, b, &righttri);
11013 dest(farrighttri, connectvertex);
11014 setorg(lefttri, connectvertex);
11015 setdest(lefttri, nextvertex);
11016 setorg(righttri, nextvertex);
11017 setdest(righttri, connectvertex);
11018 bond(lefttri, righttri);
11019 lnextself(lefttri);
11020 lprevself(righttri);
11021 bond(lefttri, righttri);
11022 lnextself(lefttri);
11023 lprevself(righttri);
11024 bond(lefttri, farlefttri);
11025 bond(righttri, farrighttri);
11026 if (!farrightflag && otriequal(farrighttri, bottommost)) {
11027 otricopy(lefttri, bottommost);
11028 }
11029
11030 if (randomnation(SAMPLERATE) == 0) {
11031 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
11032 } else if (randomnation(SAMPLERATE) == 0) {
11033 lnext(righttri, inserttri);
11034 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
11035 }
11036 }
11037 }
11038 nextevent->eventptr = (VOID *) freeevents;
11039 freeevents = nextevent;
11040
11041 if (check4events) {
11042 apex(farlefttri, leftvertex);
11043 dest(lefttri, midvertex);
11044 apex(lefttri, rightvertex);
11045 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
11046 if (lefttest > 0.0) {
11047 newevent = freeevents;
11048 freeevents = (struct event *) freeevents->eventptr;
11049 newevent->xkey = m->xminextreme;
11050 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
11051 lefttest);
11052 newevent->eventptr = (VOID *) encode(lefttri);
11053 eventheapinsert(eventheap, heapsize, newevent);
11054 heapsize++;
11055 setorg(lefttri, newevent);
11056 }
11057 apex(righttri, leftvertex);
11058 org(righttri, midvertex);
11059 apex(farrighttri, rightvertex);
11060 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
11061 if (righttest > 0.0) {
11062 newevent = freeevents;
11063 freeevents = (struct event *) freeevents->eventptr;
11064 newevent->xkey = m->xminextreme;
11065 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
11066 righttest);
11067 newevent->eventptr = (VOID *) encode(farrighttri);
11068 eventheapinsert(eventheap, heapsize, newevent);
11069 heapsize++;
11070 setorg(farrighttri, newevent);
11071 }
11072 }
11073 }
11074
11075 pooldeinit(&m->splaynodes);
11076 lprevself(bottommost);
11077 return removeghosts(m, b, &bottommost);
11078}
11079
11080#endif /* not REDUCED */
11081
11084/********* Sweepline Delaunay triangulation ends here *********/
11085
11086/********* General mesh construction routines begin here *********/
11090/*****************************************************************************/
11091/* */
11092/* delaunay() Form a Delaunay triangulation. */
11093/* */
11094/*****************************************************************************/
11095
11096#ifdef ANSI_DECLARATORS
11097long delaunay(struct mesh *m, struct behavior *b)
11098#else /* not ANSI_DECLARATORS */
11099long delaunay(m, b)
11100struct mesh *m;
11101struct behavior *b;
11102#endif /* not ANSI_DECLARATORS */
11103
11104{
11105 long hulledges;
11106
11107 m->eextras = 0;
11108 initializetrisubpools(m, b);
11109
11110#ifdef REDUCED
11111 if (!b->quiet) {
11112 printf(
11113 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11114 }
11115 hulledges = divconqdelaunay(m, b);
11116#else /* not REDUCED */
11117 if (!b->quiet) {
11118 printf("Constructing Delaunay triangulation ");
11119 if (b->incremental) {
11120 printf("by incremental method.\n");
11121 } else if (b->sweepline) {
11122 printf("by sweepline method.\n");
11123 } else {
11124 printf("by divide-and-conquer method.\n");
11125 }
11126 }
11127 if (b->incremental) {
11128 hulledges = incrementaldelaunay(m, b);
11129 } else if (b->sweepline) {
11130 hulledges = sweeplinedelaunay(m, b);
11131 } else {
11132 hulledges = divconqdelaunay(m, b);
11133 }
11134#endif /* not REDUCED */
11135
11136 if (m->triangles.items == 0) {
11137 /* The input vertices were all collinear, so there are no triangles. */
11138 return 0l;
11139 } else {
11140 return hulledges;
11141 }
11142}
11143
11144/*****************************************************************************/
11145/* */
11146/* reconstruct() Reconstruct a triangulation from its .ele (and possibly */
11147/* .poly) file. Used when the -r switch is used. */
11148/* */
11149/* Reads an .ele file and reconstructs the original mesh. If the -p switch */
11150/* is used, this procedure will also read a .poly file and reconstruct the */
11151/* subsegments of the original mesh. If the -a switch is used, this */
11152/* procedure will also read an .area file and set a maximum area constraint */
11153/* on each triangle. */
11154/* */
11155/* Vertices that are not corners of triangles, such as nodes on edges of */
11156/* subparametric elements, are discarded. */
11157/* */
11158/* This routine finds the adjacencies between triangles (and subsegments) */
11159/* by forming one stack of triangles for each vertex. Each triangle is on */
11160/* three different stacks simultaneously. Each triangle's subsegment */
11161/* pointers are used to link the items in each stack. This memory-saving */
11162/* feature makes the code harder to read. The most important thing to keep */
11163/* in mind is that each triangle is removed from a stack precisely when */
11164/* the corresponding pointer is adjusted to refer to a subsegment rather */
11165/* than the next triangle of the stack. */
11166/* */
11167/*****************************************************************************/
11168
11169#ifndef CDT_ONLY
11170
11171#ifdef TRILIBRARY
11172
11173#ifdef ANSI_DECLARATORS
11174int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11175 REAL *triangleattriblist, REAL *trianglearealist,
11176 int elements, int corners, int attribs,
11177 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11178#else /* not ANSI_DECLARATORS */
11179int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11180 elements, corners, attribs, segmentlist, segmentmarkerlist,
11181 numberofsegments)
11182struct mesh *m;
11183struct behavior *b;
11184int *trianglelist;
11185REAL *triangleattriblist;
11186REAL *trianglearealist;
11187int elements;
11188int corners;
11189int attribs;
11190int *segmentlist;
11191int *segmentmarkerlist;
11192int numberofsegments;
11193#endif /* not ANSI_DECLARATORS */
11194
11195#else /* not TRILIBRARY */
11196
11197#ifdef ANSI_DECLARATORS
11198long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11199 char *areafilename, char* polyfilename, FILE* polyfile)
11200#else /* not ANSI_DECLARATORS */
11201long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11202struct mesh *m;
11203struct behavior *b;
11204char *elefilename;
11205char *areafilename;
11206char* polyfilename;
11207FILE* polyfile;
11208#endif /* not ANSI_DECLARATORS */
11209
11210#endif /* not TRILIBRARY */
11211
11212{
11213#ifdef TRILIBRARY
11214 int vertexindex;
11215 int attribindex;
11216#else /* not TRILIBRARY */
11217 FILE *elefile;
11218 FILE *areafile;
11219 char inputline[INPUTLINESIZE];
11220 char *stringptr;
11221 int areaelements;
11222#endif /* not TRILIBRARY */
11223 struct otri triangleloop;
11224 struct otri triangleleft;
11225 struct otri checktri;
11226 struct otri checkleft;
11227 struct otri checkneighbor;
11228 struct osub subsegloop;
11229 triangle *vertexarray;
11230 triangle* prevlink;
11231 triangle nexttri;
11232 vertex tdest, tapex;
11233 vertex checkdest, checkapex;
11234 vertex shorg;
11235 vertex killvertex;
11236 vertex segmentorg, segmentdest;
11237 REAL area;
11238 int corner[3];
11239 int end[2];
11240 int killvertexindex;
11241 int incorners;
11242 int segmentmarkers;
11243 int boundmarker;
11244 int aroundvertex;
11245 long hullsize;
11246 int notfound;
11247 long elementnumber, segmentnumber;
11248 int i, j;
11249 triangle ptr; /* Temporary variable used by sym(). */
11250
11251#ifdef TRILIBRARY
11252 m->inelements = elements;
11253 incorners = corners;
11254 if (incorners < 3) {
11255 printf("Error: Triangles must have at least 3 vertices.\n");
11256 triexit(1);
11257 }
11258 m->eextras = attribs;
11259#else /* not TRILIBRARY */
11260 /* Read the triangles from an .ele file. */
11261 if (!b->quiet) {
11262 printf("Opening %s.\n", elefilename);
11263 }
11264 elefile = fopen(elefilename, "r");
11265 if (elefile == (FILE *) NULL) {
11266 printf(" Error: Cannot access file %s.\n", elefilename);
11267 triexit(1);
11268 }
11269 /* Read number of triangles, number of vertices per triangle, and */
11270 /* number of triangle attributes from .ele file. */
11271 stringptr = readline(inputline, elefile, elefilename);
11272 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11273 stringptr = findfield(stringptr);
11274 if (*stringptr == '\0') {
11275 incorners = 3;
11276 } else {
11277 incorners = (int) strtol(stringptr, &stringptr, 0);
11278 if (incorners < 3) {
11279 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11280 elefilename);
11281 triexit(1);
11282 }
11283 }
11284 stringptr = findfield(stringptr);
11285 if (*stringptr == '\0') {
11286 m->eextras = 0;
11287 } else {
11288 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11289 }
11290#endif /* not TRILIBRARY */
11291
11292 initializetrisubpools(m, b);
11293
11294 /* Create the triangles. */
11295 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11296 maketriangle(m, b, &triangleloop);
11297 /* Mark the triangle as living. */
11298 triangleloop.tri[3] = (triangle) triangleloop.tri;
11299 }
11300
11301 segmentmarkers = 0;
11302 if (b->poly) {
11303#ifdef TRILIBRARY
11304 m->insegments = numberofsegments;
11305 segmentmarkers = segmentmarkerlist != (int *) NULL;
11306#else /* not TRILIBRARY */
11307 /* Read number of segments and number of segment */
11308 /* boundary markers from .poly file. */
11309 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11310 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11311 stringptr = findfield(stringptr);
11312 if (*stringptr != '\0') {
11313 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11314 }
11315#endif /* not TRILIBRARY */
11316
11317 /* Create the subsegments. */
11318 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11319 makesubseg(m, &subsegloop);
11320 /* Mark the subsegment as living. */
11321 subsegloop.ss[2] = (subseg) subsegloop.ss;
11322 }
11323 }
11324
11325#ifdef TRILIBRARY
11326 vertexindex = 0;
11327 attribindex = 0;
11328#else /* not TRILIBRARY */
11329 if (b->vararea) {
11330 /* Open an .area file, check for consistency with the .ele file. */
11331 if (!b->quiet) {
11332 printf("Opening %s.\n", areafilename);
11333 }
11334 areafile = fopen(areafilename, "r");
11335 if (areafile == (FILE *) NULL) {
11336 printf(" Error: Cannot access file %s.\n", areafilename);
11337 triexit(1);
11338 }
11339 stringptr = readline(inputline, areafile, areafilename);
11340 areaelements = (int) strtol(stringptr, &stringptr, 0);
11341 if (areaelements != m->inelements) {
11342 printf("Error: %s and %s disagree on number of triangles.\n",
11343 elefilename, areafilename);
11344 triexit(1);
11345 }
11346 }
11347#endif /* not TRILIBRARY */
11348
11349 if (!b->quiet) {
11350 printf("Reconstructing mesh.\n");
11351 }
11352 /* Allocate a temporary array that maps each vertex to some adjacent */
11353 /* triangle. I took care to allocate all the permanent memory for */
11354 /* triangles and subsegments first. */
11355 vertexarray = (triangle *) trimalloc(m->vertices.items *
11356 (int) sizeof(triangle));
11357 /* Each vertex is initially unrepresented. */
11358 for (i = 0; i < m->vertices.items; i++) {
11359 vertexarray[i] = (triangle) m->dummytri;
11360 }
11361
11362 if (b->verbose) {
11363 printf(" Assembling triangles.\n");
11364 }
11365 /* Read the triangles from the .ele file, and link */
11366 /* together those that share an edge. */
11367 traversalinit(&m->triangles);
11368 triangleloop.tri = triangletraverse(m);
11369 elementnumber = b->firstnumber;
11370 while (triangleloop.tri != (triangle *) NULL) {
11371#ifdef TRILIBRARY
11372 /* Copy the triangle's three corners. */
11373 for (j = 0; j < 3; j++) {
11374 corner[j] = trianglelist[vertexindex++];
11375 if ((corner[j] < b->firstnumber) ||
11376 (corner[j] >= b->firstnumber + m->invertices)) {
11377 printf("Error: Triangle %ld has an invalid vertex index.\n",
11378 elementnumber);
11379 triexit(1);
11380 }
11381 }
11382#else /* not TRILIBRARY */
11383 /* Read triangle number and the triangle's three corners. */
11384 stringptr = readline(inputline, elefile, elefilename);
11385 for (j = 0; j < 3; j++) {
11386 stringptr = findfield(stringptr);
11387 if (*stringptr == '\0') {
11388 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11389 elementnumber, j + 1, elefilename);
11390 triexit(1);
11391 } else {
11392 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11393 if ((corner[j] < b->firstnumber) ||
11394 (corner[j] >= b->firstnumber + m->invertices)) {
11395 printf("Error: Triangle %ld has an invalid vertex index.\n",
11396 elementnumber);
11397 triexit(1);
11398 }
11399 }
11400 }
11401#endif /* not TRILIBRARY */
11402
11403 /* Find out about (and throw away) extra nodes. */
11404 for (j = 3; j < incorners; j++) {
11405#ifdef TRILIBRARY
11406 killvertexindex = trianglelist[vertexindex++];
11407#else /* not TRILIBRARY */
11408 stringptr = findfield(stringptr);
11409 if (*stringptr != '\0') {
11410 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11411#endif /* not TRILIBRARY */
11412 if ((killvertexindex >= b->firstnumber) &&
11413 (killvertexindex < b->firstnumber + m->invertices)) {
11414 /* Delete the non-corner vertex if it's not already deleted. */
11415 killvertex = getvertex(m, b, killvertexindex);
11416 if (vertextype(killvertex) != DEADVERTEX) {
11417 vertexdealloc(m, killvertex);
11418 }
11419 }
11420#ifndef TRILIBRARY
11421 }
11422#endif /* not TRILIBRARY */
11423 }
11424
11425 /* Read the triangle's attributes. */
11426 for (j = 0; j < m->eextras; j++) {
11427#ifdef TRILIBRARY
11428 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11429#else /* not TRILIBRARY */
11430 stringptr = findfield(stringptr);
11431 if (*stringptr == '\0') {
11432 setelemattribute(triangleloop, j, 0);
11433 } else {
11434 setelemattribute(triangleloop, j,
11435 (REAL) strtod(stringptr, &stringptr));
11436 }
11437#endif /* not TRILIBRARY */
11438 }
11439
11440 if (b->vararea) {
11441#ifdef TRILIBRARY
11442 area = trianglearealist[elementnumber - b->firstnumber];
11443#else /* not TRILIBRARY */
11444 /* Read an area constraint from the .area file. */
11445 stringptr = readline(inputline, areafile, areafilename);
11446 stringptr = findfield(stringptr);
11447 if (*stringptr == '\0') {
11448 area = -1.0; /* No constraint on this triangle. */
11449 } else {
11450 area = (REAL) strtod(stringptr, &stringptr);
11451 }
11452#endif /* not TRILIBRARY */
11453 setareabound(triangleloop, area);
11454 }
11455
11456 /* Set the triangle's vertices. */
11457 triangleloop.orient = 0;
11458 setorg(triangleloop, getvertex(m, b, corner[0]));
11459 setdest(triangleloop, getvertex(m, b, corner[1]));
11460 setapex(triangleloop, getvertex(m, b, corner[2]));
11461 /* Try linking the triangle to others that share these vertices. */
11462 for (triangleloop.orient = 0; triangleloop.orient < 3;
11463 triangleloop.orient++) {
11464 /* Take the number for the origin of triangleloop. */
11465 aroundvertex = corner[triangleloop.orient];
11466 /* Look for other triangles having this vertex. */
11467 nexttri = vertexarray[aroundvertex - b->firstnumber];
11468 /* Link the current triangle to the next one in the stack. */
11469 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11470 /* Push the current triangle onto the stack. */
11471 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11472 decode(nexttri, checktri);
11473 if (checktri.tri != m->dummytri) {
11474 dest(triangleloop, tdest);
11475 apex(triangleloop, tapex);
11476 /* Look for other triangles that share an edge. */
11477 do {
11478 dest(checktri, checkdest);
11479 apex(checktri, checkapex);
11480 if (tapex == checkdest) {
11481 /* The two triangles share an edge; bond them together. */
11482 lprev(triangleloop, triangleleft);
11483 bond(triangleleft, checktri);
11484 }
11485 if (tdest == checkapex) {
11486 /* The two triangles share an edge; bond them together. */
11487 lprev(checktri, checkleft);
11488 bond(triangleloop, checkleft);
11489 }
11490 /* Find the next triangle in the stack. */
11491 nexttri = checktri.tri[6 + checktri.orient];
11492 decode(nexttri, checktri);
11493 } while (checktri.tri != m->dummytri);
11494 }
11495 }
11496 triangleloop.tri = triangletraverse(m);
11497 elementnumber++;
11498 }
11499
11500#ifdef TRILIBRARY
11501 vertexindex = 0;
11502#else /* not TRILIBRARY */
11503 fclose(elefile);
11504 if (b->vararea) {
11505 fclose(areafile);
11506 }
11507#endif /* not TRILIBRARY */
11508
11509 hullsize = 0; /* Prepare to count the boundary edges. */
11510 if (b->poly) {
11511 if (b->verbose) {
11512 printf(" Marking segments in triangulation.\n");
11513 }
11514 /* Read the segments from the .poly file, and link them */
11515 /* to their neighboring triangles. */
11516 boundmarker = 0;
11517 traversalinit(&m->subsegs);
11518 subsegloop.ss = subsegtraverse(m);
11519 segmentnumber = b->firstnumber;
11520 while (subsegloop.ss != (subseg *) NULL) {
11521#ifdef TRILIBRARY
11522 end[0] = segmentlist[vertexindex++];
11523 end[1] = segmentlist[vertexindex++];
11524 if (segmentmarkers) {
11525 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11526 }
11527#else /* not TRILIBRARY */
11528 /* Read the endpoints of each segment, and possibly a boundary marker. */
11529 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11530 /* Skip the first (segment number) field. */
11531 stringptr = findfield(stringptr);
11532 if (*stringptr == '\0') {
11533 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11534 polyfilename);
11535 triexit(1);
11536 } else {
11537 end[0] = (int) strtol(stringptr, &stringptr, 0);
11538 }
11539 stringptr = findfield(stringptr);
11540 if (*stringptr == '\0') {
11541 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11542 segmentnumber, polyfilename);
11543 triexit(1);
11544 } else {
11545 end[1] = (int) strtol(stringptr, &stringptr, 0);
11546 }
11547 if (segmentmarkers) {
11548 stringptr = findfield(stringptr);
11549 if (*stringptr == '\0') {
11550 boundmarker = 0;
11551 } else {
11552 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11553 }
11554 }
11555#endif /* not TRILIBRARY */
11556 for (j = 0; j < 2; j++) {
11557 if ((end[j] < b->firstnumber) ||
11558 (end[j] >= b->firstnumber + m->invertices)) {
11559 printf("Error: Segment %ld has an invalid vertex index.\n",
11560 segmentnumber);
11561 triexit(1);
11562 }
11563 }
11564
11565 /* set the subsegment's vertices. */
11566 subsegloop.ssorient = 0;
11567 segmentorg = getvertex(m, b, end[0]);
11568 segmentdest = getvertex(m, b, end[1]);
11569 setsorg(subsegloop, segmentorg);
11570 setsdest(subsegloop, segmentdest);
11571 setsegorg(subsegloop, segmentorg);
11572 setsegdest(subsegloop, segmentdest);
11573 setmark(subsegloop, boundmarker);
11574 /* Try linking the subsegment to triangles that share these vertices. */
11575 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11576 subsegloop.ssorient++) {
11577 /* Take the number for the destination of subsegloop. */
11578 aroundvertex = end[1 - subsegloop.ssorient];
11579 /* Look for triangles having this vertex. */
11580 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11581 nexttri = vertexarray[aroundvertex - b->firstnumber];
11582 decode(nexttri, checktri);
11583 sorg(subsegloop, shorg);
11584 notfound = 1;
11585 /* Look for triangles having this edge. Note that I'm only */
11586 /* comparing each triangle's destination with the subsegment; */
11587 /* each triangle's apex is handled through a different vertex. */
11588 /* Because each triangle appears on three vertices' lists, each */
11589 /* occurrence of a triangle on a list can (and does) represent */
11590 /* an edge. In this way, most edges are represented twice, and */
11591 /* every triangle-subsegment bond is represented once. */
11592 while (notfound && (checktri.tri != m->dummytri)) {
11593 dest(checktri, checkdest);
11594 if (shorg == checkdest) {
11595 /* We have a match. Remove this triangle from the list. */
11596 * prevlink = checktri.tri[6 + checktri.orient];
11597 /* Bond the subsegment to the triangle. */
11598 tsbond(checktri, subsegloop);
11599 /* Check if this is a boundary edge. */
11600 sym(checktri, checkneighbor);
11601 if (checkneighbor.tri == m->dummytri) {
11602 /* The next line doesn't insert a subsegment (because there's */
11603 /* already one there), but it sets the boundary markers of */
11604 /* the existing subsegment and its vertices. */
11605 insertsubseg(m, b, &checktri, 1);
11606 hullsize++;
11607 }
11608 notfound = 0;
11609 }
11610 /* Find the next triangle in the stack. */
11611 prevlink = &checktri.tri[6 + checktri.orient];
11612 nexttri = checktri.tri[6 + checktri.orient];
11613 decode(nexttri, checktri);
11614 }
11615 }
11616 subsegloop.ss = subsegtraverse(m);
11617 segmentnumber++;
11618 }
11619 }
11620
11621 /* Mark the remaining edges as not being attached to any subsegment. */
11622 /* Also, count the (yet uncounted) boundary edges. */
11623 for (i = 0; i < m->vertices.items; i++) {
11624 /* Search the stack of triangles adjacent to a vertex. */
11625 nexttri = vertexarray[i];
11626 decode(nexttri, checktri);
11627 while (checktri.tri != m->dummytri) {
11628 /* Find the next triangle in the stack before this */
11629 /* information gets overwritten. */
11630 nexttri = checktri.tri[6 + checktri.orient];
11631 /* No adjacent subsegment. (This overwrites the stack info.) */
11632 tsdissolve(checktri);
11633 sym(checktri, checkneighbor);
11634 if (checkneighbor.tri == m->dummytri) {
11635 insertsubseg(m, b, &checktri, 1);
11636 hullsize++;
11637 }
11638 decode(nexttri, checktri);
11639 }
11640 }
11641
11642 trifree((VOID *) vertexarray);
11643 return hullsize;
11644}
11645
11646#endif /* not CDT_ONLY */
11647
11650/********* General mesh construction routines end here *********/
11651
11652/********* Segment insertion begins here *********/
11656/*****************************************************************************/
11657/* */
11658/* finddirection() Find the first triangle on the path from one point */
11659/* to another. */
11660/* */
11661/* Finds the triangle that intersects a line segment drawn from the */
11662/* origin of `searchtri' to the point `searchpoint', and returns the result */
11663/* in `searchtri'. The origin of `searchtri' does not change, even though */
11664/* the triangle returned may differ from the one passed in. This routine */
11665/* is used to find the direction to move in to get from one point to */
11666/* another. */
11667/* */
11668/* The return value notes whether the destination or apex of the found */
11669/* triangle is collinear with the two points in question. */
11670/* */
11671/*****************************************************************************/
11672
11673#ifdef ANSI_DECLARATORS
11674enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11675 struct otri *searchtri,
11676 vertex searchpoint)
11677#else /* not ANSI_DECLARATORS */
11678enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11679struct mesh *m;
11680struct behavior *b;
11681struct otri *searchtri;
11682vertex searchpoint;
11683#endif /* not ANSI_DECLARATORS */
11684
11685{
11686 struct otri checktri;
11687 vertex startvertex;
11688 vertex leftvertex, rightvertex;
11689 REAL leftccw, rightccw;
11690 int leftflag, rightflag;
11691 triangle ptr; /* Temporary variable used by onext() and oprev(). */
11692
11693 org(*searchtri, startvertex);
11694 dest(*searchtri, rightvertex);
11695 apex(*searchtri, leftvertex);
11696 /* Is `searchpoint' to the left? */
11697 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11698 leftflag = leftccw > 0.0;
11699 /* Is `searchpoint' to the right? */
11700 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11701 rightflag = rightccw > 0.0;
11702 if (leftflag && rightflag) {
11703 /* `searchtri' faces directly away from `searchpoint'. We could go left */
11704 /* or right. Ask whether it's a triangle or a boundary on the left. */
11705 onext(*searchtri, checktri);
11706 if (checktri.tri == m->dummytri) {
11707 leftflag = 0;
11708 } else {
11709 rightflag = 0;
11710 }
11711 }
11712 while (leftflag) {
11713 /* Turn left until satisfied. */
11714 onextself(*searchtri);
11715 if (searchtri->tri == m->dummytri) {
11716 printf("Internal error in finddirection(): Unable to find a\n");
11717 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11718 startvertex[1]);
11719 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11720 internalerror();
11721 }
11722 apex(*searchtri, leftvertex);
11723 rightccw = leftccw;
11724 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11725 leftflag = leftccw > 0.0;
11726 }
11727 while (rightflag) {
11728 /* Turn right until satisfied. */
11729 oprevself(*searchtri);
11730 if (searchtri->tri == m->dummytri) {
11731 printf("Internal error in finddirection(): Unable to find a\n");
11732 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11733 startvertex[1]);
11734 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11735 internalerror();
11736 }
11737 dest(*searchtri, rightvertex);
11738 leftccw = rightccw;
11739 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11740 rightflag = rightccw > 0.0;
11741 }
11742 if (leftccw == 0.0) {
11743 return LEFTCOLLINEAR;
11744 } else if (rightccw == 0.0) {
11745 return RIGHTCOLLINEAR;
11746 } else {
11747 return WITHIN;
11748 }
11749}
11750
11751/*****************************************************************************/
11752/* */
11753/* segmentintersection() Find the intersection of an existing segment */
11754/* and a segment that is being inserted. Insert */
11755/* a vertex at the intersection, splitting an */
11756/* existing subsegment. */
11757/* */
11758/* The segment being inserted connects the apex of splittri to endpoint2. */
11759/* splitsubseg is the subsegment being split, and MUST adjoin splittri. */
11760/* Hence, endpoints of the subsegment being split are the origin and */
11761/* destination of splittri. */
11762/* */
11763/* On completion, splittri is a handle having the newly inserted */
11764/* intersection point as its origin, and endpoint1 as its destination. */
11765/* */
11766/*****************************************************************************/
11767
11768#ifdef ANSI_DECLARATORS
11769void segmentintersection(struct mesh *m, struct behavior *b,
11770 struct otri *splittri, struct osub *splitsubseg,
11771 vertex endpoint2)
11772#else /* not ANSI_DECLARATORS */
11773void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11774struct mesh *m;
11775struct behavior *b;
11776struct otri *splittri;
11777struct osub *splitsubseg;
11778vertex endpoint2;
11779#endif /* not ANSI_DECLARATORS */
11780
11781{
11782 struct osub opposubseg;
11783 vertex endpoint1;
11784 vertex torg, tdest;
11785 vertex leftvertex, rightvertex;
11786 vertex newvertex;
11787 enum insertvertexresult success;
11788 //enum finddirectionresult collinear; // commented out to get gcc4.6 working
11789 REAL ex, ey;
11790 REAL tx, ty;
11791 REAL etx, ety;
11792 REAL split, denom;
11793 int i;
11794 triangle ptr; /* Temporary variable used by onext(). */
11795 subseg sptr; /* Temporary variable used by snext(). */
11796
11797 /* Find the other three segment endpoints. */
11798 apex(*splittri, endpoint1);
11799 org(*splittri, torg);
11800 dest(*splittri, tdest);
11801 /* Segment intersection formulae; see the Antonio reference. */
11802 tx = tdest[0] - torg[0];
11803 ty = tdest[1] - torg[1];
11804 ex = endpoint2[0] - endpoint1[0];
11805 ey = endpoint2[1] - endpoint1[1];
11806 etx = torg[0] - endpoint2[0];
11807 ety = torg[1] - endpoint2[1];
11808 denom = ty * ex - tx * ey;
11809 if (denom == 0.0) {
11810 printf("Internal error in segmentintersection():");
11811 printf(" Attempt to find intersection of parallel segments.\n");
11812 internalerror();
11813 }
11814 split = (ey * etx - ex * ety) / denom;
11815 /* Create the new vertex. */
11816 newvertex = (vertex) poolalloc(&m->vertices);
11817 /* Interpolate its coordinate and attributes. */
11818 for (i = 0; i < 2 + m->nextras; i++) {
11819 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11820 }
11821 setvertexmark(newvertex, mark(*splitsubseg));
11822 setvertextype(newvertex, INPUTVERTEX);
11823 if (b->verbose > 1) {
11824 printf(
11825 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11826 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11827 }
11828 /* Insert the intersection vertex. This should always succeed. */
11829 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11830 if (success != SUCCESSFULVERTEX) {
11831 printf("Internal error in segmentintersection():\n");
11832 printf(" Failure to split a segment.\n");
11833 internalerror();
11834 }
11835 /* Record a triangle whose origin is the new vertex. */
11836 setvertex2tri(newvertex, encode(*splittri));
11837 if (m->steinerleft > 0) {
11838 m->steinerleft--;
11839 }
11840
11841 /* Divide the segment into two, and correct the segment endpoints. */
11842 ssymself(*splitsubseg);
11843 spivot(*splitsubseg, opposubseg);
11844 sdissolve(*splitsubseg);
11845 sdissolve(opposubseg);
11846 do {
11847 setsegorg(*splitsubseg, newvertex);
11848 snextself(*splitsubseg);
11849 } while (splitsubseg->ss != m->dummysub);
11850 do {
11851 setsegorg(opposubseg, newvertex);
11852 snextself(opposubseg);
11853 } while (opposubseg.ss != m->dummysub);
11854
11855 /* Inserting the vertex may have caused edge flips. We wish to rediscover */
11856 /* the edge connecting endpoint1 to the new intersection vertex. */
11857 finddirection(m, b, splittri, endpoint1); // "collinear =" commented out to get gcc4.6 working
11858 dest(*splittri, rightvertex);
11859 apex(*splittri, leftvertex);
11860 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11861 onextself(*splittri);
11862 } else if ((rightvertex[0] != endpoint1[0]) ||
11863 (rightvertex[1] != endpoint1[1])) {
11864 printf("Internal error in segmentintersection():\n");
11865 printf(" Topological inconsistency after splitting a segment.\n");
11866 internalerror();
11867 }
11868 /* `splittri' should have destination endpoint1. */
11869}
11870
11871/*****************************************************************************/
11872/* */
11873/* scoutsegment() Scout the first triangle on the path from one endpoint */
11874/* to another, and check for completion (reaching the */
11875/* second endpoint), a collinear vertex, or the */
11876/* intersection of two segments. */
11877/* */
11878/* Returns one if the entire segment is successfully inserted, and zero if */
11879/* the job must be finished by conformingedge() or constrainededge(). */
11880/* */
11881/* If the first triangle on the path has the second endpoint as its */
11882/* destination or apex, a subsegment is inserted and the job is done. */
11883/* */
11884/* If the first triangle on the path has a destination or apex that lies on */
11885/* the segment, a subsegment is inserted connecting the first endpoint to */
11886/* the collinear vertex, and the search is continued from the collinear */
11887/* vertex. */
11888/* */
11889/* If the first triangle on the path has a subsegment opposite its origin, */
11890/* then there is a segment that intersects the segment being inserted. */
11891/* Their intersection vertex is inserted, splitting the subsegment. */
11892/* */
11893/*****************************************************************************/
11894
11895#ifdef ANSI_DECLARATORS
11896int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11897 vertex endpoint2, int newmark)
11898#else /* not ANSI_DECLARATORS */
11899int scoutsegment(m, b, searchtri, endpoint2, newmark)
11900struct mesh *m;
11901struct behavior *b;
11902struct otri *searchtri;
11903vertex endpoint2;
11904int newmark;
11905#endif /* not ANSI_DECLARATORS */
11906
11907{
11908 struct otri crosstri;
11909 struct osub crosssubseg;
11910 vertex leftvertex, rightvertex;
11911 enum finddirectionresult collinear;
11912 subseg sptr; /* Temporary variable used by tspivot(). */
11913
11914 collinear = finddirection(m, b, searchtri, endpoint2);
11915 dest(*searchtri, rightvertex);
11916 apex(*searchtri, leftvertex);
11917 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11918 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11919 /* The segment is already an edge in the mesh. */
11920 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11921 lprevself(*searchtri);
11922 }
11923 /* Insert a subsegment, if there isn't already one there. */
11924 insertsubseg(m, b, searchtri, newmark);
11925 return 1;
11926 } else if (collinear == LEFTCOLLINEAR) {
11927 /* We've collided with a vertex between the segment's endpoints. */
11928 /* Make the collinear vertex be the triangle's origin. */
11929 lprevself(*searchtri);
11930 insertsubseg(m, b, searchtri, newmark);
11931 /* Insert the remainder of the segment. */
11932 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11933 } else if (collinear == RIGHTCOLLINEAR) {
11934 /* We've collided with a vertex between the segment's endpoints. */
11935 insertsubseg(m, b, searchtri, newmark);
11936 /* Make the collinear vertex be the triangle's origin. */
11937 lnextself(*searchtri);
11938 /* Insert the remainder of the segment. */
11939 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11940 } else {
11941 lnext(*searchtri, crosstri);
11942 tspivot(crosstri, crosssubseg);
11943 /* Check for a crossing segment. */
11944 if (crosssubseg.ss == m->dummysub) {
11945 return 0;
11946 } else {
11947 /* Insert a vertex at the intersection. */
11948 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11949 otricopy(crosstri, *searchtri);
11950 insertsubseg(m, b, searchtri, newmark);
11951 /* Insert the remainder of the segment. */
11952 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11953 }
11954 }
11955}
11956
11957/*****************************************************************************/
11958/* */
11959/* conformingedge() Force a segment into a conforming Delaunay */
11960/* triangulation by inserting a vertex at its midpoint, */
11961/* and recursively forcing in the two half-segments if */
11962/* necessary. */
11963/* */
11964/* Generates a sequence of subsegments connecting `endpoint1' to */
11965/* `endpoint2'. `newmark' is the boundary marker of the segment, assigned */
11966/* to each new splitting vertex and subsegment. */
11967/* */
11968/* Note that conformingedge() does not always maintain the conforming */
11969/* Delaunay property. Once inserted, segments are locked into place; */
11970/* vertices inserted later (to force other segments in) may render these */
11971/* fixed segments non-Delaunay. The conforming Delaunay property will be */
11972/* restored by enforcequality() by splitting encroached subsegments. */
11973/* */
11974/*****************************************************************************/
11975
11976#ifndef REDUCED
11977#ifndef CDT_ONLY
11978
11979#ifdef ANSI_DECLARATORS
11980void conformingedge(struct mesh *m, struct behavior *b,
11981 vertex endpoint1, vertex endpoint2, int newmark)
11982#else /* not ANSI_DECLARATORS */
11983void conformingedge(m, b, endpoint1, endpoint2, newmark)
11984struct mesh *m;
11985struct behavior *b;
11986vertex endpoint1;
11987vertex endpoint2;
11988int newmark;
11989#endif /* not ANSI_DECLARATORS */
11990
11991{
11992 struct otri searchtri1, searchtri2;
11993 struct osub brokensubseg;
11994 vertex newvertex;
11995 vertex midvertex1, midvertex2;
11996 enum insertvertexresult success;
11997 int i;
11998 subseg sptr; /* Temporary variable used by tspivot(). */
11999
12000 if (b->verbose > 2) {
12001 printf("Forcing segment into triangulation by recursive splitting:\n");
12002 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
12003 endpoint2[0], endpoint2[1]);
12004 }
12005 /* Create a new vertex to insert in the middle of the segment. */
12006 newvertex = (vertex) poolalloc(&m->vertices);
12007 /* Interpolate coordinates and attributes. */
12008 for (i = 0; i < 2 + m->nextras; i++) {
12009 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
12010 }
12011 setvertexmark(newvertex, newmark);
12012 setvertextype(newvertex, SEGMENTVERTEX);
12013 /* No known triangle to search from. */
12014 searchtri1.tri = m->dummytri;
12015 /* Attempt to insert the new vertex. */
12016 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
12017 0, 0);
12018 if (success == DUPLICATEVERTEX) {
12019 if (b->verbose > 2) {
12020 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
12021 newvertex[0], newvertex[1]);
12022 }
12023 /* Use the vertex that's already there. */
12024 vertexdealloc(m, newvertex);
12025 org(searchtri1, newvertex);
12026 } else {
12027 if (success == VIOLATINGVERTEX) {
12028 if (b->verbose > 2) {
12029 printf(" Two segments intersect at (%.12g, %.12g).\n",
12030 newvertex[0], newvertex[1]);
12031 }
12032 /* By fluke, we've landed right on another segment. Split it. */
12033 tspivot(searchtri1, brokensubseg);
12034 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
12035 0, 0);
12036 if (success != SUCCESSFULVERTEX) {
12037 printf("Internal error in conformingedge():\n");
12038 printf(" Failure to split a segment.\n");
12039 internalerror();
12040 }
12041 }
12042 /* The vertex has been inserted successfully. */
12043 if (m->steinerleft > 0) {
12044 m->steinerleft--;
12045 }
12046 }
12047 otricopy(searchtri1, searchtri2);
12048 /* `searchtri1' and `searchtri2' are fastened at their origins to */
12049 /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */
12050 /* respectively. First, we must get `searchtri2' out of the way so it */
12051 /* won't be invalidated during the insertion of the first half of the */
12052 /* segment. */
12053 finddirection(m, b, &searchtri2, endpoint2);
12054 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
12055 /* The origin of searchtri1 may have changed if a collision with an */
12056 /* intervening vertex on the segment occurred. */
12057 org(searchtri1, midvertex1);
12058 conformingedge(m, b, midvertex1, endpoint1, newmark);
12059 }
12060 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
12061 /* The origin of searchtri2 may have changed if a collision with an */
12062 /* intervening vertex on the segment occurred. */
12063 org(searchtri2, midvertex2);
12064 conformingedge(m, b, midvertex2, endpoint2, newmark);
12065 }
12066}
12067
12068#endif /* not CDT_ONLY */
12069#endif /* not REDUCED */
12070
12071/*****************************************************************************/
12072/* */
12073/* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */
12074/* recursively from an existing vertex. Pay special */
12075/* attention to stacking inverted triangles. */
12076/* */
12077/* This is a support routine for inserting segments into a constrained */
12078/* Delaunay triangulation. */
12079/* */
12080/* The origin of fixuptri is treated as if it has just been inserted, and */
12081/* the local Delaunay condition needs to be enforced. It is only enforced */
12082/* in one sector, however, that being the angular range defined by */
12083/* fixuptri. */
12084/* */
12085/* This routine also needs to make decisions regarding the "stacking" of */
12086/* triangles. (Read the description of constrainededge() below before */
12087/* reading on here, so you understand the algorithm.) If the position of */
12088/* the new vertex (the origin of fixuptri) indicates that the vertex before */
12089/* it on the polygon is a reflex vertex, then "stack" the triangle by */
12090/* doing nothing. (fixuptri is an inverted triangle, which is how stacked */
12091/* triangles are identified.) */
12092/* */
12093/* Otherwise, check whether the vertex before that was a reflex vertex. */
12094/* If so, perform an edge flip, thereby eliminating an inverted triangle */
12095/* (popping it off the stack). The edge flip may result in the creation */
12096/* of a new inverted triangle, depending on whether or not the new vertex */
12097/* is visible to the vertex three edges behind on the polygon. */
12098/* */
12099/* If neither of the two vertices behind the new vertex are reflex */
12100/* vertices, fixuptri and fartri, the triangle opposite it, are not */
12101/* inverted; hence, ensure that the edge between them is locally Delaunay. */
12102/* */
12103/* `leftside' indicates whether or not fixuptri is to the left of the */
12104/* segment being inserted. (Imagine that the segment is pointing up from */
12105/* endpoint1 to endpoint2.) */
12106/* */
12107/*****************************************************************************/
12108
12109#ifdef ANSI_DECLARATORS
12110void delaunayfixup(struct mesh *m, struct behavior *b,
12111 struct otri *fixuptri, int leftside)
12112#else /* not ANSI_DECLARATORS */
12113void delaunayfixup(m, b, fixuptri, leftside)
12114struct mesh *m;
12115struct behavior *b;
12116struct otri *fixuptri;
12117int leftside;
12118#endif /* not ANSI_DECLARATORS */
12119
12120{
12121 struct otri neartri;
12122 struct otri fartri;
12123 struct osub faredge;
12124 vertex nearvertex, leftvertex, rightvertex, farvertex;
12125 triangle ptr; /* Temporary variable used by sym(). */
12126 subseg sptr; /* Temporary variable used by tspivot(). */
12127
12128 lnext(*fixuptri, neartri);
12129 sym(neartri, fartri);
12130 /* Check if the edge opposite the origin of fixuptri can be flipped. */
12131 if (fartri.tri == m->dummytri) {
12132 return;
12133 }
12134 tspivot(neartri, faredge);
12135 if (faredge.ss != m->dummysub) {
12136 return;
12137 }
12138 /* Find all the relevant vertices. */
12139 apex(neartri, nearvertex);
12140 org(neartri, leftvertex);
12141 dest(neartri, rightvertex);
12142 apex(fartri, farvertex);
12143 /* Check whether the previous polygon vertex is a reflex vertex. */
12144 if (leftside) {
12145 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12146 /* leftvertex is a reflex vertex too. Nothing can */
12147 /* be done until a convex section is found. */
12148 return;
12149 }
12150 } else {
12151 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12152 /* rightvertex is a reflex vertex too. Nothing can */
12153 /* be done until a convex section is found. */
12154 return;
12155 }
12156 }
12157 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12158 /* fartri is not an inverted triangle, and farvertex is not a reflex */
12159 /* vertex. As there are no reflex vertices, fixuptri isn't an */
12160 /* inverted triangle, either. Hence, test the edge between the */
12161 /* triangles to ensure it is locally Delaunay. */
12162 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12163 0.0) {
12164 return;
12165 }
12166 /* Not locally Delaunay; go on to an edge flip. */
12167 } /* else fartri is inverted; remove it from the stack by flipping. */
12168 flip(m, b, &neartri);
12169 lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */
12170 /* Recursively process the two triangles that result from the flip. */
12171 delaunayfixup(m, b, fixuptri, leftside);
12172 delaunayfixup(m, b, &fartri, leftside);
12173}
12174
12175/*****************************************************************************/
12176/* */
12177/* constrainededge() Force a segment into a constrained Delaunay */
12178/* triangulation by deleting the triangles it */
12179/* intersects, and triangulating the polygons that */
12180/* form on each side of it. */
12181/* */
12182/* Generates a single subsegment connecting `endpoint1' to `endpoint2'. */
12183/* The triangle `starttri' has `endpoint1' as its origin. `newmark' is the */
12184/* boundary marker of the segment. */
12185/* */
12186/* To insert a segment, every triangle whose interior intersects the */
12187/* segment is deleted. The union of these deleted triangles is a polygon */
12188/* (which is not necessarily monotone, but is close enough), which is */
12189/* divided into two polygons by the new segment. This routine's task is */
12190/* to generate the Delaunay triangulation of these two polygons. */
12191/* */
12192/* You might think of this routine's behavior as a two-step process. The */
12193/* first step is to walk from endpoint1 to endpoint2, flipping each edge */
12194/* encountered. This step creates a fan of edges connected to endpoint1, */
12195/* including the desired edge to endpoint2. The second step enforces the */
12196/* Delaunay condition on each side of the segment in an incremental manner: */
12197/* proceeding along the polygon from endpoint1 to endpoint2 (this is done */
12198/* independently on each side of the segment), each vertex is "enforced" */
12199/* as if it had just been inserted, but affecting only the previous */
12200/* vertices. The result is the same as if the vertices had been inserted */
12201/* in the order they appear on the polygon, so the result is Delaunay. */
12202/* */
12203/* In truth, constrainededge() interleaves these two steps. The procedure */
12204/* walks from endpoint1 to endpoint2, and each time an edge is encountered */
12205/* and flipped, the newly exposed vertex (at the far end of the flipped */
12206/* edge) is "enforced" upon the previously flipped edges, usually affecting */
12207/* only one side of the polygon (depending upon which side of the segment */
12208/* the vertex falls on). */
12209/* */
12210/* The algorithm is complicated by the need to handle polygons that are not */
12211/* convex. Although the polygon is not necessarily monotone, it can be */
12212/* triangulated in a manner similar to the stack-based algorithms for */
12213/* monotone polygons. For each reflex vertex (local concavity) of the */
12214/* polygon, there will be an inverted triangle formed by one of the edge */
12215/* flips. (An inverted triangle is one with negative area - that is, its */
12216/* vertices are arranged in clockwise order - and is best thought of as a */
12217/* wrinkle in the fabric of the mesh.) Each inverted triangle can be */
12218/* thought of as a reflex vertex pushed on the stack, waiting to be fixed */
12219/* later. */
12220/* */
12221/* A reflex vertex is popped from the stack when a vertex is inserted that */
12222/* is visible to the reflex vertex. (However, if the vertex behind the */
12223/* reflex vertex is not visible to the reflex vertex, a new inverted */
12224/* triangle will take its place on the stack.) These details are handled */
12225/* by the delaunayfixup() routine above. */
12226/* */
12227/*****************************************************************************/
12228
12229#ifdef ANSI_DECLARATORS
12230void constrainededge(struct mesh *m, struct behavior *b,
12231 struct otri *starttri, vertex endpoint2, int newmark)
12232#else /* not ANSI_DECLARATORS */
12233void constrainededge(m, b, starttri, endpoint2, newmark)
12234struct mesh *m;
12235struct behavior *b;
12236struct otri *starttri;
12237vertex endpoint2;
12238int newmark;
12239#endif /* not ANSI_DECLARATORS */
12240
12241{
12242 struct otri fixuptri, fixuptri2;
12243 struct osub crosssubseg;
12244 vertex endpoint1;
12245 vertex farvertex;
12246 REAL area;
12247 int collision;
12248 int done;
12249 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12250 subseg sptr; /* Temporary variable used by tspivot(). */
12251
12252 org(*starttri, endpoint1);
12253 lnext(*starttri, fixuptri);
12254 flip(m, b, &fixuptri);
12255 /* `collision' indicates whether we have found a vertex directly */
12256 /* between endpoint1 and endpoint2. */
12257 collision = 0;
12258 done = 0;
12259 do {
12260 org(fixuptri, farvertex);
12261 /* `farvertex' is the extreme point of the polygon we are "digging" */
12262 /* to get from endpoint1 to endpoint2. */
12263 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12264 oprev(fixuptri, fixuptri2);
12265 /* Enforce the Delaunay condition around endpoint2. */
12266 delaunayfixup(m, b, &fixuptri, 0);
12267 delaunayfixup(m, b, &fixuptri2, 1);
12268 done = 1;
12269 } else {
12270 /* Check whether farvertex is to the left or right of the segment */
12271 /* being inserted, to decide which edge of fixuptri to dig */
12272 /* through next. */
12273 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12274 if (area == 0.0) {
12275 /* We've collided with a vertex between endpoint1 and endpoint2. */
12276 collision = 1;
12277 oprev(fixuptri, fixuptri2);
12278 /* Enforce the Delaunay condition around farvertex. */
12279 delaunayfixup(m, b, &fixuptri, 0);
12280 delaunayfixup(m, b, &fixuptri2, 1);
12281 done = 1;
12282 } else {
12283 if (area > 0.0) { /* farvertex is to the left of the segment. */
12284 oprev(fixuptri, fixuptri2);
12285 /* Enforce the Delaunay condition around farvertex, on the */
12286 /* left side of the segment only. */
12287 delaunayfixup(m, b, &fixuptri2, 1);
12288 /* Flip the edge that crosses the segment. After the edge is */
12289 /* flipped, one of its endpoints is the fan vertex, and the */
12290 /* destination of fixuptri is the fan vertex. */
12291 lprevself(fixuptri);
12292 } else { /* farvertex is to the right of the segment. */
12293 delaunayfixup(m, b, &fixuptri, 0);
12294 /* Flip the edge that crosses the segment. After the edge is */
12295 /* flipped, one of its endpoints is the fan vertex, and the */
12296 /* destination of fixuptri is the fan vertex. */
12297 oprevself(fixuptri);
12298 }
12299 /* Check for two intersecting segments. */
12300 tspivot(fixuptri, crosssubseg);
12301 if (crosssubseg.ss == m->dummysub) {
12302 flip(m, b, &fixuptri); /* May create inverted triangle at left. */
12303 } else {
12304 /* We've collided with a segment between endpoint1 and endpoint2. */
12305 collision = 1;
12306 /* Insert a vertex at the intersection. */
12307 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12308 done = 1;
12309 }
12310 }
12311 }
12312 } while (!done);
12313 /* Insert a subsegment to make the segment permanent. */
12314 insertsubseg(m, b, &fixuptri, newmark);
12315 /* If there was a collision with an interceding vertex, install another */
12316 /* segment connecting that vertex with endpoint2. */
12317 if (collision) {
12318 /* Insert the remainder of the segment. */
12319 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12320 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12321 }
12322 }
12323}
12324
12325/*****************************************************************************/
12326/* */
12327/* insertsegment() Insert a PSLG segment into a triangulation. */
12328/* */
12329/*****************************************************************************/
12330
12331#ifdef ANSI_DECLARATORS
12332void insertsegment(struct mesh *m, struct behavior *b,
12333 vertex endpoint1, vertex endpoint2, int newmark)
12334#else /* not ANSI_DECLARATORS */
12335void insertsegment(m, b, endpoint1, endpoint2, newmark)
12336struct mesh *m;
12337struct behavior *b;
12338vertex endpoint1;
12339vertex endpoint2;
12340int newmark;
12341#endif /* not ANSI_DECLARATORS */
12342
12343{
12344 struct otri searchtri1, searchtri2;
12345 triangle encodedtri;
12346 vertex checkvertex;
12347 triangle ptr; /* Temporary variable used by sym(). */
12348
12349 if (b->verbose > 1) {
12350 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12351 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12352 }
12353
12354 /* Find a triangle whose origin is the segment's first endpoint. */
12355 checkvertex = (vertex) NULL;
12356 encodedtri = vertex2tri(endpoint1);
12357 if (encodedtri != (triangle) NULL) {
12358 decode(encodedtri, searchtri1);
12359 org(searchtri1, checkvertex);
12360 }
12361 if (checkvertex != endpoint1) {
12362 /* Find a boundary triangle to search from. */
12363 searchtri1.tri = m->dummytri;
12364 searchtri1.orient = 0;
12365 symself(searchtri1);
12366 /* Search for the segment's first endpoint by point location. */
12367 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12368 printf(
12369 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12370 printf(" (%.12g, %.12g) in triangulation.\n",
12371 endpoint1[0], endpoint1[1]);
12372 internalerror();
12373 }
12374 }
12375 /* Remember this triangle to improve subsequent point location. */
12376 otricopy(searchtri1, m->recenttri);
12377 /* Scout the beginnings of a path from the first endpoint */
12378 /* toward the second. */
12379 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12380 /* The segment was easily inserted. */
12381 return;
12382 }
12383 /* The first endpoint may have changed if a collision with an intervening */
12384 /* vertex on the segment occurred. */
12385 org(searchtri1, endpoint1);
12386
12387 /* Find a triangle whose origin is the segment's second endpoint. */
12388 checkvertex = (vertex) NULL;
12389 encodedtri = vertex2tri(endpoint2);
12390 if (encodedtri != (triangle) NULL) {
12391 decode(encodedtri, searchtri2);
12392 org(searchtri2, checkvertex);
12393 }
12394 if (checkvertex != endpoint2) {
12395 /* Find a boundary triangle to search from. */
12396 searchtri2.tri = m->dummytri;
12397 searchtri2.orient = 0;
12398 symself(searchtri2);
12399 /* Search for the segment's second endpoint by point location. */
12400 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12401 printf(
12402 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12403 printf(" (%.12g, %.12g) in triangulation.\n",
12404 endpoint2[0], endpoint2[1]);
12405 internalerror();
12406 }
12407 }
12408 /* Remember this triangle to improve subsequent point location. */
12409 otricopy(searchtri2, m->recenttri);
12410 /* Scout the beginnings of a path from the second endpoint */
12411 /* toward the first. */
12412 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12413 /* The segment was easily inserted. */
12414 return;
12415 }
12416 /* The second endpoint may have changed if a collision with an intervening */
12417 /* vertex on the segment occurred. */
12418 org(searchtri2, endpoint2);
12419
12420#ifndef REDUCED
12421#ifndef CDT_ONLY
12422 if (b->splitseg) {
12423 /* Insert vertices to force the segment into the triangulation. */
12424 conformingedge(m, b, endpoint1, endpoint2, newmark);
12425 } else {
12426#endif /* not CDT_ONLY */
12427#endif /* not REDUCED */
12428 /* Insert the segment directly into the triangulation. */
12429 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12430#ifndef REDUCED
12431#ifndef CDT_ONLY
12432 }
12433#endif /* not CDT_ONLY */
12434#endif /* not REDUCED */
12435}
12436
12437/*****************************************************************************/
12438/* */
12439/* markhull() Cover the convex hull of a triangulation with subsegments. */
12440/* */
12441/*****************************************************************************/
12442
12443#ifdef ANSI_DECLARATORS
12444void markhull(struct mesh *m, struct behavior *b)
12445#else /* not ANSI_DECLARATORS */
12446void markhull(m, b)
12447struct mesh *m;
12448struct behavior *b;
12449#endif /* not ANSI_DECLARATORS */
12450
12451{
12452 struct otri hulltri;
12453 struct otri nexttri;
12454 struct otri starttri;
12455 triangle ptr; /* Temporary variable used by sym() and oprev(). */
12456
12457 /* Find a triangle handle on the hull. */
12458 hulltri.tri = m->dummytri;
12459 hulltri.orient = 0;
12460 symself(hulltri);
12461 /* Remember where we started so we know when to stop. */
12462 otricopy(hulltri, starttri);
12463 /* Go once counterclockwise around the convex hull. */
12464 do {
12465 /* Create a subsegment if there isn't already one here. */
12466 insertsubseg(m, b, &hulltri, 1);
12467 /* To find the next hull edge, go clockwise around the next vertex. */
12468 lnextself(hulltri);
12469 oprev(hulltri, nexttri);
12470 while (nexttri.tri != m->dummytri) {
12471 otricopy(nexttri, hulltri);
12472 oprev(hulltri, nexttri);
12473 }
12474 } while (!otriequal(hulltri, starttri));
12475}
12476
12477/*****************************************************************************/
12478/* */
12479/* formskeleton() Create the segments of a triangulation, including PSLG */
12480/* segments and edges on the convex hull. */
12481/* */
12482/* The PSLG segments are read from a .poly file. The return value is the */
12483/* number of segments in the file. */
12484/* */
12485/*****************************************************************************/
12486
12487#ifdef TRILIBRARY
12488
12489#ifdef ANSI_DECLARATORS
12490void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12491 int *segmentmarkerlist, int numberofsegments)
12492#else /* not ANSI_DECLARATORS */
12493void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12494struct mesh *m;
12495struct behavior *b;
12496int *segmentlist;
12497int *segmentmarkerlist;
12498int numberofsegments;
12499#endif /* not ANSI_DECLARATORS */
12500
12501#else /* not TRILIBRARY */
12502
12503#ifdef ANSI_DECLARATORS
12504void formskeleton(struct mesh *m, struct behavior *b,
12505 FILE* polyfile, char* polyfilename)
12506#else /* not ANSI_DECLARATORS */
12507void formskeleton(m, b, polyfile, polyfilename)
12508struct mesh *m;
12509struct behavior *b;
12510FILE* polyfile;
12511char* polyfilename;
12512#endif /* not ANSI_DECLARATORS */
12513
12514#endif /* not TRILIBRARY */
12515
12516{
12517#ifdef TRILIBRARY
12518 char polyfilename[6];
12519 int index;
12520#else /* not TRILIBRARY */
12521 char inputline[INPUTLINESIZE];
12522 char *stringptr;
12523#endif /* not TRILIBRARY */
12524 vertex endpoint1, endpoint2;
12525 int segmentmarkers;
12526 int end1, end2;
12527 int boundmarker;
12528 int i;
12529
12530 if (b->poly) {
12531 if (!b->quiet) {
12532 printf("Recovering segments in Delaunay triangulation.\n");
12533 }
12534#ifdef TRILIBRARY
12535 strcpy(polyfilename, "input");
12536 m->insegments = numberofsegments;
12537 segmentmarkers = segmentmarkerlist != (int *) NULL;
12538 index = 0;
12539#else /* not TRILIBRARY */
12540 /* Read the segments from a .poly file. */
12541 /* Read number of segments and number of boundary markers. */
12542 stringptr = readline(inputline, polyfile, polyfilename);
12543 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12544 stringptr = findfield(stringptr);
12545 if (*stringptr == '\0') {
12546 segmentmarkers = 0;
12547 } else {
12548 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12549 }
12550#endif /* not TRILIBRARY */
12551 /* If the input vertices are collinear, there is no triangulation, */
12552 /* so don't try to insert segments. */
12553 if (m->triangles.items == 0) {
12554 return;
12555 }
12556
12557 /* If segments are to be inserted, compute a mapping */
12558 /* from vertices to triangles. */
12559 if (m->insegments > 0) {
12560 makevertexmap(m, b);
12561 if (b->verbose) {
12562 printf(" Recovering PSLG segments.\n");
12563 }
12564 }
12565
12566 boundmarker = 0;
12567 /* Read and insert the segments. */
12568 for (i = 0; i < m->insegments; i++) {
12569#ifdef TRILIBRARY
12570 end1 = segmentlist[index++];
12571 end2 = segmentlist[index++];
12572 if (segmentmarkers) {
12573 boundmarker = segmentmarkerlist[i];
12574 }
12575#else /* not TRILIBRARY */
12576 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12577 stringptr = findfield(stringptr);
12578 if (*stringptr == '\0') {
12579 printf("Error: Segment %d has no endpoints in %s.\n",
12580 b->firstnumber + i, polyfilename);
12581 triexit(1);
12582 } else {
12583 end1 = (int) strtol(stringptr, &stringptr, 0);
12584 }
12585 stringptr = findfield(stringptr);
12586 if (*stringptr == '\0') {
12587 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12588 b->firstnumber + i, polyfilename);
12589 triexit(1);
12590 } else {
12591 end2 = (int) strtol(stringptr, &stringptr, 0);
12592 }
12593 if (segmentmarkers) {
12594 stringptr = findfield(stringptr);
12595 if (*stringptr == '\0') {
12596 boundmarker = 0;
12597 } else {
12598 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12599 }
12600 }
12601#endif /* not TRILIBRARY */
12602 if ((end1 < b->firstnumber) ||
12603 (end1 >= b->firstnumber + m->invertices)) {
12604 if (!b->quiet) {
12605 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12606 b->firstnumber + i, polyfilename);
12607 }
12608 } else if ((end2 < b->firstnumber) ||
12609 (end2 >= b->firstnumber + m->invertices)) {
12610 if (!b->quiet) {
12611 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12612 b->firstnumber + i, polyfilename);
12613 }
12614 } else {
12615 /* Find the vertices numbered `end1' and `end2'. */
12616 endpoint1 = getvertex(m, b, end1);
12617 endpoint2 = getvertex(m, b, end2);
12618 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12619 if (!b->quiet) {
12620 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12621 b->firstnumber + i, polyfilename);
12622 }
12623 } else {
12624 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12625 }
12626 }
12627 }
12628 } else {
12629 m->insegments = 0;
12630 }
12631 if (b->convex || !b->poly) {
12632 /* Enclose the convex hull with subsegments. */
12633 if (b->verbose) {
12634 printf(" Enclosing convex hull with segments.\n");
12635 }
12636 markhull(m, b);
12637 }
12638}
12639
12642/********* Segment insertion ends here *********/
12643
12644/********* Carving out holes and concavities begins here *********/
12648/*****************************************************************************/
12649/* */
12650/* infecthull() Virally infect all of the triangles of the convex hull */
12651/* that are not protected by subsegments. Where there are */
12652/* subsegments, set boundary markers as appropriate. */
12653/* */
12654/*****************************************************************************/
12655
12656#ifdef ANSI_DECLARATORS
12657void infecthull(struct mesh *m, struct behavior *b)
12658#else /* not ANSI_DECLARATORS */
12659void infecthull(m, b)
12660struct mesh *m;
12661struct behavior *b;
12662#endif /* not ANSI_DECLARATORS */
12663
12664{
12665 struct otri hulltri;
12666 struct otri nexttri;
12667 struct otri starttri;
12668 struct osub hullsubseg;
12669 triangle **deadtriangle;
12670 vertex horg, hdest;
12671 triangle ptr; /* Temporary variable used by sym(). */
12672 subseg sptr; /* Temporary variable used by tspivot(). */
12673
12674 if (b->verbose) {
12675 printf(" Marking concavities (external triangles) for elimination.\n");
12676 }
12677 /* Find a triangle handle on the hull. */
12678 hulltri.tri = m->dummytri;
12679 hulltri.orient = 0;
12680 symself(hulltri);
12681 /* Remember where we started so we know when to stop. */
12682 otricopy(hulltri, starttri);
12683 /* Go once counterclockwise around the convex hull. */
12684 do {
12685 /* Ignore triangles that are already infected. */
12686 if (!infected(hulltri)) {
12687 /* Is the triangle protected by a subsegment? */
12688 tspivot(hulltri, hullsubseg);
12689 if (hullsubseg.ss == m->dummysub) {
12690 /* The triangle is not protected; infect it. */
12691 if (!infected(hulltri)) {
12692 infect(hulltri);
12693 deadtriangle = (triangle **) poolalloc(&m->viri);
12694 *deadtriangle = hulltri.tri;
12695 }
12696 } else {
12697 /* The triangle is protected; set boundary markers if appropriate. */
12698 if (mark(hullsubseg) == 0) {
12699 setmark(hullsubseg, 1);
12700 org(hulltri, horg);
12701 dest(hulltri, hdest);
12702 if (vertexmark(horg) == 0) {
12703 setvertexmark(horg, 1);
12704 }
12705 if (vertexmark(hdest) == 0) {
12706 setvertexmark(hdest, 1);
12707 }
12708 }
12709 }
12710 }
12711 /* To find the next hull edge, go clockwise around the next vertex. */
12712 lnextself(hulltri);
12713 oprev(hulltri, nexttri);
12714 while (nexttri.tri != m->dummytri) {
12715 otricopy(nexttri, hulltri);
12716 oprev(hulltri, nexttri);
12717 }
12718 } while (!otriequal(hulltri, starttri));
12719}
12720
12721/*****************************************************************************/
12722/* */
12723/* plague() Spread the virus from all infected triangles to any neighbors */
12724/* not protected by subsegments. Delete all infected triangles. */
12725/* */
12726/* This is the procedure that actually creates holes and concavities. */
12727/* */
12728/* This procedure operates in two phases. The first phase identifies all */
12729/* the triangles that will die, and marks them as infected. They are */
12730/* marked to ensure that each triangle is added to the virus pool only */
12731/* once, so the procedure will terminate. */
12732/* */
12733/* The second phase actually eliminates the infected triangles. It also */
12734/* eliminates orphaned vertices. */
12735/* */
12736/*****************************************************************************/
12737
12738#ifdef ANSI_DECLARATORS
12739void plague(struct mesh *m, struct behavior *b)
12740#else /* not ANSI_DECLARATORS */
12741void plague(m, b)
12742struct mesh *m;
12743struct behavior *b;
12744#endif /* not ANSI_DECLARATORS */
12745
12746{
12747 struct otri testtri;
12748 struct otri neighbor;
12749 triangle **virusloop;
12750 triangle **deadtriangle;
12751 struct osub neighborsubseg;
12752 vertex testvertex;
12753 vertex norg, ndest;
12754 vertex deadorg, deaddest, deadapex;
12755 int killorg;
12756 triangle ptr; /* Temporary variable used by sym() and onext(). */
12757 subseg sptr; /* Temporary variable used by tspivot(). */
12758
12759 if (b->verbose) {
12760 printf(" Marking neighbors of marked triangles.\n");
12761 }
12762 /* Loop through all the infected triangles, spreading the virus to */
12763 /* their neighbors, then to their neighbors' neighbors. */
12764 traversalinit(&m->viri);
12765 virusloop = (triangle **) traverse(&m->viri);
12766 while (virusloop != (triangle **) NULL) {
12767 testtri.tri = *virusloop;
12768 /* A triangle is marked as infected by messing with one of its pointers */
12769 /* to subsegments, setting it to an illegal value. Hence, we have to */
12770 /* temporarily uninfect this triangle so that we can examine its */
12771 /* adjacent subsegments. */
12772 uninfect(testtri);
12773 if (b->verbose > 2) {
12774 /* Assign the triangle an orientation for convenience in */
12775 /* checking its vertices. */
12776 testtri.orient = 0;
12777 org(testtri, deadorg);
12778 dest(testtri, deaddest);
12779 apex(testtri, deadapex);
12780 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12781 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12782 deadapex[0], deadapex[1]);
12783 }
12784 /* Check each of the triangle's three neighbors. */
12785 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12786 /* Find the neighbor. */
12787 sym(testtri, neighbor);
12788 /* Check for a subsegment between the triangle and its neighbor. */
12789 tspivot(testtri, neighborsubseg);
12790 /* Check if the neighbor is nonexistent or already infected. */
12791 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12792 if (neighborsubseg.ss != m->dummysub) {
12793 /* There is a subsegment separating the triangle from its */
12794 /* neighbor, but both triangles are dying, so the subsegment */
12795 /* dies too. */
12796 subsegdealloc(m, neighborsubseg.ss);
12797 if (neighbor.tri != m->dummytri) {
12798 /* Make sure the subsegment doesn't get deallocated again */
12799 /* later when the infected neighbor is visited. */
12800 uninfect(neighbor);
12801 tsdissolve(neighbor);
12802 infect(neighbor);
12803 }
12804 }
12805 } else { /* The neighbor exists and is not infected. */
12806 if (neighborsubseg.ss == m->dummysub) {
12807 /* There is no subsegment protecting the neighbor, so */
12808 /* the neighbor becomes infected. */
12809 if (b->verbose > 2) {
12810 org(neighbor, deadorg);
12811 dest(neighbor, deaddest);
12812 apex(neighbor, deadapex);
12813 printf(
12814 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12815 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12816 deadapex[0], deadapex[1]);
12817 }
12818 infect(neighbor);
12819 /* Ensure that the neighbor's neighbors will be infected. */
12820 deadtriangle = (triangle **) poolalloc(&m->viri);
12821 *deadtriangle = neighbor.tri;
12822 } else { /* The neighbor is protected by a subsegment. */
12823 /* Remove this triangle from the subsegment. */
12824 stdissolve(neighborsubseg);
12825 /* The subsegment becomes a boundary. Set markers accordingly. */
12826 if (mark(neighborsubseg) == 0) {
12827 setmark(neighborsubseg, 1);
12828 }
12829 org(neighbor, norg);
12830 dest(neighbor, ndest);
12831 if (vertexmark(norg) == 0) {
12832 setvertexmark(norg, 1);
12833 }
12834 if (vertexmark(ndest) == 0) {
12835 setvertexmark(ndest, 1);
12836 }
12837 }
12838 }
12839 }
12840 /* Remark the triangle as infected, so it doesn't get added to the */
12841 /* virus pool again. */
12842 infect(testtri);
12843 virusloop = (triangle **) traverse(&m->viri);
12844 }
12845
12846 if (b->verbose) {
12847 printf(" Deleting marked triangles.\n");
12848 }
12849
12850 traversalinit(&m->viri);
12851 virusloop = (triangle **) traverse(&m->viri);
12852 while (virusloop != (triangle **) NULL) {
12853 testtri.tri = *virusloop;
12854
12855 /* Check each of the three corners of the triangle for elimination. */
12856 /* This is done by walking around each vertex, checking if it is */
12857 /* still connected to at least one live triangle. */
12858 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12859 org(testtri, testvertex);
12860 /* Check if the vertex has already been tested. */
12861 if (testvertex != (vertex) NULL) {
12862 killorg = 1;
12863 /* Mark the corner of the triangle as having been tested. */
12864 setorg(testtri, NULL);
12865 /* Walk counterclockwise about the vertex. */
12866 onext(testtri, neighbor);
12867 /* Stop upon reaching a boundary or the starting triangle. */
12868 while ((neighbor.tri != m->dummytri) &&
12869 (!otriequal(neighbor, testtri))) {
12870 if (infected(neighbor)) {
12871 /* Mark the corner of this triangle as having been tested. */
12872 setorg(neighbor, NULL);
12873 } else {
12874 /* A live triangle. The vertex survives. */
12875 killorg = 0;
12876 }
12877 /* Walk counterclockwise about the vertex. */
12878 onextself(neighbor);
12879 }
12880 /* If we reached a boundary, we must walk clockwise as well. */
12881 if (neighbor.tri == m->dummytri) {
12882 /* Walk clockwise about the vertex. */
12883 oprev(testtri, neighbor);
12884 /* Stop upon reaching a boundary. */
12885 while (neighbor.tri != m->dummytri) {
12886 if (infected(neighbor)) {
12887 /* Mark the corner of this triangle as having been tested. */
12888 setorg(neighbor, NULL);
12889 } else {
12890 /* A live triangle. The vertex survives. */
12891 killorg = 0;
12892 }
12893 /* Walk clockwise about the vertex. */
12894 oprevself(neighbor);
12895 }
12896 }
12897 if (killorg) {
12898 if (b->verbose > 1) {
12899 printf(" Deleting vertex (%.12g, %.12g)\n",
12900 testvertex[0], testvertex[1]);
12901 }
12902 setvertextype(testvertex, UNDEADVERTEX);
12903 m->undeads++;
12904 }
12905 }
12906 }
12907
12908 /* Record changes in the number of boundary edges, and disconnect */
12909 /* dead triangles from their neighbors. */
12910 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12911 sym(testtri, neighbor);
12912 if (neighbor.tri == m->dummytri) {
12913 /* There is no neighboring triangle on this edge, so this edge */
12914 /* is a boundary edge. This triangle is being deleted, so this */
12915 /* boundary edge is deleted. */
12916 m->hullsize--;
12917 } else {
12918 /* Disconnect the triangle from its neighbor. */
12919 dissolve(neighbor);
12920 /* There is a neighboring triangle on this edge, so this edge */
12921 /* becomes a boundary edge when this triangle is deleted. */
12922 m->hullsize++;
12923 }
12924 }
12925 /* Return the dead triangle to the pool of triangles. */
12926 triangledealloc(m, testtri.tri);
12927 virusloop = (triangle **) traverse(&m->viri);
12928 }
12929 /* Empty the virus pool. */
12930 poolrestart(&m->viri);
12931}
12932
12933/*****************************************************************************/
12934/* */
12935/* regionplague() Spread regional attributes and/or area constraints */
12936/* (from a .poly file) throughout the mesh. */
12937/* */
12938/* This procedure operates in two phases. The first phase spreads an */
12939/* attribute and/or an area constraint through a (segment-bounded) region. */
12940/* The triangles are marked to ensure that each triangle is added to the */
12941/* virus pool only once, so the procedure will terminate. */
12942/* */
12943/* The second phase uninfects all infected triangles, returning them to */
12944/* normal. */
12945/* */
12946/*****************************************************************************/
12947
12948#ifdef ANSI_DECLARATORS
12949void regionplague(struct mesh *m, struct behavior *b,
12950 REAL attribute, REAL area)
12951#else /* not ANSI_DECLARATORS */
12952void regionplague(m, b, attribute, area)
12953struct mesh *m;
12954struct behavior *b;
12955REAL attribute;
12956REAL area;
12957#endif /* not ANSI_DECLARATORS */
12958
12959{
12960 struct otri testtri;
12961 struct otri neighbor;
12962 triangle **virusloop;
12963 triangle **regiontri;
12964 struct osub neighborsubseg;
12965 vertex regionorg, regiondest, regionapex;
12966 triangle ptr; /* Temporary variable used by sym() and onext(). */
12967 subseg sptr; /* Temporary variable used by tspivot(). */
12968
12969 if (b->verbose > 1) {
12970 printf(" Marking neighbors of marked triangles.\n");
12971 }
12972 /* Loop through all the infected triangles, spreading the attribute */
12973 /* and/or area constraint to their neighbors, then to their neighbors' */
12974 /* neighbors. */
12975 traversalinit(&m->viri);
12976 virusloop = (triangle **) traverse(&m->viri);
12977 while (virusloop != (triangle **) NULL) {
12978 testtri.tri = *virusloop;
12979 /* A triangle is marked as infected by messing with one of its pointers */
12980 /* to subsegments, setting it to an illegal value. Hence, we have to */
12981 /* temporarily uninfect this triangle so that we can examine its */
12982 /* adjacent subsegments. */
12983 uninfect(testtri);
12984 if (b->regionattrib) {
12985 /* Set an attribute. */
12986 setelemattribute(testtri, m->eextras, attribute);
12987 }
12988 if (b->vararea) {
12989 /* Set an area constraint. */
12990 setareabound(testtri, area);
12991 }
12992 if (b->verbose > 2) {
12993 /* Assign the triangle an orientation for convenience in */
12994 /* checking its vertices. */
12995 testtri.orient = 0;
12996 org(testtri, regionorg);
12997 dest(testtri, regiondest);
12998 apex(testtri, regionapex);
12999 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13000 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
13001 regionapex[0], regionapex[1]);
13002 }
13003 /* Check each of the triangle's three neighbors. */
13004 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
13005 /* Find the neighbor. */
13006 sym(testtri, neighbor);
13007 /* Check for a subsegment between the triangle and its neighbor. */
13008 tspivot(testtri, neighborsubseg);
13009 /* Make sure the neighbor exists, is not already infected, and */
13010 /* isn't protected by a subsegment. */
13011 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
13012 && (neighborsubseg.ss == m->dummysub)) {
13013 if (b->verbose > 2) {
13014 org(neighbor, regionorg);
13015 dest(neighbor, regiondest);
13016 apex(neighbor, regionapex);
13017 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13018 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
13019 regionapex[0], regionapex[1]);
13020 }
13021 /* Infect the neighbor. */
13022 infect(neighbor);
13023 /* Ensure that the neighbor's neighbors will be infected. */
13024 regiontri = (triangle **) poolalloc(&m->viri);
13025 *regiontri = neighbor.tri;
13026 }
13027 }
13028 /* Remark the triangle as infected, so it doesn't get added to the */
13029 /* virus pool again. */
13030 infect(testtri);
13031 virusloop = (triangle **) traverse(&m->viri);
13032 }
13033
13034 /* Uninfect all triangles. */
13035 if (b->verbose > 1) {
13036 printf(" Unmarking marked triangles.\n");
13037 }
13038 traversalinit(&m->viri);
13039 virusloop = (triangle **) traverse(&m->viri);
13040 while (virusloop != (triangle **) NULL) {
13041 testtri.tri = *virusloop;
13042 uninfect(testtri);
13043 virusloop = (triangle **) traverse(&m->viri);
13044 }
13045 /* Empty the virus pool. */
13046 poolrestart(&m->viri);
13047}
13048
13049/*****************************************************************************/
13050/* */
13051/* carveholes() Find the holes and infect them. Find the area */
13052/* constraints and infect them. Infect the convex hull. */
13053/* Spread the infection and kill triangles. Spread the */
13054/* area constraints. */
13055/* */
13056/* This routine mainly calls other routines to carry out all these */
13057/* functions. */
13058/* */
13059/*****************************************************************************/
13060
13061#ifdef ANSI_DECLARATORS
13062void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
13063 REAL *regionlist, int regions)
13064#else /* not ANSI_DECLARATORS */
13065void carveholes(m, b, holelist, holes, regionlist, regions)
13066struct mesh *m;
13067struct behavior *b;
13068REAL *holelist;
13069int holes;
13070REAL *regionlist;
13071int regions;
13072#endif /* not ANSI_DECLARATORS */
13073
13074{
13075 struct otri searchtri;
13076 struct otri triangleloop;
13077 struct otri *regiontris;
13078 triangle **holetri;
13079 triangle **regiontri;
13080 vertex searchorg, searchdest;
13081 enum locateresult intersect;
13082 int i;
13083 triangle ptr; /* Temporary variable used by sym(). */
13084
13085 if (!(b->quiet || (b->noholes && b->convex))) {
13086 printf("Removing unwanted triangles.\n");
13087 if (b->verbose && (holes > 0)) {
13088 printf(" Marking holes for elimination.\n");
13089 }
13090 }
13091
13092 if (regions > 0) {
13093 /* Allocate storage for the triangles in which region points fall. */
13094 regiontris = (struct otri *) trimalloc(regions *
13095 (int) sizeof(struct otri));
13096 } else {
13097 regiontris = (struct otri *) NULL;
13098 }
13099
13100 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13101 /* Initialize a pool of viri to be used for holes, concavities, */
13102 /* regional attributes, and/or regional area constraints. */
13103 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13104 }
13105
13106 if (!b->convex) {
13107 /* Mark as infected any unprotected triangles on the boundary. */
13108 /* This is one way by which concavities are created. */
13109 infecthull(m, b);
13110 }
13111
13112 if ((holes > 0) && !b->noholes) {
13113 /* Infect each triangle in which a hole lies. */
13114 for (i = 0; i < 2 * holes; i += 2) {
13115 /* Ignore holes that aren't within the bounds of the mesh. */
13116 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13117 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13118 /* Start searching from some triangle on the outer boundary. */
13119 searchtri.tri = m->dummytri;
13120 searchtri.orient = 0;
13121 symself(searchtri);
13122 /* Ensure that the hole is to the left of this boundary edge; */
13123 /* otherwise, locate() will falsely report that the hole */
13124 /* falls within the starting triangle. */
13125 org(searchtri, searchorg);
13126 dest(searchtri, searchdest);
13127 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13128 0.0) {
13129 /* Find a triangle that contains the hole. */
13130 intersect = locate(m, b, &holelist[i], &searchtri);
13131 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13132 /* Infect the triangle. This is done by marking the triangle */
13133 /* as infected and including the triangle in the virus pool. */
13134 infect(searchtri);
13135 holetri = (triangle **) poolalloc(&m->viri);
13136 *holetri = searchtri.tri;
13137 }
13138 }
13139 }
13140 }
13141 }
13142
13143 /* Now, we have to find all the regions BEFORE we carve the holes, because */
13144 /* locate() won't work when the triangulation is no longer convex. */
13145 /* (Incidentally, this is the reason why regional attributes and area */
13146 /* constraints can't be used when refining a preexisting mesh, which */
13147 /* might not be convex; they can only be used with a freshly */
13148 /* triangulated PSLG.) */
13149 if (regions > 0) {
13150 /* Find the starting triangle for each region. */
13151 for (i = 0; i < regions; i++) {
13152 regiontris[i].tri = m->dummytri;
13153 /* Ignore region points that aren't within the bounds of the mesh. */
13154 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13155 (regionlist[4 * i + 1] >= m->ymin) &&
13156 (regionlist[4 * i + 1] <= m->ymax)) {
13157 /* Start searching from some triangle on the outer boundary. */
13158 searchtri.tri = m->dummytri;
13159 searchtri.orient = 0;
13160 symself(searchtri);
13161 /* Ensure that the region point is to the left of this boundary */
13162 /* edge; otherwise, locate() will falsely report that the */
13163 /* region point falls within the starting triangle. */
13164 org(searchtri, searchorg);
13165 dest(searchtri, searchdest);
13166 if (counterclockwise(m, b, searchorg, searchdest, &regionlist[4 * i]) >
13167 0.0) {
13168 /* Find a triangle that contains the region point. */
13169 intersect = locate(m, b, &regionlist[4 * i], &searchtri);
13170 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13171 /* Record the triangle for processing after the */
13172 /* holes have been carved. */
13173 otricopy(searchtri, regiontris[i]);
13174 }
13175 }
13176 }
13177 }
13178 }
13179
13180 if (m->viri.items > 0) {
13181 /* Carve the holes and concavities. */
13182 plague(m, b);
13183 }
13184 /* The virus pool should be empty now. */
13185
13186 if (regions > 0) {
13187 if (!b->quiet) {
13188 if (b->regionattrib) {
13189 if (b->vararea) {
13190 printf("Spreading regional attributes and area constraints.\n");
13191 } else {
13192 printf("Spreading regional attributes.\n");
13193 }
13194 } else {
13195 printf("Spreading regional area constraints.\n");
13196 }
13197 }
13198 if (b->regionattrib && !b->refine) {
13199 /* Assign every triangle a regional attribute of zero. */
13200 traversalinit(&m->triangles);
13201 triangleloop.orient = 0;
13202 triangleloop.tri = triangletraverse(m);
13203 while (triangleloop.tri != (triangle *) NULL) {
13204 setelemattribute(triangleloop, m->eextras, 0.0);
13205 triangleloop.tri = triangletraverse(m);
13206 }
13207 }
13208 for (i = 0; i < regions; i++) {
13209 if (regiontris[i].tri != m->dummytri) {
13210 /* Make sure the triangle under consideration still exists. */
13211 /* It may have been eaten by the virus. */
13212 if (!deadtri(regiontris[i].tri)) {
13213 /* Put one triangle in the virus pool. */
13214 infect(regiontris[i]);
13215 regiontri = (triangle **) poolalloc(&m->viri);
13216 *regiontri = regiontris[i].tri;
13217 /* Apply one region's attribute and/or area constraint. */
13218 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13219 /* The virus pool should be empty now. */
13220 }
13221 }
13222 }
13223 if (b->regionattrib && !b->refine) {
13224 /* Note the fact that each triangle has an additional attribute. */
13225 m->eextras++;
13226 }
13227 }
13228
13229 /* Free up memory. */
13230 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13231 pooldeinit(&m->viri);
13232 }
13233 if (regions > 0) {
13234 trifree((VOID *) regiontris);
13235 }
13236}
13237
13240/********* Carving out holes and concavities ends here *********/
13241
13242/********* Mesh quality maintenance begins here *********/
13246/*****************************************************************************/
13247/* */
13248/* tallyencs() Traverse the entire list of subsegments, and check each */
13249/* to see if it is encroached. If so, add it to the list. */
13250/* */
13251/*****************************************************************************/
13252
13253#ifndef CDT_ONLY
13254
13255#ifdef ANSI_DECLARATORS
13256void tallyencs(struct mesh *m, struct behavior *b)
13257#else /* not ANSI_DECLARATORS */
13258void tallyencs(m, b)
13259struct mesh *m;
13260struct behavior *b;
13261#endif /* not ANSI_DECLARATORS */
13262
13263{
13264 struct osub subsegloop;
13265 //int dummy;
13266
13267 traversalinit(&m->subsegs);
13268 subsegloop.ssorient = 0;
13269 subsegloop.ss = subsegtraverse(m);
13270 while (subsegloop.ss != (subseg *) NULL) {
13271 /* If the segment is encroached, add it to the list. */
13272 // dummy = checkseg4encroach(m, b, &subsegloop); // "dummy =" commented out to get gcc 4.6 working
13273 checkseg4encroach(m, b, &subsegloop); // "dummy =" commented out to get gcc 4.6 working
13274 subsegloop.ss = subsegtraverse(m);
13275 }
13276}
13277
13278#endif /* not CDT_ONLY */
13279
13280/*****************************************************************************/
13281/* */
13282/* precisionerror() Print an error message for precision problems. */
13283/* */
13284/*****************************************************************************/
13285
13286#ifndef CDT_ONLY
13287
13288void precisionerror()
13289{
13290 printf("Try increasing the area criterion and/or reducing the minimum\n");
13291 printf(" allowable angle so that tiny triangles are not created.\n");
13292#ifdef SINGLE
13293 printf("Alternatively, try recompiling me with double precision\n");
13294 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13295 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13296#endif /* SINGLE */
13297}
13298
13299#endif /* not CDT_ONLY */
13300
13301/*****************************************************************************/
13302/* */
13303/* splitencsegs() Split all the encroached subsegments. */
13304/* */
13305/* Each encroached subsegment is repaired by splitting it - inserting a */
13306/* vertex at or near its midpoint. Newly inserted vertices may encroach */
13307/* upon other subsegments; these are also repaired. */
13308/* */
13309/* `triflaws' is a flag that specifies whether one should take note of new */
13310/* bad triangles that result from inserting vertices to repair encroached */
13311/* subsegments. */
13312/* */
13313/*****************************************************************************/
13314
13315#ifndef CDT_ONLY
13316
13317#ifdef ANSI_DECLARATORS
13318void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13319#else /* not ANSI_DECLARATORS */
13320void splitencsegs(m, b, triflaws)
13321struct mesh *m;
13322struct behavior *b;
13323int triflaws;
13324#endif /* not ANSI_DECLARATORS */
13325
13326{
13327 struct otri enctri;
13328 struct otri testtri;
13329 struct osub testsh;
13330 struct osub currentenc;
13331 struct badsubseg *encloop;
13332 vertex eorg, edest, eapex;
13333 vertex newvertex;
13334 enum insertvertexresult success;
13335 REAL segmentlength, nearestpoweroftwo;
13336 REAL split;
13337 REAL multiplier, divisor;
13338 int acuteorg, acuteorg2, acutedest, acutedest2;
13339 //int dummy;
13340 int i;
13341 triangle ptr; /* Temporary variable used by stpivot(). */
13342 subseg sptr; /* Temporary variable used by snext(). */
13343
13344 /* Note that steinerleft == -1 if an unlimited number */
13345 /* of Steiner points is allowed. */
13346 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13347 traversalinit(&m->badsubsegs);
13348 encloop = badsubsegtraverse(m);
13349 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13350 sdecode(encloop->encsubseg, currentenc);
13351 sorg(currentenc, eorg);
13352 sdest(currentenc, edest);
13353 /* Make sure that this segment is still the same segment it was */
13354 /* when it was determined to be encroached. If the segment was */
13355 /* enqueued multiple times (because several newly inserted */
13356 /* vertices encroached it), it may have already been split. */
13357 if (!deadsubseg(currentenc.ss) &&
13358 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13359 /* To decide where to split a segment, we need to know if the */
13360 /* segment shares an endpoint with an adjacent segment. */
13361 /* The concern is that, if we simply split every encroached */
13362 /* segment in its center, two adjacent segments with a small */
13363 /* angle between them might lead to an infinite loop; each */
13364 /* vertex added to split one segment will encroach upon the */
13365 /* other segment, which must then be split with a vertex that */
13366 /* will encroach upon the first segment, and so on forever. */
13367 /* To avoid this, imagine a set of concentric circles, whose */
13368 /* radii are powers of two, about each segment endpoint. */
13369 /* These concentric circles determine where the segment is */
13370 /* split. (If both endpoints are shared with adjacent */
13371 /* segments, split the segment in the middle, and apply the */
13372 /* concentric circles for later splittings.) */
13373
13374 /* Is the origin shared with another segment? */
13375 stpivot(currentenc, enctri);
13376 lnext(enctri, testtri);
13377 tspivot(testtri, testsh);
13378 acuteorg = testsh.ss != m->dummysub;
13379 /* Is the destination shared with another segment? */
13380 lnextself(testtri);
13381 tspivot(testtri, testsh);
13382 acutedest = testsh.ss != m->dummysub;
13383
13384 /* If we're using Chew's algorithm (rather than Ruppert's) */
13385 /* to define encroachment, delete free vertices from the */
13386 /* subsegment's diametral circle. */
13387 if (!b->conformdel && !acuteorg && !acutedest) {
13388 apex(enctri, eapex);
13389 while ((vertextype(eapex) == FREEVERTEX) &&
13390 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13391 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13392 deletevertex(m, b, &testtri);
13393 stpivot(currentenc, enctri);
13394 apex(enctri, eapex);
13395 lprev(enctri, testtri);
13396 }
13397 }
13398
13399 /* Now, check the other side of the segment, if there's a triangle */
13400 /* there. */
13401 sym(enctri, testtri);
13402 if (testtri.tri != m->dummytri) {
13403 /* Is the destination shared with another segment? */
13404 lnextself(testtri);
13405 tspivot(testtri, testsh);
13406 acutedest2 = testsh.ss != m->dummysub;
13407 acutedest = acutedest || acutedest2;
13408 /* Is the origin shared with another segment? */
13409 lnextself(testtri);
13410 tspivot(testtri, testsh);
13411 acuteorg2 = testsh.ss != m->dummysub;
13412 acuteorg = acuteorg || acuteorg2;
13413
13414 /* Delete free vertices from the subsegment's diametral circle. */
13415 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13416 org(testtri, eapex);
13417 while ((vertextype(eapex) == FREEVERTEX) &&
13418 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13419 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13420 deletevertex(m, b, &testtri);
13421 sym(enctri, testtri);
13422 apex(testtri, eapex);
13423 lprevself(testtri);
13424 }
13425 }
13426 }
13427
13428 /* Use the concentric circles if exactly one endpoint is shared */
13429 /* with another adjacent segment. */
13430 if (acuteorg || acutedest) {
13431 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13432 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13433 /* Find the power of two that most evenly splits the segment. */
13434 /* The worst case is a 2:1 ratio between subsegment lengths. */
13435 nearestpoweroftwo = 1.0;
13436 while (segmentlength > 3.0 * nearestpoweroftwo) {
13437 nearestpoweroftwo *= 2.0;
13438 }
13439 while (segmentlength < 1.5 * nearestpoweroftwo) {
13440 nearestpoweroftwo *= 0.5;
13441 }
13442 /* Where do we split the segment? */
13443 split = nearestpoweroftwo / segmentlength;
13444 if (acutedest) {
13445 split = 1.0 - split;
13446 }
13447 } else {
13448 /* If we're not worried about adjacent segments, split */
13449 /* this segment in the middle. */
13450 split = 0.5;
13451 }
13452
13453 /* Create the new vertex. */
13454 newvertex = (vertex) poolalloc(&m->vertices);
13455 /* Interpolate its coordinate and attributes. */
13456 for (i = 0; i < 2 + m->nextras; i++) {
13457 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13458 }
13459
13460 if (!b->noexact) {
13461 /* Roundoff in the above calculation may yield a `newvertex' */
13462 /* that is not precisely collinear with `eorg' and `edest'. */
13463 /* Improve collinearity by one step of iterative refinement. */
13464 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13465 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13466 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13467 if ((multiplier != 0.0) && (divisor != 0.0)) {
13468 multiplier = multiplier / divisor;
13469 /* Watch out for NANs. */
13470 if (multiplier == multiplier) {
13471 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13472 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13473 }
13474 }
13475 }
13476
13477 setvertexmark(newvertex, mark(currentenc));
13478 setvertextype(newvertex, SEGMENTVERTEX);
13479 if (b->verbose > 1) {
13480 printf(
13481 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13482 eorg[0], eorg[1], edest[0], edest[1],
13483 newvertex[0], newvertex[1]);
13484 }
13485 /* Check whether the new vertex lies on an endpoint. */
13486 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13487 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13488 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13489 newvertex[0], newvertex[1]);
13490 printf("I attempted to split a segment to a smaller size than\n");
13491 printf(" can be accommodated by the finite precision of\n");
13492 printf(" floating point arithmetic.\n");
13493 precisionerror();
13494 triexit(1);
13495 }
13496 /* Insert the splitting vertex. This should always succeed. */
13497 success = insertvertex(m, b, newvertex, &enctri, &currentenc,
13498 1, triflaws);
13499 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13500 printf("Internal error in splitencsegs():\n");
13501 printf(" Failure to split a segment.\n");
13502 internalerror();
13503 }
13504 if (m->steinerleft > 0) {
13505 m->steinerleft--;
13506 }
13507 /* Check the two new subsegments to see if they're encroached. */
13508 //dummy = checkseg4encroach(m, b, &currentenc); // commented out to get gcc 4.6 working
13509 checkseg4encroach(m, b, &currentenc); // "dummy =" commented out to get gcc 4.6 working
13510 snextself(currentenc);
13511 //dummy = checkseg4encroach(m, b, &currentenc); // commented out to get gcc 4.6 working
13512 checkseg4encroach(m, b, &currentenc); // "dummy =" commented out to get gcc 4.6 working
13513 }
13514
13515 badsubsegdealloc(m, encloop);
13516 encloop = badsubsegtraverse(m);
13517 }
13518 }
13519}
13520
13521#endif /* not CDT_ONLY */
13522
13523/*****************************************************************************/
13524/* */
13525/* tallyfaces() Test every triangle in the mesh for quality measures. */
13526/* */
13527/*****************************************************************************/
13528
13529#ifndef CDT_ONLY
13530
13531#ifdef ANSI_DECLARATORS
13532void tallyfaces(struct mesh *m, struct behavior *b)
13533#else /* not ANSI_DECLARATORS */
13534void tallyfaces(m, b)
13535struct mesh *m;
13536struct behavior *b;
13537#endif /* not ANSI_DECLARATORS */
13538
13539{
13540 struct otri triangleloop;
13541
13542 if (b->verbose) {
13543 printf(" Making a list of bad triangles.\n");
13544 }
13545 traversalinit(&m->triangles);
13546 triangleloop.orient = 0;
13547 triangleloop.tri = triangletraverse(m);
13548 while (triangleloop.tri != (triangle *) NULL) {
13549 /* If the triangle is bad, enqueue it. */
13550 testtriangle(m, b, &triangleloop);
13551 triangleloop.tri = triangletraverse(m);
13552 }
13553}
13554
13555#endif /* not CDT_ONLY */
13556
13557/*****************************************************************************/
13558/* */
13559/* splittriangle() Inserts a vertex at the circumcenter of a triangle. */
13560/* Deletes the newly inserted vertex if it encroaches */
13561/* upon a segment. */
13562/* */
13563/*****************************************************************************/
13564
13565#ifndef CDT_ONLY
13566
13567#ifdef ANSI_DECLARATORS
13568void splittriangle(struct mesh *m, struct behavior *b,
13569 struct badtriang *badtri)
13570#else /* not ANSI_DECLARATORS */
13571void splittriangle(m, b, badtri)
13572struct mesh *m;
13573struct behavior *b;
13574struct badtriang *badtri;
13575#endif /* not ANSI_DECLARATORS */
13576
13577{
13578 struct otri badotri;
13579 vertex borg, bdest, bapex;
13580 vertex newvertex;
13581 REAL xi, eta;
13582 enum insertvertexresult success;
13583 int errorflag;
13584 int i;
13585
13586 decode(badtri->poortri, badotri);
13587 org(badotri, borg);
13588 dest(badotri, bdest);
13589 apex(badotri, bapex);
13590 /* Make sure that this triangle is still the same triangle it was */
13591 /* when it was tested and determined to be of bad quality. */
13592 /* Subsequent transformations may have made it a different triangle. */
13593 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13594 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13595 if (b->verbose > 1) {
13596 printf(" Splitting this triangle at its circumcenter:\n");
13597 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13598 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13599 }
13600
13601 errorflag = 0;
13602 /* Create a new vertex at the triangle's circumcenter. */
13603 newvertex = (vertex) poolalloc(&m->vertices);
13604 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13605
13606 /* Check whether the new vertex lies on a triangle vertex. */
13607 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13608 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13609 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13610 if (!b->quiet) {
13611 printf(
13612 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13613 newvertex[0], newvertex[1]);
13614 errorflag = 1;
13615 }
13616 vertexdealloc(m, newvertex);
13617 } else {
13618 for (i = 2; i < 2 + m->nextras; i++) {
13619 /* Interpolate the vertex attributes at the circumcenter. */
13620 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13621 + eta * (bapex[i] - borg[i]);
13622 }
13623 /* The new vertex must be in the interior, and therefore is a */
13624 /* free vertex with a marker of zero. */
13625 setvertexmark(newvertex, 0);
13626 setvertextype(newvertex, FREEVERTEX);
13627
13628 /* Ensure that the handle `badotri' does not represent the longest */
13629 /* edge of the triangle. This ensures that the circumcenter must */
13630 /* fall to the left of this edge, so point location will work. */
13631 /* (If the angle org-apex-dest exceeds 90 degrees, then the */
13632 /* circumcenter lies outside the org-dest edge, and eta is */
13633 /* negative. Roundoff error might prevent eta from being */
13634 /* negative when it should be, so I test eta against xi.) */
13635 if (eta < xi) {
13636 lprevself(badotri);
13637 }
13638
13639 /* Insert the circumcenter, searching from the edge of the triangle, */
13640 /* and maintain the Delaunay property of the triangulation. */
13641 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13642 1, 1);
13643 if (success == SUCCESSFULVERTEX) {
13644 if (m->steinerleft > 0) {
13645 m->steinerleft--;
13646 }
13647 } else if (success == ENCROACHINGVERTEX) {
13648 /* If the newly inserted vertex encroaches upon a subsegment, */
13649 /* delete the new vertex. */
13650 undovertex(m, b);
13651 if (b->verbose > 1) {
13652 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13653 }
13654 vertexdealloc(m, newvertex);
13655 } else if (success == VIOLATINGVERTEX) {
13656 /* Failed to insert the new vertex, but some subsegment was */
13657 /* marked as being encroached. */
13658 vertexdealloc(m, newvertex);
13659 } else { /* success == DUPLICATEVERTEX */
13660 /* Couldn't insert the new vertex because a vertex is already there. */
13661 if (!b->quiet) {
13662 printf(
13663 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13664 newvertex[0], newvertex[1]);
13665 errorflag = 1;
13666 }
13667 vertexdealloc(m, newvertex);
13668 }
13669 }
13670 if (errorflag) {
13671 if (b->verbose) {
13672 printf(" The new vertex is at the circumcenter of triangle\n");
13673 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13674 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13675 }
13676 printf("This probably means that I am trying to refine triangles\n");
13677 printf(" to a smaller size than can be accommodated by the finite\n");
13678 printf(" precision of floating point arithmetic. (You can be\n");
13679 printf(" sure of this if I fail to terminate.)\n");
13680 precisionerror();
13681 }
13682 }
13683}
13684
13685#endif /* not CDT_ONLY */
13686
13687/*****************************************************************************/
13688/* */
13689/* enforcequality() Remove all the encroached subsegments and bad */
13690/* triangles from the triangulation. */
13691/* */
13692/*****************************************************************************/
13693
13694#ifndef CDT_ONLY
13695
13696#ifdef ANSI_DECLARATORS
13697void enforcequality(struct mesh *m, struct behavior *b)
13698#else /* not ANSI_DECLARATORS */
13699void enforcequality(m, b)
13700struct mesh *m;
13701struct behavior *b;
13702#endif /* not ANSI_DECLARATORS */
13703
13704{
13705 struct badtriang *badtri;
13706 int i;
13707
13708 if (!b->quiet) {
13709 printf("Adding Steiner points to enforce quality.\n");
13710 }
13711 /* Initialize the pool of encroached subsegments. */
13712 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13713 BADSUBSEGPERBLOCK, 0);
13714 if (b->verbose) {
13715 printf(" Looking for encroached subsegments.\n");
13716 }
13717 /* Test all segments to see if they're encroached. */
13718 tallyencs(m, b);
13719 if (b->verbose && (m->badsubsegs.items > 0)) {
13720 printf(" Splitting encroached subsegments.\n");
13721 }
13722 /* Fix encroached subsegments without noting bad triangles. */
13723 splitencsegs(m, b, 0);
13724 /* At this point, if we haven't run out of Steiner points, the */
13725 /* triangulation should be (conforming) Delaunay. */
13726
13727 /* Next, we worry about enforcing triangle quality. */
13728 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13729 /* Initialize the pool of bad triangles. */
13730 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13731 BADTRIPERBLOCK, 0);
13732 /* Initialize the queues of bad triangles. */
13733 for (i = 0; i < 4096; i++) {
13734 m->queuefront[i] = (struct badtriang *) NULL;
13735 }
13736 m->firstnonemptyq = -1;
13737 /* Test all triangles to see if they're bad. */
13738 tallyfaces(m, b);
13739 /* Initialize the pool of recently flipped triangles. */
13740 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13741 FLIPSTACKERPERBLOCK, 0);
13742 m->checkquality = 1;
13743 if (b->verbose) {
13744 printf(" Splitting bad triangles.\n");
13745 }
13746 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13747 /* Fix one bad triangle by inserting a vertex at its circumcenter. */
13748 badtri = dequeuebadtriang(m);
13749 splittriangle(m, b, badtri);
13750 if (m->badsubsegs.items > 0) {
13751 /* Put bad triangle back in queue for another try later. */
13752 enqueuebadtriang(m, b, badtri);
13753 /* Fix any encroached subsegments that resulted. */
13754 /* Record any new bad triangles that result. */
13755 splitencsegs(m, b, 1);
13756 } else {
13757 /* Return the bad triangle to the pool. */
13758 pooldealloc(&m->badtriangles, (VOID *) badtri);
13759 }
13760 }
13761 }
13762 /* At this point, if the "-D" switch was selected and we haven't run out */
13763 /* of Steiner points, the triangulation should be (conforming) Delaunay */
13764 /* and have no low-quality triangles. */
13765
13766 /* Might we have run out of Steiner points too soon? */
13767 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13768 (m->steinerleft == 0)) {
13769 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13770 if (m->badsubsegs.items == 1) {
13771 printf(" one encroached subsegment, and therefore might not be truly\n"
13772 );
13773 } else {
13774 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13775 , m->badsubsegs.items);
13776 }
13777 printf(" Delaunay. If the Delaunay property is important to you,\n");
13778 printf(" try increasing the number of Steiner points (controlled by\n");
13779 printf(" the -S switch) slightly and try again.\n\n");
13780 }
13781}
13782
13783#endif /* not CDT_ONLY */
13784
13787/********* Mesh quality maintenance ends here *********/
13788
13789/*****************************************************************************/
13790/* */
13791/* highorder() Create extra nodes for quadratic subparametric elements. */
13792/* */
13793/*****************************************************************************/
13794
13795#ifdef ANSI_DECLARATORS
13796void highorder(struct mesh *m, struct behavior *b)
13797#else /* not ANSI_DECLARATORS */
13798void highorder(m, b)
13799struct mesh *m;
13800struct behavior *b;
13801#endif /* not ANSI_DECLARATORS */
13802
13803{
13804 struct otri triangleloop, trisym;
13805 struct osub checkmark;
13806 vertex newvertex;
13807 vertex torg, tdest;
13808 int i;
13809 triangle ptr; /* Temporary variable used by sym(). */
13810 subseg sptr; /* Temporary variable used by tspivot(). */
13811
13812 if (!b->quiet) {
13813 printf("Adding vertices for second-order triangles.\n");
13814 }
13815 /* The following line ensures that dead items in the pool of nodes */
13816 /* cannot be allocated for the extra nodes associated with high */
13817 /* order elements. This ensures that the primary nodes (at the */
13818 /* corners of elements) will occur earlier in the output files, and */
13819 /* have lower indices, than the extra nodes. */
13820 m->vertices.deaditemstack = (VOID *) NULL;
13821
13822 traversalinit(&m->triangles);
13823 triangleloop.tri = triangletraverse(m);
13824 /* To loop over the set of edges, loop over all triangles, and look at */
13825 /* the three edges of each triangle. If there isn't another triangle */
13826 /* adjacent to the edge, operate on the edge. If there is another */
13827 /* adjacent triangle, operate on the edge only if the current triangle */
13828 /* has a smaller pointer than its neighbor. This way, each edge is */
13829 /* considered only once. */
13830 while (triangleloop.tri != (triangle *) NULL) {
13831 for (triangleloop.orient = 0; triangleloop.orient < 3;
13832 triangleloop.orient++) {
13833 sym(triangleloop, trisym);
13834 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13835 org(triangleloop, torg);
13836 dest(triangleloop, tdest);
13837 /* Create a new node in the middle of the edge. Interpolate */
13838 /* its attributes. */
13839 newvertex = (vertex) poolalloc(&m->vertices);
13840 for (i = 0; i < 2 + m->nextras; i++) {
13841 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13842 }
13843 /* Set the new node's marker to zero or one, depending on */
13844 /* whether it lies on a boundary. */
13845 setvertexmark(newvertex, trisym.tri == m->dummytri);
13846 setvertextype(newvertex,
13847 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13848 if (b->usesegments) {
13849 tspivot(triangleloop, checkmark);
13850 /* If this edge is a segment, transfer the marker to the new node. */
13851 if (checkmark.ss != m->dummysub) {
13852 setvertexmark(newvertex, mark(checkmark));
13853 setvertextype(newvertex, SEGMENTVERTEX);
13854 }
13855 }
13856 if (b->verbose > 1) {
13857 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13858 }
13859 /* Record the new node in the (one or two) adjacent elements. */
13860 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13861 (triangle) newvertex;
13862 if (trisym.tri != m->dummytri) {
13863 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13864 }
13865 }
13866 }
13867 triangleloop.tri = triangletraverse(m);
13868 }
13869}
13870
13871/********* File I/O routines begin here *********/
13875/*****************************************************************************/
13876/* */
13877/* readline() Read a nonempty line from a file. */
13878/* */
13879/* A line is considered "nonempty" if it contains something that looks like */
13880/* a number. Comments (prefaced by `#') are ignored. */
13881/* */
13882/*****************************************************************************/
13883
13884#ifndef TRILIBRARY
13885
13886#ifdef ANSI_DECLARATORS
13887char *readline(char *string, FILE *infile, char *infilename)
13888#else /* not ANSI_DECLARATORS */
13889char *readline(string, infile, infilename)
13890char *string;
13891FILE *infile;
13892char *infilename;
13893#endif /* not ANSI_DECLARATORS */
13894
13895{
13896 char *result;
13897
13898 /* Search for something that looks like a number. */
13899 do {
13900 result = fgets(string, INPUTLINESIZE, infile);
13901 if (result == (char *) NULL) {
13902 printf(" Error: Unexpected end of file in %s.\n", infilename);
13903 triexit(1);
13904 }
13905 /* Skip anything that doesn't look like a number, a comment, */
13906 /* or the end of a line. */
13907 while ((*result != '\0') && (*result != '#')
13908 && (*result != '.') && (*result != '+') && (*result != '-')
13909 && ((*result < '0') || (*result > '9'))) {
13910 result++;
13911 }
13912 /* If it's a comment or end of line, read another line and try again. */
13913 } while ((*result == '#') || (*result == '\0'));
13914 return result;
13915}
13916
13917#endif /* not TRILIBRARY */
13918
13919/*****************************************************************************/
13920/* */
13921/* findfield() Find the next field of a string. */
13922/* */
13923/* Jumps past the current field by searching for whitespace, then jumps */
13924/* past the whitespace to find the next field. */
13925/* */
13926/*****************************************************************************/
13927
13928#ifndef TRILIBRARY
13929
13930#ifdef ANSI_DECLARATORS
13931char *findfield(char *string)
13932#else /* not ANSI_DECLARATORS */
13933char *findfield(string)
13934char *string;
13935#endif /* not ANSI_DECLARATORS */
13936
13937{
13938 char *result;
13939
13940 result = string;
13941 /* Skip the current field. Stop upon reaching whitespace. */
13942 while ((*result != '\0') && (*result != '#')
13943 && (*result != ' ') && (*result != '\t')) {
13944 result++;
13945 }
13946 /* Now skip the whitespace and anything else that doesn't look like a */
13947 /* number, a comment, or the end of a line. */
13948 while ((*result != '\0') && (*result != '#')
13949 && (*result != '.') && (*result != '+') && (*result != '-')
13950 && ((*result < '0') || (*result > '9'))) {
13951 result++;
13952 }
13953 /* Check for a comment (prefixed with `#'). */
13954 if (*result == '#') {
13955 *result = '\0';
13956 }
13957 return result;
13958}
13959
13960#endif /* not TRILIBRARY */
13961
13962/*****************************************************************************/
13963/* */
13964/* readnodes() Read the vertices from a file, which may be a .node or */
13965/* .poly file. */
13966/* */
13967/*****************************************************************************/
13968
13969#ifndef TRILIBRARY
13970
13971#ifdef ANSI_DECLARATORS
13972void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13973 char* polyfilename, FILE **polyfile)
13974#else /* not ANSI_DECLARATORS */
13975void readnodes(m, b, nodefilename, polyfilename, polyfile)
13976struct mesh *m;
13977struct behavior *b;
13978char *nodefilename;
13979char* polyfilename;
13980FILE **polyfile;
13981#endif /* not ANSI_DECLARATORS */
13982
13983{
13984 FILE *infile;
13985 vertex vertexloop;
13986 char inputline[INPUTLINESIZE];
13987 char *stringptr;
13988 char *infilename;
13989 REAL x, y;
13990 int firstnode;
13991 int nodemarkers;
13992 int currentmarker;
13993 int i, j;
13994
13995 if (b->poly) {
13996 /* Read the vertices from a .poly file. */
13997 if (!b->quiet) {
13998 printf("Opening %s.\n", polyfilename);
13999 }
14000 * polyfile = fopen(polyfilename, "r");
14001 if (*polyfile == (FILE *) NULL) {
14002 printf(" Error: Cannot access file %s.\n", polyfilename);
14003 triexit(1);
14004 }
14005 /* Read number of vertices, number of dimensions, number of vertex */
14006 /* attributes, and number of boundary markers. */
14007 stringptr = readline(inputline,* polyfile, polyfilename);
14008 m->invertices = (int) strtol(stringptr, &stringptr, 0);
14009 stringptr = findfield(stringptr);
14010 if (*stringptr == '\0') {
14011 m->mesh_dim = 2;
14012 } else {
14013 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
14014 }
14015 stringptr = findfield(stringptr);
14016 if (*stringptr == '\0') {
14017 m->nextras = 0;
14018 } else {
14019 m->nextras = (int) strtol(stringptr, &stringptr, 0);
14020 }
14021 stringptr = findfield(stringptr);
14022 if (*stringptr == '\0') {
14023 nodemarkers = 0;
14024 } else {
14025 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
14026 }
14027 if (m->invertices > 0) {
14028 infile =* polyfile;
14029 infilename = polyfilename;
14030 m->readnodefile = 0;
14031 } else {
14032 /* If the .poly file claims there are zero vertices, that means that */
14033 /* the vertices should be read from a separate .node file. */
14034 m->readnodefile = 1;
14035 infilename = nodefilename;
14036 }
14037 } else {
14038 m->readnodefile = 1;
14039 infilename = nodefilename;
14040 * polyfile = (FILE *) NULL;
14041 }
14042
14043 if (m->readnodefile) {
14044 /* Read the vertices from a .node file. */
14045 if (!b->quiet) {
14046 printf("Opening %s.\n", nodefilename);
14047 }
14048 infile = fopen(nodefilename, "r");
14049 if (infile == (FILE *) NULL) {
14050 printf(" Error: Cannot access file %s.\n", nodefilename);
14051 triexit(1);
14052 }
14053 /* Read number of vertices, number of dimensions, number of vertex */
14054 /* attributes, and number of boundary markers. */
14055 stringptr = readline(inputline, infile, nodefilename);
14056 m->invertices = (int) strtol(stringptr, &stringptr, 0);
14057 stringptr = findfield(stringptr);
14058 if (*stringptr == '\0') {
14059 m->mesh_dim = 2;
14060 } else {
14061 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
14062 }
14063 stringptr = findfield(stringptr);
14064 if (*stringptr == '\0') {
14065 m->nextras = 0;
14066 } else {
14067 m->nextras = (int) strtol(stringptr, &stringptr, 0);
14068 }
14069 stringptr = findfield(stringptr);
14070 if (*stringptr == '\0') {
14071 nodemarkers = 0;
14072 } else {
14073 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
14074 }
14075 }
14076
14077 if (m->invertices < 3) {
14078 printf("Error: Input must have at least three input vertices.\n");
14079 triexit(1);
14080 }
14081 if (m->mesh_dim != 2) {
14082 printf("Error: Triangle only works with two-dimensional meshes.\n");
14083 triexit(1);
14084 }
14085 if (m->nextras == 0) {
14086 b->weighted = 0;
14087 }
14088
14089 initializevertexpool(m, b);
14090
14091 /* Read the vertices. */
14092 for (i = 0; i < m->invertices; i++) {
14093 vertexloop = (vertex) poolalloc(&m->vertices);
14094 stringptr = readline(inputline, infile, infilename);
14095 if (i == 0) {
14096 firstnode = (int) strtol(stringptr, &stringptr, 0);
14097 if ((firstnode == 0) || (firstnode == 1)) {
14098 b->firstnumber = firstnode;
14099 }
14100 }
14101 stringptr = findfield(stringptr);
14102 if (*stringptr == '\0') {
14103 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14104 triexit(1);
14105 }
14106 x = (REAL) strtod(stringptr, &stringptr);
14107 stringptr = findfield(stringptr);
14108 if (*stringptr == '\0') {
14109 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14110 triexit(1);
14111 }
14112 y = (REAL) strtod(stringptr, &stringptr);
14113 vertexloop[0] = x;
14114 vertexloop[1] = y;
14115 /* Read the vertex attributes. */
14116 for (j = 2; j < 2 + m->nextras; j++) {
14117 stringptr = findfield(stringptr);
14118 if (*stringptr == '\0') {
14119 vertexloop[j] = 0.0;
14120 } else {
14121 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14122 }
14123 }
14124 if (nodemarkers) {
14125 /* Read a vertex marker. */
14126 stringptr = findfield(stringptr);
14127 if (*stringptr == '\0') {
14128 setvertexmark(vertexloop, 0);
14129 } else {
14130 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14131 setvertexmark(vertexloop, currentmarker);
14132 }
14133 } else {
14134 /* If no markers are specified in the file, they default to zero. */
14135 setvertexmark(vertexloop, 0);
14136 }
14137 setvertextype(vertexloop, INPUTVERTEX);
14138 /* Determine the smallest and largest x and y coordinates. */
14139 if (i == 0) {
14140 m->xmin = m->xmax = x;
14141 m->ymin = m->ymax = y;
14142 } else {
14143 m->xmin = (x < m->xmin) ? x : m->xmin;
14144 m->xmax = (x > m->xmax) ? x : m->xmax;
14145 m->ymin = (y < m->ymin) ? y : m->ymin;
14146 m->ymax = (y > m->ymax) ? y : m->ymax;
14147 }
14148 }
14149 if (m->readnodefile) {
14150 fclose(infile);
14151 }
14152
14153 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14154 /* Delaunay algorithm. */
14155 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14156}
14157
14158#endif /* not TRILIBRARY */
14159
14160/*****************************************************************************/
14161/* */
14162/* transfernodes() Read the vertices from memory. */
14163/* */
14164/*****************************************************************************/
14165
14166#ifdef TRILIBRARY
14167
14168#ifdef ANSI_DECLARATORS
14169void transfernodes(struct mesh *m, struct behavior *b, REAL* pointlist,
14170 REAL* pointattriblist, int* pointmarkerlist,
14171 int numberofpoints, int numberofpointattribs)
14172#else /* not ANSI_DECLARATORS */
14173void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14174 numberofpoints, numberofpointattribs)
14175struct mesh *m;
14176struct behavior *b;
14177REAL* pointlist;
14178REAL* pointattriblist;
14179int* pointmarkerlist;
14180int numberofpoints;
14181int numberofpointattribs;
14182#endif /* not ANSI_DECLARATORS */
14183
14184{
14185 vertex vertexloop;
14186 REAL x, y;
14187 int i, j;
14188 int coordindex;
14189 int attribindex;
14190
14191 m->invertices = numberofpoints;
14192 m->mesh_dim = 2;
14193 m->nextras = numberofpointattribs;
14194 m->readnodefile = 0;
14195 if (m->invertices < 3) {
14196 printf("Error: Input must have at least three input vertices.\n");
14197 triexit(1);
14198 }
14199 if (m->nextras == 0) {
14200 b->weighted = 0;
14201 }
14202
14203 initializevertexpool(m, b);
14204
14205 /* Read the vertices. */
14206 coordindex = 0;
14207 attribindex = 0;
14208 for (i = 0; i < m->invertices; i++) {
14209 vertexloop = (vertex) poolalloc(&m->vertices);
14210 /* Read the vertex coordinates. */
14211 x = vertexloop[0] = pointlist[coordindex++];
14212 y = vertexloop[1] = pointlist[coordindex++];
14213 /* Read the vertex attributes. */
14214 for (j = 0; j < numberofpointattribs; j++) {
14215 vertexloop[2 + j] = pointattriblist[attribindex++];
14216 }
14217 if (pointmarkerlist != (int *) NULL) {
14218 /* Read a vertex marker. */
14219 setvertexmark(vertexloop, pointmarkerlist[i]);
14220 } else {
14221 /* If no markers are specified, they default to zero. */
14222 setvertexmark(vertexloop, 0);
14223 }
14224 setvertextype(vertexloop, INPUTVERTEX);
14225 /* Determine the smallest and largest x and y coordinates. */
14226 if (i == 0) {
14227 m->xmin = m->xmax = x;
14228 m->ymin = m->ymax = y;
14229 } else {
14230 m->xmin = (x < m->xmin) ? x : m->xmin;
14231 m->xmax = (x > m->xmax) ? x : m->xmax;
14232 m->ymin = (y < m->ymin) ? y : m->ymin;
14233 m->ymax = (y > m->ymax) ? y : m->ymax;
14234 }
14235 }
14236
14237 /* Nonexistent x value used as a flag to mark circle events in sweepline */
14238 /* Delaunay algorithm. */
14239 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14240}
14241
14242#endif /* TRILIBRARY */
14243
14244/*****************************************************************************/
14245/* */
14246/* readholes() Read the holes, and possibly regional attributes and area */
14247/* constraints, from a .poly file. */
14248/* */
14249/*****************************************************************************/
14250
14251#ifndef TRILIBRARY
14252
14253#ifdef ANSI_DECLARATORS
14254void readholes(struct mesh *m, struct behavior *b,
14255 FILE* polyfile, char* polyfilename, REAL **hlist, int *holes,
14256 REAL **rlist, int *regions)
14257#else /* not ANSI_DECLARATORS */
14258void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14259struct mesh *m;
14260struct behavior *b;
14261FILE* polyfile;
14262char* polyfilename;
14263REAL **hlist;
14264int *holes;
14265REAL **rlist;
14266int *regions;
14267#endif /* not ANSI_DECLARATORS */
14268
14269{
14270 REAL *holelist;
14271 REAL *regionlist;
14272 char inputline[INPUTLINESIZE];
14273 char *stringptr;
14274 int index;
14275 int i;
14276
14277 /* Read the holes. */
14278 stringptr = readline(inputline, polyfile, polyfilename);
14279 *holes = (int) strtol(stringptr, &stringptr, 0);
14280 if (*holes > 0) {
14281 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14282 *hlist = holelist;
14283 for (i = 0; i < 2 * *holes; i += 2) {
14284 stringptr = readline(inputline, polyfile, polyfilename);
14285 stringptr = findfield(stringptr);
14286 if (*stringptr == '\0') {
14287 printf("Error: Hole %d has no x coordinate.\n",
14288 b->firstnumber + (i >> 1));
14289 triexit(1);
14290 } else {
14291 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14292 }
14293 stringptr = findfield(stringptr);
14294 if (*stringptr == '\0') {
14295 printf("Error: Hole %d has no y coordinate.\n",
14296 b->firstnumber + (i >> 1));
14297 triexit(1);
14298 } else {
14299 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14300 }
14301 }
14302 } else {
14303 *hlist = (REAL *) NULL;
14304 }
14305
14306#ifndef CDT_ONLY
14307 if ((b->regionattrib || b->vararea) && !b->refine) {
14308 /* Read the area constraints. */
14309 stringptr = readline(inputline, polyfile, polyfilename);
14310 *regions = (int) strtol(stringptr, &stringptr, 0);
14311 if (*regions > 0) {
14312 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14313 *rlist = regionlist;
14314 index = 0;
14315 for (i = 0; i < *regions; i++) {
14316 stringptr = readline(inputline, polyfile, polyfilename);
14317 stringptr = findfield(stringptr);
14318 if (*stringptr == '\0') {
14319 printf("Error: Region %d has no x coordinate.\n",
14320 b->firstnumber + i);
14321 triexit(1);
14322 } else {
14323 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14324 }
14325 stringptr = findfield(stringptr);
14326 if (*stringptr == '\0') {
14327 printf("Error: Region %d has no y coordinate.\n",
14328 b->firstnumber + i);
14329 triexit(1);
14330 } else {
14331 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14332 }
14333 stringptr = findfield(stringptr);
14334 if (*stringptr == '\0') {
14335 printf(
14336 "Error: Region %d has no region attribute or area constraint.\n",
14337 b->firstnumber + i);
14338 triexit(1);
14339 } else {
14340 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14341 }
14342 stringptr = findfield(stringptr);
14343 if (*stringptr == '\0') {
14344 regionlist[index] = regionlist[index - 1];
14345 } else {
14346 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14347 }
14348 index++;
14349 }
14350 }
14351 } else {
14352 /* Set `*regions' to zero to avoid an accidental free() later. */
14353 *regions = 0;
14354 *rlist = (REAL *) NULL;
14355 }
14356#endif /* not CDT_ONLY */
14357
14358 fclose(polyfile);
14359}
14360
14361#endif /* not TRILIBRARY */
14362
14363/*****************************************************************************/
14364/* */
14365/* finishfile() Write the command line to the output file so the user */
14366/* can remember how the file was generated. Close the file. */
14367/* */
14368/*****************************************************************************/
14369
14370#ifndef TRILIBRARY
14371
14372#ifdef ANSI_DECLARATORS
14373void finishfile(FILE *outfile, int argc, char **argv)
14374#else /* not ANSI_DECLARATORS */
14375void finishfile(outfile, argc, argv)
14376FILE *outfile;
14377int argc;
14378char **argv;
14379#endif /* not ANSI_DECLARATORS */
14380
14381{
14382 int i;
14383
14384 fprintf(outfile, "# Generated by");
14385 for (i = 0; i < argc; i++) {
14386 fprintf(outfile, " ");
14387 fputs(argv[i], outfile);
14388 }
14389 fprintf(outfile, "\n");
14390 fclose(outfile);
14391}
14392
14393#endif /* not TRILIBRARY */
14394
14395/*****************************************************************************/
14396/* */
14397/* writenodes() Number the vertices and write them to a .node file. */
14398/* */
14399/* To save memory, the vertex numbers are written over the boundary markers */
14400/* after the vertices are written to a file. */
14401/* */
14402/*****************************************************************************/
14403
14404#ifdef TRILIBRARY
14405
14406#ifdef ANSI_DECLARATORS
14407void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14408 REAL **pointattriblist, int **pointmarkerlist)
14409#else /* not ANSI_DECLARATORS */
14410void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14411struct mesh *m;
14412struct behavior *b;
14413REAL **pointlist;
14414REAL **pointattriblist;
14415int **pointmarkerlist;
14416#endif /* not ANSI_DECLARATORS */
14417
14418#else /* not TRILIBRARY */
14419
14420#ifdef ANSI_DECLARATORS
14421void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14422 int argc, char **argv)
14423#else /* not ANSI_DECLARATORS */
14424void writenodes(m, b, nodefilename, argc, argv)
14425struct mesh *m;
14426struct behavior *b;
14427char *nodefilename;
14428int argc;
14429char **argv;
14430#endif /* not ANSI_DECLARATORS */
14431
14432#endif /* not TRILIBRARY */
14433
14434{
14435#ifdef TRILIBRARY
14436 REAL* plist;
14437 REAL* palist;
14438 int* pmlist;
14439 int coordindex;
14440 int attribindex;
14441#else /* not TRILIBRARY */
14442 FILE *outfile;
14443#endif /* not TRILIBRARY */
14444 vertex vertexloop;
14445 long outvertices;
14446 int vertexnumber;
14447 int i;
14448
14449 if (b->jettison) {
14450 outvertices = m->vertices.items - m->undeads;
14451 } else {
14452 outvertices = m->vertices.items;
14453 }
14454
14455#ifdef TRILIBRARY
14456 if (!b->quiet) {
14457 printf("Writing vertices.\n");
14458 }
14459 /* Allocate memory for output vertices if necessary. */
14460 if (*pointlist == (REAL *) NULL) {
14461 * pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14462 }
14463 /* Allocate memory for output vertex attributes if necessary. */
14464 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14465 * pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14466 sizeof(REAL)));
14467 }
14468 /* Allocate memory for output vertex markers if necessary. */
14469 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14470 * pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14471 }
14472 plist =* pointlist;
14473 palist =* pointattriblist;
14474 pmlist =* pointmarkerlist;
14475 coordindex = 0;
14476 attribindex = 0;
14477#else /* not TRILIBRARY */
14478 if (!b->quiet) {
14479 printf("Writing %s.\n", nodefilename);
14480 }
14481 outfile = fopen(nodefilename, "w");
14482 if (outfile == (FILE *) NULL) {
14483 printf(" Error: Cannot create file %s.\n", nodefilename);
14484 triexit(1);
14485 }
14486 /* Number of vertices, number of dimensions, number of vertex attributes, */
14487 /* and number of boundary markers (zero or one). */
14488 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14489 m->nextras, 1 - b->nobound);
14490#endif /* not TRILIBRARY */
14491
14492 traversalinit(&m->vertices);
14493 vertexnumber = b->firstnumber;
14494 vertexloop = vertextraverse(m);
14495 while (vertexloop != (vertex) NULL) {
14496 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14497#ifdef TRILIBRARY
14498 /* X and y coordinates. */
14499 plist[coordindex++] = vertexloop[0];
14500 plist[coordindex++] = vertexloop[1];
14501 /* Vertex attributes. */
14502 for (i = 0; i < m->nextras; i++) {
14503 palist[attribindex++] = vertexloop[2 + i];
14504 }
14505 if (!b->nobound) {
14506 /* Copy the boundary marker. */
14507 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14508 }
14509#else /* not TRILIBRARY */
14510 /* Vertex number, x and y coordinates. */
14511 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14512 vertexloop[1]);
14513 for (i = 0; i < m->nextras; i++) {
14514 /* Write an attribute. */
14515 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14516 }
14517 if (b->nobound) {
14518 fprintf(outfile, "\n");
14519 } else {
14520 /* Write the boundary marker. */
14521 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14522 }
14523#endif /* not TRILIBRARY */
14524
14525 setvertexmark(vertexloop, vertexnumber);
14526 vertexnumber++;
14527 }
14528 vertexloop = vertextraverse(m);
14529 }
14530
14531#ifndef TRILIBRARY
14532 finishfile(outfile, argc, argv);
14533#endif /* not TRILIBRARY */
14534}
14535
14536/*****************************************************************************/
14537/* */
14538/* numbernodes() Number the vertices. */
14539/* */
14540/* Each vertex is assigned a marker equal to its number. */
14541/* */
14542/* Used when writenodes() is not called because no .node file is written. */
14543/* */
14544/*****************************************************************************/
14545
14546#ifdef ANSI_DECLARATORS
14547void numbernodes(struct mesh *m, struct behavior *b)
14548#else /* not ANSI_DECLARATORS */
14549void numbernodes(m, b)
14550struct mesh *m;
14551struct behavior *b;
14552#endif /* not ANSI_DECLARATORS */
14553
14554{
14555 vertex vertexloop;
14556 int vertexnumber;
14557
14558 traversalinit(&m->vertices);
14559 vertexnumber = b->firstnumber;
14560 vertexloop = vertextraverse(m);
14561 while (vertexloop != (vertex) NULL) {
14562 setvertexmark(vertexloop, vertexnumber);
14563 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14564 vertexnumber++;
14565 }
14566 vertexloop = vertextraverse(m);
14567 }
14568}
14569
14570/*****************************************************************************/
14571/* */
14572/* writeelements() Write the triangles to an .ele file. */
14573/* */
14574/*****************************************************************************/
14575
14576#ifdef TRILIBRARY
14577
14578#ifdef ANSI_DECLARATORS
14579void writeelements(struct mesh *m, struct behavior *b,
14580 int **trianglelist, REAL **triangleattriblist)
14581#else /* not ANSI_DECLARATORS */
14582void writeelements(m, b, trianglelist, triangleattriblist)
14583struct mesh *m;
14584struct behavior *b;
14585int **trianglelist;
14586REAL **triangleattriblist;
14587#endif /* not ANSI_DECLARATORS */
14588
14589#else /* not TRILIBRARY */
14590
14591#ifdef ANSI_DECLARATORS
14592void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14593 int argc, char **argv)
14594#else /* not ANSI_DECLARATORS */
14595void writeelements(m, b, elefilename, argc, argv)
14596struct mesh *m;
14597struct behavior *b;
14598char *elefilename;
14599int argc;
14600char **argv;
14601#endif /* not ANSI_DECLARATORS */
14602
14603#endif /* not TRILIBRARY */
14604
14605{
14606#ifdef TRILIBRARY
14607 int *tlist;
14608 REAL *talist;
14609 int vertexindex;
14610 int attribindex;
14611#else /* not TRILIBRARY */
14612 FILE *outfile;
14613#endif /* not TRILIBRARY */
14614 struct otri triangleloop;
14615 vertex p1, p2, p3;
14616 vertex mid1, mid2, mid3;
14617 long elementnumber;
14618 int i;
14619
14620#ifdef TRILIBRARY
14621 if (!b->quiet) {
14622 printf("Writing triangles.\n");
14623 }
14624 /* Allocate memory for output triangles if necessary. */
14625 if (*trianglelist == (int *) NULL) {
14626 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14627 ((b->order + 1) * (b->order + 2) /
14628 2) * sizeof(int)));
14629 }
14630 /* Allocate memory for output triangle attributes if necessary. */
14631 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14632 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14633 m->eextras *
14634 sizeof(REAL)));
14635 }
14636 tlist = *trianglelist;
14637 talist = *triangleattriblist;
14638 vertexindex = 0;
14639 attribindex = 0;
14640#else /* not TRILIBRARY */
14641 if (!b->quiet) {
14642 printf("Writing %s.\n", elefilename);
14643 }
14644 outfile = fopen(elefilename, "w");
14645 if (outfile == (FILE *) NULL) {
14646 printf(" Error: Cannot create file %s.\n", elefilename);
14647 triexit(1);
14648 }
14649 /* Number of triangles, vertices per triangle, attributes per triangle. */
14650 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14651 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14652#endif /* not TRILIBRARY */
14653
14654 traversalinit(&m->triangles);
14655 triangleloop.tri = triangletraverse(m);
14656 triangleloop.orient = 0;
14657 elementnumber = b->firstnumber;
14658 while (triangleloop.tri != (triangle *) NULL) {
14659 org(triangleloop, p1);
14660 dest(triangleloop, p2);
14661 apex(triangleloop, p3);
14662 if (b->order == 1) {
14663#ifdef TRILIBRARY
14664 tlist[vertexindex++] = vertexmark(p1);
14665 tlist[vertexindex++] = vertexmark(p2);
14666 tlist[vertexindex++] = vertexmark(p3);
14667#else /* not TRILIBRARY */
14668 /* Triangle number, indices for three vertices. */
14669 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14670 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14671#endif /* not TRILIBRARY */
14672 } else {
14673 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14674 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14675 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14676#ifdef TRILIBRARY
14677 tlist[vertexindex++] = vertexmark(p1);
14678 tlist[vertexindex++] = vertexmark(p2);
14679 tlist[vertexindex++] = vertexmark(p3);
14680 tlist[vertexindex++] = vertexmark(mid1);
14681 tlist[vertexindex++] = vertexmark(mid2);
14682 tlist[vertexindex++] = vertexmark(mid3);
14683#else /* not TRILIBRARY */
14684 /* Triangle number, indices for six vertices. */
14685 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14686 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14687 vertexmark(mid2), vertexmark(mid3));
14688#endif /* not TRILIBRARY */
14689 }
14690
14691#ifdef TRILIBRARY
14692 for (i = 0; i < m->eextras; i++) {
14693 talist[attribindex++] = elemattribute(triangleloop, i);
14694 }
14695#else /* not TRILIBRARY */
14696 for (i = 0; i < m->eextras; i++) {
14697 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14698 }
14699 fprintf(outfile, "\n");
14700#endif /* not TRILIBRARY */
14701
14702 triangleloop.tri = triangletraverse(m);
14703 elementnumber++;
14704 }
14705
14706#ifndef TRILIBRARY
14707 finishfile(outfile, argc, argv);
14708#endif /* not TRILIBRARY */
14709}
14710
14711/*****************************************************************************/
14712/* */
14713/* writepoly() Write the segments and holes to a .poly file. */
14714/* */
14715/*****************************************************************************/
14716
14717#ifdef TRILIBRARY
14718
14719#ifdef ANSI_DECLARATORS
14720void writepoly(struct mesh *m, struct behavior *b,
14721 int **segmentlist, int **segmentmarkerlist)
14722#else /* not ANSI_DECLARATORS */
14723void writepoly(m, b, segmentlist, segmentmarkerlist)
14724struct mesh *m;
14725struct behavior *b;
14726int **segmentlist;
14727int **segmentmarkerlist;
14728#endif /* not ANSI_DECLARATORS */
14729
14730#else /* not TRILIBRARY */
14731
14732#ifdef ANSI_DECLARATORS
14733void writepoly(struct mesh *m, struct behavior *b, char* polyfilename,
14734 REAL *holelist, int holes, REAL *regionlist, int regions,
14735 int argc, char **argv)
14736#else /* not ANSI_DECLARATORS */
14737void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14738 argc, argv)
14739struct mesh *m;
14740struct behavior *b;
14741char* polyfilename;
14742REAL *holelist;
14743int holes;
14744REAL *regionlist;
14745int regions;
14746int argc;
14747char **argv;
14748#endif /* not ANSI_DECLARATORS */
14749
14750#endif /* not TRILIBRARY */
14751
14752{
14753#ifdef TRILIBRARY
14754 int *slist;
14755 int *smlist;
14756 int index;
14757#else /* not TRILIBRARY */
14758 FILE *outfile;
14759 long holenumber, regionnumber;
14760#endif /* not TRILIBRARY */
14761 struct osub subsegloop;
14762 vertex endpoint1, endpoint2;
14763 long subsegnumber;
14764
14765#ifdef TRILIBRARY
14766 if (!b->quiet) {
14767 printf("Writing segments.\n");
14768 }
14769 /* Allocate memory for output segments if necessary. */
14770 if (*segmentlist == (int *) NULL) {
14771 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14772 sizeof(int)));
14773 }
14774 /* Allocate memory for output segment markers if necessary. */
14775 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14776 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14777 sizeof(int)));
14778 }
14779 slist = *segmentlist;
14780 smlist = *segmentmarkerlist;
14781 index = 0;
14782#else /* not TRILIBRARY */
14783 if (!b->quiet) {
14784 printf("Writing %s.\n", polyfilename);
14785 }
14786 outfile = fopen(polyfilename, "w");
14787 if (outfile == (FILE *) NULL) {
14788 printf(" Error: Cannot create file %s.\n", polyfilename);
14789 triexit(1);
14790 }
14791 /* The zero indicates that the vertices are in a separate .node file. */
14792 /* Followed by number of dimensions, number of vertex attributes, */
14793 /* and number of boundary markers (zero or one). */
14794 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14795 1 - b->nobound);
14796 /* Number of segments, number of boundary markers (zero or one). */
14797 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14798#endif /* not TRILIBRARY */
14799
14800 traversalinit(&m->subsegs);
14801 subsegloop.ss = subsegtraverse(m);
14802 subsegloop.ssorient = 0;
14803 subsegnumber = b->firstnumber;
14804 while (subsegloop.ss != (subseg *) NULL) {
14805 sorg(subsegloop, endpoint1);
14806 sdest(subsegloop, endpoint2);
14807#ifdef TRILIBRARY
14808 /* Copy indices of the segment's two endpoints. */
14809 slist[index++] = vertexmark(endpoint1);
14810 slist[index++] = vertexmark(endpoint2);
14811 if (!b->nobound) {
14812 /* Copy the boundary marker. */
14813 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14814 }
14815#else /* not TRILIBRARY */
14816 /* Segment number, indices of its two endpoints, and possibly a marker. */
14817 if (b->nobound) {
14818 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14819 vertexmark(endpoint1), vertexmark(endpoint2));
14820 } else {
14821 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14822 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14823 }
14824#endif /* not TRILIBRARY */
14825
14826 subsegloop.ss = subsegtraverse(m);
14827 subsegnumber++;
14828 }
14829
14830#ifndef TRILIBRARY
14831#ifndef CDT_ONLY
14832 fprintf(outfile, "%d\n", holes);
14833 if (holes > 0) {
14834 for (holenumber = 0; holenumber < holes; holenumber++) {
14835 /* Hole number, x and y coordinates. */
14836 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14837 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14838 }
14839 }
14840 if (regions > 0) {
14841 fprintf(outfile, "%d\n", regions);
14842 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14843 /* Region number, x and y coordinates, attribute, maximum area. */
14844 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14845 b->firstnumber + regionnumber,
14846 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14847 regionlist[4 * regionnumber + 2],
14848 regionlist[4 * regionnumber + 3]);
14849 }
14850 }
14851#endif /* not CDT_ONLY */
14852
14853 finishfile(outfile, argc, argv);
14854#endif /* not TRILIBRARY */
14855}
14856
14857/*****************************************************************************/
14858/* */
14859/* writeedges() Write the edges to an .edge file. */
14860/* */
14861/*****************************************************************************/
14862
14863#ifdef TRILIBRARY
14864
14865#ifdef ANSI_DECLARATORS
14866void writeedges(struct mesh *m, struct behavior *b,
14867 int **edgelist, int **edgemarkerlist)
14868#else /* not ANSI_DECLARATORS */
14869void writeedges(m, b, edgelist, edgemarkerlist)
14870struct mesh *m;
14871struct behavior *b;
14872int **edgelist;
14873int **edgemarkerlist;
14874#endif /* not ANSI_DECLARATORS */
14875
14876#else /* not TRILIBRARY */
14877
14878#ifdef ANSI_DECLARATORS
14879void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14880 int argc, char **argv)
14881#else /* not ANSI_DECLARATORS */
14882void writeedges(m, b, edgefilename, argc, argv)
14883struct mesh *m;
14884struct behavior *b;
14885char *edgefilename;
14886int argc;
14887char **argv;
14888#endif /* not ANSI_DECLARATORS */
14889
14890#endif /* not TRILIBRARY */
14891
14892{
14893#ifdef TRILIBRARY
14894 int *elist;
14895 int *emlist;
14896 int index;
14897#else /* not TRILIBRARY */
14898 FILE *outfile;
14899#endif /* not TRILIBRARY */
14900 struct otri triangleloop, trisym;
14901 struct osub checkmark;
14902 vertex p1, p2;
14903 long edgenumber;
14904 triangle ptr; /* Temporary variable used by sym(). */
14905 subseg sptr; /* Temporary variable used by tspivot(). */
14906
14907#ifdef TRILIBRARY
14908 if (!b->quiet) {
14909 printf("Writing edges.\n");
14910 }
14911 /* Allocate memory for edges if necessary. */
14912 if (*edgelist == (int *) NULL) {
14913 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14914 }
14915 /* Allocate memory for edge markers if necessary. */
14916 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14917 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14918 }
14919 elist = *edgelist;
14920 emlist = *edgemarkerlist;
14921 index = 0;
14922#else /* not TRILIBRARY */
14923 if (!b->quiet) {
14924 printf("Writing %s.\n", edgefilename);
14925 }
14926 outfile = fopen(edgefilename, "w");
14927 if (outfile == (FILE *) NULL) {
14928 printf(" Error: Cannot create file %s.\n", edgefilename);
14929 triexit(1);
14930 }
14931 /* Number of edges, number of boundary markers (zero or one). */
14932 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14933#endif /* not TRILIBRARY */
14934
14935 traversalinit(&m->triangles);
14936 triangleloop.tri = triangletraverse(m);
14937 edgenumber = b->firstnumber;
14938 /* To loop over the set of edges, loop over all triangles, and look at */
14939 /* the three edges of each triangle. If there isn't another triangle */
14940 /* adjacent to the edge, operate on the edge. If there is another */
14941 /* adjacent triangle, operate on the edge only if the current triangle */
14942 /* has a smaller pointer than its neighbor. This way, each edge is */
14943 /* considered only once. */
14944 while (triangleloop.tri != (triangle *) NULL) {
14945 for (triangleloop.orient = 0; triangleloop.orient < 3;
14946 triangleloop.orient++) {
14947 sym(triangleloop, trisym);
14948 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14949 org(triangleloop, p1);
14950 dest(triangleloop, p2);
14951#ifdef TRILIBRARY
14952 elist[index++] = vertexmark(p1);
14953 elist[index++] = vertexmark(p2);
14954#endif /* TRILIBRARY */
14955 if (b->nobound) {
14956#ifndef TRILIBRARY
14957 /* Edge number, indices of two endpoints. */
14958 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14959 vertexmark(p1), vertexmark(p2));
14960#endif /* not TRILIBRARY */
14961 } else {
14962 /* Edge number, indices of two endpoints, and a boundary marker. */
14963 /* If there's no subsegment, the boundary marker is zero. */
14964 if (b->usesegments) {
14965 tspivot(triangleloop, checkmark);
14966 if (checkmark.ss == m->dummysub) {
14967#ifdef TRILIBRARY
14968 emlist[edgenumber - b->firstnumber] = 0;
14969#else /* not TRILIBRARY */
14970 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14971 vertexmark(p1), vertexmark(p2), 0);
14972#endif /* not TRILIBRARY */
14973 } else {
14974#ifdef TRILIBRARY
14975 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14976#else /* not TRILIBRARY */
14977 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14978 vertexmark(p1), vertexmark(p2), mark(checkmark));
14979#endif /* not TRILIBRARY */
14980 }
14981 } else {
14982#ifdef TRILIBRARY
14983 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14984#else /* not TRILIBRARY */
14985 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14986 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14987#endif /* not TRILIBRARY */
14988 }
14989 }
14990 edgenumber++;
14991 }
14992 }
14993 triangleloop.tri = triangletraverse(m);
14994 }
14995
14996#ifndef TRILIBRARY
14997 finishfile(outfile, argc, argv);
14998#endif /* not TRILIBRARY */
14999}
15000
15001/*****************************************************************************/
15002/* */
15003/* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */
15004/* file. */
15005/* */
15006/* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
15007/* Hence, the Voronoi vertices are listed by traversing the Delaunay */
15008/* triangles, and the Voronoi edges are listed by traversing the Delaunay */
15009/* edges. */
15010/* */
15011/* WARNING: In order to assign numbers to the Voronoi vertices, this */
15012/* procedure messes up the subsegments or the extra nodes of every */
15013/* element. Hence, you should call this procedure last. */
15014/* */
15015/*****************************************************************************/
15016
15017#ifdef TRILIBRARY
15018
15019#ifdef ANSI_DECLARATORS
15020void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
15021 REAL **vpointattriblist, int **vpointmarkerlist,
15022 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
15023#else /* not ANSI_DECLARATORS */
15024void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
15025 vedgelist, vedgemarkerlist, vnormlist)
15026struct mesh *m;
15027struct behavior *b;
15028REAL **vpointlist;
15029REAL **vpointattriblist;
15030int **vpointmarkerlist;
15031int **vedgelist;
15032int **vedgemarkerlist;
15033REAL **vnormlist;
15034#endif /* not ANSI_DECLARATORS */
15035
15036#else /* not TRILIBRARY */
15037
15038#ifdef ANSI_DECLARATORS
15039void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
15040 char *vedgefilename, int argc, char **argv)
15041#else /* not ANSI_DECLARATORS */
15042void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
15043struct mesh *m;
15044struct behavior *b;
15045char *vnodefilename;
15046char *vedgefilename;
15047int argc;
15048char **argv;
15049#endif /* not ANSI_DECLARATORS */
15050
15051#endif /* not TRILIBRARY */
15052
15053{
15054#ifdef TRILIBRARY
15055 REAL* plist;
15056 REAL* palist;
15057 int *elist;
15058 REAL *normlist;
15059 int coordindex;
15060 int attribindex;
15061#else /* not TRILIBRARY */
15062 FILE *outfile;
15063#endif /* not TRILIBRARY */
15064 struct otri triangleloop, trisym;
15065 vertex torg, tdest, tapex;
15066 REAL circumcenter[2];
15067 REAL xi, eta;
15068 long vnodenumber, vedgenumber;
15069 int p1, p2;
15070 int i;
15071 triangle ptr; /* Temporary variable used by sym(). */
15072
15073#ifdef TRILIBRARY
15074 if (!b->quiet) {
15075 printf("Writing Voronoi vertices.\n");
15076 }
15077 /* Allocate memory for Voronoi vertices if necessary. */
15078 if (*vpointlist == (REAL *) NULL) {
15079 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
15080 sizeof(REAL)));
15081 }
15082 /* Allocate memory for Voronoi vertex attributes if necessary. */
15083 if (*vpointattriblist == (REAL *) NULL) {
15084 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15085 m->nextras * sizeof(REAL)));
15086 }
15087 *vpointmarkerlist = (int *) NULL;
15088 plist = *vpointlist;
15089 palist = *vpointattriblist;
15090 coordindex = 0;
15091 attribindex = 0;
15092#else /* not TRILIBRARY */
15093 if (!b->quiet) {
15094 printf("Writing %s.\n", vnodefilename);
15095 }
15096 outfile = fopen(vnodefilename, "w");
15097 if (outfile == (FILE *) NULL) {
15098 printf(" Error: Cannot create file %s.\n", vnodefilename);
15099 triexit(1);
15100 }
15101 /* Number of triangles, two dimensions, number of vertex attributes, */
15102 /* no markers. */
15103 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15104#endif /* not TRILIBRARY */
15105
15106 traversalinit(&m->triangles);
15107 triangleloop.tri = triangletraverse(m);
15108 triangleloop.orient = 0;
15109 vnodenumber = b->firstnumber;
15110 while (triangleloop.tri != (triangle *) NULL) {
15111 org(triangleloop, torg);
15112 dest(triangleloop, tdest);
15113 apex(triangleloop, tapex);
15114 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15115#ifdef TRILIBRARY
15116 /* X and y coordinates. */
15117 plist[coordindex++] = circumcenter[0];
15118 plist[coordindex++] = circumcenter[1];
15119 for (i = 2; i < 2 + m->nextras; i++) {
15120 /* Interpolate the vertex attributes at the circumcenter. */
15121 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15122 + eta * (tapex[i] - torg[i]);
15123 }
15124#else /* not TRILIBRARY */
15125 /* Voronoi vertex number, x and y coordinates. */
15126 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15127 circumcenter[1]);
15128 for (i = 2; i < 2 + m->nextras; i++) {
15129 /* Interpolate the vertex attributes at the circumcenter. */
15130 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15131 + eta * (tapex[i] - torg[i]));
15132 }
15133 fprintf(outfile, "\n");
15134#endif /* not TRILIBRARY */
15135
15136 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15137 triangleloop.tri = triangletraverse(m);
15138 vnodenumber++;
15139 }
15140
15141#ifndef TRILIBRARY
15142 finishfile(outfile, argc, argv);
15143#endif /* not TRILIBRARY */
15144
15145#ifdef TRILIBRARY
15146 if (!b->quiet) {
15147 printf("Writing Voronoi edges.\n");
15148 }
15149 /* Allocate memory for output Voronoi edges if necessary. */
15150 if (*vedgelist == (int *) NULL) {
15151 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15152 }
15153 *vedgemarkerlist = (int *) NULL;
15154 /* Allocate memory for output Voronoi norms if necessary. */
15155 if (*vnormlist == (REAL *) NULL) {
15156 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15157 }
15158 elist = *vedgelist;
15159 normlist = *vnormlist;
15160 coordindex = 0;
15161#else /* not TRILIBRARY */
15162 if (!b->quiet) {
15163 printf("Writing %s.\n", vedgefilename);
15164 }
15165 outfile = fopen(vedgefilename, "w");
15166 if (outfile == (FILE *) NULL) {
15167 printf(" Error: Cannot create file %s.\n", vedgefilename);
15168 triexit(1);
15169 }
15170 /* Number of edges, zero boundary markers. */
15171 fprintf(outfile, "%ld %d\n", m->edges, 0);
15172#endif /* not TRILIBRARY */
15173
15174 traversalinit(&m->triangles);
15175 triangleloop.tri = triangletraverse(m);
15176 vedgenumber = b->firstnumber;
15177 /* To loop over the set of edges, loop over all triangles, and look at */
15178 /* the three edges of each triangle. If there isn't another triangle */
15179 /* adjacent to the edge, operate on the edge. If there is another */
15180 /* adjacent triangle, operate on the edge only if the current triangle */
15181 /* has a smaller pointer than its neighbor. This way, each edge is */
15182 /* considered only once. */
15183 while (triangleloop.tri != (triangle *) NULL) {
15184 for (triangleloop.orient = 0; triangleloop.orient < 3;
15185 triangleloop.orient++) {
15186 sym(triangleloop, trisym);
15187 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15188 /* Find the number of this triangle (and Voronoi vertex). */
15189 p1 = * (int *) (triangleloop.tri + 6);
15190 if (trisym.tri == m->dummytri) {
15191 org(triangleloop, torg);
15192 dest(triangleloop, tdest);
15193#ifdef TRILIBRARY
15194 /* Copy an infinite ray. Index of one endpoint, and -1. */
15195 elist[coordindex] = p1;
15196 normlist[coordindex++] = tdest[1] - torg[1];
15197 elist[coordindex] = -1;
15198 normlist[coordindex++] = torg[0] - tdest[0];
15199#else /* not TRILIBRARY */
15200 /* Write an infinite ray. Edge number, index of one endpoint, -1, */
15201 /* and x and y coordinates of a vector representing the */
15202 /* direction of the ray. */
15203 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15204 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15205#endif /* not TRILIBRARY */
15206 } else {
15207 /* Find the number of the adjacent triangle (and Voronoi vertex). */
15208 p2 = * (int *) (trisym.tri + 6);
15209 /* Finite edge. Write indices of two endpoints. */
15210#ifdef TRILIBRARY
15211 elist[coordindex] = p1;
15212 normlist[coordindex++] = 0.0;
15213 elist[coordindex] = p2;
15214 normlist[coordindex++] = 0.0;
15215#else /* not TRILIBRARY */
15216 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15217#endif /* not TRILIBRARY */
15218 }
15219 vedgenumber++;
15220 }
15221 }
15222 triangleloop.tri = triangletraverse(m);
15223 }
15224
15225#ifndef TRILIBRARY
15226 finishfile(outfile, argc, argv);
15227#endif /* not TRILIBRARY */
15228}
15229
15230#ifdef TRILIBRARY
15231
15232#ifdef ANSI_DECLARATORS
15233void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15234#else /* not ANSI_DECLARATORS */
15235void writeneighbors(m, b, neighborlist)
15236struct mesh *m;
15237struct behavior *b;
15238int **neighborlist;
15239#endif /* not ANSI_DECLARATORS */
15240
15241#else /* not TRILIBRARY */
15242
15243#ifdef ANSI_DECLARATORS
15244void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15245 int argc, char **argv)
15246#else /* not ANSI_DECLARATORS */
15247void writeneighbors(m, b, neighborfilename, argc, argv)
15248struct mesh *m;
15249struct behavior *b;
15250char *neighborfilename;
15251int argc;
15252char **argv;
15253#endif /* not ANSI_DECLARATORS */
15254
15255#endif /* not TRILIBRARY */
15256
15257{
15258#ifdef TRILIBRARY
15259 int *nlist;
15260 int index;
15261#else /* not TRILIBRARY */
15262 FILE *outfile;
15263#endif /* not TRILIBRARY */
15264 struct otri triangleloop, trisym;
15265 long elementnumber;
15266 int neighbor1, neighbor2, neighbor3;
15267 triangle ptr; /* Temporary variable used by sym(). */
15268
15269#ifdef TRILIBRARY
15270 if (!b->quiet) {
15271 printf("Writing neighbors.\n");
15272 }
15273 /* Allocate memory for neighbors if necessary. */
15274 if (*neighborlist == (int *) NULL) {
15275 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15276 sizeof(int)));
15277 }
15278 nlist = *neighborlist;
15279 index = 0;
15280#else /* not TRILIBRARY */
15281 if (!b->quiet) {
15282 printf("Writing %s.\n", neighborfilename);
15283 }
15284 outfile = fopen(neighborfilename, "w");
15285 if (outfile == (FILE *) NULL) {
15286 printf(" Error: Cannot create file %s.\n", neighborfilename);
15287 triexit(1);
15288 }
15289 /* Number of triangles, three neighbors per triangle. */
15290 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15291#endif /* not TRILIBRARY */
15292
15293 traversalinit(&m->triangles);
15294 triangleloop.tri = triangletraverse(m);
15295 triangleloop.orient = 0;
15296 elementnumber = b->firstnumber;
15297 while (triangleloop.tri != (triangle *) NULL) {
15298 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15299 triangleloop.tri = triangletraverse(m);
15300 elementnumber++;
15301 }
15302 * (int *) (m->dummytri + 6) = -1;
15303
15304 traversalinit(&m->triangles);
15305 triangleloop.tri = triangletraverse(m);
15306 elementnumber = b->firstnumber;
15307 while (triangleloop.tri != (triangle *) NULL) {
15308 triangleloop.orient = 1;
15309 sym(triangleloop, trisym);
15310 neighbor1 = * (int *) (trisym.tri + 6);
15311 triangleloop.orient = 2;
15312 sym(triangleloop, trisym);
15313 neighbor2 = * (int *) (trisym.tri + 6);
15314 triangleloop.orient = 0;
15315 sym(triangleloop, trisym);
15316 neighbor3 = * (int *) (trisym.tri + 6);
15317#ifdef TRILIBRARY
15318 nlist[index++] = neighbor1;
15319 nlist[index++] = neighbor2;
15320 nlist[index++] = neighbor3;
15321#else /* not TRILIBRARY */
15322 /* Triangle number, neighboring triangle numbers. */
15323 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15324 neighbor1, neighbor2, neighbor3);
15325#endif /* not TRILIBRARY */
15326
15327 triangleloop.tri = triangletraverse(m);
15328 elementnumber++;
15329 }
15330
15331#ifndef TRILIBRARY
15332 finishfile(outfile, argc, argv);
15333#endif /* not TRILIBRARY */
15334}
15335
15336/*****************************************************************************/
15337/* */
15338/* writeoff() Write the triangulation to an .off file. */
15339/* */
15340/* OFF stands for the Object File Format, a format used by the Geometry */
15341/* Center's Geomview package. */
15342/* */
15343/*****************************************************************************/
15344
15345#ifndef TRILIBRARY
15346
15347#ifdef ANSI_DECLARATORS
15348void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15349 int argc, char **argv)
15350#else /* not ANSI_DECLARATORS */
15351void writeoff(m, b, offfilename, argc, argv)
15352struct mesh *m;
15353struct behavior *b;
15354char *offfilename;
15355int argc;
15356char **argv;
15357#endif /* not ANSI_DECLARATORS */
15358
15359{
15360 FILE *outfile;
15361 struct otri triangleloop;
15362 vertex vertexloop;
15363 vertex p1, p2, p3;
15364 long outvertices;
15365
15366 if (!b->quiet) {
15367 printf("Writing %s.\n", offfilename);
15368 }
15369
15370 if (b->jettison) {
15371 outvertices = m->vertices.items - m->undeads;
15372 } else {
15373 outvertices = m->vertices.items;
15374 }
15375
15376 outfile = fopen(offfilename, "w");
15377 if (outfile == (FILE *) NULL) {
15378 printf(" Error: Cannot create file %s.\n", offfilename);
15379 triexit(1);
15380 }
15381 /* Number of vertices, triangles, and edges. */
15382 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15383 m->edges);
15384
15385 /* Write the vertices. */
15386 traversalinit(&m->vertices);
15387 vertexloop = vertextraverse(m);
15388 while (vertexloop != (vertex) NULL) {
15389 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15390 /* The "0.0" is here because the OFF format uses 3D coordinates. */
15391 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15392 0.0);
15393 }
15394 vertexloop = vertextraverse(m);
15395 }
15396
15397 /* Write the triangles. */
15398 traversalinit(&m->triangles);
15399 triangleloop.tri = triangletraverse(m);
15400 triangleloop.orient = 0;
15401 while (triangleloop.tri != (triangle *) NULL) {
15402 org(triangleloop, p1);
15403 dest(triangleloop, p2);
15404 apex(triangleloop, p3);
15405 /* The "3" means a three-vertex polygon. */
15406 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15407 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15408 triangleloop.tri = triangletraverse(m);
15409 }
15410 finishfile(outfile, argc, argv);
15411}
15412
15413#endif /* not TRILIBRARY */
15414
15417/********* File I/O routines end here *********/
15418
15419/*****************************************************************************/
15420/* */
15421/* quality_statistics() Print statistics about the quality of the mesh. */
15422/* */
15423/*****************************************************************************/
15424
15425#ifdef ANSI_DECLARATORS
15426void quality_statistics(struct mesh *m, struct behavior *b)
15427#else /* not ANSI_DECLARATORS */
15428void quality_statistics(m, b)
15429struct mesh *m;
15430struct behavior *b;
15431#endif /* not ANSI_DECLARATORS */
15432
15433{
15434 struct otri triangleloop;
15435 vertex p[3];
15436 REAL cossquaretable[8];
15437 REAL ratiotable[16];
15438 REAL dx[3], dy[3];
15439 REAL edgelength[3];
15440 REAL dotproduct;
15441 REAL cossquare;
15442 REAL triarea;
15443 REAL shortest, longest;
15444 REAL trilongest2;
15445 REAL smallestarea, biggestarea;
15446 REAL triminaltitude2;
15447 REAL minaltitude;
15448 REAL triaspect2;
15449 REAL worstaspect;
15450 REAL smallestangle, biggestangle;
15451 REAL radconst, degconst;
15452 int angletable[18];
15453 int aspecttable[16];
15454 int aspectindex;
15455 int tendegree;
15456 int acutebiggest;
15457 int i, ii, j, k;
15458
15459 printf("Mesh quality statistics:\n\n");
15460 radconst = PI / 18.0;
15461 degconst = 180.0 / PI;
15462 for (i = 0; i < 8; i++) {
15463 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15464 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15465 }
15466 for (i = 0; i < 18; i++) {
15467 angletable[i] = 0;
15468 }
15469
15470 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15471 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15472 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15473 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15474 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15475 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15476 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15477 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15478 for (i = 0; i < 16; i++) {
15479 aspecttable[i] = 0;
15480 }
15481
15482 worstaspect = 0.0;
15483 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15484 minaltitude = minaltitude * minaltitude;
15485 shortest = minaltitude;
15486 longest = 0.0;
15487 smallestarea = minaltitude;
15488 biggestarea = 0.0;
15489 worstaspect = 0.0;
15490 smallestangle = 0.0;
15491 biggestangle = 2.0;
15492 acutebiggest = 1;
15493
15494 traversalinit(&m->triangles);
15495 triangleloop.tri = triangletraverse(m);
15496 triangleloop.orient = 0;
15497 while (triangleloop.tri != (triangle *) NULL) {
15498 org(triangleloop, p[0]);
15499 dest(triangleloop, p[1]);
15500 apex(triangleloop, p[2]);
15501 trilongest2 = 0.0;
15502
15503 for (i = 0; i < 3; i++) {
15504 j = plus1mod3[i];
15505 k = minus1mod3[i];
15506 dx[i] = p[j][0] - p[k][0];
15507 dy[i] = p[j][1] - p[k][1];
15508 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15509 if (edgelength[i] > trilongest2) {
15510 trilongest2 = edgelength[i];
15511 }
15512 if (edgelength[i] > longest) {
15513 longest = edgelength[i];
15514 }
15515 if (edgelength[i] < shortest) {
15516 shortest = edgelength[i];
15517 }
15518 }
15519
15520 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15521 if (triarea < smallestarea) {
15522 smallestarea = triarea;
15523 }
15524 if (triarea > biggestarea) {
15525 biggestarea = triarea;
15526 }
15527 triminaltitude2 = triarea * triarea / trilongest2;
15528 if (triminaltitude2 < minaltitude) {
15529 minaltitude = triminaltitude2;
15530 }
15531 triaspect2 = trilongest2 / triminaltitude2;
15532 if (triaspect2 > worstaspect) {
15533 worstaspect = triaspect2;
15534 }
15535 aspectindex = 0;
15536 while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15537 && (aspectindex < 15)) {
15538 aspectindex++;
15539 }
15540 aspecttable[aspectindex]++;
15541
15542 for (i = 0; i < 3; i++) {
15543 j = plus1mod3[i];
15544 k = minus1mod3[i];
15545 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15546 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15547 tendegree = 8;
15548 for (ii = 7; ii >= 0; ii--) {
15549 if (cossquare > cossquaretable[ii]) {
15550 tendegree = ii;
15551 }
15552 }
15553 if (dotproduct <= 0.0) {
15554 angletable[tendegree]++;
15555 if (cossquare > smallestangle) {
15556 smallestangle = cossquare;
15557 }
15558 if (acutebiggest && (cossquare < biggestangle)) {
15559 biggestangle = cossquare;
15560 }
15561 } else {
15562 angletable[17 - tendegree]++;
15563 if (acutebiggest || (cossquare > biggestangle)) {
15564 biggestangle = cossquare;
15565 acutebiggest = 0;
15566 }
15567 }
15568 }
15569 triangleloop.tri = triangletraverse(m);
15570 }
15571
15572 shortest = sqrt(shortest);
15573 longest = sqrt(longest);
15574 minaltitude = sqrt(minaltitude);
15575 worstaspect = sqrt(worstaspect);
15576 smallestarea *= 0.5;
15577 biggestarea *= 0.5;
15578 if (smallestangle >= 1.0) {
15579 smallestangle = 0.0;
15580 } else {
15581 smallestangle = degconst * acos(sqrt(smallestangle));
15582 }
15583 if (biggestangle >= 1.0) {
15584 biggestangle = 180.0;
15585 } else {
15586 if (acutebiggest) {
15587 biggestangle = degconst * acos(sqrt(biggestangle));
15588 } else {
15589 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15590 }
15591 }
15592
15593 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15594 smallestarea, biggestarea);
15595 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15596 shortest, longest);
15597 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15598 minaltitude, worstaspect);
15599
15600 printf(" Triangle aspect ratio histogram:\n");
15601 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15602 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15603 aspecttable[8]);
15604 for (i = 1; i < 7; i++) {
15605 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15606 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15607 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15608 }
15609 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15610 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15611 aspecttable[15]);
15612 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15613
15614 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15615 smallestangle, biggestangle);
15616
15617 printf(" Angle histogram:\n");
15618 for (i = 0; i < 9; i++) {
15619 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15620 i * 10, i * 10 + 10, angletable[i],
15621 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15622 }
15623 printf("\n");
15624}
15625
15626/*****************************************************************************/
15627/* */
15628/* statistics() Print all sorts of cool facts. */
15629/* */
15630/*****************************************************************************/
15631
15632#ifdef ANSI_DECLARATORS
15633void statistics(struct mesh *m, struct behavior *b)
15634#else /* not ANSI_DECLARATORS */
15635void statistics(m, b)
15636struct mesh *m;
15637struct behavior *b;
15638#endif /* not ANSI_DECLARATORS */
15639
15640{
15641 printf("\nStatistics:\n\n");
15642 printf(" Input vertices: %d\n", m->invertices);
15643 if (b->refine) {
15644 printf(" Input triangles: %d\n", m->inelements);
15645 }
15646 if (b->poly) {
15647 printf(" Input segments: %d\n", m->insegments);
15648 if (!b->refine) {
15649 printf(" Input holes: %d\n", m->holes);
15650 }
15651 }
15652
15653 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15654 printf(" Mesh triangles: %ld\n", m->triangles.items);
15655 printf(" Mesh edges: %ld\n", m->edges);
15656 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15657 if (b->poly || b->refine) {
15658 printf(" Mesh interior boundary edges: %ld\n",
15659 m->subsegs.items - m->hullsize);
15660 printf(" Mesh subsegments (constrained edges): %ld\n",
15661 m->subsegs.items);
15662 }
15663 printf("\n");
15664
15665 if (b->verbose) {
15666 quality_statistics(m, b);
15667 printf("Memory allocation statistics:\n\n");
15668 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15669 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15670 if (m->subsegs.maxitems > 0) {
15671 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15672 }
15673 if (m->viri.maxitems > 0) {
15674 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15675 }
15676 if (m->badsubsegs.maxitems > 0) {
15677 printf(" Maximum number of encroached subsegments: %ld\n",
15678 m->badsubsegs.maxitems);
15679 }
15680 if (m->badtriangles.maxitems > 0) {
15681 printf(" Maximum number of bad triangles: %ld\n",
15682 m->badtriangles.maxitems);
15683 }
15684 if (m->flipstackers.maxitems > 0) {
15685 printf(" Maximum number of stacked triangle flips: %ld\n",
15686 m->flipstackers.maxitems);
15687 }
15688 if (m->splaynodes.maxitems > 0) {
15689 printf(" Maximum number of splay tree nodes: %ld\n",
15690 m->splaynodes.maxitems);
15691 }
15692 printf(" Approximate heap memory use (bytes): %ld\n\n",
15693 m->vertices.maxitems * m->vertices.itembytes +
15694 m->triangles.maxitems * m->triangles.itembytes +
15695 m->subsegs.maxitems * m->subsegs.itembytes +
15696 m->viri.maxitems * m->viri.itembytes +
15697 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15698 m->badtriangles.maxitems * m->badtriangles.itembytes +
15699 m->flipstackers.maxitems * m->flipstackers.itembytes +
15700 m->splaynodes.maxitems * m->splaynodes.itembytes);
15701
15702 printf("Algorithmic statistics:\n\n");
15703 if (!b->weighted) {
15704 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15705 } else {
15706 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15707 }
15708 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15709 if (m->hyperbolacount > 0) {
15710 printf(" Number of right-of-hyperbola tests: %ld\n",
15711 m->hyperbolacount);
15712 }
15713 if (m->circletopcount > 0) {
15714 printf(" Number of circle top computations: %ld\n",
15715 m->circletopcount);
15716 }
15717 if (m->circumcentercount > 0) {
15718 printf(" Number of triangle circumcenter computations: %ld\n",
15719 m->circumcentercount);
15720 }
15721 printf("\n");
15722 }
15723}
15724
15725/*****************************************************************************/
15726/* */
15727/* main() or triangulate() Gosh, do everything. */
15728/* */
15729/* The sequence is roughly as follows. Many of these steps can be skipped, */
15730/* depending on the command line switches. */
15731/* */
15732/* - Initialize constants and parse the command line. */
15733/* - Read the vertices from a file and either */
15734/* - triangulate them (no -r), or */
15735/* - read an old mesh from files and reconstruct it (-r). */
15736/* - Insert the PSLG segments (-p), and possibly segments on the convex */
15737/* hull (-c). */
15738/* - Read the holes (-p), regional attributes (-pA), and regional area */
15739/* constraints (-pa). Carve the holes and concavities, and spread the */
15740/* regional attributes and area constraints. */
15741/* - Enforce the constraints on minimum angle (-q) and maximum area (-a). */
15742/* Also enforce the conforming Delaunay property (-q and -a). */
15743/* - Compute the number of edges in the resulting mesh. */
15744/* - Promote the mesh's linear triangles to higher order elements (-o). */
15745/* - Write the output files and print the statistics. */
15746/* - Check the consistency and Delaunay property of the mesh (-C). */
15747/* */
15748/*****************************************************************************/
15749
15750#ifdef TRILIBRARY
15751
15752#ifdef ANSI_DECLARATORS
15753void triangulate(char *triswitches, struct triangulateio *in,
15754 struct triangulateio *out, struct triangulateio *vorout)
15755#else /* not ANSI_DECLARATORS */
15756void triangulate(triswitches, in, out, vorout)
15757char *triswitches;
15758struct triangulateio *in;
15759struct triangulateio *out;
15760struct triangulateio *vorout;
15761#endif /* not ANSI_DECLARATORS */
15762
15763#else /* not TRILIBRARY */
15764
15765#ifdef ANSI_DECLARATORS
15766int main(int argc, char **argv)
15767#else /* not ANSI_DECLARATORS */
15768int main(argc, argv)
15769int argc;
15770char **argv;
15771#endif /* not ANSI_DECLARATORS */
15772
15773#endif /* not TRILIBRARY */
15774
15775{
15776 struct mesh m;
15777 struct behavior b;
15778 REAL *holearray; /* Array of holes. */
15779 REAL *regionarray; /* Array of regional attributes and area constraints. */
15780#ifndef TRILIBRARY
15781 FILE* polyfile;
15782#endif /* not TRILIBRARY */
15783#ifndef NO_TIMER
15784 /* Variables for timing the performance of Triangle. The types are */
15785 /* defined in sys/time.h. */
15786 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15787 struct timezone tz;
15788#endif /* not NO_TIMER */
15789
15790#ifndef NO_TIMER
15791 gettimeofday(&tv0, &tz);
15792#endif /* not NO_TIMER */
15793
15794 triangleinit(&m);
15795#ifdef TRILIBRARY
15796 parsecommandline(1, &triswitches, &b);
15797#else /* not TRILIBRARY */
15798 parsecommandline(argc, argv, &b);
15799#endif /* not TRILIBRARY */
15800 m.steinerleft = b.steiner;
15801
15802#ifdef TRILIBRARY
15803 transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15804 in->pointmarkerlist, in->numberofpoints,
15805 in->numberofpointattributes);
15806#else /* not TRILIBRARY */
15807 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15808#endif /* not TRILIBRARY */
15809
15810#ifndef NO_TIMER
15811 if (!b.quiet) {
15812 gettimeofday(&tv1, &tz);
15813 }
15814#endif /* not NO_TIMER */
15815
15816#ifdef CDT_ONLY
15817 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15818#else /* not CDT_ONLY */
15819 if (b.refine) {
15820 /* Read and reconstruct a mesh. */
15821#ifdef TRILIBRARY
15822 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15823 in->triangleattributelist, in->trianglearealist,
15824 in->numberoftriangles, in->numberofcorners,
15825 in->numberoftriangleattributes,
15826 in->segmentlist, in->segmentmarkerlist,
15827 in->numberofsegments);
15828#else /* not TRILIBRARY */
15829 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15830 b.inpolyfilename, polyfile);
15831#endif /* not TRILIBRARY */
15832 } else {
15833 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
15834 }
15835#endif /* not CDT_ONLY */
15836
15837#ifndef NO_TIMER
15838 if (!b.quiet) {
15839 gettimeofday(&tv2, &tz);
15840 if (b.refine) {
15841 printf("Mesh reconstruction");
15842 } else {
15843 printf("Delaunay");
15844 }
15845 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15846 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15847 }
15848#endif /* not NO_TIMER */
15849
15850 /* Ensure that no vertex can be mistaken for a triangular bounding */
15851 /* box vertex in insertvertex(). */
15852 m.infvertex1 = (vertex) NULL;
15853 m.infvertex2 = (vertex) NULL;
15854 m.infvertex3 = (vertex) NULL;
15855
15856 if (b.usesegments) {
15857 m.checksegments = 1; /* Segments will be introduced next. */
15858 if (!b.refine) {
15859 /* Insert PSLG segments and/or convex hull segments. */
15860#ifdef TRILIBRARY
15861 formskeleton(&m, &b, in->segmentlist,
15862 in->segmentmarkerlist, in->numberofsegments);
15863#else /* not TRILIBRARY */
15864 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15865#endif /* not TRILIBRARY */
15866 }
15867 }
15868
15869#ifndef NO_TIMER
15870 if (!b.quiet) {
15871 gettimeofday(&tv3, &tz);
15872 if (b.usesegments && !b.refine) {
15873 printf("Segment milliseconds: %ld\n",
15874 1000l * (tv3.tv_sec - tv2.tv_sec) +
15875 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15876 }
15877 }
15878#endif /* not NO_TIMER */
15879
15880 if (b.poly && (m.triangles.items > 0)) {
15881#ifdef TRILIBRARY
15882 holearray = in->holelist;
15883 m.holes = in->numberofholes;
15884 regionarray = in->regionlist;
15885 m.regions = in->numberofregions;
15886#else /* not TRILIBRARY */
15887 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15888 &regionarray, &m.regions);
15889#endif /* not TRILIBRARY */
15890 if (!b.refine) {
15891 /* Carve out holes and concavities. */
15892 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15893 }
15894 } else {
15895 /* Without a PSLG, there can be no holes or regional attributes */
15896 /* or area constraints. The following are set to zero to avoid */
15897 /* an accidental free() later. */
15898 m.holes = 0;
15899 m.regions = 0;
15900 }
15901
15902#ifndef NO_TIMER
15903 if (!b.quiet) {
15904 gettimeofday(&tv4, &tz);
15905 if (b.poly && !b.refine) {
15906 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15907 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15908 }
15909 }
15910#endif /* not NO_TIMER */
15911
15912#ifndef CDT_ONLY
15913 if (b.quality && (m.triangles.items > 0)) {
15914 enforcequality(&m, &b); /* Enforce angle and area constraints. */
15915 }
15916#endif /* not CDT_ONLY */
15917
15918#ifndef NO_TIMER
15919 if (!b.quiet) {
15920 gettimeofday(&tv5, &tz);
15921#ifndef CDT_ONLY
15922 if (b.quality) {
15923 printf("Quality milliseconds: %ld\n",
15924 1000l * (tv5.tv_sec - tv4.tv_sec) +
15925 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15926 }
15927#endif /* not CDT_ONLY */
15928 }
15929#endif /* not NO_TIMER */
15930
15931 /* Calculate the number of edges. */
15932 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15933
15934 if (b.order > 1) {
15935 highorder(&m, &b); /* Promote elements to higher polynomial order. */
15936 }
15937 if (!b.quiet) {
15938 printf("\n");
15939 }
15940
15941#ifdef TRILIBRARY
15942 if (b.jettison) {
15943 out->numberofpoints = m.vertices.items - m.undeads;
15944 } else {
15945 out->numberofpoints = m.vertices.items;
15946 }
15947 out->numberofpointattributes = m.nextras;
15948 out->numberoftriangles = m.triangles.items;
15949 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15950 out->numberoftriangleattributes = m.eextras;
15951 out->numberofedges = m.edges;
15952 if (b.usesegments) {
15953 out->numberofsegments = m.subsegs.items;
15954 } else {
15955 out->numberofsegments = m.hullsize;
15956 }
15957 if (vorout != (struct triangulateio *) NULL) {
15958 vorout->numberofpoints = m.triangles.items;
15959 vorout->numberofpointattributes = m.nextras;
15960 vorout->numberofedges = m.edges;
15961 }
15962#endif /* TRILIBRARY */
15963 /* If not using iteration numbers, don't write a .node file if one was */
15964 /* read, because the original one would be overwritten! */
15965 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15966 if (!b.quiet) {
15967#ifdef TRILIBRARY
15968 printf("NOT writing vertices.\n");
15969#else /* not TRILIBRARY */
15970 printf("NOT writing a .node file.\n");
15971#endif /* not TRILIBRARY */
15972 }
15973 numbernodes(&m, &b); /* We must remember to number the vertices. */
15974 } else {
15975 /* writenodes() numbers the vertices too. */
15976#ifdef TRILIBRARY
15977 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15978 &out->pointmarkerlist);
15979#else /* not TRILIBRARY */
15980 writenodes(&m, &b, b.outnodefilename, argc, argv);
15981#endif /* TRILIBRARY */
15982 }
15983 if (b.noelewritten) {
15984 if (!b.quiet) {
15985#ifdef TRILIBRARY
15986 printf("NOT writing triangles.\n");
15987#else /* not TRILIBRARY */
15988 printf("NOT writing an .ele file.\n");
15989#endif /* not TRILIBRARY */
15990 }
15991 } else {
15992#ifdef TRILIBRARY
15993 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15994#else /* not TRILIBRARY */
15995 writeelements(&m, &b, b.outelefilename, argc, argv);
15996#endif /* not TRILIBRARY */
15997 }
15998 /* The -c switch (convex switch) causes a PSLG to be written */
15999 /* even if none was read. */
16000 if (b.poly || b.convex) {
16001 /* If not using iteration numbers, don't overwrite the .poly file. */
16002 if (b.nopolywritten || b.noiterationnum) {
16003 if (!b.quiet) {
16004#ifdef TRILIBRARY
16005 printf("NOT writing segments.\n");
16006#else /* not TRILIBRARY */
16007 printf("NOT writing a .poly file.\n");
16008#endif /* not TRILIBRARY */
16009 }
16010 } else {
16011#ifdef TRILIBRARY
16012 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
16013 out->numberofholes = m.holes;
16014 out->numberofregions = m.regions;
16015 if (b.poly) {
16016 out->holelist = in->holelist;
16017 out->regionlist = in->regionlist;
16018 } else {
16019 out->holelist = (REAL *) NULL;
16020 out->regionlist = (REAL *) NULL;
16021 }
16022#else /* not TRILIBRARY */
16023 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
16024 m.regions, argc, argv);
16025#endif /* not TRILIBRARY */
16026 }
16027 }
16028#ifndef TRILIBRARY
16029#ifndef CDT_ONLY
16030 if (m.regions > 0) {
16031 trifree((VOID *) regionarray);
16032 }
16033#endif /* not CDT_ONLY */
16034 if (m.holes > 0) {
16035 trifree((VOID *) holearray);
16036 }
16037 if (b.geomview) {
16038 writeoff(&m, &b, b.offfilename, argc, argv);
16039 }
16040#endif /* not TRILIBRARY */
16041 if (b.edgesout) {
16042#ifdef TRILIBRARY
16043 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
16044#else /* not TRILIBRARY */
16045 writeedges(&m, &b, b.edgefilename, argc, argv);
16046#endif /* not TRILIBRARY */
16047 }
16048 if (b.voronoi) {
16049#ifdef TRILIBRARY
16050 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
16051 &vorout->pointmarkerlist, &vorout->edgelist,
16052 &vorout->edgemarkerlist, &vorout->normlist);
16053#else /* not TRILIBRARY */
16054 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
16055#endif /* not TRILIBRARY */
16056 }
16057 if (b.neighbors) {
16058#ifdef TRILIBRARY
16059 writeneighbors(&m, &b, &out->neighborlist);
16060#else /* not TRILIBRARY */
16061 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
16062#endif /* not TRILIBRARY */
16063 }
16064
16065 if (!b.quiet) {
16066#ifndef NO_TIMER
16067 gettimeofday(&tv6, &tz);
16068 printf("\nOutput milliseconds: %ld\n",
16069 1000l * (tv6.tv_sec - tv5.tv_sec) +
16070 (tv6.tv_usec - tv5.tv_usec) / 1000l);
16071 printf("Total running milliseconds: %ld\n",
16072 1000l * (tv6.tv_sec - tv0.tv_sec) +
16073 (tv6.tv_usec - tv0.tv_usec) / 1000l);
16074#endif /* not NO_TIMER */
16075
16076 statistics(&m, &b);
16077 }
16078
16079#ifndef REDUCED
16080 if (b.docheck) {
16081 checkmesh(&m, &b);
16082 checkdelaunay(&m, &b);
16083 }
16084#endif /* not REDUCED */
16085
16086 triangledeinit(&m, &b);
16087#ifndef TRILIBRARY
16088 return 0;
16089#endif /* not TRILIBRARY */
16090}