PageRenderTime 115ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 2ms

/contrib/gtkgensurf/triangle.c

https://gitlab.com/illwieckz/netradiant
C | 12631 lines | 8857 code | 874 blank | 2900 comment | 1792 complexity | 8758741fd6acfa480a2e2328d8de068f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. #define ANSI_DECLARATORS
  2. /*****************************************************************************/
  3. /* */
  4. /* 888888888 ,o, / 888 */
  5. /* 888 88o88o " o8888o 88o8888o o88888o 888 o88888o */
  6. /* 888 888 888 88b 888 888 888 888 888 d888 88b */
  7. /* 888 888 888 o88^o888 888 888 "88888" 888 8888oo888 */
  8. /* 888 888 888 C888 888 888 888 / 888 q888 */
  9. /* 888 888 888 "88o^888 888 888 Cb 888 "88oooo" */
  10. /* "8oo8D */
  11. /* */
  12. /* A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator. */
  13. /* (triangle.c) */
  14. /* */
  15. /* Version 1.3 */
  16. /* July 19, 1996 */
  17. /* */
  18. /* Copyright 1996 */
  19. /* Jonathan Richard Shewchuk */
  20. /* School of Computer Science */
  21. /* Carnegie Mellon University */
  22. /* 5000 Forbes Avenue */
  23. /* Pittsburgh, Pennsylvania 15213-3891 */
  24. /* jrs@cs.cmu.edu */
  25. /* */
  26. /* This program may be freely redistributed under the condition that the */
  27. /* copyright notices (including this entire header and the copyright */
  28. /* notice printed when the `-h' switch is selected) are not removed, and */
  29. /* no compensation is received. Private, research, and institutional */
  30. /* use is free. You may distribute modified versions of this code UNDER */
  31. /* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */
  32. /* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */
  33. /* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */
  34. /* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */
  35. /* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */
  36. /* WITH THE AUTHOR. (If you are not directly supplying this code to a */
  37. /* customer, and you are instead telling them how they can obtain it for */
  38. /* free, then you are not required to make any arrangement with me.) */
  39. /* */
  40. /* Hypertext instructions for Triangle are available on the Web at */
  41. /* */
  42. /* http://www.cs.cmu.edu/~quake/triangle.html */
  43. /* */
  44. /* Some of the references listed below are marked [*]. These are available */
  45. /* for downloading from the Web page */
  46. /* */
  47. /* http://www.cs.cmu.edu/~quake/triangle.research.html */
  48. /* */
  49. /* A paper discussing some aspects of Triangle is available. See Jonathan */
  50. /* Richard Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator */
  51. /* and Delaunay Triangulator," First Workshop on Applied Computational */
  52. /* Geometry, ACM, May 1996. [*] */
  53. /* */
  54. /* Triangle was created as part of the Archimedes project in the School of */
  55. /* Computer Science at Carnegie Mellon University. Archimedes is a */
  56. /* system for compiling parallel finite element solvers. For further */
  57. /* information, see Anja Feldmann, Omar Ghattas, John R. Gilbert, Gary L. */
  58. /* Miller, David R. O'Hallaron, Eric J. Schwabe, Jonathan R. Shewchuk, */
  59. /* and Shang-Hua Teng, "Automated Parallel Solution of Unstructured PDE */
  60. /* Problems." To appear in Communications of the ACM, we hope. */
  61. /* */
  62. /* The quality mesh generation algorithm is due to Jim Ruppert, "A */
  63. /* Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh */
  64. /* Generation," Journal of Algorithms 18(3):548-585, May 1995. [*] */
  65. /* */
  66. /* My implementation of the divide-and-conquer and incremental Delaunay */
  67. /* triangulation algorithms follows closely the presentation of Guibas */
  68. /* and Stolfi, even though I use a triangle-based data structure instead */
  69. /* of their quad-edge data structure. (In fact, I originally implemented */
  70. /* Triangle using the quad-edge data structure, but switching to a */
  71. /* triangle-based data structure sped Triangle by a factor of two.) The */
  72. /* mesh manipulation primitives and the two aforementioned Delaunay */
  73. /* triangulation algorithms are described by Leonidas J. Guibas and Jorge */
  74. /* Stolfi, "Primitives for the Manipulation of General Subdivisions and */
  75. /* the Computation of Voronoi Diagrams," ACM Transactions on Graphics */
  76. /* 4(2):74-123, April 1985. */
  77. /* */
  78. /* Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai */
  79. /* Lee and Bruce J. Schachter, "Two Algorithms for Constructing the */
  80. /* Delaunay Triangulation," International Journal of Computer and */
  81. /* Information Science 9(3):219-242, 1980. The idea to improve the */
  82. /* divide-and-conquer algorithm by alternating between vertical and */
  83. /* horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and- */
  84. /* Conquer Algorithm for Constructing Delaunay Triangulations," */
  85. /* Algorithmica 2(2):137-151, 1987. */
  86. /* */
  87. /* The incremental insertion algorithm was first proposed by C. L. Lawson, */
  88. /* "Software for C1 Surface Interpolation," in Mathematical Software III, */
  89. /* John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977. */
  90. /* For point location, I use the algorithm of Ernst P. Mucke, Isaac */
  91. /* Saias, and Binhai Zhu, "Fast Randomized Point Location Without */
  92. /* Preprocessing in Two- and Three-dimensional Delaunay Triangulations," */
  93. /* Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
  94. /* ACM, May 1996. [*] If I were to randomize the order of point */
  95. /* insertion (I currently don't bother), their result combined with the */
  96. /* result of Leonidas J. Guibas, Donald E. Knuth, and Micha Sharir, */
  97. /* "Randomized Incremental Construction of Delaunay and Voronoi */
  98. /* Diagrams," Algorithmica 7(4):381-413, 1992, would yield an expected */
  99. /* O(n^{4/3}) bound on running time. */
  100. /* */
  101. /* The O(n log n) sweepline Delaunay triangulation algorithm is taken from */
  102. /* Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams", */
  103. /* Algorithmica 2(2):153-174, 1987. A random sample of edges on the */
  104. /* boundary of the triangulation are maintained in a splay tree for the */
  105. /* purpose of point location. Splay trees are described by Daniel */
  106. /* Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
  107. /* Trees," Journal of the ACM 32(3):652-686, July 1985. */
  108. /* */
  109. /* The algorithms for exact computation of the signs of determinants are */
  110. /* described in Jonathan Richard Shewchuk, "Adaptive Precision Floating- */
  111. /* Point Arithmetic and Fast Robust Geometric Predicates," Technical */
  112. /* Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon */
  113. /* University, Pittsburgh, Pennsylvania, May 1996. [*] (Submitted to */
  114. /* Discrete & Computational Geometry.) An abbreviated version appears as */
  115. /* Jonathan Richard Shewchuk, "Robust Adaptive Floating-Point Geometric */
  116. /* Predicates," Proceedings of the Twelfth Annual Symposium on Computa- */
  117. /* tional Geometry, ACM, May 1996. [*] Many of the ideas for my exact */
  118. /* arithmetic routines originate with Douglas M. Priest, "Algorithms for */
  119. /* Arbitrary Precision Floating Point Arithmetic," Tenth Symposium on */
  120. /* Computer Arithmetic, 132-143, IEEE Computer Society Press, 1991. [*] */
  121. /* Many of the ideas for the correct evaluation of the signs of */
  122. /* determinants are taken from Steven Fortune and Christopher J. Van Wyk, */
  123. /* "Efficient Exact Arithmetic for Computational Geometry," Proceedings */
  124. /* of the Ninth Annual Symposium on Computational Geometry, ACM, */
  125. /* pp. 163-172, May 1993, and from Steven Fortune, "Numerical Stability */
  126. /* of Algorithms for 2D Delaunay Triangulations," International Journal */
  127. /* of Computational Geometry & Applications 5(1-2):193-213, March-June */
  128. /* 1995. */
  129. /* */
  130. /* For definitions of and results involving Delaunay triangulations, */
  131. /* constrained and conforming versions thereof, and other aspects of */
  132. /* triangular mesh generation, see the excellent survey by Marshall Bern */
  133. /* and David Eppstein, "Mesh Generation and Optimal Triangulation," in */
  134. /* Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang, */
  135. /* editors, World Scientific, Singapore, pp. 23-90, 1992. */
  136. /* */
  137. /* The time for incrementally adding PSLG (planar straight line graph) */
  138. /* segments to create a constrained Delaunay triangulation is probably */
  139. /* O(n^2) per segment in the worst case and O(n) per edge in the common */
  140. /* case, where n is the number of triangles that intersect the segment */
  141. /* before it is inserted. This doesn't count point location, which can */
  142. /* be much more expensive. (This note does not apply to conforming */
  143. /* Delaunay triangulations, for which a different method is used to */
  144. /* insert segments.) */
  145. /* */
  146. /* The time for adding segments to a conforming Delaunay triangulation is */
  147. /* not clear, but does not depend upon n alone. In some cases, very */
  148. /* small features (like a point lying next to a segment) can cause a */
  149. /* single segment to be split an arbitrary number of times. Of course, */
  150. /* floating-point precision is a practical barrier to how much this can */
  151. /* happen. */
  152. /* */
  153. /* The time for deleting a point from a Delaunay triangulation is O(n^2) in */
  154. /* the worst case and O(n) in the common case, where n is the degree of */
  155. /* the point being deleted. I could improve this to expected O(n) time */
  156. /* by "inserting" the neighboring vertices in random order, but n is */
  157. /* usually quite small, so it's not worth the bother. (The O(n) time */
  158. /* for random insertion follows from L. Paul Chew, "Building Voronoi */
  159. /* Diagrams for Convex Polygons in Linear Expected Time," Technical */
  160. /* Report PCS-TR90-147, Department of Mathematics and Computer Science, */
  161. /* Dartmouth College, 1990. */
  162. /* */
  163. /* Ruppert's Delaunay refinement algorithm typically generates triangles */
  164. /* at a linear rate (constant time per triangle) after the initial */
  165. /* triangulation is formed. There may be pathological cases where more */
  166. /* time is required, but these never arise in practice. */
  167. /* */
  168. /* The segment intersection formulae are straightforward. If you want to */
  169. /* see them derived, see Franklin Antonio. "Faster Line Segment */
  170. /* Intersection." In Graphics Gems III (David Kirk, editor), pp. 199- */
  171. /* 202. Academic Press, Boston, 1992. */
  172. /* */
  173. /* If you make any improvements to this code, please please please let me */
  174. /* know, so that I may obtain the improvements. Even if you don't change */
  175. /* the code, I'd still love to hear what it's being used for. */
  176. /* */
  177. /* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */
  178. /* whatsoever. This code is provided "as-is". Use at your own risk. */
  179. /* */
  180. /*****************************************************************************/
  181. /* For single precision (which will save some memory and reduce paging), */
  182. /* define the symbol SINGLE by using the -DSINGLE compiler switch or by */
  183. /* writing "#define SINGLE" below. */
  184. /* */
  185. /* For double precision (which will allow you to refine meshes to a smaller */
  186. /* edge length), leave SINGLE undefined. */
  187. /* */
  188. /* Double precision uses more memory, but improves the resolution of the */
  189. /* meshes you can generate with Triangle. It also reduces the likelihood */
  190. /* of a floating exception due to overflow. Finally, it is much faster */
  191. /* than single precision on 64-bit architectures like the DEC Alpha. I */
  192. /* recommend double precision unless you want to generate a mesh for which */
  193. /* you do not have enough memory. */
  194. #define SINGLE
  195. #ifdef SINGLE
  196. #define REAL float
  197. #else /* not SINGLE */
  198. #define REAL double
  199. #endif /* not SINGLE */
  200. /* If yours is not a Unix system, define the NO_TIMER compiler switch to */
  201. /* remove the Unix-specific timing code. */
  202. #define NO_TIMER
  203. /* To insert lots of self-checks for internal errors, define the SELF_CHECK */
  204. /* symbol. This will slow down the program significantly. It is best to */
  205. /* define the symbol using the -DSELF_CHECK compiler switch, but you could */
  206. /* write "#define SELF_CHECK" below. If you are modifying this code, I */
  207. /* recommend you turn self-checks on. */
  208. /* #define SELF_CHECK */
  209. /* To compile Triangle as a callable object library (triangle.o), define the */
  210. /* TRILIBRARY symbol. Read the file triangle.h for details on how to call */
  211. /* the procedure triangulate() that results. */
  212. #define TRILIBRARY
  213. /* It is possible to generate a smaller version of Triangle using one or */
  214. /* both of the following symbols. Define the REDUCED symbol to eliminate */
  215. /* all features that are primarily of research interest; specifically, the */
  216. /* -i, -F, -s, and -C switches. Define the CDT_ONLY symbol to eliminate */
  217. /* all meshing algorithms above and beyond constrained Delaunay */
  218. /* triangulation; specifically, the -r, -q, -a, -S, and -s switches. */
  219. /* These reductions are most likely to be useful when generating an object */
  220. /* library (triangle.o) by defining the TRILIBRARY symbol. */
  221. #define REDUCED
  222. #define CDT_ONLY
  223. /* On some machines, the exact arithmetic routines might be defeated by the */
  224. /* use of internal extended precision floating-point registers. Sometimes */
  225. /* this problem can be fixed by defining certain values to be volatile, */
  226. /* thus forcing them to be stored to memory and rounded off. This isn't */
  227. /* a great solution, though, as it slows Triangle down. */
  228. /* */
  229. /* To try this out, write "#define INEXACT volatile" below. Normally, */
  230. /* however, INEXACT should be defined to be nothing. ("#define INEXACT".) */
  231. #define INEXACT /* Nothing */
  232. /* #define INEXACT volatile */
  233. /* Maximum number of characters in a file name (including the null). */
  234. #define FILENAMESIZE 512
  235. /* Maximum number of characters in a line read from a file (including the */
  236. /* null). */
  237. #define INPUTLINESIZE 512
  238. /* For efficiency, a variety of data structures are allocated in bulk. The */
  239. /* following constants determine how many of each structure is allocated */
  240. /* at once. */
  241. #define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */
  242. #define SHELLEPERBLOCK 508 /* Number of shell edges allocated at once. */
  243. #define POINTPERBLOCK 4092 /* Number of points allocated at once. */
  244. #define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */
  245. /* Number of encroached segments allocated at once. */
  246. #define BADSEGMENTPERBLOCK 252
  247. /* Number of skinny triangles allocated at once. */
  248. #define BADTRIPERBLOCK 4092
  249. /* Number of splay tree nodes allocated at once. */
  250. #define SPLAYNODEPERBLOCK 508
  251. /* The point marker DEADPOINT is an arbitrary number chosen large enough to */
  252. /* (hopefully) not conflict with user boundary markers. Make sure that it */
  253. /* is small enough to fit into your machine's integer size. */
  254. #define DEADPOINT -1073741824
  255. /* The next line is used to outsmart some very stupid compilers. If your */
  256. /* compiler is smarter, feel free to replace the "int" with "void". */
  257. /* Not that it matters. */
  258. #define VOID int
  259. /* Two constants for algorithms based on random sampling. Both constants */
  260. /* have been chosen empirically to optimize their respective algorithms. */
  261. /* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */
  262. /* how large a random sample of triangles to inspect. */
  263. #define SAMPLEFACTOR 11
  264. /* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
  265. /* of boundary edges should be maintained in the splay tree for point */
  266. /* location on the front. */
  267. #define SAMPLERATE 10
  268. /* A number that speaks for itself, every kissable digit. */
  269. #define PI 3.141592653589793238462643383279502884197169399375105820974944592308
  270. /* Another fave. */
  271. #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
  272. /* And here's one for those of you who are intimidated by math. */
  273. #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
  274. #include <stdio.h>
  275. #include <string.h>
  276. #include <math.h>
  277. #ifndef NO_TIMER
  278. #include <sys/time.h>
  279. #endif /* NO_TIMER */
  280. #ifdef TRILIBRARY
  281. #include "triangle.h"
  282. #endif /* TRILIBRARY */
  283. /* The following obscenity seems to be necessary to ensure that this program */
  284. /* will port to Dec Alphas running OSF/1, because their stdio.h file commits */
  285. /* the unpardonable sin of including stdlib.h. Hence, malloc(), free(), and */
  286. /* exit() may or may not already be defined at this point. I declare these */
  287. /* functions explicitly because some non-ANSI C compilers lack stdlib.h. */
  288. #ifndef _STDLIB_H_
  289. extern void *malloc();
  290. extern void free();
  291. extern void exit();
  292. extern double strtod();
  293. extern long strtol();
  294. #endif /* _STDLIB_H_ */
  295. /* A few forward declarations. */
  296. void poolrestart();
  297. #ifndef TRILIBRARY
  298. char *readline();
  299. char *findfield();
  300. #endif /* not TRILIBRARY */
  301. /* Labels that signify whether a record consists primarily of pointers or of */
  302. /* floating-point words. Used to make decisions about data alignment. */
  303. enum wordtype {POINTER, FLOATINGPOINT};
  304. /* Labels that signify the result of point location. The result of a */
  305. /* search indicates that the point falls in the interior of a triangle, on */
  306. /* an edge, on a vertex, or outside the mesh. */
  307. enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
  308. /* Labels that signify the result of site insertion. The result indicates */
  309. /* that the point was inserted with complete success, was inserted but */
  310. /* encroaches on a segment, was not inserted because it lies on a segment, */
  311. /* or was not inserted because another point occupies the same location. */
  312. enum insertsiteresult {SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT,
  313. DUPLICATEPOINT};
  314. /* Labels that signify the result of direction finding. The result */
  315. /* indicates that a segment connecting the two query points falls within */
  316. /* the direction triangle, along the left edge of the direction triangle, */
  317. /* or along the right edge of the direction triangle. */
  318. enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
  319. /* Labels that signify the result of the circumcenter computation routine. */
  320. /* The return value indicates which edge of the triangle is shortest. */
  321. enum circumcenterresult {OPPOSITEORG, OPPOSITEDEST, OPPOSITEAPEX};
  322. /*****************************************************************************/
  323. /* */
  324. /* The basic mesh data structures */
  325. /* */
  326. /* There are three: points, triangles, and shell edges (abbreviated */
  327. /* `shelle'). These three data structures, linked by pointers, comprise */
  328. /* the mesh. A point simply represents a point in space and its properties.*/
  329. /* A triangle is a triangle. A shell edge is a special data structure used */
  330. /* to represent impenetrable segments in the mesh (including the outer */
  331. /* boundary, boundaries of holes, and internal boundaries separating two */
  332. /* triangulated regions). Shell edges represent boundaries defined by the */
  333. /* user that triangles may not lie across. */
  334. /* */
  335. /* A triangle consists of a list of three vertices, a list of three */
  336. /* adjoining triangles, a list of three adjoining shell edges (when shell */
  337. /* edges are used), an arbitrary number of optional user-defined floating- */
  338. /* point attributes, and an optional area constraint. The latter is an */
  339. /* upper bound on the permissible area of each triangle in a region, used */
  340. /* for mesh refinement. */
  341. /* */
  342. /* For a triangle on a boundary of the mesh, some or all of the neighboring */
  343. /* triangles may not be present. For a triangle in the interior of the */
  344. /* mesh, often no neighboring shell edges are present. Such absent */
  345. /* triangles and shell edges are never represented by NULL pointers; they */
  346. /* are represented by two special records: `dummytri', the triangle that */
  347. /* fills "outer space", and `dummysh', the omnipresent shell edge. */
  348. /* `dummytri' and `dummysh' are used for several reasons; for instance, */
  349. /* they can be dereferenced and their contents examined without causing the */
  350. /* memory protection exception that would occur if NULL were dereferenced. */
  351. /* */
  352. /* However, it is important to understand that a triangle includes other */
  353. /* information as well. The pointers to adjoining vertices, triangles, and */
  354. /* shell edges are ordered in a way that indicates their geometric relation */
  355. /* to each other. Furthermore, each of these pointers contains orientation */
  356. /* information. Each pointer to an adjoining triangle indicates which face */
  357. /* of that triangle is contacted. Similarly, each pointer to an adjoining */
  358. /* shell edge indicates which side of that shell edge is contacted, and how */
  359. /* the shell edge is oriented relative to the triangle. */
  360. /* */
  361. /* Shell edges are found abutting edges of triangles; either sandwiched */
  362. /* between two triangles, or resting against one triangle on an exterior */
  363. /* boundary or hole boundary. */
  364. /* */
  365. /* A shell edge consists of a list of two vertices, a list of two */
  366. /* adjoining shell edges, and a list of two adjoining triangles. One of */
  367. /* the two adjoining triangles may not be present (though there should */
  368. /* always be one), and neighboring shell edges might not be present. */
  369. /* Shell edges also store a user-defined integer "boundary marker". */
  370. /* Typically, this integer is used to indicate what sort of boundary */
  371. /* conditions are to be applied at that location in a finite element */
  372. /* simulation. */
  373. /* */
  374. /* Like triangles, shell edges maintain information about the relative */
  375. /* orientation of neighboring objects. */
  376. /* */
  377. /* Points are relatively simple. A point is a list of floating point */
  378. /* numbers, starting with the x, and y coordinates, followed by an */
  379. /* arbitrary number of optional user-defined floating-point attributes, */
  380. /* followed by an integer boundary marker. During the segment insertion */
  381. /* phase, there is also a pointer from each point to a triangle that may */
  382. /* contain it. Each pointer is not always correct, but when one is, it */
  383. /* speeds up segment insertion. These pointers are assigned values once */
  384. /* at the beginning of the segment insertion phase, and are not used or */
  385. /* updated at any other time. Edge swapping during segment insertion will */
  386. /* render some of them incorrect. Hence, don't rely upon them for */
  387. /* anything. For the most part, points do not have any information about */
  388. /* what triangles or shell edges they are linked to. */
  389. /* */
  390. /*****************************************************************************/
  391. /*****************************************************************************/
  392. /* */
  393. /* Handles */
  394. /* */
  395. /* The oriented triangle (`triedge') and oriented shell edge (`edge') data */
  396. /* structures defined below do not themselves store any part of the mesh. */
  397. /* The mesh itself is made of `triangle's, `shelle's, and `point's. */
  398. /* */
  399. /* Oriented triangles and oriented shell edges will usually be referred to */
  400. /* as "handles". A handle is essentially a pointer into the mesh; it */
  401. /* allows you to "hold" one particular part of the mesh. Handles are used */
  402. /* to specify the regions in which one is traversing and modifying the mesh.*/
  403. /* A single `triangle' may be held by many handles, or none at all. (The */
  404. /* latter case is not a memory leak, because the triangle is still */
  405. /* connected to other triangles in the mesh.) */
  406. /* */
  407. /* A `triedge' is a handle that holds a triangle. It holds a specific side */
  408. /* of the triangle. An `edge' is a handle that holds a shell edge. It */
  409. /* holds either the left or right side of the edge. */
  410. /* */
  411. /* Navigation about the mesh is accomplished through a set of mesh */
  412. /* manipulation primitives, further below. Many of these primitives take */
  413. /* a handle and produce a new handle that holds the mesh near the first */
  414. /* handle. Other primitives take two handles and glue the corresponding */
  415. /* parts of the mesh together. The exact position of the handles is */
  416. /* important. For instance, when two triangles are glued together by the */
  417. /* bond() primitive, they are glued by the sides on which the handles lie. */
  418. /* */
  419. /* Because points have no information about which triangles they are */
  420. /* attached to, I commonly represent a point by use of a handle whose */
  421. /* origin is the point. A single handle can simultaneously represent a */
  422. /* triangle, an edge, and a point. */
  423. /* */
  424. /*****************************************************************************/
  425. /* The triangle data structure. Each triangle contains three pointers to */
  426. /* adjoining triangles, plus three pointers to vertex points, plus three */
  427. /* pointers to shell edges (defined below; these pointers are usually */
  428. /* `dummysh'). It may or may not also contain user-defined attributes */
  429. /* and/or a floating-point "area constraint". It may also contain extra */
  430. /* pointers for nodes, when the user asks for high-order elements. */
  431. /* Because the size and structure of a `triangle' is not decided until */
  432. /* runtime, I haven't simply defined the type `triangle' to be a struct. */
  433. typedef REAL **triangle; /* Really: typedef triangle *triangle */
  434. /* An oriented triangle: includes a pointer to a triangle and orientation. */
  435. /* The orientation denotes an edge of the triangle. Hence, there are */
  436. /* three possible orientations. By convention, each edge is always */
  437. /* directed to point counterclockwise about the corresponding triangle. */
  438. struct triedge {
  439. triangle *tri;
  440. int orient; /* Ranges from 0 to 2. */
  441. };
  442. /* The shell data structure. Each shell edge contains two pointers to */
  443. /* adjoining shell edges, plus two pointers to vertex points, plus two */
  444. /* pointers to adjoining triangles, plus one shell marker. */
  445. typedef REAL **shelle; /* Really: typedef shelle *shelle */
  446. /* An oriented shell edge: includes a pointer to a shell edge and an */
  447. /* orientation. The orientation denotes a side of the edge. Hence, there */
  448. /* are two possible orientations. By convention, the edge is always */
  449. /* directed so that the "side" denoted is the right side of the edge. */
  450. struct edge {
  451. shelle *sh;
  452. int shorient; /* Ranges from 0 to 1. */
  453. };
  454. /* The point data structure. Each point is actually an array of REALs. */
  455. /* The number of REALs is unknown until runtime. An integer boundary */
  456. /* marker, and sometimes a pointer to a triangle, is appended after the */
  457. /* REALs. */
  458. typedef REAL *point;
  459. /* A queue used to store encroached segments. Each segment's vertices are */
  460. /* stored so that one can check whether a segment is still the same. */
  461. struct badsegment {
  462. struct edge encsegment; /* An encroached segment. */
  463. point segorg, segdest; /* The two vertices. */
  464. struct badsegment *nextsegment; /* Pointer to next encroached segment. */
  465. };
  466. /* A queue used to store bad triangles. The key is the square of the cosine */
  467. /* of the smallest angle of the triangle. Each triangle's vertices are */
  468. /* stored so that one can check whether a triangle is still the same. */
  469. struct badface {
  470. struct triedge badfacetri; /* A bad triangle. */
  471. REAL key; /* cos^2 of smallest (apical) angle. */
  472. point faceorg, facedest, faceapex; /* The three vertices. */
  473. struct badface *nextface; /* Pointer to next bad triangle. */
  474. };
  475. /* A node in a heap used to store events for the sweepline Delaunay */
  476. /* algorithm. Nodes do not point directly to their parents or children in */
  477. /* the heap. Instead, each node knows its position in the heap, and can */
  478. /* look up its parent and children in a separate array. The `eventptr' */
  479. /* points either to a `point' or to a triangle (in encoded format, so that */
  480. /* an orientation is included). In the latter case, the origin of the */
  481. /* oriented triangle is the apex of a "circle event" of the sweepline */
  482. /* algorithm. To distinguish site events from circle events, all circle */
  483. /* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */
  484. struct event {
  485. REAL xkey, ykey; /* Coordinates of the event. */
  486. VOID *eventptr; /* Can be a point or the location of a circle event. */
  487. int heapposition; /* Marks this event's position in the heap. */
  488. };
  489. /* A node in the splay tree. Each node holds an oriented ghost triangle */
  490. /* that represents a boundary edge of the growing triangulation. When a */
  491. /* circle event covers two boundary edges with a triangle, so that they */
  492. /* are no longer boundary edges, those edges are not immediately deleted */
  493. /* from the tree; rather, they are lazily deleted when they are next */
  494. /* encountered. (Since only a random sample of boundary edges are kept */
  495. /* in the tree, lazy deletion is faster.) `keydest' is used to verify */
  496. /* that a triangle is still the same as when it entered the splay tree; if */
  497. /* it has been rotated (due to a circle event), it no longer represents a */
  498. /* boundary edge and should be deleted. */
  499. struct splaynode {
  500. struct triedge keyedge; /* Lprev of an edge on the front. */
  501. point keydest; /* Used to verify that splay node is still live. */
  502. struct splaynode *lchild, *rchild; /* Children in splay tree. */
  503. };
  504. /* A type used to allocate memory. firstblock is the first block of items. */
  505. /* nowblock is the block from which items are currently being allocated. */
  506. /* nextitem points to the next slab of free memory for an item. */
  507. /* deaditemstack is the head of a linked list (stack) of deallocated items */
  508. /* that can be recycled. unallocateditems is the number of items that */
  509. /* remain to be allocated from nowblock. */
  510. /* */
  511. /* Traversal is the process of walking through the entire list of items, and */
  512. /* is separate from allocation. Note that a traversal will visit items on */
  513. /* the "deaditemstack" stack as well as live items. pathblock points to */
  514. /* the block currently being traversed. pathitem points to the next item */
  515. /* to be traversed. pathitemsleft is the number of items that remain to */
  516. /* be traversed in pathblock. */
  517. /* */
  518. /* itemwordtype is set to POINTER or FLOATINGPOINT, and is used to suggest */
  519. /* what sort of word the record is primarily made up of. alignbytes */
  520. /* determines how new records should be aligned in memory. itembytes and */
  521. /* itemwords are the length of a record in bytes (after rounding up) and */
  522. /* words. itemsperblock is the number of items allocated at once in a */
  523. /* single block. items is the number of currently allocated items. */
  524. /* maxitems is the maximum number of items that have been allocated at */
  525. /* once; it is the current number of items plus the number of records kept */
  526. /* on deaditemstack. */
  527. struct memorypool {
  528. VOID **firstblock, **nowblock;
  529. VOID *nextitem;
  530. VOID *deaditemstack;
  531. VOID **pathblock;
  532. VOID *pathitem;
  533. enum wordtype itemwordtype;
  534. int alignbytes;
  535. int itembytes, itemwords;
  536. int itemsperblock;
  537. long items, maxitems;
  538. int unallocateditems;
  539. int pathitemsleft;
  540. };
  541. /* Variables used to allocate memory for triangles, shell edges, points, */
  542. /* viri (triangles being eaten), bad (encroached) segments, bad (skinny */
  543. /* or too large) triangles, and splay tree nodes. */
  544. static struct memorypool triangles;
  545. static struct memorypool shelles;
  546. static struct memorypool points;
  547. static struct memorypool viri;
  548. static struct memorypool badsegments;
  549. static struct memorypool badtriangles;
  550. static struct memorypool splaynodes;
  551. /* Variables that maintain the bad triangle queues. The tails are pointers */
  552. /* to the pointers that have to be filled in to enqueue an item. */
  553. static struct badface *queuefront[64];
  554. static struct badface **queuetail[64];
  555. static REAL xmin, xmax, ymin, ymax; /* x and y bounds. */
  556. static REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */
  557. static int inpoints; /* Number of input points. */
  558. static int inelements; /* Number of input triangles. */
  559. static int insegments; /* Number of input segments. */
  560. static int holes; /* Number of input holes. */
  561. static int regions; /* Number of input regions. */
  562. static long edges; /* Number of output edges. */
  563. static int mesh_dim; /* Dimension (ought to be 2). */
  564. static int nextras; /* Number of attributes per point. */
  565. static int eextras; /* Number of attributes per triangle. */
  566. static long hullsize; /* Number of edges of convex hull. */
  567. static int triwords; /* Total words per triangle. */
  568. static int shwords; /* Total words per shell edge. */
  569. static int pointmarkindex; /* Index to find boundary marker of a point. */
  570. static int point2triindex; /* Index to find a triangle adjacent to a point. */
  571. static int highorderindex; /* Index to find extra nodes for high-order elements. */
  572. static int elemattribindex; /* Index to find attributes of a triangle. */
  573. static int areaboundindex; /* Index to find area bound of a triangle. */
  574. static int checksegments; /* Are there segments in the triangulation yet? */
  575. static int readnodefile; /* Has a .node file been read? */
  576. static long samples; /* Number of random samples for point location. */
  577. static unsigned long randomseed; /* Current random number seed. */
  578. static REAL splitter; /* Used to split REAL factors for exact multiplication. */
  579. static REAL epsilon; /* Floating-point machine epsilon. */
  580. static REAL resulterrbound;
  581. static REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
  582. static REAL iccerrboundA, iccerrboundB, iccerrboundC;
  583. static long incirclecount; /* Number of incircle tests performed. */
  584. static long counterclockcount; /* Number of counterclockwise tests performed. */
  585. static long hyperbolacount; /* Number of right-of-hyperbola tests performed. */
  586. static long circumcentercount; /* Number of circumcenter calculations performed. */
  587. static long circletopcount; /* Number of circle top calculations performed. */
  588. /* Switches for the triangulator. */
  589. /* poly: -p switch. refine: -r switch. */
  590. /* quality: -q switch. */
  591. /* minangle: minimum angle bound, specified after -q switch. */
  592. /* goodangle: cosine squared of minangle. */
  593. /* vararea: -a switch without number. */
  594. /* fixedarea: -a switch with number. */
  595. /* maxarea: maximum area bound, specified after -a switch. */
  596. /* regionattrib: -A switch. convex: -c switch. */
  597. /* firstnumber: inverse of -z switch. All items are numbered starting */
  598. /* from firstnumber. */
  599. /* edgesout: -e switch. voronoi: -v switch. */
  600. /* neighbors: -n switch. geomview: -g switch. */
  601. /* nobound: -B switch. nopolywritten: -P switch. */
  602. /* nonodewritten: -N switch. noelewritten: -E switch. */
  603. /* noiterationnum: -I switch. noholes: -O switch. */
  604. /* noexact: -X switch. */
  605. /* order: element order, specified after -o switch. */
  606. /* nobisect: count of how often -Y switch is selected. */
  607. /* steiner: maximum number of Steiner points, specified after -S switch. */
  608. /* steinerleft: number of Steiner points not yet used. */
  609. /* incremental: -i switch. sweepline: -F switch. */
  610. /* dwyer: inverse of -l switch. */
  611. /* splitseg: -s switch. */
  612. /* docheck: -C switch. */
  613. /* quiet: -Q switch. verbose: count of how often -V switch is selected. */
  614. /* useshelles: -p, -r, -q, or -c switch; determines whether shell edges */
  615. /* are used at all. */
  616. /* */
  617. /* Read the instructions to find out the meaning of these switches. */
  618. static int poly, refine, quality, vararea, fixedarea, regionattrib, convex;
  619. static int firstnumber;
  620. static int edgesout, voronoi, neighbors, geomview;
  621. static int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
  622. static int noholes, noexact;
  623. static int incremental, sweepline, dwyer;
  624. static int splitseg;
  625. static int docheck;
  626. static int quiet, verbose;
  627. static int useshelles;
  628. static int order;
  629. static int nobisect;
  630. static int steiner, steinerleft;
  631. static REAL minangle, goodangle;
  632. static REAL maxarea;
  633. /* Variables for file names. */
  634. #ifndef TRILIBRARY
  635. char innodefilename[FILENAMESIZE];
  636. char inelefilename[FILENAMESIZE];
  637. char inpolyfilename[FILENAMESIZE];
  638. char areafilename[FILENAMESIZE];
  639. char outnodefilename[FILENAMESIZE];
  640. char outelefilename[FILENAMESIZE];
  641. char outpolyfilename[FILENAMESIZE];
  642. char edgefilename[FILENAMESIZE];
  643. char vnodefilename[FILENAMESIZE];
  644. char vedgefilename[FILENAMESIZE];
  645. char neighborfilename[FILENAMESIZE];
  646. char offfilename[FILENAMESIZE];
  647. #endif /* not TRILIBRARY */
  648. /* Triangular bounding box points. */
  649. static point infpoint1, infpoint2, infpoint3;
  650. /* Pointer to the `triangle' that occupies all of "outer space". */
  651. static triangle *dummytri;
  652. static triangle *dummytribase; /* Keep base address so we can free() it later. */
  653. /* Pointer to the omnipresent shell edge. Referenced by any triangle or */
  654. /* shell edge that isn't really connected to a shell edge at that */
  655. /* location. */
  656. static shelle *dummysh;
  657. static shelle *dummyshbase; /* Keep base address so we can free() it later. */
  658. /* Pointer to a recently visited triangle. Improves point location if */
  659. /* proximate points are inserted sequentially. */
  660. static struct triedge recenttri;
  661. /*****************************************************************************/
  662. /* */
  663. /* Mesh manipulation primitives. Each triangle contains three pointers to */
  664. /* other triangles, with orientations. Each pointer points not to the */
  665. /* first byte of a triangle, but to one of the first three bytes of a */
  666. /* triangle. It is necessary to extract both the triangle itself and the */
  667. /* orientation. To save memory, I keep both pieces of information in one */
  668. /* pointer. To make this possible, I assume that all triangles are aligned */
  669. /* to four-byte boundaries. The `decode' routine below decodes a pointer, */
  670. /* extracting an orientation (in the range 0 to 2) and a pointer to the */
  671. /* beginning of a triangle. The `encode' routine compresses a pointer to a */
  672. /* triangle and an orientation into a single pointer. My assumptions that */
  673. /* triangles are four-byte-aligned and that the `unsigned long' type is */
  674. /* long enough to hold a pointer are two of the few kludges in this program.*/
  675. /* */
  676. /* Shell edges are manipulated similarly. A pointer to a shell edge */
  677. /* carries both an address and an orientation in the range 0 to 1. */
  678. /* */
  679. /* The other primitives take an oriented triangle or oriented shell edge, */
  680. /* and return an oriented triangle or oriented shell edge or point; or they */
  681. /* change the connections in the data structure. */
  682. /* */
  683. /*****************************************************************************/
  684. /********* Mesh manipulation primitives begin here *********/
  685. /** **/
  686. /** **/
  687. /* Fast lookup arrays to speed some of the mesh manipulation primitives. */
  688. int plus1mod3[3] = {1, 2, 0};
  689. int minus1mod3[3] = {2, 0, 1};
  690. /********* Primitives for triangles *********/
  691. /* */
  692. /* */
  693. /* decode() converts a pointer to an oriented triangle. The orientation is */
  694. /* extracted from the two least significant bits of the pointer. */
  695. #define decode( ptr, triedge ) \
  696. ( triedge ).orient = (int) ( (unsigned long) ( ptr ) & (unsigned long) 3l ); \
  697. ( triedge ).tri = (triangle *) \
  698. ( (unsigned long) ( ptr ) ^ (unsigned long) ( triedge ).orient )
  699. /* encode() compresses an oriented triangle into a single pointer. It */
  700. /* relies on the assumption that all triangles are aligned to four-byte */
  701. /* boundaries, so the two least significant bits of (triedge).tri are zero.*/
  702. #define encode( triedge ) \
  703. (triangle) ( (unsigned long) ( triedge ).tri | (unsigned long) ( triedge ).orient )
  704. /* The following edge manipulation primitives are all described by Guibas */
  705. /* and Stolfi. However, they use an edge-based data structure, whereas I */
  706. /* am using a triangle-based data structure. */
  707. /* sym() finds the abutting triangle, on the same edge. Note that the */
  708. /* edge direction is necessarily reversed, because triangle/edge handles */
  709. /* are always directed counterclockwise around the triangle. */
  710. #define sym( triedge1, triedge2 ) \
  711. ptr = ( triedge1 ).tri[( triedge1 ).orient]; \
  712. decode( ptr, triedge2 );
  713. #define symself( triedge ) \
  714. ptr = ( triedge ).tri[( triedge ).orient]; \
  715. decode( ptr, triedge );
  716. /* lnext() finds the next edge (counterclockwise) of a triangle. */
  717. #define lnext( triedge1, triedge2 ) \
  718. ( triedge2 ).tri = ( triedge1 ).tri; \
  719. ( triedge2 ).orient = plus1mod3[( triedge1 ).orient]
  720. #define lnextself( triedge ) \
  721. ( triedge ).orient = plus1mod3[( triedge ).orient]
  722. /* lprev() finds the previous edge (clockwise) of a triangle. */
  723. #define lprev( triedge1, triedge2 ) \
  724. ( triedge2 ).tri = ( triedge1 ).tri; \
  725. ( triedge2 ).orient = minus1mod3[( triedge1 ).orient]
  726. #define lprevself( triedge ) \
  727. ( triedge ).orient = minus1mod3[( triedge ).orient]
  728. /* onext() spins counterclockwise around a point; that is, it finds the next */
  729. /* edge with the same origin in the counterclockwise direction. This edge */
  730. /* will be part of a different triangle. */
  731. #define onext( triedge1, triedge2 ) \
  732. lprev( triedge1, triedge2 ); \
  733. symself( triedge2 );
  734. #define onextself( triedge ) \
  735. lprevself( triedge ); \
  736. symself( triedge );
  737. /* oprev() spins clockwise around a point; that is, it finds the next edge */
  738. /* with the same origin in the clockwise direction. This edge will be */
  739. /* part of a different triangle. */
  740. #define oprev( triedge1, triedge2 ) \
  741. sym( triedge1, triedge2 ); \
  742. lnextself( triedge2 );
  743. #define oprevself( triedge ) \
  744. symself( triedge ); \
  745. lnextself( triedge );
  746. /* dnext() spins counterclockwise around a point; that is, it finds the next */
  747. /* edge with the same destination in the counterclockwise direction. This */
  748. /* edge will be part of a different triangle. */
  749. #define dnext( triedge1, triedge2 ) \
  750. sym( triedge1, triedge2 ); \
  751. lprevself( triedge2 );
  752. #define dnextself( triedge ) \
  753. symself( triedge ); \
  754. lprevself( triedge );
  755. /* dprev() spins clockwise around a point; that is, it finds the next edge */
  756. /* with the same destination in the clockwise direction. This edge will */
  757. /* be part of a different triangle. */
  758. #define dprev( triedge1, triedge2 ) \
  759. lnext( triedge1, triedge2 ); \
  760. symself( triedge2 );
  761. #define dprevself( triedge ) \
  762. lnextself( triedge ); \
  763. symself( triedge );
  764. /* rnext() moves one edge counterclockwise about the adjacent triangle. */
  765. /* (It's best understood by reading Guibas and Stolfi. It involves */
  766. /* changing triangles twice.) */
  767. #define rnext( triedge1, triedge2 ) \
  768. sym( triedge1, triedge2 ); \
  769. lnextself( triedge2 ); \
  770. symself( triedge2 );
  771. #define rnextself( triedge ) \
  772. symself( triedge ); \
  773. lnextself( triedge ); \
  774. symself( triedge );
  775. /* rnext() moves one edge clockwise about the adjacent triangle. */
  776. /* (It's best understood by reading Guibas and Stolfi. It involves */
  777. /* changing triangles twice.) */
  778. #define rprev( triedge1, triedge2 ) \
  779. sym( triedge1, triedge2 ); \
  780. lprevself( triedge2 ); \
  781. symself( triedge2 );
  782. #define rprevself( triedge ) \
  783. symself( triedge ); \
  784. lprevself( triedge ); \
  785. symself( triedge );
  786. /* These primitives determine or set the origin, destination, or apex of a */
  787. /* triangle. */
  788. #define org( triedge, pointptr ) \
  789. pointptr = (point) ( triedge ).tri[plus1mod3[( triedge ).orient] + 3]
  790. #define dest( triedge, pointptr ) \
  791. pointptr = (point) ( triedge ).tri[minus1mod3[( triedge ).orient] + 3]
  792. #define apex( triedge, pointptr ) \
  793. pointptr = (point) ( triedge ).tri[( triedge ).orient + 3]
  794. #define setorg( triedge, pointptr ) \
  795. ( triedge ).tri[plus1mod3[( triedge ).orient] + 3] = (triangle) pointptr
  796. #define setdest( triedge, pointptr ) \
  797. ( triedge ).tri[minus1mod3[( triedge ).orient] + 3] = (triangle) pointptr
  798. #define setapex( triedge, pointptr ) \
  799. ( triedge ).tri[( triedge ).orient + 3] = (triangle) pointptr
  800. #define setvertices2null( triedge ) \
  801. ( triedge ).tri[3] = (triangle) NULL; \
  802. ( triedge ).tri[4] = (triangle) NULL; \
  803. ( triedge ).tri[5] = (triangle) NULL;
  804. /* Bond two triangles together. */
  805. #define bond( triedge1, triedge2 ) \
  806. ( triedge1 ).tri[( triedge1 ).orient] = encode( triedge2 ); \
  807. ( triedge2 ).tri[( triedge2 ).orient] = encode( triedge1 )
  808. /* Dissolve a bond (from one side). Note that the other triangle will still */
  809. /* think it's connected to this triangle. Usually, however, the other */
  810. /* triangle is being deleted entirely, or bonded to another triangle, so */
  811. /* it doesn't matter. */
  812. #define dissolve( triedge ) \
  813. ( triedge ).tri[( triedge ).orient] = (triangle) dummytri
  814. /* Copy a triangle/edge handle. */
  815. #define triedgecopy( triedge1, triedge2 ) \
  816. ( triedge2 ).tri = ( triedge1 ).tri; \
  817. ( triedge2 ).orient = ( triedge1 ).orient
  818. /* Test for equality of triangle/edge handles. */
  819. #define triedgeequal( triedge1, triedge2 ) \
  820. ( ( ( triedge1 ).tri == ( triedge2 ).tri ) && \
  821. ( ( triedge1 ).orient == ( triedge2 ).orient ) )
  822. /* Primitives to infect or cure a triangle with the virus. These rely on */
  823. /* the assumption that all shell edges are aligned to four-byte boundaries.*/
  824. #define infect( triedge ) \
  825. ( triedge ).tri[6] = (triangle) \
  826. ( (unsigned long) ( triedge ).tri[6] | (unsigned long) 2l )
  827. #define uninfect( triedge ) \
  828. ( triedge ).tri[6] = (triangle) \
  829. ( (unsigned long) ( triedge ).tri[6] & ~(unsigned long) 2l )
  830. /* Test a triangle for viral infection. */
  831. #define infected( triedge ) \
  832. ( ( (unsigned long) ( triedge ).tri[6] & (unsigned long) 2l ) != 0 )
  833. /* Check or set a triangle's attributes. */
  834. #define elemattribute( triedge, attnum ) \
  835. ( (REAL *) ( triedge ).tri )[elemattribindex + ( attnum )]
  836. #define setelemattribute( triedge, attnum, value ) \
  837. ( (REAL *) ( triedge ).tri )[elemattribindex + ( attnum )] = (REAL)value
  838. /* Check or set a triangle's maximum area bound. */
  839. #define areabound( triedge ) ( (REAL *) ( triedge ).tri )[areaboundindex]
  840. #define setareabound( triedge, value ) \
  841. ( (REAL *) ( triedge ).tri )[areaboundindex] = (REAL)value
  842. /********* Primitives for shell edges *********/
  843. /* */
  844. /* */
  845. /* sdecode() converts a pointer to an oriented shell edge. The orientation */
  846. /* is extracted from the least significant bit of the pointer. The two */
  847. /* least significant bits (one for orientation, one for viral infection) */
  848. /* are masked out to produce the real pointer. */
  849. #define sdecode( sptr, edge ) \
  850. ( edge ).shorient = (int) ( (unsigned long) ( sptr ) & (unsigned long) 1l ); \
  851. ( edge ).sh = (shelle *) \
  852. ( (unsigned long) ( sptr ) & ~(unsigned long) 3l )
  853. /* sencode() compresses an oriented shell edge into a single pointer. It */
  854. /* relies on the assumption that all shell edges are aligned to two-byte */
  855. /* boundaries, so the least significant bit of (edge).sh is zero. */
  856. #define sencode( edge ) \
  857. (shelle) ( (unsigned long) ( edge ).sh | (unsigned long) ( edge ).shorient )
  858. /* ssym() toggles the orientation of a shell edge. */
  859. #define ssym( edge1, edge2 ) \
  860. ( edge2 ).sh = ( edge1 ).sh; \
  861. ( edge2 ).shorient = 1 - ( edge1 ).shorient
  862. #define ssymself( edge ) \
  863. ( edge ).shorient = 1 - ( edge ).shorient
  864. /* spivot() finds the other shell edge (from the same segment) that shares */
  865. /* the same origin. */
  866. #define spivot( edge1, edge2 ) \
  867. sptr = ( edge1 ).sh[( edge1 ).shorient]; \
  868. sdecode( sptr, edge2 )
  869. #define spivotself( edge ) \
  870. sptr = ( edge ).sh[( edge ).shorient]; \
  871. sdecode( sptr, edge )
  872. /* snext() finds the next shell edge (from the same segment) in sequence; */
  873. /* one whose origin is the input shell edge's destination. */
  874. #define snext( edge1, edge2 ) \
  875. sptr = ( edge1 ).sh[1 - ( edge1 ).shorient]; \
  876. sdecode( sptr, edge2 )
  877. #define snextself( edge ) \
  878. sptr = ( edge ).sh[1 - ( edge ).shorient]; \
  879. sdecode( sptr, edge )
  880. /* These primitives determine or set the origin or destination of a shell */
  881. /* edge. */
  882. #define sorg( edge, pointptr ) \
  883. pointptr = (point) ( edge ).sh[2 + ( edge ).shorient]
  884. #define sdest( edge, pointptr ) \
  885. pointptr = (point) ( edge ).sh[3 - ( edge ).shorient]
  886. #define setsorg( edge, pointptr ) \
  887. ( edge ).sh[2 + ( edge ).shorient] = (shelle) pointptr
  888. #define setsdest( edge, pointptr ) \
  889. ( edge ).sh[3 - ( edge ).shorient] = (shelle) pointptr
  890. /* These primitives read or set a shell marker. Shell markers are used to */
  891. /* hold user boundary information. */
  892. #define mark( edge ) ( *(int *) ( ( edge ).sh + 6 ) )
  893. #define setmark( edge, value ) \
  894. *(int *) ( ( edge ).sh + 6 ) = value
  895. /* Bond two shell edges together. */
  896. #define sbond( edge1, edge2 ) \
  897. ( edge1 ).sh[( edge1 ).shorient] = sencode( edge2 ); \
  898. ( edge2 ).sh[( edge2 ).shorient] = sencode( edge1 )
  899. /* Dissolve a shell edge bond (from one side). Note that the other shell */
  900. /* edge will still think it's connected to this shell edge. */
  901. #define sdissolve( edge ) \
  902. ( edge ).sh[( edge ).shorient] = (shelle) dummysh
  903. /* Copy a shell edge. */
  904. #define shellecopy( edge1, edge2 ) \
  905. ( edge2 ).sh = ( edge1 ).sh; \
  906. ( edge2 ).shorient = ( edge1 ).shorient
  907. /* Test for equality of shell edges. */
  908. #define shelleequal( edge1, edge2 ) \
  909. ( ( ( edge1 ).sh == ( edge2 ).sh ) && \
  910. ( ( edge1 ).shorient == ( edge2 ).shorient ) )
  911. /********* Primitives for interacting triangles and shell edges *********/
  912. /* */
  913. /* */
  914. /* tspivot() finds a shell edge abutting a triangle. */
  915. #define tspivot( triedge, edge ) \
  916. sptr = (shelle) ( triedge ).tri[6 + ( triedge ).orient]; \
  917. sdecode( sptr, edge )
  918. /* stpivot() finds a triangle abutting a shell edge. It requires that the */
  919. /* variable `ptr' of type `triangle' be defined. */
  920. #define stpivot( edge, triedge ) \
  921. ptr = (triangle) ( edge ).sh[4 + ( edge ).shorient]; \
  922. decode( ptr, triedge )
  923. /* Bond a triangle to a shell edge. */
  924. #define tsbond( triedge, edge ) \
  925. ( triedge ).tri[6 + ( triedge ).orient] = (triangle) sencode( edge ); \
  926. ( edge ).sh[4 + ( edge ).shorient] = (shelle) encode( triedge )
  927. /* Dissolve a bond (from the triangle side). */
  928. #define tsdissolve( triedge ) \
  929. ( triedge ).tri[6 + ( triedge ).orient] = (triangle) dummysh
  930. /* Dissolve a bond (from the shell edge side). */
  931. #define stdissolve( edge ) \
  932. ( edge ).sh[4 + ( edge ).shorient] = (shelle) dummytri
  933. /********* Primitives for points *********/
  934. /* */
  935. /* */
  936. #define pointmark( pt ) ( (int *) ( pt ) )[pointmarkindex]
  937. #define setpointmark( pt, value ) \
  938. ( (int *) ( pt ) )[pointmarkindex] = value
  939. #define point2tri( pt ) ( (triangle *) ( pt ) )[point2triindex]
  940. #define setpoint2tri( pt, value ) \
  941. ( (triangle *) ( pt ) )[point2triindex] = value
  942. /** **/
  943. /** **/
  944. /********* Mesh manipulation primitives end here *********/
  945. /********* User interaction routines begin here *********/
  946. /** **/
  947. /** **/
  948. /*****************************************************************************/
  949. /* */
  950. /* syntax() Print list of command line switches. */
  951. /* */
  952. /*****************************************************************************/
  953. #ifndef TRILIBRARY
  954. void syntax(){
  955. #ifdef CDT_ONLY
  956. #ifdef REDUCED
  957. printf( "triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n" );
  958. #else /* not REDUCED */
  959. printf( "triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n" );
  960. #endif /* not REDUCED */
  961. #else /* not CDT_ONLY */
  962. #ifdef REDUCED
  963. printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n" );
  964. #else /* not REDUCED */
  965. printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n" );
  966. #endif /* not REDUCED */
  967. #endif /* not CDT_ONLY */
  968. printf( " -p Triangulates a Planar Straight Line Graph (.poly file).\n" );
  969. #ifndef CDT_ONLY
  970. printf( " -r Refines a previously generated mesh.\n" );
  971. printf(
  972. " -q Quality mesh generation. A minimum angle may be specified.\n" );
  973. printf( " -a Applies a maximum triangle area constraint.\n" );
  974. #endif /* not CDT_ONLY */
  975. printf(
  976. " -A Applies attributes to identify elements in certain regions.\n" );
  977. printf( " -c Encloses the convex hull with segments.\n" );
  978. printf( " -e Generates an edge list.\n" );
  979. printf( " -v Generates a Voronoi diagram.\n" );
  980. printf( " -n Generates a list of triangle neighbors.\n" );
  981. printf( " -g Generates an .off file for Geomview.\n" );
  982. printf( " -B Suppresses output of boundary information.\n" );
  983. printf( " -P Suppresses output of .poly file.\n" );
  984. printf( " -N Suppresses output of .node file.\n" );
  985. printf( " -E Suppresses output of .ele file.\n" );
  986. printf( " -I Suppresses mesh iteration numbers.\n" );
  987. printf( " -O Ignores holes in .poly file.\n" );
  988. printf( " -X Suppresses use of exact arithmetic.\n" );
  989. printf( " -z Numbers all items starting from zero (rather than one).\n" );
  990. printf( " -o2 Generates second-order subparametric elements.\n" );
  991. #ifndef CDT_ONLY
  992. printf( " -Y Suppresses boundary segment splitting.\n" );
  993. printf( " -S Specifies maximum number of added Steiner points.\n" );
  994. #endif /* not CDT_ONLY */
  995. #ifndef REDUCED
  996. printf( " -i Uses incremental method, rather than divide-and-conquer.\n" );
  997. printf( " -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n" );
  998. #endif /* not REDUCED */
  999. printf( " -l Uses vertical cuts only, rather than alternating cuts.\n" );
  1000. #ifndef REDUCED
  1001. #ifndef CDT_ONLY
  1002. printf(
  1003. " -s Force segments into mesh by splitting (instead of using CDT).\n" );
  1004. #endif /* not CDT_ONLY */
  1005. printf( " -C Check consistency of final mesh.\n" );
  1006. #endif /* not REDUCED */
  1007. printf( " -Q Quiet: No terminal output except errors.\n" );
  1008. printf( " -V Verbose: Detailed information on what I'm doing.\n" );
  1009. printf( " -h Help: Detailed instructions for Triangle.\n" );
  1010. exit( 0 );
  1011. }
  1012. #endif /* not TRILIBRARY */
  1013. /*****************************************************************************/
  1014. /* */
  1015. /* info() Print out complete instructions. */
  1016. /* */
  1017. /*****************************************************************************/
  1018. #ifndef TRILIBRARY
  1019. void info(){
  1020. printf( "Triangle\n" );
  1021. printf(
  1022. "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n" );
  1023. printf( "Version 1.3\n\n" );
  1024. printf(
  1025. "Copyright 1996 Jonathan Richard Shewchuk (bugs/comments to jrs@cs.cmu.edu)\n"
  1026. );
  1027. printf( "School of Computer Science / Carnegie Mellon University\n" );
  1028. printf( "5000 Forbes Avenue / Pittsburgh, Pennsylvania 15213-3891\n" );
  1029. printf(
  1030. "Created as part of the Archimedes project (tools for parallel FEM).\n" );
  1031. printf(
  1032. "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n" );
  1033. printf( "There is no warranty whatsoever. Use at your own risk.\n" );
  1034. #ifdef SINGLE
  1035. printf( "This executable is compiled for single precision arithmetic.\n\n\n" );
  1036. #else /* not SINGLE */
  1037. printf( "This executable is compiled for double precision arithmetic.\n\n\n" );
  1038. #endif /* not SINGLE */
  1039. printf(
  1040. "Triangle generates exact Delaunay triangulations, constrained Delaunay\n" );
  1041. printf(
  1042. "triangulations, and quality conforming Delaunay triangulations. The latter\n"
  1043. );
  1044. printf(
  1045. "can be generated with no small angles, and are thus suitable for finite\n" );
  1046. printf(
  1047. "element analysis. If no command line switches are specified, your .node\n" );
  1048. printf(
  1049. "input file will be read, and the Delaunay triangulation will be returned in\n"
  1050. );
  1051. printf( ".node and .ele output files. The command syntax is:\n\n" );
  1052. #ifdef CDT_ONLY
  1053. #ifdef REDUCED
  1054. printf( "triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n\n" );
  1055. #else /* not REDUCED */
  1056. printf( "triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n\n" );
  1057. #endif /* not REDUCED */
  1058. #else /* not CDT_ONLY */
  1059. #ifdef REDUCED
  1060. printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n\n" );
  1061. #else /* not REDUCED */
  1062. printf( "triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n" );
  1063. #endif /* not REDUCED */
  1064. #endif /* not CDT_ONLY */
  1065. printf(
  1066. "Underscores indicate that numbers may optionally follow certain switches;\n" );
  1067. printf(
  1068. "do not leave any space between a switch and its numeric parameter.\n" );
  1069. printf(
  1070. "input_file must be a file with extension .node, or extension .poly if the\n" );
  1071. printf(
  1072. "-p switch is used. If -r is used, you must supply .node and .ele files,\n" );
  1073. printf(
  1074. "and possibly a .poly file and .area file as well. The formats of these\n" );
  1075. printf( "files are described below.\n\n" );
  1076. printf( "Command Line Switches:\n\n" );
  1077. printf(
  1078. " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
  1079. );
  1080. printf(
  1081. " points, segments, holes, and regional attributes and area\n" );
  1082. printf(
  1083. " constraints. Will generate a constrained Delaunay triangulation\n" );
  1084. printf(
  1085. " fitting the input; or, if -s, -q, or -a is used, a conforming\n" );
  1086. printf(
  1087. " Delaunay triangulation. If -p is not used, Triangle reads a .node\n"
  1088. );
  1089. printf( " file by default.\n" );
  1090. printf(
  1091. " -r Refines a previously generated mesh. The mesh is read from a .node\n"
  1092. );
  1093. printf(
  1094. " file and an .ele file. If -p is also used, a .poly file is read\n" );
  1095. printf(
  1096. " and used to constrain edges in the mesh. Further details on\n" );
  1097. printf( " refinement are given below.\n" );
  1098. printf(
  1099. " -q Quality mesh generation by Jim Ruppert's Delaunay refinement\n" );
  1100. printf(
  1101. " algorithm. Adds points to the mesh to ensure that no angles\n" );
  1102. printf(
  1103. " smaller than 20 degrees occur. An alternative minimum angle may be\n"
  1104. );
  1105. printf(
  1106. " specified after the `q'. If the minimum angle is 20.7 degrees or\n" );
  1107. printf(
  1108. " smaller, the triangulation algorithm is theoretically guaranteed to\n"
  1109. );
  1110. printf(
  1111. " terminate (assuming infinite precision arithmetic - Triangle may\n" );
  1112. printf(
  1113. " fail to terminate if you run out of precision). In practice, the\n" );
  1114. printf(
  1115. " algorithm often succeeds for minimum angles up to 33.8 degrees.\n" );
  1116. printf(
  1117. " For highly refined meshes, however, it may be necessary to reduce\n" );
  1118. printf(
  1119. " the minimum angle to well below 20 to avoid problems associated\n" );
  1120. printf(
  1121. " with insufficient floating-point precision. The specified angle\n" );
  1122. printf( " may include a decimal point.\n" );
  1123. printf(
  1124. " -a Imposes a maximum triangle area. If a number follows the `a', no\n" );
  1125. printf(
  1126. " triangle will be generated whose area is larger than that number.\n" );
  1127. printf(
  1128. " If no number is specified, an .area file (if -r is used) or .poly\n" );
  1129. printf(
  1130. " file (if -r is not used) specifies a number of maximum area\n" );
  1131. printf(
  1132. " constraints. An .area file contains a separate area constraint for\n"
  1133. );
  1134. printf(
  1135. " each triangle, and is useful for refining a finite element mesh\n" );
  1136. printf(
  1137. " based on a posteriori error estimates. A .poly file can optionally\n"
  1138. );
  1139. printf(
  1140. " contain an area constraint for each segment-bounded region, thereby\n"
  1141. );
  1142. printf(
  1143. " enforcing triangle densities in a first triangulation. You can\n" );
  1144. printf(
  1145. " impose both a fixed area constraint and a varying area constraint\n" );
  1146. printf(
  1147. " by invoking the -a switch twice, once with and once without a\n" );
  1148. printf(
  1149. " number following. Each area specified may include a decimal point.\n"
  1150. );
  1151. printf(
  1152. " -A Assigns an additional attribute to each triangle that identifies\n" );
  1153. printf(
  1154. " what segment-bounded region each triangle belongs to. Attributes\n" );
  1155. printf(
  1156. " are assigned to regions by the .poly file. If a region is not\n" );
  1157. printf(
  1158. " explicitly marked by the .poly file, triangles in that region are\n" );
  1159. printf(
  1160. " assigned an attribute of zero. The -A switch has an effect only\n" );
  1161. printf( " when the -p switch is used and the -r switch is not.\n" );
  1162. printf(
  1163. " -c Creates segments on the convex hull of the triangulation. If you\n" );
  1164. printf(
  1165. " are triangulating a point set, this switch causes a .poly file to\n" );
  1166. printf(
  1167. " be written, containing all edges in the convex hull. (By default,\n"
  1168. );
  1169. printf(
  1170. " a .poly file is written only if a .poly file is read.) If you are\n"
  1171. );
  1172. printf(
  1173. " triangulating a PSLG, this switch specifies that the interior of\n" );
  1174. printf(
  1175. " the convex hull of the PSLG should be triangulated. If you do not\n"
  1176. );
  1177. printf(
  1178. " use this switch when triangulating a PSLG, it is assumed that you\n" );
  1179. printf(
  1180. " have identified the region to be triangulated by surrounding it\n" );
  1181. printf(
  1182. " with segments of the input PSLG. Beware: if you are not careful,\n"
  1183. );
  1184. printf(
  1185. " this switch can cause the introduction of an extremely thin angle\n" );
  1186. printf(
  1187. " between a PSLG segment and a convex hull segment, which can cause\n" );
  1188. printf(
  1189. " overrefinement or failure if Triangle runs out of precision. If\n" );
  1190. printf(
  1191. " you are refining a mesh, the -c switch works differently; it\n" );
  1192. printf(
  1193. " generates the set of boundary edges of the mesh, rather than the\n" );
  1194. printf( " convex hull.\n" );
  1195. printf(
  1196. " -e Outputs (to an .edge file) a list of edges of the triangulation.\n" );
  1197. printf(
  1198. " -v Outputs the Voronoi diagram associated with the triangulation.\n" );
  1199. printf( " Does not attempt to detect degeneracies.\n" );
  1200. printf(
  1201. " -n Outputs (to a .neigh file) a list of triangles neighboring each\n" );
  1202. printf( " triangle.\n" );
  1203. printf(
  1204. " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
  1205. );
  1206. printf( " viewing with the Geometry Center's Geomview package.\n" );
  1207. printf(
  1208. " -B No boundary markers in the output .node, .poly, and .edge output\n" );
  1209. printf(
  1210. " files. See the detailed discussion of boundary markers below.\n" );
  1211. printf(
  1212. " -P No output .poly file. Saves disk space, but you lose the ability\n" );
  1213. printf(
  1214. " to impose segment constraints on later refinements of the mesh.\n" );
  1215. printf( " -N No output .node file.\n" );
  1216. printf( " -E No output .ele file.\n" );
  1217. printf(
  1218. " -I No iteration numbers. Suppresses the output of .node and .poly\n" );
  1219. printf(
  1220. " files, so your input files won't be overwritten. (If your input is\n"
  1221. );
  1222. printf(
  1223. " a .poly file only, a .node file will be written.) Cannot be used\n" );
  1224. printf(
  1225. " with the -r switch, because that would overwrite your input .ele\n" );
  1226. printf(
  1227. " file. Shouldn't be used with the -s, -q, or -a switch if you are\n" );
  1228. printf(
  1229. " using a .node file for input, because no .node file will be\n" );
  1230. printf( " written, so there will be no record of any added points.\n" );
  1231. printf( " -O No holes. Ignores the holes in the .poly file.\n" );
  1232. printf(
  1233. " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
  1234. );
  1235. printf(
  1236. " arithmetic for certain tests if it thinks the inexact tests are not\n"
  1237. );
  1238. printf(
  1239. " accurate enough. Exact arithmetic ensures the robustness of the\n" );
  1240. printf(
  1241. " triangulation algorithms, despite floating-point roundoff error.\n" );
  1242. printf(
  1243. " Disabling exact arithmetic with the -X switch will cause a small\n" );
  1244. printf(
  1245. " improvement in speed and create the possibility (albeit small) that\n"
  1246. );
  1247. printf(
  1248. " Triangle will fail to produce a valid mesh. Not recommended.\n" );
  1249. printf(
  1250. " -z Numbers all items starting from zero (rather than one). Note that\n"
  1251. );
  1252. printf(
  1253. " this switch is normally overrided by the value used to number the\n" );
  1254. printf(
  1255. " first point of the input .node or .poly file. However, this switch\n"
  1256. );
  1257. printf( " is useful when calling Triangle from another program.\n" );
  1258. printf(
  1259. " -o2 Generates second-order subparametric elements with six nodes each.\n"
  1260. );
  1261. printf(
  1262. " -Y No new points on the boundary. This switch is useful when the mesh\n"
  1263. );
  1264. printf(
  1265. " boundary must be preserved so that it conforms to some adjacent\n" );
  1266. printf(
  1267. " mesh. Be forewarned that you will probably sacrifice some of the\n" );
  1268. printf(
  1269. " quality of the mesh; Triangle will try, but the resulting mesh may\n"
  1270. );
  1271. printf(
  1272. " contain triangles of poor aspect ratio. Works well if all the\n" );
  1273. printf(
  1274. " boundary points are closely spaced. Specify this switch twice\n" );
  1275. printf(
  1276. " (`-YY') to prevent all segment splitting, including internal\n" );
  1277. printf( " boundaries.\n" );
  1278. printf(
  1279. " -S Specifies the maximum number of Steiner points (points that are not\n"
  1280. );
  1281. printf(
  1282. " in the input, but are added to meet the constraints of minimum\n" );
  1283. printf(
  1284. " angle and maximum area). The default is to allow an unlimited\n" );
  1285. printf(
  1286. " number. If you specify this switch with no number after it,\n" );
  1287. printf(
  1288. " the limit is set to zero. Triangle always adds points at segment\n" );
  1289. printf(
  1290. " intersections, even if it needs to use more points than the limit\n" );
  1291. printf(
  1292. " you set. When Triangle inserts segments by splitting (-s), it\n" );
  1293. printf(
  1294. " always adds enough points to ensure that all the segments appear in\n"
  1295. );
  1296. printf(
  1297. " the triangulation, again ignoring the limit. Be forewarned that\n" );
  1298. printf(
  1299. " the -S switch may result in a conforming triangulation that is not\n"
  1300. );
  1301. printf(
  1302. " truly Delaunay, because Triangle may be forced to stop adding\n" );
  1303. printf(
  1304. " points when the mesh is in a state where a segment is non-Delaunay\n"
  1305. );
  1306. printf(
  1307. " and needs to be split. If so, Triangle will print a warning.\n" );
  1308. printf(
  1309. " -i Uses an incremental rather than divide-and-conquer algorithm to\n" );
  1310. printf(
  1311. " form a Delaunay triangulation. Try it if the divide-and-conquer\n" );
  1312. printf( " algorithm fails.\n" );
  1313. printf(
  1314. " -F Uses Steven Fortune's sweepline algorithm to form a Delaunay\n" );
  1315. printf(
  1316. " triangulation. Warning: does not use exact arithmetic for all\n" );
  1317. printf( " calculations. An exact result is not guaranteed.\n" );
  1318. printf(
  1319. " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n" );
  1320. printf(
  1321. " default, Triangle uses alternating vertical and horizontal cuts,\n" );
  1322. printf(
  1323. " which usually improve the speed except with point sets that are\n" );
  1324. printf(
  1325. " small or short and wide. This switch is primarily of theoretical\n" );
  1326. printf( " interest.\n" );
  1327. printf(
  1328. " -s Specifies that segments should be forced into the triangulation by\n"
  1329. );
  1330. printf(
  1331. " recursively splitting them at their midpoints, rather than by\n" );
  1332. printf(
  1333. " generating a constrained Delaunay triangulation. Segment splitting\n"
  1334. );
  1335. printf(
  1336. " is true to Ruppert's original algorithm, but can create needlessly\n"
  1337. );
  1338. printf( " small triangles near external small features.\n" );
  1339. printf(
  1340. " -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
  1341. );
  1342. printf(
  1343. " checking, even if the -X switch is used. Useful if you suspect\n" );
  1344. printf( " Triangle is buggy.\n" );
  1345. printf(
  1346. " -Q Quiet: Suppresses all explanation of what Triangle is doing, unless\n"
  1347. );
  1348. printf( " an error occurs.\n" );
  1349. printf(
  1350. " -V Verbose: Gives detailed information about what Triangle is doing.\n" );
  1351. printf(
  1352. " Add more `V's for increasing amount of detail. `-V' gives\n" );
  1353. printf(
  1354. " information on algorithmic progress and more detailed statistics.\n" );
  1355. printf(
  1356. " `-VV' gives point-by-point details, and will print so much that\n" );
  1357. printf(
  1358. " Triangle will run much more slowly. `-VVV' gives information only\n"
  1359. );
  1360. printf( " a debugger could love.\n" );
  1361. printf( " -h Help: Displays these instructions.\n" );
  1362. printf( "\n" );
  1363. printf( "Definitions:\n" );
  1364. printf( "\n" );
  1365. printf(
  1366. " A Delaunay triangulation of a point set is a triangulation whose vertices\n"
  1367. );
  1368. printf(
  1369. " are the point set, having the property that no point in the point set\n" );
  1370. printf(
  1371. " falls in the interior of the circumcircle (circle that passes through all\n"
  1372. );
  1373. printf( " three vertices) of any triangle in the triangulation.\n\n" );
  1374. printf(
  1375. " A Voronoi diagram of a point set is a subdivision of the plane into\n" );
  1376. printf(
  1377. " polygonal regions (some of which may be infinite), where each region is\n" );
  1378. printf(
  1379. " the set of points in the plane that are closer to some input point than\n" );
  1380. printf(
  1381. " to any other input point. (The Voronoi diagram is the geometric dual of\n"
  1382. );
  1383. printf( " the Delaunay triangulation.)\n\n" );
  1384. printf(
  1385. " A Planar Straight Line Graph (PSLG) is a collection of points and\n" );
  1386. printf(
  1387. " segments. Segments are simply edges, whose endpoints are points in the\n" );
  1388. printf(
  1389. " PSLG. The file format for PSLGs (.poly files) is described below.\n" );
  1390. printf( "\n" );
  1391. printf(
  1392. " A constrained Delaunay triangulation of a PSLG is similar to a Delaunay\n" );
  1393. printf(
  1394. " triangulation, but each PSLG segment is present as a single edge in the\n" );
  1395. printf(
  1396. " triangulation. (A constrained Delaunay triangulation is not truly a\n" );
  1397. printf( " Delaunay triangulation.)\n\n" );
  1398. printf(
  1399. " A conforming Delaunay triangulation of a PSLG is a true Delaunay\n" );
  1400. printf(
  1401. " triangulation in which each PSLG segment may have been subdivided into\n" );
  1402. printf(
  1403. " several edges by the insertion of additional points. These inserted\n" );
  1404. printf(
  1405. " points are necessary to allow the segments to exist in the mesh while\n" );
  1406. printf( " maintaining the Delaunay property.\n\n" );
  1407. printf( "File Formats:\n\n" );
  1408. printf(
  1409. " All files may contain comments prefixed by the character '#'. Points,\n" );
  1410. printf(
  1411. " triangles, edges, holes, and maximum area constraints must be numbered\n" );
  1412. printf(
  1413. " consecutively, starting from either 1 or 0. Whichever you choose, all\n" );
  1414. printf(
  1415. " input files must be consistent; if the nodes are numbered from 1, so must\n"
  1416. );
  1417. printf(
  1418. " be all other objects. Triangle automatically detects your choice while\n" );
  1419. printf(
  1420. " reading the .node (or .poly) file. (When calling Triangle from another\n" );
  1421. printf(
  1422. " program, use the -z switch if you wish to number objects from zero.)\n" );
  1423. printf( " Examples of these file formats are given below.\n\n" );
  1424. printf( " .node files:\n" );
  1425. printf(
  1426. " First line: <# of points> <dimension (must be 2)> <# of attributes>\n" );
  1427. printf(
  1428. " <# of boundary markers (0 or 1)>\n"
  1429. );
  1430. printf(
  1431. " Remaining lines: <point #> <x> <y> [attributes] [boundary marker]\n" );
  1432. printf( "\n" );
  1433. printf(
  1434. " The attributes, which are typically floating-point values of physical\n" );
  1435. printf(
  1436. " quantities (such as mass or conductivity) associated with the nodes of\n"
  1437. );
  1438. printf(
  1439. " a finite element mesh, are copied unchanged to the output mesh. If -s,\n"
  1440. );
  1441. printf(
  1442. " -q, or -a is selected, each new Steiner point added to the mesh will\n" );
  1443. printf( " have attributes assigned to it by linear interpolation.\n\n" );
  1444. printf(
  1445. " If the fourth entry of the first line is `1', the last column of the\n" );
  1446. printf(
  1447. " remainder of the file is assumed to contain boundary markers. Boundary\n"
  1448. );
  1449. printf(
  1450. " markers are used to identify boundary points and points resting on PSLG\n"
  1451. );
  1452. printf(
  1453. " segments; a complete description appears in a section below. The .node\n"
  1454. );
  1455. printf(
  1456. " file produced by Triangle will contain boundary markers in the last\n" );
  1457. printf( " column unless they are suppressed by the -B switch.\n\n" );
  1458. printf( " .ele files:\n" );
  1459. printf(
  1460. " First line: <# of triangles> <points per triangle> <# of attributes>\n" );
  1461. printf(
  1462. " Remaining lines: <triangle #> <point> <point> <point> ... [attributes]\n"
  1463. );
  1464. printf( "\n" );
  1465. printf(
  1466. " Points are indices into the corresponding .node file. The first three\n"
  1467. );
  1468. printf(
  1469. " points are the corners, and are listed in counterclockwise order around\n"
  1470. );
  1471. printf(
  1472. " each triangle. (The remaining points, if any, depend on the type of\n" );
  1473. printf(
  1474. " finite element used.) The attributes are just like those of .node\n" );
  1475. printf(
  1476. " files. Because there is no simple mapping from input to output\n" );
  1477. printf(
  1478. " triangles, an attempt is made to interpolate attributes, which may\n" );
  1479. printf(
  1480. " result in a good deal of diffusion of attributes among nearby triangles\n"
  1481. );
  1482. printf(
  1483. " as the triangulation is refined. Diffusion does not occur across\n" );
  1484. printf(
  1485. " segments, so attributes used to identify segment-bounded regions remain\n"
  1486. );
  1487. printf(
  1488. " intact. In output .ele files, all triangles have three points each\n" );
  1489. printf(
  1490. " unless the -o2 switch is used, in which case they have six, and the\n" );
  1491. printf(
  1492. " fourth, fifth, and sixth points lie on the midpoints of the edges\n" );
  1493. printf( " opposite the first, second, and third corners.\n\n" );
  1494. printf( " .poly files:\n" );
  1495. printf(
  1496. " First line: <# of points> <dimension (must be 2)> <# of attributes>\n" );
  1497. printf(
  1498. " <# of boundary markers (0 or 1)>\n"
  1499. );
  1500. printf(
  1501. " Following lines: <point #> <x> <y> [attributes] [boundary marker]\n" );
  1502. printf( " One line: <# of segments> <# of boundary markers (0 or 1)>\n" );
  1503. printf(
  1504. " Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n" );
  1505. printf( " One line: <# of holes>\n" );
  1506. printf( " Following lines: <hole #> <x> <y>\n" );
  1507. printf(
  1508. " Optional line: <# of regional attributes and/or area constraints>\n" );
  1509. printf(
  1510. " Optional following lines: <constraint #> <x> <y> <attrib> <max area>\n" );
  1511. printf( "\n" );
  1512. printf(
  1513. " A .poly file represents a PSLG, as well as some additional information.\n"
  1514. );
  1515. printf(
  1516. " The first section lists all the points, and is identical to the format\n"
  1517. );
  1518. printf(
  1519. " of .node files. <# of points> may be set to zero to indicate that the\n"
  1520. );
  1521. printf(
  1522. " points are listed in a separate .node file; .poly files produced by\n" );
  1523. printf(
  1524. " Triangle always have this format. This has the advantage that a point\n"
  1525. );
  1526. printf(
  1527. " set may easily be triangulated with or without segments. (The same\n" );
  1528. printf(
  1529. " effect can be achieved, albeit using more disk space, by making a copy\n"
  1530. );
  1531. printf(
  1532. " of the .poly file with the extension .node; all sections of the file\n" );
  1533. printf( " but the first are ignored.)\n\n" );
  1534. printf(
  1535. " The second section lists the segments. Segments are edges whose\n" );
  1536. printf(
  1537. " presence in the triangulation is enforced. Each segment is specified\n" );
  1538. printf(
  1539. " by listing the indices of its two endpoints. This means that you must\n"
  1540. );
  1541. printf(
  1542. " include its endpoints in the point list. If -s, -q, and -a are not\n" );
  1543. printf(
  1544. " selected, Triangle will produce a constrained Delaunay triangulation,\n" );
  1545. printf(
  1546. " in which each segment appears as a single edge in the triangulation.\n" );
  1547. printf(
  1548. " If -q or -a is selected, Triangle will produce a conforming Delaunay\n" );
  1549. printf(
  1550. " triangulation, in which segments may be subdivided into smaller edges.\n"
  1551. );
  1552. printf( " Each segment, like each point, may have a boundary marker.\n\n" );
  1553. printf(
  1554. " The third section lists holes (and concavities, if -c is selected) in\n" );
  1555. printf(
  1556. " the triangulation. Holes are specified by identifying a point inside\n" );
  1557. printf(
  1558. " each hole. After the triangulation is formed, Triangle creates holes\n" );
  1559. printf(
  1560. " by eating triangles, spreading out from each hole point until its\n" );
  1561. printf(
  1562. " progress is blocked by PSLG segments; you must be careful to enclose\n" );
  1563. printf(
  1564. " each hole in segments, or your whole triangulation may be eaten away.\n" );
  1565. printf(
  1566. " If the two triangles abutting a segment are eaten, the segment itself\n" );
  1567. printf(
  1568. " is also eaten. Do not place a hole directly on a segment; if you do,\n" );
  1569. printf( " Triangle will choose one side of the segment arbitrarily.\n\n" );
  1570. printf(
  1571. " The optional fourth section lists regional attributes (to be assigned\n" );
  1572. printf(
  1573. " to all triangles in a region) and regional constraints on the maximum\n" );
  1574. printf(
  1575. " triangle area. Triangle will read this section only if the -A switch\n" );
  1576. printf(
  1577. " is used or the -a switch is used without a number following it, and the\n"
  1578. );
  1579. printf(
  1580. " -r switch is not used. Regional attributes and area constraints are\n" );
  1581. printf(
  1582. " propagated in the same manner as holes; you specify a point for each\n" );
  1583. printf(
  1584. " attribute and/or constraint, and the attribute and/or constraint will\n" );
  1585. printf(
  1586. " affect the whole region (bounded by segments) containing the point. If\n"
  1587. );
  1588. printf(
  1589. " two values are written on a line after the x and y coordinate, the\n" );
  1590. printf(
  1591. " former is assumed to be a regional attribute (but will only be applied\n"
  1592. );
  1593. printf(
  1594. " if the -A switch is selected), and the latter is assumed to be a\n" );
  1595. printf(
  1596. " regional area constraint (but will only be applied if the -a switch is\n"
  1597. );
  1598. printf(
  1599. " selected). You may also specify just one value after the coordinates,\n"
  1600. );
  1601. printf(
  1602. " which can serve as both an attribute and an area constraint, depending\n"
  1603. );
  1604. printf(
  1605. " on the choice of switches. If you are using the -A and -a switches\n" );
  1606. printf(
  1607. " simultaneously and wish to assign an attribute to some region without\n" );
  1608. printf( " imposing an area constraint, use a negative maximum area.\n\n" );
  1609. printf(
  1610. " When a triangulation is created from a .poly file, you must either\n" );
  1611. printf(
  1612. " enclose the entire region to be triangulated in PSLG segments, or\n" );
  1613. printf(
  1614. " use the -c switch, which encloses the convex hull of the input point\n" );
  1615. printf(
  1616. " set. If you do not use the -c switch, Triangle will eat all triangles\n"
  1617. );
  1618. printf(
  1619. " on the outer boundary that are not protected by segments; if you are\n" );
  1620. printf(
  1621. " not careful, your whole triangulation may be eaten away. If you do\n" );
  1622. printf(
  1623. " use the -c switch, you can still produce concavities by appropriate\n" );
  1624. printf( " placement of holes just inside the convex hull.\n\n" );
  1625. printf(
  1626. " An ideal PSLG has no intersecting segments, nor any points that lie\n" );
  1627. printf(
  1628. " upon segments (except, of course, the endpoints of each segment.) You\n"
  1629. );
  1630. printf(
  1631. " aren't required to make your .poly files ideal, but you should be aware\n"
  1632. );
  1633. printf(
  1634. " of what can go wrong. Segment intersections are relatively safe -\n" );
  1635. printf(
  1636. " Triangle will calculate the intersection points for you and add them to\n"
  1637. );
  1638. printf(
  1639. " the triangulation - as long as your machine's floating-point precision\n"
  1640. );
  1641. printf(
  1642. " doesn't become a problem. You are tempting the fates if you have three\n"
  1643. );
  1644. printf(
  1645. " segments that cross at the same location, and expect Triangle to figure\n"
  1646. );
  1647. printf(
  1648. " out where the intersection point is. Thanks to floating-point roundoff\n"
  1649. );
  1650. printf(
  1651. " error, Triangle will probably decide that the three segments intersect\n"
  1652. );
  1653. printf(
  1654. " at three different points, and you will find a minuscule triangle in\n" );
  1655. printf(
  1656. " your output - unless Triangle tries to refine the tiny triangle, uses\n" );
  1657. printf(
  1658. " up the last bit of machine precision, and fails to terminate at all.\n" );
  1659. printf(
  1660. " You're better off putting the intersection point in the input files,\n" );
  1661. printf(
  1662. " and manually breaking up each segment into two. Similarly, if you\n" );
  1663. printf(
  1664. " place a point at the middle of a segment, and hope that Triangle will\n" );
  1665. printf(
  1666. " break up the segment at that point, you might get lucky. On the other\n"
  1667. );
  1668. printf(
  1669. " hand, Triangle might decide that the point doesn't lie precisely on the\n"
  1670. );
  1671. printf(
  1672. " line, and you'll have a needle-sharp triangle in your output - or a lot\n"
  1673. );
  1674. printf( " of tiny triangles if you're generating a quality mesh.\n\n" );
  1675. printf(
  1676. " When Triangle reads a .poly file, it also writes a .poly file, which\n" );
  1677. printf(
  1678. " includes all edges that are part of input segments. If the -c switch\n" );
  1679. printf(
  1680. " is used, the output .poly file will also include all of the edges on\n" );
  1681. printf(
  1682. " the convex hull. Hence, the output .poly file is useful for finding\n" );
  1683. printf(
  1684. " edges associated with input segments and setting boundary conditions in\n"
  1685. );
  1686. printf(
  1687. " finite element simulations. More importantly, you will need it if you\n"
  1688. );
  1689. printf(
  1690. " plan to refine the output mesh, and don't want segments to be missing\n" );
  1691. printf( " in later triangulations.\n\n" );
  1692. printf( " .area files:\n" );
  1693. printf( " First line: <# of triangles>\n" );
  1694. printf( " Following lines: <triangle #> <maximum area>\n\n" );
  1695. printf(
  1696. " An .area file associates with each triangle a maximum area that is used\n"
  1697. );
  1698. printf(
  1699. " for mesh refinement. As with other file formats, every triangle must\n" );
  1700. printf(
  1701. " be represented, and they must be numbered consecutively. A triangle\n" );
  1702. printf(
  1703. " may be left unconstrained by assigning it a negative maximum area.\n" );
  1704. printf( "\n" );
  1705. printf( " .edge files:\n" );
  1706. printf( " First line: <# of edges> <# of boundary markers (0 or 1)>\n" );
  1707. printf(
  1708. " Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n" );
  1709. printf( "\n" );
  1710. printf(
  1711. " Endpoints are indices into the corresponding .node file. Triangle can\n"
  1712. );
  1713. printf(
  1714. " produce .edge files (use the -e switch), but cannot read them. The\n" );
  1715. printf(
  1716. " optional column of boundary markers is suppressed by the -B switch.\n" );
  1717. printf( "\n" );
  1718. printf(
  1719. " In Voronoi diagrams, one also finds a special kind of edge that is an\n" );
  1720. printf(
  1721. " infinite ray with only one endpoint. For these edges, a different\n" );
  1722. printf( " format is used:\n\n" );
  1723. printf( " <edge #> <endpoint> -1 <direction x> <direction y>\n\n" );
  1724. printf(
  1725. " The `direction' is a floating-point vector that indicates the direction\n"
  1726. );
  1727. printf( " of the infinite ray.\n\n" );
  1728. printf( " .neigh files:\n" );
  1729. printf(
  1730. " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
  1731. );
  1732. printf(
  1733. " Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n" );
  1734. printf( "\n" );
  1735. printf(
  1736. " Neighbors are indices into the corresponding .ele file. An index of -1\n"
  1737. );
  1738. printf(
  1739. " indicates a mesh boundary, and therefore no neighbor. Triangle can\n" );
  1740. printf(
  1741. " produce .neigh files (use the -n switch), but cannot read them.\n" );
  1742. printf( "\n" );
  1743. printf(
  1744. " The first neighbor of triangle i is opposite the first corner of\n" );
  1745. printf( " triangle i, and so on.\n\n" );
  1746. printf( "Boundary Markers:\n\n" );
  1747. printf(
  1748. " Boundary markers are tags used mainly to identify which output points and\n"
  1749. );
  1750. printf(
  1751. " edges are associated with which PSLG segment, and to identify which\n" );
  1752. printf(
  1753. " points and edges occur on a boundary of the triangulation. A common use\n"
  1754. );
  1755. printf(
  1756. " is to determine where boundary conditions should be applied to a finite\n" );
  1757. printf(
  1758. " element mesh. You can prevent boundary markers from being written into\n" );
  1759. printf( " files produced by Triangle by using the -B switch.\n\n" );
  1760. printf(
  1761. " The boundary marker associated with each segment in an output .poly file\n"
  1762. );
  1763. printf( " or edge in an output .edge file is chosen as follows:\n" );
  1764. printf(
  1765. " - If an output edge is part or all of a PSLG segment with a nonzero\n" );
  1766. printf(
  1767. " boundary marker, then the edge is assigned the same marker.\n" );
  1768. printf(
  1769. " - Otherwise, if the edge occurs on a boundary of the triangulation\n" );
  1770. printf(
  1771. " (including boundaries of holes), then the edge is assigned the marker\n"
  1772. );
  1773. printf( " one (1).\n" );
  1774. printf( " - Otherwise, the edge is assigned the marker zero (0).\n" );
  1775. printf(
  1776. " The boundary marker associated with each point in an output .node file is\n"
  1777. );
  1778. printf( " chosen as follows:\n" );
  1779. printf(
  1780. " - If a point is assigned a nonzero boundary marker in the input file,\n" );
  1781. printf(
  1782. " then it is assigned the same marker in the output .node file.\n" );
  1783. printf(
  1784. " - Otherwise, if the point lies on a PSLG segment (including the\n" );
  1785. printf(
  1786. " segment's endpoints) with a nonzero boundary marker, then the point\n" );
  1787. printf(
  1788. " is assigned the same marker. If the point lies on several such\n" );
  1789. printf( " segments, one of the markers is chosen arbitrarily.\n" );
  1790. printf(
  1791. " - Otherwise, if the point occurs on a boundary of the triangulation,\n" );
  1792. printf( " then the point is assigned the marker one (1).\n" );
  1793. printf( " - Otherwise, the point is assigned the marker zero (0).\n" );
  1794. printf( "\n" );
  1795. printf(
  1796. " If you want Triangle to determine for you which points and edges are on\n" );
  1797. printf(
  1798. " the boundary, assign them the boundary marker zero (or use no markers at\n"
  1799. );
  1800. printf(
  1801. " all) in your input files. Alternatively, you can mark some of them and\n" );
  1802. printf( " leave others marked zero, allowing Triangle to label them.\n\n" );
  1803. printf( "Triangulation Iteration Numbers:\n\n" );
  1804. printf(
  1805. " Because Triangle can read and refine its own triangulations, input\n" );
  1806. printf(
  1807. " and output files have iteration numbers. For instance, Triangle might\n" );
  1808. printf(
  1809. " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n" );
  1810. printf(
  1811. " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n" );
  1812. printf( " mesh.4.poly. Files with no iteration number are treated as if\n" );
  1813. printf(
  1814. " their iteration number is zero; hence, Triangle might read the file\n" );
  1815. printf(
  1816. " points.node, triangulate it, and produce the files points.1.node and\n" );
  1817. printf( " points.1.ele.\n\n" );
  1818. printf(
  1819. " Iteration numbers allow you to create a sequence of successively finer\n" );
  1820. printf(
  1821. " meshes suitable for multigrid methods. They also allow you to produce a\n"
  1822. );
  1823. printf(
  1824. " sequence of meshes using error estimate-driven mesh refinement.\n" );
  1825. printf( "\n" );
  1826. printf(
  1827. " If you're not using refinement or quality meshing, and you don't like\n" );
  1828. printf(
  1829. " iteration numbers, use the -I switch to disable them. This switch will\n" );
  1830. printf(
  1831. " also disable output of .node and .poly files to prevent your input files\n"
  1832. );
  1833. printf(
  1834. " from being overwritten. (If the input is a .poly file that contains its\n"
  1835. );
  1836. printf( " own points, a .node file will be written.)\n\n" );
  1837. printf( "Examples of How to Use Triangle:\n\n" );
  1838. printf(
  1839. " `triangle dots' will read points from dots.node, and write their Delaunay\n"
  1840. );
  1841. printf(
  1842. " triangulation to dots.1.node and dots.1.ele. (dots.1.node will be\n" );
  1843. printf(
  1844. " identical to dots.node.) `triangle -I dots' writes the triangulation to\n"
  1845. );
  1846. printf(
  1847. " dots.ele instead. (No additional .node file is needed, so none is\n" );
  1848. printf( " written.)\n\n" );
  1849. printf(
  1850. " `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly\n"
  1851. );
  1852. printf(
  1853. " object.1.node, if the points are omitted from object.1.poly) and write\n" );
  1854. printf( " their constrained Delaunay triangulation to object.2.node and\n" );
  1855. printf(
  1856. " object.2.ele. The segments will be copied to object.2.poly, and all\n" );
  1857. printf( " edges will be written to object.2.edge.\n\n" );
  1858. printf(
  1859. " `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and\n" );
  1860. printf(
  1861. " possibly object.node), generate a mesh whose angles are all greater than\n"
  1862. );
  1863. printf(
  1864. " 31.5 degrees and whose triangles all have area smaller than 0.1, and\n" );
  1865. printf(
  1866. " write the mesh to object.1.node and object.1.ele. Each segment may have\n"
  1867. );
  1868. printf(
  1869. " been broken up into multiple edges; the resulting constrained edges are\n" );
  1870. printf( " written to object.1.poly.\n\n" );
  1871. printf(
  1872. " Here is a sample file `box.poly' describing a square with a square hole:\n"
  1873. );
  1874. printf( "\n" );
  1875. printf(
  1876. " # A box with eight points in 2D, no attributes, one boundary marker.\n" );
  1877. printf( " 8 2 0 1\n" );
  1878. printf( " # Outer box has these vertices:\n" );
  1879. printf( " 1 0 0 0\n" );
  1880. printf( " 2 0 3 0\n" );
  1881. printf( " 3 3 0 0\n" );
  1882. printf( " 4 3 3 33 # A special marker for this point.\n" );
  1883. printf( " # Inner square has these vertices:\n" );
  1884. printf( " 5 1 1 0\n" );
  1885. printf( " 6 1 2 0\n" );
  1886. printf( " 7 2 1 0\n" );
  1887. printf( " 8 2 2 0\n" );
  1888. printf( " # Five segments with boundary markers.\n" );
  1889. printf( " 5 1\n" );
  1890. printf( " 1 1 2 5 # Left side of outer box.\n" );
  1891. printf( " 2 5 7 0 # Segments 2 through 5 enclose the hole.\n" );
  1892. printf( " 3 7 8 0\n" );
  1893. printf( " 4 8 6 10\n" );
  1894. printf( " 5 6 5 0\n" );
  1895. printf( " # One hole in the middle of the inner square.\n" );
  1896. printf( " 1\n" );
  1897. printf( " 1 1.5 1.5\n\n" );
  1898. printf(
  1899. " Note that some segments are missing from the outer square, so one must\n" );
  1900. printf(
  1901. " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
  1902. );
  1903. printf(
  1904. " file `box.1.node', with twelve points. The last four points were added\n" );
  1905. printf(
  1906. " to meet the angle constraint. Points 1, 2, and 9 have markers from\n" );
  1907. printf(
  1908. " segment 1. Points 6 and 8 have markers from segment 4. All the other\n" );
  1909. printf(
  1910. " points but 4 have been marked to indicate that they lie on a boundary.\n" );
  1911. printf( "\n" );
  1912. printf( " 12 2 0 1\n" );
  1913. printf( " 1 0 0 5\n" );
  1914. printf( " 2 0 3 5\n" );
  1915. printf( " 3 3 0 1\n" );
  1916. printf( " 4 3 3 33\n" );
  1917. printf( " 5 1 1 1\n" );
  1918. printf( " 6 1 2 10\n" );
  1919. printf( " 7 2 1 1\n" );
  1920. printf( " 8 2 2 10\n" );
  1921. printf( " 9 0 1.5 5\n" );
  1922. printf( " 10 1.5 0 1\n" );
  1923. printf( " 11 3 1.5 1\n" );
  1924. printf( " 12 1.5 3 1\n" );
  1925. printf( " # Generated by triangle -pqc box.poly\n\n" );
  1926. printf( " Here is the output file `box.1.ele', with twelve triangles.\n\n" );
  1927. printf( " 12 3 0\n" );
  1928. printf( " 1 5 6 9\n" );
  1929. printf( " 2 10 3 7\n" );
  1930. printf( " 3 6 8 12\n" );
  1931. printf( " 4 9 1 5\n" );
  1932. printf( " 5 6 2 9\n" );
  1933. printf( " 6 7 3 11\n" );
  1934. printf( " 7 11 4 8\n" );
  1935. printf( " 8 7 5 10\n" );
  1936. printf( " 9 12 2 6\n" );
  1937. printf( " 10 8 7 11\n" );
  1938. printf( " 11 5 1 10\n" );
  1939. printf( " 12 8 4 12\n" );
  1940. printf( " # Generated by triangle -pqc box.poly\n\n" );
  1941. printf(
  1942. " Here is the output file `box.1.poly'. Note that segments have been added\n"
  1943. );
  1944. printf(
  1945. " to represent the convex hull, and some segments have been split by newly\n"
  1946. );
  1947. printf(
  1948. " added points. Note also that <# of points> is set to zero to indicate\n" );
  1949. printf( " that the points should be read from the .node file.\n\n" );
  1950. printf( " 0 2 0 1\n" );
  1951. printf( " 12 1\n" );
  1952. printf( " 1 1 9 5\n" );
  1953. printf( " 2 5 7 1\n" );
  1954. printf( " 3 8 7 1\n" );
  1955. printf( " 4 6 8 10\n" );
  1956. printf( " 5 5 6 1\n" );
  1957. printf( " 6 3 10 1\n" );
  1958. printf( " 7 4 11 1\n" );
  1959. printf( " 8 2 12 1\n" );
  1960. printf( " 9 9 2 5\n" );
  1961. printf( " 10 10 1 1\n" );
  1962. printf( " 11 11 3 1\n" );
  1963. printf( " 12 12 4 1\n" );
  1964. printf( " 1\n" );
  1965. printf( " 1 1.5 1.5\n" );
  1966. printf( " # Generated by triangle -pqc box.poly\n\n" );
  1967. printf( "Refinement and Area Constraints:\n\n" );
  1968. printf(
  1969. " The -r switch causes a mesh (.node and .ele files) to be read and\n" );
  1970. printf(
  1971. " refined. If the -p switch is also used, a .poly file is read and used to\n"
  1972. );
  1973. printf(
  1974. " specify edges that are constrained and cannot be eliminated (although\n" );
  1975. printf(
  1976. " they can be divided into smaller edges) by the refinement process.\n" );
  1977. printf( "\n" );
  1978. printf(
  1979. " When you refine a mesh, you generally want to impose tighter quality\n" );
  1980. printf(
  1981. " constraints. One way to accomplish this is to use -q with a larger\n" );
  1982. printf(
  1983. " angle, or -a followed by a smaller area than you used to generate the\n" );
  1984. printf(
  1985. " mesh you are refining. Another way to do this is to create an .area\n" );
  1986. printf(
  1987. " file, which specifies a maximum area for each triangle, and use the -a\n" );
  1988. printf(
  1989. " switch (without a number following). Each triangle's area constraint is\n"
  1990. );
  1991. printf(
  1992. " applied to that triangle. Area constraints tend to diffuse as the mesh\n" );
  1993. printf(
  1994. " is refined, so if there are large variations in area constraint between\n" );
  1995. printf( " adjacent triangles, you may not get the results you want.\n\n" );
  1996. printf(
  1997. " If you are refining a mesh composed of linear (three-node) elements, the\n"
  1998. );
  1999. printf(
  2000. " output mesh will contain all the nodes present in the input mesh, in the\n"
  2001. );
  2002. printf(
  2003. " same order, with new nodes added at the end of the .node file. However,\n"
  2004. );
  2005. printf(
  2006. " there is no guarantee that each output element is contained in a single\n" );
  2007. printf(
  2008. " input element. Often, output elements will overlap two input elements,\n" );
  2009. printf(
  2010. " and input edges are not present in the output mesh. Hence, a sequence of\n"
  2011. );
  2012. printf(
  2013. " refined meshes will form a hierarchy of nodes, but not a hierarchy of\n" );
  2014. printf(
  2015. " elements. If you a refining a mesh of higher-order elements, the\n" );
  2016. printf(
  2017. " hierarchical property applies only to the nodes at the corners of an\n" );
  2018. printf( " element; other nodes may not be present in the refined mesh.\n\n" );
  2019. printf(
  2020. " It is important to understand that maximum area constraints in .poly\n" );
  2021. printf(
  2022. " files are handled differently from those in .area files. A maximum area\n"
  2023. );
  2024. printf(
  2025. " in a .poly file applies to the whole (segment-bounded) region in which a\n"
  2026. );
  2027. printf(
  2028. " point falls, whereas a maximum area in an .area file applies to only one\n"
  2029. );
  2030. printf(
  2031. " triangle. Area constraints in .poly files are used only when a mesh is\n" );
  2032. printf(
  2033. " first generated, whereas area constraints in .area files are used only to\n"
  2034. );
  2035. printf(
  2036. " refine an existing mesh, and are typically based on a posteriori error\n" );
  2037. printf(
  2038. " estimates resulting from a finite element simulation on that mesh.\n" );
  2039. printf( "\n" );
  2040. printf(
  2041. " `triangle -rq25 object.1' will read object.1.node and object.1.ele, then\n"
  2042. );
  2043. printf(
  2044. " refine the triangulation to enforce a 25 degree minimum angle, and then\n" );
  2045. printf(
  2046. " write the refined triangulation to object.2.node and object.2.ele.\n" );
  2047. printf( "\n" );
  2048. printf(
  2049. " `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and\n" );
  2050. printf(
  2051. " z.3.area. After reconstructing the mesh and its segments, Triangle will\n"
  2052. );
  2053. printf(
  2054. " refine the mesh so that no triangle has area greater than 6.2, and\n" );
  2055. printf(
  2056. " furthermore the triangles satisfy the maximum area constraints in\n" );
  2057. printf(
  2058. " z.3.area. The output is written to z.4.node, z.4.ele, and z.4.poly.\n" );
  2059. printf( "\n" );
  2060. printf(
  2061. " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n" );
  2062. printf(
  2063. " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n" );
  2064. printf( " suitable for multigrid.\n\n" );
  2065. printf( "Convex Hulls and Mesh Boundaries:\n\n" );
  2066. printf(
  2067. " If the input is a point set (rather than a PSLG), Triangle produces its\n" );
  2068. printf(
  2069. " convex hull as a by-product in the output .poly file if you use the -c\n" );
  2070. printf(
  2071. " switch. There are faster algorithms for finding a two-dimensional convex\n"
  2072. );
  2073. printf(
  2074. " hull than triangulation, of course, but this one comes for free. If the\n"
  2075. );
  2076. printf(
  2077. " input is an unconstrained mesh (you are using the -r switch but not the\n" );
  2078. printf(
  2079. " -p switch), Triangle produces a list of its boundary edges (including\n" );
  2080. printf( " hole boundaries) as a by-product if you use the -c switch.\n\n" );
  2081. printf( "Voronoi Diagrams:\n\n" );
  2082. printf(
  2083. " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n" );
  2084. printf(
  2085. " .v.edge. For example, `triangle -v points' will read points.node,\n" );
  2086. printf(
  2087. " produce its Delaunay triangulation in points.1.node and points.1.ele,\n" );
  2088. printf(
  2089. " and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.\n" );
  2090. printf(
  2091. " The .v.node file contains a list of all Voronoi vertices, and the .v.edge\n"
  2092. );
  2093. printf(
  2094. " file contains a list of all Voronoi edges, some of which may be infinite\n"
  2095. );
  2096. printf(
  2097. " rays. (The choice of filenames makes it easy to run the set of Voronoi\n" );
  2098. printf( " vertices through Triangle, if so desired.)\n\n" );
  2099. printf(
  2100. " This implementation does not use exact arithmetic to compute the Voronoi\n"
  2101. );
  2102. printf(
  2103. " vertices, and does not check whether neighboring vertices are identical.\n"
  2104. );
  2105. printf(
  2106. " Be forewarned that if the Delaunay triangulation is degenerate or\n" );
  2107. printf(
  2108. " near-degenerate, the Voronoi diagram may have duplicate points, crossing\n"
  2109. );
  2110. printf(
  2111. " edges, or infinite rays whose direction vector is zero. Also, if you\n" );
  2112. printf(
  2113. " generate a constrained (as opposed to conforming) Delaunay triangulation,\n"
  2114. );
  2115. printf(
  2116. " or if the triangulation has holes, the corresponding Voronoi diagram is\n" );
  2117. printf( " likely to have crossing edges and unlikely to make sense.\n\n" );
  2118. printf( "Mesh Topology:\n\n" );
  2119. printf(
  2120. " You may wish to know which triangles are adjacent to a certain Delaunay\n" );
  2121. printf(
  2122. " edge in an .edge file, which Voronoi regions are adjacent to a certain\n" );
  2123. printf(
  2124. " Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n"
  2125. );
  2126. printf(
  2127. " each other. All of this information can be found by cross-referencing\n" );
  2128. printf(
  2129. " output files with the recollection that the Delaunay triangulation and\n" );
  2130. printf( " the Voronoi diagrams are planar duals.\n\n" );
  2131. printf(
  2132. " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n" );
  2133. printf(
  2134. " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n" );
  2135. printf(
  2136. " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n" );
  2137. printf(
  2138. " vertex j of the corresponding .v.node file; and Voronoi region k is the\n" );
  2139. printf( " dual of point k of the corresponding .node file.\n\n" );
  2140. printf(
  2141. " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n" );
  2142. printf(
  2143. " vertices of the corresponding Voronoi edge; their dual triangles are on\n" );
  2144. printf(
  2145. " the left and right of the Delaunay edge, respectively. To find the\n" );
  2146. printf(
  2147. " Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the\n"
  2148. );
  2149. printf(
  2150. " corresponding Delaunay edge; their dual regions are on the right and left\n"
  2151. );
  2152. printf(
  2153. " of the Voronoi edge, respectively. To find which Voronoi regions are\n" );
  2154. printf( " adjacent to each other, just read the list of Delaunay edges.\n" );
  2155. printf( "\n" );
  2156. printf( "Statistics:\n" );
  2157. printf( "\n" );
  2158. printf(
  2159. " After generating a mesh, Triangle prints a count of the number of points,\n"
  2160. );
  2161. printf(
  2162. " triangles, edges, boundary edges, and segments in the output mesh. If\n" );
  2163. printf(
  2164. " you've forgotten the statistics for an existing mesh, the -rNEP switches\n"
  2165. );
  2166. printf(
  2167. " (or -rpNEP if you've got a .poly file for the existing mesh) will\n" );
  2168. printf( " regenerate these statistics without writing any output.\n\n" );
  2169. printf(
  2170. " The -V switch produces extended statistics, including a rough estimate\n" );
  2171. printf(
  2172. " of memory use and a histogram of triangle aspect ratios and angles in the\n"
  2173. );
  2174. printf( " mesh.\n\n" );
  2175. printf( "Exact Arithmetic:\n\n" );
  2176. printf(
  2177. " Triangle uses adaptive exact arithmetic to perform what computational\n" );
  2178. printf(
  2179. " geometers call the `orientation' and `incircle' tests. If the floating-\n"
  2180. );
  2181. printf(
  2182. " point arithmetic of your machine conforms to the IEEE 754 standard (as\n" );
  2183. printf(
  2184. " most workstations do), and does not use extended precision internal\n" );
  2185. printf(
  2186. " registers, then your output is guaranteed to be an absolutely true\n" );
  2187. printf( " Delaunay or conforming Delaunay triangulation, roundoff error\n" );
  2188. printf(
  2189. " notwithstanding. The word `adaptive' implies that these arithmetic\n" );
  2190. printf(
  2191. " routines compute the result only to the precision necessary to guarantee\n"
  2192. );
  2193. printf(
  2194. " correctness, so they are usually nearly as fast as their approximate\n" );
  2195. printf(
  2196. " counterparts. The exact tests can be disabled with the -X switch. On\n" );
  2197. printf(
  2198. " most inputs, this switch will reduce the computation time by about eight\n"
  2199. );
  2200. printf(
  2201. " percent - it's not worth the risk. There are rare difficult inputs\n" );
  2202. printf(
  2203. " (having many collinear and cocircular points), however, for which the\n" );
  2204. printf(
  2205. " difference could be a factor of two. These are precisely the inputs most\n"
  2206. );
  2207. printf( " likely to cause errors if you use the -X switch.\n\n" );
  2208. printf(
  2209. " Unfortunately, these routines don't solve every numerical problem. Exact\n"
  2210. );
  2211. printf(
  2212. " arithmetic is not used to compute the positions of points, because the\n" );
  2213. printf(
  2214. " bit complexity of point coordinates would grow without bound. Hence,\n" );
  2215. printf(
  2216. " segment intersections aren't computed exactly; in very unusual cases,\n" );
  2217. printf(
  2218. " roundoff error in computing an intersection point might actually lead to\n"
  2219. );
  2220. printf(
  2221. " an inverted triangle and an invalid triangulation. (This is one reason\n" );
  2222. printf(
  2223. " to compute your own intersection points in your .poly files.) Similarly,\n"
  2224. );
  2225. printf(
  2226. " exact arithmetic is not used to compute the vertices of the Voronoi\n" );
  2227. printf( " diagram.\n\n" );
  2228. printf(
  2229. " Underflow and overflow can also cause difficulties; the exact arithmetic\n"
  2230. );
  2231. printf(
  2232. " routines do not ameliorate out-of-bounds exponents, which can arise\n" );
  2233. printf(
  2234. " during the orientation and incircle tests. As a rule of thumb, you\n" );
  2235. printf(
  2236. " should ensure that your input values are within a range such that their\n" );
  2237. printf(
  2238. " third powers can be taken without underflow or overflow. Underflow can\n" );
  2239. printf(
  2240. " silently prevent the tests from being performed exactly, while overflow\n" );
  2241. printf( " will typically cause a floating exception.\n\n" );
  2242. printf( "Calling Triangle from Another Program:\n\n" );
  2243. printf( " Read the file triangle.h for details.\n\n" );
  2244. printf( "Troubleshooting:\n\n" );
  2245. printf( " Please read this section before mailing me bugs.\n\n" );
  2246. printf( " `My output mesh has no triangles!'\n\n" );
  2247. printf(
  2248. " If you're using a PSLG, you've probably failed to specify a proper set\n"
  2249. );
  2250. printf(
  2251. " of bounding segments, or forgotten to use the -c switch. Or you may\n" );
  2252. printf(
  2253. " have placed a hole badly. To test these possibilities, try again with\n"
  2254. );
  2255. printf(
  2256. " the -c and -O switches. Alternatively, all your input points may be\n" );
  2257. printf(
  2258. " collinear, in which case you can hardly expect to triangulate them.\n" );
  2259. printf( "\n" );
  2260. printf( " `Triangle doesn't terminate, or just crashes.'\n" );
  2261. printf( "\n" );
  2262. printf(
  2263. " Bad things can happen when triangles get so small that the distance\n" );
  2264. printf(
  2265. " between their vertices isn't much larger than the precision of your\n" );
  2266. printf(
  2267. " machine's arithmetic. If you've compiled Triangle for single-precision\n"
  2268. );
  2269. printf(
  2270. " arithmetic, you might do better by recompiling it for double-precision.\n"
  2271. );
  2272. printf(
  2273. " Then again, you might just have to settle for more lenient constraints\n"
  2274. );
  2275. printf(
  2276. " on the minimum angle and the maximum area than you had planned.\n" );
  2277. printf( "\n" );
  2278. printf(
  2279. " You can minimize precision problems by ensuring that the origin lies\n" );
  2280. printf(
  2281. " inside your point set, or even inside the densest part of your\n" );
  2282. printf(
  2283. " mesh. On the other hand, if you're triangulating an object whose x\n" );
  2284. printf(
  2285. " coordinates all fall between 6247133 and 6247134, you're not leaving\n" );
  2286. printf( " much floating-point precision for Triangle to work with.\n\n" );
  2287. printf(
  2288. " Precision problems can occur covertly if the input PSLG contains two\n" );
  2289. printf(
  2290. " segments that meet (or intersect) at a very small angle, or if such an\n"
  2291. );
  2292. printf(
  2293. " angle is introduced by the -c switch, which may occur if a point lies\n" );
  2294. printf(
  2295. " ever-so-slightly inside the convex hull, and is connected by a PSLG\n" );
  2296. printf(
  2297. " segment to a point on the convex hull. If you don't realize that a\n" );
  2298. printf(
  2299. " small angle is being formed, you might never discover why Triangle is\n" );
  2300. printf(
  2301. " crashing. To check for this possibility, use the -S switch (with an\n" );
  2302. printf(
  2303. " appropriate limit on the number of Steiner points, found by trial-and-\n"
  2304. );
  2305. printf(
  2306. " error) to stop Triangle early, and view the output .poly file with\n" );
  2307. printf(
  2308. " Show Me (described below). Look carefully for small angles between\n" );
  2309. printf(
  2310. " segments; zoom in closely, as such segments might look like a single\n" );
  2311. printf( " segment from a distance.\n\n" );
  2312. printf(
  2313. " If some of the input values are too large, Triangle may suffer a\n" );
  2314. printf(
  2315. " floating exception due to overflow when attempting to perform an\n" );
  2316. printf(
  2317. " orientation or incircle test. (Read the section on exact arithmetic\n" );
  2318. printf(
  2319. " above.) Again, I recommend compiling Triangle for double (rather\n" );
  2320. printf( " than single) precision arithmetic.\n\n" );
  2321. printf(
  2322. " `The numbering of the output points doesn't match the input points.'\n" );
  2323. printf( "\n" );
  2324. printf(
  2325. " You may have eaten some of your input points with a hole, or by placing\n"
  2326. );
  2327. printf( " them outside the area enclosed by segments.\n\n" );
  2328. printf(
  2329. " `Triangle executes without incident, but when I look at the resulting\n" );
  2330. printf(
  2331. " mesh, it has overlapping triangles or other geometric inconsistencies.'\n" );
  2332. printf( "\n" );
  2333. printf(
  2334. " If you select the -X switch, Triangle's divide-and-conquer Delaunay\n" );
  2335. printf(
  2336. " triangulation algorithm occasionally makes mistakes due to floating-\n" );
  2337. printf(
  2338. " point roundoff error. Although these errors are rare, don't use the -X\n"
  2339. );
  2340. printf( " switch. If you still have problems, please report the bug.\n" );
  2341. printf( "\n" );
  2342. printf(
  2343. " Strange things can happen if you've taken liberties with your PSLG. Do\n" );
  2344. printf(
  2345. " you have a point lying in the middle of a segment? Triangle sometimes\n" );
  2346. printf(
  2347. " copes poorly with that sort of thing. Do you want to lay out a collinear\n"
  2348. );
  2349. printf(
  2350. " row of evenly spaced, segment-connected points? Have you simply defined\n"
  2351. );
  2352. printf(
  2353. " one long segment connecting the leftmost point to the rightmost point,\n" );
  2354. printf(
  2355. " and a bunch of points lying along it? This method occasionally works,\n" );
  2356. printf(
  2357. " especially with horizontal and vertical lines, but often it doesn't, and\n"
  2358. );
  2359. printf(
  2360. " you'll have to connect each adjacent pair of points with a separate\n" );
  2361. printf( " segment. If you don't like it, tough.\n\n" );
  2362. printf(
  2363. " Furthermore, if you have segments that intersect other than at their\n" );
  2364. printf(
  2365. " endpoints, try not to let the intersections fall extremely close to PSLG\n"
  2366. );
  2367. printf( " points or each other.\n\n" );
  2368. printf(
  2369. " If you have problems refining a triangulation not produced by Triangle:\n" );
  2370. printf(
  2371. " Are you sure the triangulation is geometrically valid? Is it formatted\n" );
  2372. printf(
  2373. " correctly for Triangle? Are the triangles all listed so the first three\n"
  2374. );
  2375. printf( " points are their corners in counterclockwise order?\n\n" );
  2376. printf( "Show Me:\n\n" );
  2377. printf(
  2378. " Triangle comes with a separate program named `Show Me', whose primary\n" );
  2379. printf(
  2380. " purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
  2381. );
  2382. printf(
  2383. " purpose is to check the validity of your input files, and do so more\n" );
  2384. printf(
  2385. " thoroughly than Triangle does. Show Me requires that you have the X\n" );
  2386. printf(
  2387. " Windows system. If you didn't receive Show Me with Triangle, complain to\n"
  2388. );
  2389. printf( " whomever you obtained Triangle from, then send me mail.\n\n" );
  2390. printf( "Triangle on the Web:\n\n" );
  2391. printf(
  2392. " To see an illustrated, updated version of these instructions, check out\n" );
  2393. printf( "\n" );
  2394. printf( " http://www.cs.cmu.edu/~quake/triangle.html\n" );
  2395. printf( "\n" );
  2396. printf( "A Brief Plea:\n" );
  2397. printf( "\n" );
  2398. printf(
  2399. " If you use Triangle, and especially if you use it to accomplish real\n" );
  2400. printf(
  2401. " work, I would like very much to hear from you. A short letter or email\n" );
  2402. printf(
  2403. " (to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to\n" );
  2404. printf(
  2405. " me. The more people I know are using this program, the more easily I can\n"
  2406. );
  2407. printf(
  2408. " justify spending time on improvements and on the three-dimensional\n" );
  2409. printf(
  2410. " successor to Triangle, which in turn will benefit you. Also, I can put\n" );
  2411. printf(
  2412. " you on a list to receive email whenever a new version of Triangle is\n" );
  2413. printf( " available.\n\n" );
  2414. printf(
  2415. " If you use a mesh generated by Triangle in a publication, please include\n"
  2416. );
  2417. printf( " an acknowledgment as well.\n\n" );
  2418. printf( "Research credit:\n\n" );
  2419. printf(
  2420. " Of course, I can take credit for only a fraction of the ideas that made\n" );
  2421. printf(
  2422. " this mesh generator possible. Triangle owes its existence to the efforts\n"
  2423. );
  2424. printf(
  2425. " of many fine computational geometers and other researchers, including\n" );
  2426. printf(
  2427. " Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n" );
  2428. printf(
  2429. " Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n" );
  2430. printf(
  2431. " Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n" );
  2432. printf(
  2433. " Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher\n"
  2434. );
  2435. printf(
  2436. " J. Van Wyk, David F. Watson, and Binhai Zhu. See the comments at the\n" );
  2437. printf( " beginning of the source code for references.\n\n" );
  2438. exit( 0 );
  2439. }
  2440. #endif /* not TRILIBRARY */
  2441. /*****************************************************************************/
  2442. /* */
  2443. /* internalerror() Ask the user to send me the defective product. Exit. */
  2444. /* */
  2445. /*****************************************************************************/
  2446. void internalerror(){
  2447. printf( " Please report this bug to jrs@cs.cmu.edu\n" );
  2448. printf( " Include the message above, your input data set, and the exact\n" );
  2449. printf( " command line you used to run Triangle.\n" );
  2450. exit( 1 );
  2451. }
  2452. /*****************************************************************************/
  2453. /* */
  2454. /* parsecommandline() Read the command line, identify switches, and set */
  2455. /* up options and file names. */
  2456. /* */
  2457. /* The effects of this routine are felt entirely through global variables. */
  2458. /* */
  2459. /*****************************************************************************/
  2460. void parsecommandline( argc, argv )
  2461. int argc;
  2462. char **argv;
  2463. {
  2464. #ifdef TRILIBRARY
  2465. #define STARTINDEX 0
  2466. #else /* not TRILIBRARY */
  2467. #define STARTINDEX 1
  2468. int increment;
  2469. int meshnumber;
  2470. #endif /* not TRILIBRARY */
  2471. int i, j;
  2472. #ifndef CDT_ONLY
  2473. int k;
  2474. char workstring[FILENAMESIZE];
  2475. #endif
  2476. poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0;
  2477. firstnumber = 1;
  2478. edgesout = voronoi = neighbors = geomview = 0;
  2479. nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0;
  2480. noholes = noexact = 0;
  2481. incremental = sweepline = 0;
  2482. dwyer = 1;
  2483. splitseg = 0;
  2484. docheck = 0;
  2485. nobisect = 0;
  2486. steiner = -1;
  2487. order = 1;
  2488. minangle = 0.0;
  2489. maxarea = -1.0;
  2490. quiet = verbose = 0;
  2491. #ifndef TRILIBRARY
  2492. innodefilename[0] = '\0';
  2493. #endif /* not TRILIBRARY */
  2494. for ( i = STARTINDEX; i < argc; i++ ) {
  2495. #ifndef TRILIBRARY
  2496. if ( argv[i][0] == '-' ) {
  2497. #endif /* not TRILIBRARY */
  2498. for ( j = STARTINDEX; argv[i][j] != '\0'; j++ ) {
  2499. if ( argv[i][j] == 'p' ) {
  2500. poly = 1;
  2501. }
  2502. #ifndef CDT_ONLY
  2503. if ( argv[i][j] == 'r' ) {
  2504. refine = 1;
  2505. }
  2506. if ( argv[i][j] == 'q' ) {
  2507. quality = 1;
  2508. if ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) ||
  2509. ( argv[i][j + 1] == '.' ) ) {
  2510. k = 0;
  2511. while ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) ||
  2512. ( argv[i][j + 1] == '.' ) ) {
  2513. j++;
  2514. workstring[k] = argv[i][j];
  2515. k++;
  2516. }
  2517. workstring[k] = '\0';
  2518. minangle = (REAL) strtod( workstring, (char **) NULL );
  2519. }
  2520. else {
  2521. minangle = 20.0;
  2522. }
  2523. }
  2524. if ( argv[i][j] == 'a' ) {
  2525. quality = 1;
  2526. if ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) ||
  2527. ( argv[i][j + 1] == '.' ) ) {
  2528. fixedarea = 1;
  2529. k = 0;
  2530. while ( ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) ||
  2531. ( argv[i][j + 1] == '.' ) ) {
  2532. j++;
  2533. workstring[k] = argv[i][j];
  2534. k++;
  2535. }
  2536. workstring[k] = '\0';
  2537. maxarea = (REAL) strtod( workstring, (char **) NULL );
  2538. if ( maxarea <= 0.0 ) {
  2539. printf( "Error: Maximum area must be greater than zero.\n" );
  2540. exit( 1 );
  2541. }
  2542. }
  2543. else {
  2544. vararea = 1;
  2545. }
  2546. }
  2547. #endif /* not CDT_ONLY */
  2548. if ( argv[i][j] == 'A' ) {
  2549. regionattrib = 1;
  2550. }
  2551. if ( argv[i][j] == 'c' ) {
  2552. convex = 1;
  2553. }
  2554. if ( argv[i][j] == 'z' ) {
  2555. firstnumber = 0;
  2556. }
  2557. if ( argv[i][j] == 'e' ) {
  2558. edgesout = 1;
  2559. }
  2560. if ( argv[i][j] == 'v' ) {
  2561. voronoi = 1;
  2562. }
  2563. if ( argv[i][j] == 'n' ) {
  2564. neighbors = 1;
  2565. }
  2566. if ( argv[i][j] == 'g' ) {
  2567. geomview = 1;
  2568. }
  2569. if ( argv[i][j] == 'B' ) {
  2570. nobound = 1;
  2571. }
  2572. if ( argv[i][j] == 'P' ) {
  2573. nopolywritten = 1;
  2574. }
  2575. if ( argv[i][j] == 'N' ) {
  2576. nonodewritten = 1;
  2577. }
  2578. if ( argv[i][j] == 'E' ) {
  2579. noelewritten = 1;
  2580. }
  2581. #ifndef TRILIBRARY
  2582. if ( argv[i][j] == 'I' ) {
  2583. noiterationnum = 1;
  2584. }
  2585. #endif /* not TRILIBRARY */
  2586. if ( argv[i][j] == 'O' ) {
  2587. noholes = 1;
  2588. }
  2589. if ( argv[i][j] == 'X' ) {
  2590. noexact = 1;
  2591. }
  2592. if ( argv[i][j] == 'o' ) {
  2593. if ( argv[i][j + 1] == '2' ) {
  2594. j++;
  2595. order = 2;
  2596. }
  2597. }
  2598. #ifndef CDT_ONLY
  2599. if ( argv[i][j] == 'Y' ) {
  2600. nobisect++;
  2601. }
  2602. if ( argv[i][j] == 'S' ) {
  2603. steiner = 0;
  2604. while ( ( argv[i][j + 1] >= '0' ) && ( argv[i][j + 1] <= '9' ) ) {
  2605. j++;
  2606. steiner = steiner * 10 + (int) ( argv[i][j] - '0' );
  2607. }
  2608. }
  2609. #endif /* not CDT_ONLY */
  2610. #ifndef REDUCED
  2611. if ( argv[i][j] == 'i' ) {
  2612. incremental = 1;
  2613. }
  2614. if ( argv[i][j] == 'F' ) {
  2615. sweepline = 1;
  2616. }
  2617. #endif /* not REDUCED */
  2618. if ( argv[i][j] == 'l' ) {
  2619. dwyer = 0;
  2620. }
  2621. #ifndef REDUCED
  2622. #ifndef CDT_ONLY
  2623. if ( argv[i][j] == 's' ) {
  2624. splitseg = 1;
  2625. }
  2626. #endif /* not CDT_ONLY */
  2627. if ( argv[i][j] == 'C' ) {
  2628. docheck = 1;
  2629. }
  2630. #endif /* not REDUCED */
  2631. if ( argv[i][j] == 'Q' ) {
  2632. quiet = 1;
  2633. }
  2634. if ( argv[i][j] == 'V' ) {
  2635. verbose++;
  2636. }
  2637. #ifndef TRILIBRARY
  2638. if ( ( argv[i][j] == 'h' ) || ( argv[i][j] == 'H' ) ||
  2639. ( argv[i][j] == '?' ) ) {
  2640. info();
  2641. }
  2642. #endif /* not TRILIBRARY */
  2643. }
  2644. #ifndef TRILIBRARY
  2645. } else {
  2646. strncpy( innodefilename, argv[i], FILENAMESIZE - 1 );
  2647. innodefilename[FILENAMESIZE - 1] = '\0';
  2648. }
  2649. #endif /* not TRILIBRARY */
  2650. }
  2651. #ifndef TRILIBRARY
  2652. if ( innodefilename[0] == '\0' ) {
  2653. syntax();
  2654. }
  2655. if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".node" ) ) {
  2656. innodefilename[strlen( innodefilename ) - 5] = '\0';
  2657. }
  2658. if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".poly" ) ) {
  2659. innodefilename[strlen( innodefilename ) - 5] = '\0';
  2660. poly = 1;
  2661. }
  2662. #ifndef CDT_ONLY
  2663. if ( !strcmp( &innodefilename[strlen( innodefilename ) - 4], ".ele" ) ) {
  2664. innodefilename[strlen( innodefilename ) - 4] = '\0';
  2665. refine = 1;
  2666. }
  2667. if ( !strcmp( &innodefilename[strlen( innodefilename ) - 5], ".area" ) ) {
  2668. innodefilename[strlen( innodefilename ) - 5] = '\0';
  2669. refine = 1;
  2670. quality = 1;
  2671. vararea = 1;
  2672. }
  2673. #endif /* not CDT_ONLY */
  2674. #endif /* not TRILIBRARY */
  2675. steinerleft = steiner;
  2676. useshelles = poly || refine || quality || convex;
  2677. goodangle = (REAL)cos( minangle * PI / 180.0 );
  2678. goodangle *= goodangle;
  2679. if ( refine && noiterationnum ) {
  2680. printf(
  2681. "Error: You cannot use the -I switch when refining a triangulation.\n" );
  2682. exit( 1 );
  2683. }
  2684. /* Be careful not to allocate space for element area constraints that */
  2685. /* will never be assigned any value (other than the default -1.0). */
  2686. if ( !refine && !poly ) {
  2687. vararea = 0;
  2688. }
  2689. /* Be careful not to add an extra attribute to each element unless the */
  2690. /* input supports it (PSLG in, but not refining a preexisting mesh). */
  2691. if ( refine || !poly ) {
  2692. regionattrib = 0;
  2693. }
  2694. #ifndef TRILIBRARY
  2695. strcpy( inpolyfilename, innodefilename );
  2696. strcpy( inelefilename, innodefilename );
  2697. strcpy( areafilename, innodefilename );
  2698. increment = 0;
  2699. strcpy( workstring, innodefilename );
  2700. j = 1;
  2701. while ( workstring[j] != '\0' ) {
  2702. if ( ( workstring[j] == '.' ) && ( workstring[j + 1] != '\0' ) ) {
  2703. increment = j + 1;
  2704. }
  2705. j++;
  2706. }
  2707. meshnumber = 0;
  2708. if ( increment > 0 ) {
  2709. j = increment;
  2710. do {
  2711. if ( ( workstring[j] >= '0' ) && ( workstring[j] <= '9' ) ) {
  2712. meshnumber = meshnumber * 10 + (int) ( workstring[j] - '0' );
  2713. }
  2714. else {
  2715. increment = 0;
  2716. }
  2717. j++;
  2718. } while ( workstring[j] != '\0' );
  2719. }
  2720. if ( noiterationnum ) {
  2721. strcpy( outnodefilename, innodefilename );
  2722. strcpy( outelefilename, innodefilename );
  2723. strcpy( edgefilename, innodefilename );
  2724. strcpy( vnodefilename, innodefilename );
  2725. strcpy( vedgefilename, innodefilename );
  2726. strcpy( neighborfilename, innodefilename );
  2727. strcpy( offfilename, innodefilename );
  2728. strcat( outnodefilename, ".node" );
  2729. strcat( outelefilename, ".ele" );
  2730. strcat( edgefilename, ".edge" );
  2731. strcat( vnodefilename, ".v.node" );
  2732. strcat( vedgefilename, ".v.edge" );
  2733. strcat( neighborfilename, ".neigh" );
  2734. strcat( offfilename, ".off" );
  2735. }
  2736. else if ( increment == 0 ) {
  2737. strcpy( outnodefilename, innodefilename );
  2738. strcpy( outpolyfilename, innodefilename );
  2739. strcpy( outelefilename, innodefilename );
  2740. strcpy( edgefilename, innodefilename );
  2741. strcpy( vnodefilename, innodefilename );
  2742. strcpy( vedgefilename, innodefilename );
  2743. strcpy( neighborfilename, innodefilename );
  2744. strcpy( offfilename, innodefilename );
  2745. strcat( outnodefilename, ".1.node" );
  2746. strcat( outpolyfilename, ".1.poly" );
  2747. strcat( outelefilename, ".1.ele" );
  2748. strcat( edgefilename, ".1.edge" );
  2749. strcat( vnodefilename, ".1.v.node" );
  2750. strcat( vedgefilename, ".1.v.edge" );
  2751. strcat( neighborfilename, ".1.neigh" );
  2752. strcat( offfilename, ".1.off" );
  2753. }
  2754. else {
  2755. workstring[increment] = '%';
  2756. workstring[increment + 1] = 'd';
  2757. workstring[increment + 2] = '\0';
  2758. sprintf( outnodefilename, workstring, meshnumber + 1 );
  2759. strcpy( outpolyfilename, outnodefilename );
  2760. strcpy( outelefilename, outnodefilename );
  2761. strcpy( edgefilename, outnodefilename );
  2762. strcpy( vnodefilename, outnodefilename );
  2763. strcpy( vedgefilename, outnodefilename );
  2764. strcpy( neighborfilename, outnodefilename );
  2765. strcpy( offfilename, outnodefilename );
  2766. strcat( outnodefilename, ".node" );
  2767. strcat( outpolyfilename, ".poly" );
  2768. strcat( outelefilename, ".ele" );
  2769. strcat( edgefilename, ".edge" );
  2770. strcat( vnodefilename, ".v.node" );
  2771. strcat( vedgefilename, ".v.edge" );
  2772. strcat( neighborfilename, ".neigh" );
  2773. strcat( offfilename, ".off" );
  2774. }
  2775. strcat( innodefilename, ".node" );
  2776. strcat( inpolyfilename, ".poly" );
  2777. strcat( inelefilename, ".ele" );
  2778. strcat( areafilename, ".area" );
  2779. #endif /* not TRILIBRARY */
  2780. }
  2781. /** **/
  2782. /** **/
  2783. /********* User interaction routines begin here *********/
  2784. /********* Debugging routines begin here *********/
  2785. /** **/
  2786. /** **/
  2787. /*****************************************************************************/
  2788. /* */
  2789. /* printtriangle() Print out the details of a triangle/edge handle. */
  2790. /* */
  2791. /* I originally wrote this procedure to simplify debugging; it can be */
  2792. /* called directly from the debugger, and presents information about a */
  2793. /* triangle/edge handle in digestible form. It's also used when the */
  2794. /* highest level of verbosity (`-VVV') is specified. */
  2795. /* */
  2796. /*****************************************************************************/
  2797. void printtriangle( t )
  2798. struct triedge *t;
  2799. {
  2800. struct triedge printtri;
  2801. struct edge printsh;
  2802. point printpoint;
  2803. printf( "triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
  2804. t->orient );
  2805. decode( t->tri[0], printtri );
  2806. if ( printtri.tri == dummytri ) {
  2807. printf( " [0] = Outer space\n" );
  2808. }
  2809. else {
  2810. printf( " [0] = x%lx %d\n", (unsigned long) printtri.tri,
  2811. printtri.orient );
  2812. }
  2813. decode( t->tri[1], printtri );
  2814. if ( printtri.tri == dummytri ) {
  2815. printf( " [1] = Outer space\n" );
  2816. }
  2817. else {
  2818. printf( " [1] = x%lx %d\n", (unsigned long) printtri.tri,
  2819. printtri.orient );
  2820. }
  2821. decode( t->tri[2], printtri );
  2822. if ( printtri.tri == dummytri ) {
  2823. printf( " [2] = Outer space\n" );
  2824. }
  2825. else {
  2826. printf( " [2] = x%lx %d\n", (unsigned long) printtri.tri,
  2827. printtri.orient );
  2828. }
  2829. org( *t, printpoint );
  2830. if ( printpoint == (point) NULL ) {
  2831. printf( " Origin[%d] = NULL\n", ( t->orient + 1 ) % 3 + 3 );
  2832. }
  2833. else{
  2834. printf( " Origin[%d] = x%lx (%.12g, %.12g)\n",
  2835. ( t->orient + 1 ) % 3 + 3, (unsigned long) printpoint,
  2836. printpoint[0], printpoint[1] );
  2837. }
  2838. dest( *t, printpoint );
  2839. if ( printpoint == (point) NULL ) {
  2840. printf( " Dest [%d] = NULL\n", ( t->orient + 2 ) % 3 + 3 );
  2841. }
  2842. else{
  2843. printf( " Dest [%d] = x%lx (%.12g, %.12g)\n",
  2844. ( t->orient + 2 ) % 3 + 3, (unsigned long) printpoint,
  2845. printpoint[0], printpoint[1] );
  2846. }
  2847. apex( *t, printpoint );
  2848. if ( printpoint == (point) NULL ) {
  2849. printf( " Apex [%d] = NULL\n", t->orient + 3 );
  2850. }
  2851. else{
  2852. printf( " Apex [%d] = x%lx (%.12g, %.12g)\n",
  2853. t->orient + 3, (unsigned long) printpoint,
  2854. printpoint[0], printpoint[1] );
  2855. }
  2856. if ( useshelles ) {
  2857. sdecode( t->tri[6], printsh );
  2858. if ( printsh.sh != dummysh ) {
  2859. printf( " [6] = x%lx %d\n", (unsigned long) printsh.sh,
  2860. printsh.shorient );
  2861. }
  2862. sdecode( t->tri[7], printsh );
  2863. if ( printsh.sh != dummysh ) {
  2864. printf( " [7] = x%lx %d\n", (unsigned long) printsh.sh,
  2865. printsh.shorient );
  2866. }
  2867. sdecode( t->tri[8], printsh );
  2868. if ( printsh.sh != dummysh ) {
  2869. printf( " [8] = x%lx %d\n", (unsigned long) printsh.sh,
  2870. printsh.shorient );
  2871. }
  2872. }
  2873. if ( vararea ) {
  2874. printf( " Area constraint: %.4g\n", areabound( *t ) );
  2875. }
  2876. }
  2877. /*****************************************************************************/
  2878. /* */
  2879. /* printshelle() Print out the details of a shell edge handle. */
  2880. /* */
  2881. /* I originally wrote this procedure to simplify debugging; it can be */
  2882. /* called directly from the debugger, and presents information about a */
  2883. /* shell edge handle in digestible form. It's also used when the highest */
  2884. /* level of verbosity (`-VVV') is specified. */
  2885. /* */
  2886. /*****************************************************************************/
  2887. void printshelle( s )
  2888. struct edge *s;
  2889. {
  2890. struct edge printsh;
  2891. struct triedge printtri;
  2892. point printpoint;
  2893. printf( "shell edge x%lx with orientation %d and mark %d:\n",
  2894. (unsigned long) s->sh, s->shorient, mark( *s ) );
  2895. sdecode( s->sh[0], printsh );
  2896. if ( printsh.sh == dummysh ) {
  2897. printf( " [0] = No shell\n" );
  2898. }
  2899. else {
  2900. printf( " [0] = x%lx %d\n", (unsigned long) printsh.sh,
  2901. printsh.shorient );
  2902. }
  2903. sdecode( s->sh[1], printsh );
  2904. if ( printsh.sh == dummysh ) {
  2905. printf( " [1] = No shell\n" );
  2906. }
  2907. else {
  2908. printf( " [1] = x%lx %d\n", (unsigned long) printsh.sh,
  2909. printsh.shorient );
  2910. }
  2911. sorg( *s, printpoint );
  2912. if ( printpoint == (point) NULL ) {
  2913. printf( " Origin[%d] = NULL\n", 2 + s->shorient );
  2914. }
  2915. else{
  2916. printf( " Origin[%d] = x%lx (%.12g, %.12g)\n",
  2917. 2 + s->shorient, (unsigned long) printpoint,
  2918. printpoint[0], printpoint[1] );
  2919. }
  2920. sdest( *s, printpoint );
  2921. if ( printpoint == (point) NULL ) {
  2922. printf( " Dest [%d] = NULL\n", 3 - s->shorient );
  2923. }
  2924. else{
  2925. printf( " Dest [%d] = x%lx (%.12g, %.12g)\n",
  2926. 3 - s->shorient, (unsigned long) printpoint,
  2927. printpoint[0], printpoint[1] );
  2928. }
  2929. decode( s->sh[4], printtri );
  2930. if ( printtri.tri == dummytri ) {
  2931. printf( " [4] = Outer space\n" );
  2932. }
  2933. else {
  2934. printf( " [4] = x%lx %d\n", (unsigned long) printtri.tri,
  2935. printtri.orient );
  2936. }
  2937. decode( s->sh[5], printtri );
  2938. if ( printtri.tri == dummytri ) {
  2939. printf( " [5] = Outer space\n" );
  2940. }
  2941. else {
  2942. printf( " [5] = x%lx %d\n", (unsigned long) printtri.tri,
  2943. printtri.orient );
  2944. }
  2945. }
  2946. /** **/
  2947. /** **/
  2948. /********* Debugging routines end here *********/
  2949. /********* Memory management routines begin here *********/
  2950. /** **/
  2951. /** **/
  2952. /*****************************************************************************/
  2953. /* */
  2954. /* poolinit() Initialize a pool of memory for allocation of items. */
  2955. /* */
  2956. /* This routine initializes the machinery for allocating items. A `pool' */
  2957. /* is created whose records have size at least `bytecount'. Items will be */
  2958. /* allocated in `itemcount'-item blocks. Each item is assumed to be a */
  2959. /* collection of words, and either pointers or floating-point values are */
  2960. /* assumed to be the "primary" word type. (The "primary" word type is used */
  2961. /* to determine alignment of items.) If `alignment' isn't zero, all items */
  2962. /* will be `alignment'-byte aligned in memory. `alignment' must be either */
  2963. /* a multiple or a factor of the primary word size; powers of two are safe. */
  2964. /* `alignment' is normally used to create a few unused bits at the bottom */
  2965. /* of each item's pointer, in which information may be stored. */
  2966. /* */
  2967. /* Don't change this routine unless you understand it. */
  2968. /* */
  2969. /*****************************************************************************/
  2970. void poolinit( pool, bytecount, itemcount, wtype, alignment )
  2971. struct memorypool *pool;
  2972. int bytecount;
  2973. int itemcount;
  2974. enum wordtype wtype;
  2975. int alignment;
  2976. {
  2977. int wordsize;
  2978. /* Initialize values in the pool. */
  2979. pool->itemwordtype = wtype;
  2980. wordsize = ( pool->itemwordtype == POINTER ) ? sizeof( VOID * ) : sizeof( REAL );
  2981. /* Find the proper alignment, which must be at least as large as: */
  2982. /* - The parameter `alignment'. */
  2983. /* - The primary word type, to avoid unaligned accesses. */
  2984. /* - sizeof(VOID *), so the stack of dead items can be maintained */
  2985. /* without unaligned accesses. */
  2986. if ( alignment > wordsize ) {
  2987. pool->alignbytes = alignment;
  2988. }
  2989. else {
  2990. pool->alignbytes = wordsize;
  2991. }
  2992. if ( sizeof( VOID * ) > pool->alignbytes ) {
  2993. pool->alignbytes = sizeof( VOID * );
  2994. }
  2995. pool->itemwords = ( ( bytecount + pool->alignbytes - 1 ) / pool->alignbytes )
  2996. * ( pool->alignbytes / wordsize );
  2997. pool->itembytes = pool->itemwords * wordsize;
  2998. pool->itemsperblock = itemcount;
  2999. /* Allocate a block of items. Space for `itemsperblock' items and one */
  3000. /* pointer (to point to the next block) are allocated, as well as space */
  3001. /* to ensure alignment of the items. */
  3002. pool->firstblock = (VOID **) malloc( pool->itemsperblock * pool->itembytes
  3003. + sizeof( VOID * ) + pool->alignbytes );
  3004. if ( pool->firstblock == (VOID **) NULL ) {
  3005. printf( "Error: Out of memory.\n" );
  3006. exit( 1 );
  3007. }
  3008. /* Set the next block pointer to NULL. */
  3009. *( pool->firstblock ) = (VOID *) NULL;
  3010. poolrestart( pool );
  3011. }
  3012. /*****************************************************************************/
  3013. /* */
  3014. /* poolrestart() Deallocate all items in a pool. */
  3015. /* */
  3016. /* The pool is returned to its starting state, except that no memory is */
  3017. /* freed to the operating system. Rather, the previously allocated blocks */
  3018. /* are ready to be reused. */
  3019. /* */
  3020. /*****************************************************************************/
  3021. void poolrestart( pool )
  3022. struct memorypool *pool;
  3023. {
  3024. unsigned long alignptr;
  3025. pool->items = 0;
  3026. pool->maxitems = 0;
  3027. /* Set the currently active block. */
  3028. pool->nowblock = pool->firstblock;
  3029. /* Find the first item in the pool. Increment by the size of (VOID *). */
  3030. alignptr = (unsigned long) ( pool->nowblock + 1 );
  3031. /* Align the item on an `alignbytes'-byte boundary. */
  3032. pool->nextitem = (VOID *)
  3033. ( alignptr + (unsigned long) pool->alignbytes
  3034. - ( alignptr % (unsigned long) pool->alignbytes ) );
  3035. /* There are lots of unallocated items left in this block. */
  3036. pool->unallocateditems = pool->itemsperblock;
  3037. /* The stack of deallocated items is empty. */
  3038. pool->deaditemstack = (VOID *) NULL;
  3039. }
  3040. /*****************************************************************************/
  3041. /* */
  3042. /* pooldeinit() Free to the operating system all memory taken by a pool. */
  3043. /* */
  3044. /*****************************************************************************/
  3045. void pooldeinit( pool )
  3046. struct memorypool *pool;
  3047. {
  3048. while ( pool->firstblock != (VOID **) NULL ) {
  3049. pool->nowblock = (VOID **) *( pool->firstblock );
  3050. free( pool->firstblock );
  3051. pool->firstblock = pool->nowblock;
  3052. }
  3053. }
  3054. /*****************************************************************************/
  3055. /* */
  3056. /* poolalloc() Allocate space for an item. */
  3057. /* */
  3058. /*****************************************************************************/
  3059. VOID *poolalloc( pool )
  3060. struct memorypool *pool;
  3061. {
  3062. VOID *newitem;
  3063. VOID **newblock;
  3064. unsigned long alignptr;
  3065. /* First check the linked list of dead items. If the list is not */
  3066. /* empty, allocate an item from the list rather than a fresh one. */
  3067. if ( pool->deaditemstack != (VOID *) NULL ) {
  3068. newitem = pool->deaditemstack; /* Take first item in list. */
  3069. pool->deaditemstack = *(VOID **) pool->deaditemstack;
  3070. }
  3071. else {
  3072. /* Check if there are any free items left in the current block. */
  3073. if ( pool->unallocateditems == 0 ) {
  3074. /* Check if another block must be allocated. */
  3075. if ( *( pool->nowblock ) == (VOID *) NULL ) {
  3076. /* Allocate a new block of items, pointed to by the previous block. */
  3077. newblock = (VOID **) malloc( pool->itemsperblock * pool->itembytes
  3078. + sizeof( VOID * ) + pool->alignbytes );
  3079. if ( newblock == (VOID **) NULL ) {
  3080. printf( "Error: Out of memory.\n" );
  3081. exit( 1 );
  3082. }
  3083. *( pool->nowblock ) = (VOID *) newblock;
  3084. /* The next block pointer is NULL. */
  3085. *newblock = (VOID *) NULL;
  3086. }
  3087. /* Move to the new block. */
  3088. pool->nowblock = (VOID **) *( pool->nowblock );
  3089. /* Find the first item in the block. */
  3090. /* Increment by the size of (VOID *). */
  3091. alignptr = (unsigned long) ( pool->nowblock + 1 );
  3092. /* Align the item on an `alignbytes'-byte boundary. */
  3093. pool->nextitem = (VOID *)
  3094. ( alignptr + (unsigned long) pool->alignbytes
  3095. - ( alignptr % (unsigned long) pool->alignbytes ) );
  3096. /* There are lots of unallocated items left in this block. */
  3097. pool->unallocateditems = pool->itemsperblock;
  3098. }
  3099. /* Allocate a new item. */
  3100. newitem = pool->nextitem;
  3101. /* Advance `nextitem' pointer to next free item in block. */
  3102. if ( pool->itemwordtype == POINTER ) {
  3103. pool->nextitem = (VOID *) ( (VOID **) pool->nextitem + pool->itemwords );
  3104. }
  3105. else {
  3106. pool->nextitem = (VOID *) ( (REAL *) pool->nextitem + pool->itemwords );
  3107. }
  3108. pool->unallocateditems--;
  3109. pool->maxitems++;
  3110. }
  3111. pool->items++;
  3112. return newitem;
  3113. }
  3114. /*****************************************************************************/
  3115. /* */
  3116. /* pooldealloc() Deallocate space for an item. */
  3117. /* */
  3118. /* The deallocated space is stored in a queue for later reuse. */
  3119. /* */
  3120. /*****************************************************************************/
  3121. void pooldealloc( pool, dyingitem )
  3122. struct memorypool *pool;
  3123. VOID *dyingitem;
  3124. {
  3125. /* Push freshly killed item onto stack. */
  3126. *( (VOID **) dyingitem ) = pool->deaditemstack;
  3127. pool->deaditemstack = dyingitem;
  3128. pool->items--;
  3129. }
  3130. /*****************************************************************************/
  3131. /* */
  3132. /* traversalinit() Prepare to traverse the entire list of items. */
  3133. /* */
  3134. /* This routine is used in conjunction with traverse(). */
  3135. /* */
  3136. /*****************************************************************************/
  3137. void traversalinit( pool )
  3138. struct memorypool *pool;
  3139. {
  3140. unsigned long alignptr;
  3141. /* Begin the traversal in the first block. */
  3142. pool->pathblock = pool->firstblock;
  3143. /* Find the first item in the block. Increment by the size of (VOID *). */
  3144. alignptr = (unsigned long) ( pool->pathblock + 1 );
  3145. /* Align with item on an `alignbytes'-byte boundary. */
  3146. pool->pathitem = (VOID *)
  3147. ( alignptr + (unsigned long) pool->alignbytes
  3148. - ( alignptr % (unsigned long) pool->alignbytes ) );
  3149. /* Set the number of items left in the current block. */
  3150. pool->pathitemsleft = pool->itemsperblock;
  3151. }
  3152. /*****************************************************************************/
  3153. /* */
  3154. /* traverse() Find the next item in the list. */
  3155. /* */
  3156. /* This routine is used in conjunction with traversalinit(). Be forewarned */
  3157. /* that this routine successively returns all items in the list, including */
  3158. /* deallocated ones on the deaditemqueue. It's up to you to figure out */
  3159. /* which ones are actually dead. Why? I don't want to allocate extra */
  3160. /* space just to demarcate dead items. It can usually be done more */
  3161. /* space-efficiently by a routine that knows something about the structure */
  3162. /* of the item. */
  3163. /* */
  3164. /*****************************************************************************/
  3165. VOID *traverse( pool )
  3166. struct memorypool *pool;
  3167. {
  3168. VOID *newitem;
  3169. unsigned long alignptr;
  3170. /* Stop upon exhausting the list of items. */
  3171. if ( pool->pathitem == pool->nextitem ) {
  3172. return (VOID *) NULL;
  3173. }
  3174. /* Check whether any untraversed items remain in the current block. */
  3175. if ( pool->pathitemsleft == 0 ) {
  3176. /* Find the next block. */
  3177. pool->pathblock = (VOID **) *( pool->pathblock );
  3178. /* Find the first item in the block. Increment by the size of (VOID *). */
  3179. alignptr = (unsigned long) ( pool->pathblock + 1 );
  3180. /* Align with item on an `alignbytes'-byte boundary. */
  3181. pool->pathitem = (VOID *)
  3182. ( alignptr + (unsigned long) pool->alignbytes
  3183. - ( alignptr % (unsigned long) pool->alignbytes ) );
  3184. /* Set the number of items left in the current block. */
  3185. pool->pathitemsleft = pool->itemsperblock;
  3186. }
  3187. newitem = pool->pathitem;
  3188. /* Find the next item in the block. */
  3189. if ( pool->itemwordtype == POINTER ) {
  3190. pool->pathitem = (VOID *) ( (VOID **) pool->pathitem + pool->itemwords );
  3191. }
  3192. else {
  3193. pool->pathitem = (VOID *) ( (REAL *) pool->pathitem + pool->itemwords );
  3194. }
  3195. pool->pathitemsleft--;
  3196. return newitem;
  3197. }
  3198. /*****************************************************************************/
  3199. /* */
  3200. /* dummyinit() Initialize the triangle that fills "outer space" and the */
  3201. /* omnipresent shell edge. */
  3202. /* */
  3203. /* The triangle that fills "outer space", called `dummytri', is pointed to */
  3204. /* by every triangle and shell edge on a boundary (be it outer or inner) of */
  3205. /* the triangulation. Also, `dummytri' points to one of the triangles on */
  3206. /* the convex hull (until the holes and concavities are carved), making it */
  3207. /* possible to find a starting triangle for point location. */
  3208. /* */
  3209. /* The omnipresent shell edge, `dummysh', is pointed to by every triangle */
  3210. /* or shell edge that doesn't have a full complement of real shell edges */
  3211. /* to point to. */
  3212. /* */
  3213. /*****************************************************************************/
  3214. void dummyinit( trianglewords, shellewords )
  3215. int trianglewords;
  3216. int shellewords;
  3217. {
  3218. unsigned long alignptr;
  3219. /* `triwords' and `shwords' are used by the mesh manipulation primitives */
  3220. /* to extract orientations of triangles and shell edges from pointers. */
  3221. triwords = trianglewords; /* Initialize `triwords' once and for all. */
  3222. shwords = shellewords; /* Initialize `shwords' once and for all. */
  3223. /* Set up `dummytri', the `triangle' that occupies "outer space". */
  3224. dummytribase = (triangle *) malloc( triwords * sizeof( triangle )
  3225. + triangles.alignbytes );
  3226. if ( dummytribase == (triangle *) NULL ) {
  3227. printf( "Error: Out of memory.\n" );
  3228. exit( 1 );
  3229. }
  3230. /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
  3231. alignptr = (unsigned long) dummytribase;
  3232. dummytri = (triangle *)
  3233. ( alignptr + (unsigned long) triangles.alignbytes
  3234. - ( alignptr % (unsigned long) triangles.alignbytes ) );
  3235. /* Initialize the three adjoining triangles to be "outer space". These */
  3236. /* will eventually be changed by various bonding operations, but their */
  3237. /* values don't really matter, as long as they can legally be */
  3238. /* dereferenced. */
  3239. dummytri[0] = (triangle) dummytri;
  3240. dummytri[1] = (triangle) dummytri;
  3241. dummytri[2] = (triangle) dummytri;
  3242. /* Three NULL vertex points. */
  3243. dummytri[3] = (triangle) NULL;
  3244. dummytri[4] = (triangle) NULL;
  3245. dummytri[5] = (triangle) NULL;
  3246. if ( useshelles ) {
  3247. /* Set up `dummysh', the omnipresent "shell edge" pointed to by any */
  3248. /* triangle side or shell edge end that isn't attached to a real shell */
  3249. /* edge. */
  3250. dummyshbase = (shelle *) malloc( shwords * sizeof( shelle )
  3251. + shelles.alignbytes );
  3252. if ( dummyshbase == (shelle *) NULL ) {
  3253. printf( "Error: Out of memory.\n" );
  3254. exit( 1 );
  3255. }
  3256. /* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */
  3257. alignptr = (unsigned long) dummyshbase;
  3258. dummysh = (shelle *)
  3259. ( alignptr + (unsigned long) shelles.alignbytes
  3260. - ( alignptr % (unsigned long) shelles.alignbytes ) );
  3261. /* Initialize the two adjoining shell edges to be the omnipresent shell */
  3262. /* edge. These will eventually be changed by various bonding */
  3263. /* operations, but their values don't really matter, as long as they */
  3264. /* can legally be dereferenced. */
  3265. dummysh[0] = (shelle) dummysh;
  3266. dummysh[1] = (shelle) dummysh;
  3267. /* Two NULL vertex points. */
  3268. dummysh[2] = (shelle) NULL;
  3269. dummysh[3] = (shelle) NULL;
  3270. /* Initialize the two adjoining triangles to be "outer space". */
  3271. dummysh[4] = (shelle) dummytri;
  3272. dummysh[5] = (shelle) dummytri;
  3273. /* Set the boundary marker to zero. */
  3274. *(int *) ( dummysh + 6 ) = 0;
  3275. /* Initialize the three adjoining shell edges of `dummytri' to be */
  3276. /* the omnipresent shell edge. */
  3277. dummytri[6] = (triangle) dummysh;
  3278. dummytri[7] = (triangle) dummysh;
  3279. dummytri[8] = (triangle) dummysh;
  3280. }
  3281. }
  3282. /*****************************************************************************/
  3283. /* */
  3284. /* initializepointpool() Calculate the size of the point data structure */
  3285. /* and initialize its memory pool. */
  3286. /* */
  3287. /* This routine also computes the `pointmarkindex' and `point2triindex' */
  3288. /* indices used to find values within each point. */
  3289. /* */
  3290. /*****************************************************************************/
  3291. void initializepointpool(){
  3292. int pointsize;
  3293. /* The index within each point at which the boundary marker is found. */
  3294. /* Ensure the point marker is aligned to a sizeof(int)-byte address. */
  3295. pointmarkindex = ( ( mesh_dim + nextras ) * sizeof( REAL ) + sizeof( int ) - 1 )
  3296. / sizeof( int );
  3297. pointsize = ( pointmarkindex + 1 ) * sizeof( int );
  3298. if ( poly ) {
  3299. /* The index within each point at which a triangle pointer is found. */
  3300. /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
  3301. point2triindex = ( pointsize + sizeof( triangle ) - 1 ) / sizeof( triangle );
  3302. pointsize = ( point2triindex + 1 ) * sizeof( triangle );
  3303. }
  3304. /* Initialize the pool of points. */
  3305. poolinit( &points, pointsize, POINTPERBLOCK,
  3306. ( sizeof( REAL ) >= sizeof( triangle ) ) ? FLOATINGPOINT : POINTER, 0 );
  3307. }
  3308. /*****************************************************************************/
  3309. /* */
  3310. /* initializetrisegpools() Calculate the sizes of the triangle and shell */
  3311. /* edge data structures and initialize their */
  3312. /* memory pools. */
  3313. /* */
  3314. /* This routine also computes the `highorderindex', `elemattribindex', and */
  3315. /* `areaboundindex' indices used to find values within each triangle. */
  3316. /* */
  3317. /*****************************************************************************/
  3318. void initializetrisegpools(){
  3319. int trisize;
  3320. /* The index within each triangle at which the extra nodes (above three) */
  3321. /* associated with high order elements are found. There are three */
  3322. /* pointers to other triangles, three pointers to corners, and possibly */
  3323. /* three pointers to shell edges before the extra nodes. */
  3324. highorderindex = 6 + ( useshelles * 3 );
  3325. /* The number of bytes occupied by a triangle. */
  3326. trisize = ( ( order + 1 ) * ( order + 2 ) / 2 + ( highorderindex - 3 ) ) *
  3327. sizeof( triangle );
  3328. /* The index within each triangle at which its attributes are found, */
  3329. /* where the index is measured in REALs. */
  3330. elemattribindex = ( trisize + sizeof( REAL ) - 1 ) / sizeof( REAL );
  3331. /* The index within each triangle at which the maximum area constraint */
  3332. /* is found, where the index is measured in REALs. Note that if the */
  3333. /* `regionattrib' flag is set, an additional attribute will be added. */
  3334. areaboundindex = elemattribindex + eextras + regionattrib;
  3335. /* If triangle attributes or an area bound are needed, increase the number */
  3336. /* of bytes occupied by a triangle. */
  3337. if ( vararea ) {
  3338. trisize = ( areaboundindex + 1 ) * sizeof( REAL );
  3339. }
  3340. else if ( eextras + regionattrib > 0 ) {
  3341. trisize = areaboundindex * sizeof( REAL );
  3342. }
  3343. /* If a Voronoi diagram or triangle neighbor graph is requested, make */
  3344. /* sure there's room to store an integer index in each triangle. This */
  3345. /* integer index can occupy the same space as the shell edges or */
  3346. /* attributes or area constraint or extra nodes. */
  3347. if ( ( voronoi || neighbors ) &&
  3348. ( trisize < 6 * sizeof( triangle ) + sizeof( int ) ) ) {
  3349. trisize = 6 * sizeof( triangle ) + sizeof( int );
  3350. }
  3351. /* Having determined the memory size of a triangle, initialize the pool. */
  3352. poolinit( &triangles, trisize, TRIPERBLOCK, POINTER, 4 );
  3353. if ( useshelles ) {
  3354. /* Initialize the pool of shell edges. */
  3355. poolinit( &shelles, 6 * sizeof( triangle ) + sizeof( int ), SHELLEPERBLOCK,
  3356. POINTER, 4 );
  3357. /* Initialize the "outer space" triangle and omnipresent shell edge. */
  3358. dummyinit( triangles.itemwords, shelles.itemwords );
  3359. }
  3360. else {
  3361. /* Initialize the "outer space" triangle. */
  3362. dummyinit( triangles.itemwords, 0 );
  3363. }
  3364. }
  3365. /*****************************************************************************/
  3366. /* */
  3367. /* triangledealloc() Deallocate space for a triangle, marking it dead. */
  3368. /* */
  3369. /*****************************************************************************/
  3370. void triangledealloc( dyingtriangle )
  3371. triangle * dyingtriangle;
  3372. {
  3373. /* Set triangle's vertices to NULL. This makes it possible to */
  3374. /* detect dead triangles when traversing the list of all triangles. */
  3375. dyingtriangle[3] = (triangle) NULL;
  3376. dyingtriangle[4] = (triangle) NULL;
  3377. dyingtriangle[5] = (triangle) NULL;
  3378. pooldealloc( &triangles, (VOID *) dyingtriangle );
  3379. }
  3380. /*****************************************************************************/
  3381. /* */
  3382. /* triangletraverse() Traverse the triangles, skipping dead ones. */
  3383. /* */
  3384. /*****************************************************************************/
  3385. triangle *triangletraverse(){
  3386. triangle *newtriangle;
  3387. do {
  3388. newtriangle = (triangle *) traverse( &triangles );
  3389. if ( newtriangle == (triangle *) NULL ) {
  3390. return (triangle *) NULL;
  3391. }
  3392. } while ( newtriangle[3] == (triangle) NULL ); /* Skip dead ones. */
  3393. return newtriangle;
  3394. }
  3395. /*****************************************************************************/
  3396. /* */
  3397. /* shelledealloc() Deallocate space for a shell edge, marking it dead. */
  3398. /* */
  3399. /*****************************************************************************/
  3400. void shelledealloc( dyingshelle )
  3401. shelle * dyingshelle;
  3402. {
  3403. /* Set shell edge's vertices to NULL. This makes it possible to */
  3404. /* detect dead shells when traversing the list of all shells. */
  3405. dyingshelle[2] = (shelle) NULL;
  3406. dyingshelle[3] = (shelle) NULL;
  3407. pooldealloc( &shelles, (VOID *) dyingshelle );
  3408. }
  3409. /*****************************************************************************/
  3410. /* */
  3411. /* shelletraverse() Traverse the shell edges, skipping dead ones. */
  3412. /* */
  3413. /*****************************************************************************/
  3414. shelle *shelletraverse(){
  3415. shelle *newshelle;
  3416. do {
  3417. newshelle = (shelle *) traverse( &shelles );
  3418. if ( newshelle == (shelle *) NULL ) {
  3419. return (shelle *) NULL;
  3420. }
  3421. } while ( newshelle[2] == (shelle) NULL ); /* Skip dead ones. */
  3422. return newshelle;
  3423. }
  3424. /*****************************************************************************/
  3425. /* */
  3426. /* pointdealloc() Deallocate space for a point, marking it dead. */
  3427. /* */
  3428. /*****************************************************************************/
  3429. void pointdealloc( dyingpoint )
  3430. point dyingpoint;
  3431. {
  3432. /* Mark the point as dead. This makes it possible to detect dead points */
  3433. /* when traversing the list of all points. */
  3434. setpointmark( dyingpoint, DEADPOINT );
  3435. pooldealloc( &points, (VOID *) dyingpoint );
  3436. }
  3437. /*****************************************************************************/
  3438. /* */
  3439. /* pointtraverse() Traverse the points, skipping dead ones. */
  3440. /* */
  3441. /*****************************************************************************/
  3442. point pointtraverse(){
  3443. point newpoint;
  3444. do {
  3445. newpoint = (point) traverse( &points );
  3446. if ( newpoint == (point) NULL ) {
  3447. return (point) NULL;
  3448. }
  3449. } while ( pointmark( newpoint ) == DEADPOINT ); /* Skip dead ones. */
  3450. return newpoint;
  3451. }
  3452. /*****************************************************************************/
  3453. /* */
  3454. /* badsegmentdealloc() Deallocate space for a bad segment, marking it */
  3455. /* dead. */
  3456. /* */
  3457. /*****************************************************************************/
  3458. #ifndef CDT_ONLY
  3459. void badsegmentdealloc( dyingseg )
  3460. struct edge *dyingseg;
  3461. {
  3462. /* Set segment's orientation to -1. This makes it possible to */
  3463. /* detect dead segments when traversing the list of all segments. */
  3464. dyingseg->shorient = -1;
  3465. pooldealloc( &badsegments, (VOID *) dyingseg );
  3466. }
  3467. #endif /* not CDT_ONLY */
  3468. /*****************************************************************************/
  3469. /* */
  3470. /* badsegmenttraverse() Traverse the bad segments, skipping dead ones. */
  3471. /* */
  3472. /*****************************************************************************/
  3473. #ifndef CDT_ONLY
  3474. struct edge *badsegmenttraverse(){
  3475. struct edge *newseg;
  3476. do {
  3477. newseg = (struct edge *) traverse( &badsegments );
  3478. if ( newseg == (struct edge *) NULL ) {
  3479. return (struct edge *) NULL;
  3480. }
  3481. } while ( newseg->shorient == -1 ); /* Skip dead ones. */
  3482. return newseg;
  3483. }
  3484. #endif /* not CDT_ONLY */
  3485. /*****************************************************************************/
  3486. /* */
  3487. /* getpoint() Get a specific point, by number, from the list. */
  3488. /* */
  3489. /* The first point is number 'firstnumber'. */
  3490. /* */
  3491. /* Note that this takes O(n) time (with a small constant, if POINTPERBLOCK */
  3492. /* is large). I don't care to take the trouble to make it work in constant */
  3493. /* time. */
  3494. /* */
  3495. /*****************************************************************************/
  3496. point getpoint( number )
  3497. int number;
  3498. {
  3499. VOID **getblock;
  3500. point foundpoint;
  3501. unsigned long alignptr;
  3502. int current;
  3503. getblock = points.firstblock;
  3504. current = firstnumber;
  3505. /* Find the right block. */
  3506. while ( current + points.itemsperblock <= number ) {
  3507. getblock = (VOID **) *getblock;
  3508. current += points.itemsperblock;
  3509. }
  3510. /* Now find the right point. */
  3511. alignptr = (unsigned long) ( getblock + 1 );
  3512. foundpoint = (point) ( alignptr + (unsigned long) points.alignbytes
  3513. - ( alignptr % (unsigned long) points.alignbytes ) );
  3514. while ( current < number ) {
  3515. foundpoint += points.itemwords;
  3516. current++;
  3517. }
  3518. return foundpoint;
  3519. }
  3520. /*****************************************************************************/
  3521. /* */
  3522. /* triangledeinit() Free all remaining allocated memory. */
  3523. /* */
  3524. /*****************************************************************************/
  3525. void triangledeinit(){
  3526. pooldeinit( &triangles );
  3527. free( dummytribase );
  3528. if ( useshelles ) {
  3529. pooldeinit( &shelles );
  3530. free( dummyshbase );
  3531. }
  3532. pooldeinit( &points );
  3533. #ifndef CDT_ONLY
  3534. if ( quality ) {
  3535. pooldeinit( &badsegments );
  3536. if ( ( minangle > 0.0 ) || vararea || fixedarea ) {
  3537. pooldeinit( &badtriangles );
  3538. }
  3539. }
  3540. #endif /* not CDT_ONLY */
  3541. }
  3542. /** **/
  3543. /** **/
  3544. /********* Memory management routines end here *********/
  3545. /********* Constructors begin here *********/
  3546. /** **/
  3547. /** **/
  3548. /*****************************************************************************/
  3549. /* */
  3550. /* maketriangle() Create a new triangle with orientation zero. */
  3551. /* */
  3552. /*****************************************************************************/
  3553. void maketriangle( newtriedge )
  3554. struct triedge *newtriedge;
  3555. {
  3556. int i;
  3557. newtriedge->tri = (triangle *) poolalloc( &triangles );
  3558. /* Initialize the three adjoining triangles to be "outer space". */
  3559. newtriedge->tri[0] = (triangle) dummytri;
  3560. newtriedge->tri[1] = (triangle) dummytri;
  3561. newtriedge->tri[2] = (triangle) dummytri;
  3562. /* Three NULL vertex points. */
  3563. newtriedge->tri[3] = (triangle) NULL;
  3564. newtriedge->tri[4] = (triangle) NULL;
  3565. newtriedge->tri[5] = (triangle) NULL;
  3566. /* Initialize the three adjoining shell edges to be the omnipresent */
  3567. /* shell edge. */
  3568. if ( useshelles ) {
  3569. newtriedge->tri[6] = (triangle) dummysh;
  3570. newtriedge->tri[7] = (triangle) dummysh;
  3571. newtriedge->tri[8] = (triangle) dummysh;
  3572. }
  3573. for ( i = 0; i < eextras; i++ ) {
  3574. setelemattribute( *newtriedge, i, 0.0 );
  3575. }
  3576. if ( vararea ) {
  3577. setareabound( *newtriedge, -1.0 );
  3578. }
  3579. newtriedge->orient = 0;
  3580. }
  3581. /*****************************************************************************/
  3582. /* */
  3583. /* makeshelle() Create a new shell edge with orientation zero. */
  3584. /* */
  3585. /*****************************************************************************/
  3586. void makeshelle( newedge )
  3587. struct edge *newedge;
  3588. {
  3589. newedge->sh = (shelle *) poolalloc( &shelles );
  3590. /* Initialize the two adjoining shell edges to be the omnipresent */
  3591. /* shell edge. */
  3592. newedge->sh[0] = (shelle) dummysh;
  3593. newedge->sh[1] = (shelle) dummysh;
  3594. /* Two NULL vertex points. */
  3595. newedge->sh[2] = (shelle) NULL;
  3596. newedge->sh[3] = (shelle) NULL;
  3597. /* Initialize the two adjoining triangles to be "outer space". */
  3598. newedge->sh[4] = (shelle) dummytri;
  3599. newedge->sh[5] = (shelle) dummytri;
  3600. /* Set the boundary marker to zero. */
  3601. setmark( *newedge, 0 );
  3602. newedge->shorient = 0;
  3603. }
  3604. /** **/
  3605. /** **/
  3606. /********* Constructors end here *********/
  3607. /********* Determinant evaluation routines begin here *********/
  3608. /** **/
  3609. /** **/
  3610. /* The adaptive exact arithmetic geometric predicates implemented herein are */
  3611. /* described in detail in my Technical Report CMU-CS-96-140. The complete */
  3612. /* reference is given in the header. */
  3613. /* Which of the following two methods of finding the absolute values is */
  3614. /* fastest is compiler-dependent. A few compilers can inline and optimize */
  3615. /* the fabs() call; but most will incur the overhead of a function call, */
  3616. /* which is disastrously slow. A faster way on IEEE machines might be to */
  3617. /* mask the appropriate bit, but that's difficult to do in C. */
  3618. #define Absolute( a ) ( ( a ) >= 0.0 ? ( a ) : -( a ) )
  3619. /* #define Absolute(a) fabs(a) */
  3620. /* Many of the operations are broken up into two pieces, a main part that */
  3621. /* performs an approximate operation, and a "tail" that computes the */
  3622. /* roundoff error of that operation. */
  3623. /* */
  3624. /* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */
  3625. /* Split(), and Two_Product() are all implemented as described in the */
  3626. /* reference. Each of these macros requires certain variables to be */
  3627. /* defined in the calling routine. The variables `bvirt', `c', `abig', */
  3628. /* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */
  3629. /* they store the result of an operation that may incur roundoff error. */
  3630. /* The input parameter `x' (or the highest numbered `x_' parameter) must */
  3631. /* also be declared `INEXACT'. */
  3632. #define Fast_Two_Sum_Tail( a, b, x, y ) \
  3633. bvirt = x - a; \
  3634. y = b - bvirt
  3635. #define Fast_Two_Sum( a, b, x, y ) \
  3636. x = (REAL) ( a + b ); \
  3637. Fast_Two_Sum_Tail( a, b, x, y )
  3638. #define Two_Sum_Tail( a, b, x, y ) \
  3639. bvirt = (REAL) ( x - a ); \
  3640. avirt = x - bvirt; \
  3641. bround = b - bvirt; \
  3642. around = a - avirt; \
  3643. y = around + bround
  3644. #define Two_Sum( a, b, x, y ) \
  3645. x = (REAL) ( a + b ); \
  3646. Two_Sum_Tail( a, b, x, y )
  3647. #define Two_Diff_Tail( a, b, x, y ) \
  3648. bvirt = (REAL) ( a - x ); \
  3649. avirt = x + bvirt; \
  3650. bround = bvirt - b; \
  3651. around = a - avirt; \
  3652. y = around + bround
  3653. #define Two_Diff( a, b, x, y ) \
  3654. x = (REAL) ( a - b ); \
  3655. Two_Diff_Tail( a, b, x, y )
  3656. #define Split( a, ahi, alo ) \
  3657. c = (REAL) ( splitter * a ); \
  3658. abig = (REAL) ( c - a ); \
  3659. ahi = (REAL)( c - abig ); \
  3660. alo = (REAL)( a - ahi )
  3661. #define Two_Product_Tail( a, b, x, y ) \
  3662. Split( a, ahi, alo ); \
  3663. Split( b, bhi, blo ); \
  3664. err1 = x - ( ahi * bhi ); \
  3665. err2 = err1 - ( alo * bhi ); \
  3666. err3 = err2 - ( ahi * blo ); \
  3667. y = ( alo * blo ) - err3
  3668. #define Two_Product( a, b, x, y ) \
  3669. x = (REAL) ( a * b ); \
  3670. Two_Product_Tail( a, b, x, y )
  3671. /* Two_Product_Presplit() is Two_Product() where one of the inputs has */
  3672. /* already been split. Avoids redundant splitting. */
  3673. #define Two_Product_Presplit( a, b, bhi, blo, x, y ) \
  3674. x = (REAL) ( a * b ); \
  3675. Split( a, ahi, alo ); \
  3676. err1 = x - ( ahi * bhi ); \
  3677. err2 = err1 - ( alo * bhi ); \
  3678. err3 = err2 - ( ahi * blo ); \
  3679. y = ( alo * blo ) - err3
  3680. /* Square() can be done more quickly than Two_Product(). */
  3681. #define Square_Tail( a, x, y ) \
  3682. Split( a, ahi, alo ); \
  3683. err1 = x - ( ahi * ahi ); \
  3684. err3 = err1 - ( ( ahi + ahi ) * alo ); \
  3685. y = ( alo * alo ) - err3
  3686. #define Square( a, x, y ) \
  3687. x = (REAL) ( a * a ); \
  3688. Square_Tail( a, x, y )
  3689. /* Macros for summing expansions of various fixed lengths. These are all */
  3690. /* unrolled versions of Expansion_Sum(). */
  3691. #define Two_One_Sum( a1, a0, b, x2, x1, x0 ) \
  3692. Two_Sum( a0, b, _i, x0 ); \
  3693. Two_Sum( a1, _i, x2, x1 )
  3694. #define Two_One_Diff( a1, a0, b, x2, x1, x0 ) \
  3695. Two_Diff( a0, b, _i, x0 ); \
  3696. Two_Sum( a1, _i, x2, x1 )
  3697. #define Two_Two_Sum( a1, a0, b1, b0, x3, x2, x1, x0 ) \
  3698. Two_One_Sum( a1, a0, b0, _j, _0, x0 ); \
  3699. Two_One_Sum( _j, _0, b1, x3, x2, x1 )
  3700. #define Two_Two_Diff( a1, a0, b1, b0, x3, x2, x1, x0 ) \
  3701. Two_One_Diff( a1, a0, b0, _j, _0, x0 ); \
  3702. Two_One_Diff( _j, _0, b1, x3, x2, x1 )
  3703. /*****************************************************************************/
  3704. /* */
  3705. /* exactinit() Initialize the variables used for exact arithmetic. */
  3706. /* */
  3707. /* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
  3708. /* floating-point arithmetic. `epsilon' bounds the relative roundoff */
  3709. /* error. It is used for floating-point error analysis. */
  3710. /* */
  3711. /* `splitter' is used to split floating-point numbers into two half- */
  3712. /* length significands for exact multiplication. */
  3713. /* */
  3714. /* I imagine that a highly optimizing compiler might be too smart for its */
  3715. /* own good, and somehow cause this routine to fail, if it pretends that */
  3716. /* floating-point arithmetic is too much like real arithmetic. */
  3717. /* */
  3718. /* Don't change this routine unless you fully understand it. */
  3719. /* */
  3720. /*****************************************************************************/
  3721. void exactinit(){
  3722. REAL half;
  3723. REAL check, lastcheck;
  3724. int every_other;
  3725. every_other = 1;
  3726. half = 0.5;
  3727. epsilon = 1.0;
  3728. splitter = 1.0;
  3729. check = 1.0;
  3730. /* Repeatedly divide `epsilon' by two until it is too small to add to */
  3731. /* one without causing roundoff. (Also check if the sum is equal to */
  3732. /* the previous sum, for machines that round up instead of using exact */
  3733. /* rounding. Not that these routines will work on such machines anyway. */
  3734. do {
  3735. lastcheck = check;
  3736. epsilon *= half;
  3737. if ( every_other ) {
  3738. splitter *= 2.0;
  3739. }
  3740. every_other = !every_other;
  3741. check = (REAL)( 1.0 + epsilon );
  3742. } while ( ( check != 1.0 ) && ( check != lastcheck ) );
  3743. splitter += 1.0;
  3744. if ( verbose > 1 ) {
  3745. printf( "Floating point roundoff is of magnitude %.17g\n", epsilon );
  3746. printf( "Floating point splitter is %.17g\n", splitter );
  3747. }
  3748. /* Error bounds for orientation and incircle tests. */
  3749. resulterrbound = (REAL)( ( 3.0 + 8.0 * epsilon ) * epsilon );
  3750. ccwerrboundA = (REAL)( ( 3.0 + 16.0 * epsilon ) * epsilon );
  3751. ccwerrboundB = (REAL)( ( 2.0 + 12.0 * epsilon ) * epsilon );
  3752. ccwerrboundC = (REAL)( ( 9.0 + 64.0 * epsilon ) * epsilon * epsilon );
  3753. iccerrboundA = (REAL)( ( 10.0 + 96.0 * epsilon ) * epsilon );
  3754. iccerrboundB = (REAL)( ( 4.0 + 48.0 * epsilon ) * epsilon );
  3755. iccerrboundC = (REAL)( ( 44.0 + 576.0 * epsilon ) * epsilon * epsilon );
  3756. }
  3757. /*****************************************************************************/
  3758. /* */
  3759. /* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
  3760. /* components from the output expansion. */
  3761. /* */
  3762. /* Sets h = e + f. See my Robust Predicates paper for details. */
  3763. /* */
  3764. /* If round-to-even is used (as with IEEE 754), maintains the strongly */
  3765. /* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
  3766. /* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
  3767. /* properties. */
  3768. /* */
  3769. /*****************************************************************************/
  3770. int fast_expansion_sum_zeroelim( elen, e, flen, f, h ) /* h cannot be e or f. */
  3771. int elen;
  3772. REAL *e;
  3773. int flen;
  3774. REAL *f;
  3775. REAL *h;
  3776. {
  3777. REAL Q;
  3778. INEXACT REAL Qnew;
  3779. INEXACT REAL hh;
  3780. INEXACT REAL bvirt;
  3781. REAL avirt, bround, around;
  3782. int eindex, findex, hindex;
  3783. REAL enow, fnow;
  3784. enow = e[0];
  3785. fnow = f[0];
  3786. eindex = findex = 0;
  3787. if ( ( fnow > enow ) == ( fnow > -enow ) ) {
  3788. Q = enow;
  3789. enow = e[++eindex];
  3790. }
  3791. else {
  3792. Q = fnow;
  3793. fnow = f[++findex];
  3794. }
  3795. hindex = 0;
  3796. if ( ( eindex < elen ) && ( findex < flen ) ) {
  3797. if ( ( fnow > enow ) == ( fnow > -enow ) ) {
  3798. Fast_Two_Sum( enow, Q, Qnew, hh );
  3799. enow = e[++eindex];
  3800. }
  3801. else {
  3802. Fast_Two_Sum( fnow, Q, Qnew, hh );
  3803. fnow = f[++findex];
  3804. }
  3805. Q = Qnew;
  3806. if ( hh != 0.0 ) {
  3807. h[hindex++] = hh;
  3808. }
  3809. while ( ( eindex < elen ) && ( findex < flen ) ) {
  3810. if ( ( fnow > enow ) == ( fnow > -enow ) ) {
  3811. Two_Sum( Q, enow, Qnew, hh );
  3812. enow = e[++eindex];
  3813. }
  3814. else {
  3815. Two_Sum( Q, fnow, Qnew, hh );
  3816. fnow = f[++findex];
  3817. }
  3818. Q = Qnew;
  3819. if ( hh != 0.0 ) {
  3820. h[hindex++] = hh;
  3821. }
  3822. }
  3823. }
  3824. while ( eindex < elen ) {
  3825. Two_Sum( Q, enow, Qnew, hh );
  3826. enow = e[++eindex];
  3827. Q = Qnew;
  3828. if ( hh != 0.0 ) {
  3829. h[hindex++] = hh;
  3830. }
  3831. }
  3832. while ( findex < flen ) {
  3833. Two_Sum( Q, fnow, Qnew, hh );
  3834. fnow = f[++findex];
  3835. Q = Qnew;
  3836. if ( hh != 0.0 ) {
  3837. h[hindex++] = hh;
  3838. }
  3839. }
  3840. if ( ( Q != 0.0 ) || ( hindex == 0 ) ) {
  3841. h[hindex++] = Q;
  3842. }
  3843. return hindex;
  3844. }
  3845. /*****************************************************************************/
  3846. /* */
  3847. /* scale_expansion_zeroelim() Multiply an expansion by a scalar, */
  3848. /* eliminating zero components from the */
  3849. /* output expansion. */
  3850. /* */
  3851. /* Sets h = be. See my Robust Predicates paper for details. */
  3852. /* */
  3853. /* Maintains the nonoverlapping property. If round-to-even is used (as */
  3854. /* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */
  3855. /* properties as well. (That is, if e has one of these properties, so */
  3856. /* will h.) */
  3857. /* */
  3858. /*****************************************************************************/
  3859. int scale_expansion_zeroelim( elen, e, b, h ) /* e and h cannot be the same. */
  3860. int elen;
  3861. REAL *e;
  3862. REAL b;
  3863. REAL *h;
  3864. {
  3865. INEXACT REAL Q, sum;
  3866. REAL hh;
  3867. INEXACT REAL product1;
  3868. REAL product0;
  3869. int eindex, hindex;
  3870. REAL enow;
  3871. INEXACT REAL bvirt;
  3872. REAL avirt, bround, around;
  3873. INEXACT REAL c;
  3874. INEXACT REAL abig;
  3875. REAL ahi, alo, bhi, blo;
  3876. REAL err1, err2, err3;
  3877. Split( b, bhi, blo );
  3878. Two_Product_Presplit( e[0], b, bhi, blo, Q, hh );
  3879. hindex = 0;
  3880. if ( hh != 0 ) {
  3881. h[hindex++] = hh;
  3882. }
  3883. for ( eindex = 1; eindex < elen; eindex++ ) {
  3884. enow = e[eindex];
  3885. Two_Product_Presplit( enow, b, bhi, blo, product1, product0 );
  3886. Two_Sum( Q, product0, sum, hh );
  3887. if ( hh != 0 ) {
  3888. h[hindex++] = hh;
  3889. }
  3890. Fast_Two_Sum( product1, sum, Q, hh );
  3891. if ( hh != 0 ) {
  3892. h[hindex++] = hh;
  3893. }
  3894. }
  3895. if ( ( Q != 0.0 ) || ( hindex == 0 ) ) {
  3896. h[hindex++] = Q;
  3897. }
  3898. return hindex;
  3899. }
  3900. /*****************************************************************************/
  3901. /* */
  3902. /* estimate() Produce a one-word estimate of an expansion's value. */
  3903. /* */
  3904. /* See my Robust Predicates paper for details. */
  3905. /* */
  3906. /*****************************************************************************/
  3907. REAL estimate( elen, e )
  3908. int elen;
  3909. REAL *e;
  3910. {
  3911. REAL Q;
  3912. int eindex;
  3913. Q = e[0];
  3914. for ( eindex = 1; eindex < elen; eindex++ ) {
  3915. Q += e[eindex];
  3916. }
  3917. return Q;
  3918. }
  3919. /*****************************************************************************/
  3920. /* */
  3921. /* counterclockwise() Return a positive value if the points pa, pb, and */
  3922. /* pc occur in counterclockwise order; a negative */
  3923. /* value if they occur in clockwise order; and zero */
  3924. /* if they are collinear. The result is also a rough */
  3925. /* approximation of twice the signed area of the */
  3926. /* triangle defined by the three points. */
  3927. /* */
  3928. /* Uses exact arithmetic if necessary to ensure a correct answer. The */
  3929. /* result returned is the determinant of a matrix. This determinant is */
  3930. /* computed adaptively, in the sense that exact arithmetic is used only to */
  3931. /* the degree it is needed to ensure that the returned value has the */
  3932. /* correct sign. Hence, this function is usually quite fast, but will run */
  3933. /* more slowly when the input points are collinear or nearly so. */
  3934. /* */
  3935. /* See my Robust Predicates paper for details. */
  3936. /* */
  3937. /*****************************************************************************/
  3938. REAL counterclockwiseadapt( pa, pb, pc, detsum )
  3939. point pa;
  3940. point pb;
  3941. point pc;
  3942. REAL detsum;
  3943. {
  3944. INEXACT REAL acx, acy, bcx, bcy;
  3945. REAL acxtail, acytail, bcxtail, bcytail;
  3946. INEXACT REAL detleft, detright;
  3947. REAL detlefttail, detrighttail;
  3948. REAL det, errbound;
  3949. REAL B[4], C1[8], C2[12], D[16];
  3950. INEXACT REAL B3;
  3951. int C1length, C2length, Dlength;
  3952. REAL u[4];
  3953. INEXACT REAL u3;
  3954. INEXACT REAL s1, t1;
  3955. REAL s0, t0;
  3956. INEXACT REAL bvirt;
  3957. REAL avirt, bround, around;
  3958. INEXACT REAL c;
  3959. INEXACT REAL abig;
  3960. REAL ahi, alo, bhi, blo;
  3961. REAL err1, err2, err3;
  3962. INEXACT REAL _i, _j;
  3963. REAL _0;
  3964. acx = (REAL) ( pa[0] - pc[0] );
  3965. bcx = (REAL) ( pb[0] - pc[0] );
  3966. acy = (REAL) ( pa[1] - pc[1] );
  3967. bcy = (REAL) ( pb[1] - pc[1] );
  3968. Two_Product( acx, bcy, detleft, detlefttail );
  3969. Two_Product( acy, bcx, detright, detrighttail );
  3970. Two_Two_Diff( detleft, detlefttail, detright, detrighttail,
  3971. B3, B[2], B[1], B[0] );
  3972. B[3] = B3;
  3973. det = estimate( 4, B );
  3974. errbound = (REAL)( ccwerrboundB * detsum );
  3975. if ( ( det >= errbound ) || ( -det >= errbound ) ) {
  3976. return det;
  3977. }
  3978. Two_Diff_Tail( pa[0], pc[0], acx, acxtail );
  3979. Two_Diff_Tail( pb[0], pc[0], bcx, bcxtail );
  3980. Two_Diff_Tail( pa[1], pc[1], acy, acytail );
  3981. Two_Diff_Tail( pb[1], pc[1], bcy, bcytail );
  3982. if ( ( acxtail == 0.0 ) && ( acytail == 0.0 )
  3983. && ( bcxtail == 0.0 ) && ( bcytail == 0.0 ) ) {
  3984. return det;
  3985. }
  3986. errbound = (REAL)( ccwerrboundC * detsum + resulterrbound * Absolute( det ) );
  3987. det += ( acx * bcytail + bcy * acxtail )
  3988. - ( acy * bcxtail + bcx * acytail );
  3989. if ( ( det >= errbound ) || ( -det >= errbound ) ) {
  3990. return det;
  3991. }
  3992. Two_Product( acxtail, bcy, s1, s0 );
  3993. Two_Product( acytail, bcx, t1, t0 );
  3994. Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] );
  3995. u[3] = u3;
  3996. C1length = fast_expansion_sum_zeroelim( 4, B, 4, u, C1 );
  3997. Two_Product( acx, bcytail, s1, s0 );
  3998. Two_Product( acy, bcxtail, t1, t0 );
  3999. Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] );
  4000. u[3] = u3;
  4001. C2length = fast_expansion_sum_zeroelim( C1length, C1, 4, u, C2 );
  4002. Two_Product( acxtail, bcytail, s1, s0 );
  4003. Two_Product( acytail, bcxtail, t1, t0 );
  4004. Two_Two_Diff( s1, s0, t1, t0, u3, u[2], u[1], u[0] );
  4005. u[3] = u3;
  4006. Dlength = fast_expansion_sum_zeroelim( C2length, C2, 4, u, D );
  4007. return( D[Dlength - 1] );
  4008. }
  4009. REAL counterclockwise( pa, pb, pc )
  4010. point pa;
  4011. point pb;
  4012. point pc;
  4013. {
  4014. REAL detleft, detright, det;
  4015. REAL detsum, errbound;
  4016. counterclockcount++;
  4017. detleft = ( pa[0] - pc[0] ) * ( pb[1] - pc[1] );
  4018. detright = ( pa[1] - pc[1] ) * ( pb[0] - pc[0] );
  4019. det = detleft - detright;
  4020. if ( noexact ) {
  4021. return det;
  4022. }
  4023. if ( detleft > 0.0 ) {
  4024. if ( detright <= 0.0 ) {
  4025. return det;
  4026. }
  4027. else {
  4028. detsum = detleft + detright;
  4029. }
  4030. }
  4031. else if ( detleft < 0.0 ) {
  4032. if ( detright >= 0.0 ) {
  4033. return det;
  4034. }
  4035. else {
  4036. detsum = -detleft - detright;
  4037. }
  4038. }
  4039. else {
  4040. return det;
  4041. }
  4042. errbound = ccwerrboundA * detsum;
  4043. if ( ( det >= errbound ) || ( -det >= errbound ) ) {
  4044. return det;
  4045. }
  4046. return counterclockwiseadapt( pa, pb, pc, detsum );
  4047. }
  4048. /*****************************************************************************/
  4049. /* */
  4050. /* incircle() Return a positive value if the point pd lies inside the */
  4051. /* circle passing through pa, pb, and pc; a negative value if */
  4052. /* it lies outside; and zero if the four points are cocircular.*/
  4053. /* The points pa, pb, and pc must be in counterclockwise */
  4054. /* order, or the sign of the result will be reversed. */
  4055. /* */
  4056. /* Uses exact arithmetic if necessary to ensure a correct answer. The */
  4057. /* result returned is the determinant of a matrix. This determinant is */
  4058. /* computed adaptively, in the sense that exact arithmetic is used only to */
  4059. /* the degree it is needed to ensure that the returned value has the */
  4060. /* correct sign. Hence, this function is usually quite fast, but will run */
  4061. /* more slowly when the input points are cocircular or nearly so. */
  4062. /* */
  4063. /* See my Robust Predicates paper for details. */
  4064. /* */
  4065. /*****************************************************************************/
  4066. REAL incircleadapt( pa, pb, pc, pd, permanent )
  4067. point pa;
  4068. point pb;
  4069. point pc;
  4070. point pd;
  4071. REAL permanent;
  4072. {
  4073. INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
  4074. REAL det, errbound;
  4075. INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
  4076. REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
  4077. REAL bc[4], ca[4], ab[4];
  4078. INEXACT REAL bc3, ca3, ab3;
  4079. REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
  4080. int axbclen, axxbclen, aybclen, ayybclen, alen;
  4081. REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
  4082. int bxcalen, bxxcalen, bycalen, byycalen, blen;
  4083. REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
  4084. int cxablen, cxxablen, cyablen, cyyablen, clen;
  4085. REAL abdet[64];
  4086. int ablen;
  4087. REAL fin1[1152], fin2[1152];
  4088. REAL *finnow, *finother, *finswap;
  4089. int finlength;
  4090. REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
  4091. INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
  4092. REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
  4093. REAL aa[4], bb[4], cc[4];
  4094. INEXACT REAL aa3, bb3, cc3;
  4095. INEXACT REAL ti1, tj1;
  4096. REAL ti0, tj0;
  4097. REAL u[4], v[4];
  4098. INEXACT REAL u3, v3;
  4099. REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
  4100. REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
  4101. int temp8len, temp16alen, temp16blen, temp16clen;
  4102. int temp32alen, temp32blen, temp48len, temp64len;
  4103. REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
  4104. int axtbblen, axtcclen, aytbblen, aytcclen;
  4105. REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
  4106. int bxtaalen, bxtcclen, bytaalen, bytcclen;
  4107. REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
  4108. int cxtaalen, cxtbblen, cytaalen, cytbblen;
  4109. REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
  4110. int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
  4111. REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
  4112. int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
  4113. REAL axtbctt[8], aytbctt[8], bxtcatt[8];
  4114. REAL bytcatt[8], cxtabtt[8], cytabtt[8];
  4115. int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
  4116. REAL abt[8], bct[8], cat[8];
  4117. int abtlen, bctlen, catlen;
  4118. REAL abtt[4], bctt[4], catt[4];
  4119. int abttlen, bcttlen, cattlen;
  4120. INEXACT REAL abtt3, bctt3, catt3;
  4121. REAL negate;
  4122. INEXACT REAL bvirt;
  4123. REAL avirt, bround, around;
  4124. INEXACT REAL c;
  4125. INEXACT REAL abig;
  4126. REAL ahi, alo, bhi, blo;
  4127. REAL err1, err2, err3;
  4128. INEXACT REAL _i, _j;
  4129. REAL _0;
  4130. adx = (REAL) ( pa[0] - pd[0] );
  4131. bdx = (REAL) ( pb[0] - pd[0] );
  4132. cdx = (REAL) ( pc[0] - pd[0] );
  4133. ady = (REAL) ( pa[1] - pd[1] );
  4134. bdy = (REAL) ( pb[1] - pd[1] );
  4135. cdy = (REAL) ( pc[1] - pd[1] );
  4136. Two_Product( bdx, cdy, bdxcdy1, bdxcdy0 );
  4137. Two_Product( cdx, bdy, cdxbdy1, cdxbdy0 );
  4138. Two_Two_Diff( bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0] );
  4139. bc[3] = bc3;
  4140. axbclen = scale_expansion_zeroelim( 4, bc, adx, axbc );
  4141. axxbclen = scale_expansion_zeroelim( axbclen, axbc, adx, axxbc );
  4142. aybclen = scale_expansion_zeroelim( 4, bc, ady, aybc );
  4143. ayybclen = scale_expansion_zeroelim( aybclen, aybc, ady, ayybc );
  4144. alen = fast_expansion_sum_zeroelim( axxbclen, axxbc, ayybclen, ayybc, adet );
  4145. Two_Product( cdx, ady, cdxady1, cdxady0 );
  4146. Two_Product( adx, cdy, adxcdy1, adxcdy0 );
  4147. Two_Two_Diff( cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0] );
  4148. ca[3] = ca3;
  4149. bxcalen = scale_expansion_zeroelim( 4, ca, bdx, bxca );
  4150. bxxcalen = scale_expansion_zeroelim( bxcalen, bxca, bdx, bxxca );
  4151. bycalen = scale_expansion_zeroelim( 4, ca, bdy, byca );
  4152. byycalen = scale_expansion_zeroelim( bycalen, byca, bdy, byyca );
  4153. blen = fast_expansion_sum_zeroelim( bxxcalen, bxxca, byycalen, byyca, bdet );
  4154. Two_Product( adx, bdy, adxbdy1, adxbdy0 );
  4155. Two_Product( bdx, ady, bdxady1, bdxady0 );
  4156. Two_Two_Diff( adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0] );
  4157. ab[3] = ab3;
  4158. cxablen = scale_expansion_zeroelim( 4, ab, cdx, cxab );
  4159. cxxablen = scale_expansion_zeroelim( cxablen, cxab, cdx, cxxab );
  4160. cyablen = scale_expansion_zeroelim( 4, ab, cdy, cyab );
  4161. cyyablen = scale_expansion_zeroelim( cyablen, cyab, cdy, cyyab );
  4162. clen = fast_expansion_sum_zeroelim( cxxablen, cxxab, cyyablen, cyyab, cdet );
  4163. ablen = fast_expansion_sum_zeroelim( alen, adet, blen, bdet, abdet );
  4164. finlength = fast_expansion_sum_zeroelim( ablen, abdet, clen, cdet, fin1 );
  4165. det = estimate( finlength, fin1 );
  4166. errbound = (REAL)( iccerrboundB * permanent );
  4167. if ( ( det >= errbound ) || ( -det >= errbound ) ) {
  4168. return det;
  4169. }
  4170. Two_Diff_Tail( pa[0], pd[0], adx, adxtail );
  4171. Two_Diff_Tail( pa[1], pd[1], ady, adytail );
  4172. Two_Diff_Tail( pb[0], pd[0], bdx, bdxtail );
  4173. Two_Diff_Tail( pb[1], pd[1], bdy, bdytail );
  4174. Two_Diff_Tail( pc[0], pd[0], cdx, cdxtail );
  4175. Two_Diff_Tail( pc[1], pd[1], cdy, cdytail );
  4176. if ( ( adxtail == 0.0 ) && ( bdxtail == 0.0 ) && ( cdxtail == 0.0 )
  4177. && ( adytail == 0.0 ) && ( bdytail == 0.0 ) && ( cdytail == 0.0 ) ) {
  4178. return det;
  4179. }
  4180. errbound = (REAL)( iccerrboundC * permanent + resulterrbound * Absolute( det ) );
  4181. det += (REAL)( ( ( adx * adx + ady * ady ) * ( ( bdx * cdytail + cdy * bdxtail )
  4182. - ( bdy * cdxtail + cdx * bdytail ) )
  4183. + 2.0 * ( adx * adxtail + ady * adytail ) * ( bdx * cdy - bdy * cdx ) )
  4184. + ( ( bdx * bdx + bdy * bdy ) * ( ( cdx * adytail + ady * cdxtail )
  4185. - ( cdy * adxtail + adx * cdytail ) )
  4186. + 2.0 * ( bdx * bdxtail + bdy * bdytail ) * ( cdx * ady - cdy * adx ) )
  4187. + ( ( cdx * cdx + cdy * cdy ) * ( ( adx * bdytail + bdy * adxtail )
  4188. - ( ady * bdxtail + bdx * adytail ) )
  4189. + 2.0 * ( cdx * cdxtail + cdy * cdytail ) * ( adx * bdy - ady * bdx ) ) );
  4190. if ( ( det >= errbound ) || ( -det >= errbound ) ) {
  4191. return det;
  4192. }
  4193. finnow = fin1;
  4194. finother = fin2;
  4195. if ( ( bdxtail != 0.0 ) || ( bdytail != 0.0 )
  4196. || ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) ) {
  4197. Square( adx, adxadx1, adxadx0 );
  4198. Square( ady, adyady1, adyady0 );
  4199. Two_Two_Sum( adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0] );
  4200. aa[3] = aa3;
  4201. }
  4202. if ( ( cdxtail != 0.0 ) || ( cdytail != 0.0 )
  4203. || ( adxtail != 0.0 ) || ( adytail != 0.0 ) ) {
  4204. Square( bdx, bdxbdx1, bdxbdx0 );
  4205. Square( bdy, bdybdy1, bdybdy0 );
  4206. Two_Two_Sum( bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0] );
  4207. bb[3] = bb3;
  4208. }
  4209. if ( ( adxtail != 0.0 ) || ( adytail != 0.0 )
  4210. || ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) ) {
  4211. Square( cdx, cdxcdx1, cdxcdx0 );
  4212. Square( cdy, cdycdy1, cdycdy0 );
  4213. Two_Two_Sum( cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0] );
  4214. cc[3] = cc3;
  4215. }
  4216. if ( adxtail != 0.0 ) {
  4217. axtbclen = scale_expansion_zeroelim( 4, bc, adxtail, axtbc );
  4218. temp16alen = scale_expansion_zeroelim( axtbclen, axtbc, 2.0 * adx,
  4219. temp16a );
  4220. axtcclen = scale_expansion_zeroelim( 4, cc, adxtail, axtcc );
  4221. temp16blen = scale_expansion_zeroelim( axtcclen, axtcc, bdy, temp16b );
  4222. axtbblen = scale_expansion_zeroelim( 4, bb, adxtail, axtbb );
  4223. temp16clen = scale_expansion_zeroelim( axtbblen, axtbb, -cdy, temp16c );
  4224. temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4225. temp16blen, temp16b, temp32a );
  4226. temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c,
  4227. temp32alen, temp32a, temp48 );
  4228. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4229. temp48, finother );
  4230. finswap = finnow; finnow = finother; finother = finswap;
  4231. }
  4232. if ( adytail != 0.0 ) {
  4233. aytbclen = scale_expansion_zeroelim( 4, bc, adytail, aytbc );
  4234. temp16alen = scale_expansion_zeroelim( aytbclen, aytbc, 2.0 * ady,
  4235. temp16a );
  4236. aytbblen = scale_expansion_zeroelim( 4, bb, adytail, aytbb );
  4237. temp16blen = scale_expansion_zeroelim( aytbblen, aytbb, cdx, temp16b );
  4238. aytcclen = scale_expansion_zeroelim( 4, cc, adytail, aytcc );
  4239. temp16clen = scale_expansion_zeroelim( aytcclen, aytcc, -bdx, temp16c );
  4240. temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4241. temp16blen, temp16b, temp32a );
  4242. temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c,
  4243. temp32alen, temp32a, temp48 );
  4244. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4245. temp48, finother );
  4246. finswap = finnow; finnow = finother; finother = finswap;
  4247. }
  4248. if ( bdxtail != 0.0 ) {
  4249. bxtcalen = scale_expansion_zeroelim( 4, ca, bdxtail, bxtca );
  4250. temp16alen = scale_expansion_zeroelim( bxtcalen, bxtca, 2.0 * bdx,
  4251. temp16a );
  4252. bxtaalen = scale_expansion_zeroelim( 4, aa, bdxtail, bxtaa );
  4253. temp16blen = scale_expansion_zeroelim( bxtaalen, bxtaa, cdy, temp16b );
  4254. bxtcclen = scale_expansion_zeroelim( 4, cc, bdxtail, bxtcc );
  4255. temp16clen = scale_expansion_zeroelim( bxtcclen, bxtcc, -ady, temp16c );
  4256. temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4257. temp16blen, temp16b, temp32a );
  4258. temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c,
  4259. temp32alen, temp32a, temp48 );
  4260. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4261. temp48, finother );
  4262. finswap = finnow; finnow = finother; finother = finswap;
  4263. }
  4264. if ( bdytail != 0.0 ) {
  4265. bytcalen = scale_expansion_zeroelim( 4, ca, bdytail, bytca );
  4266. temp16alen = scale_expansion_zeroelim( bytcalen, bytca, 2.0 * bdy,
  4267. temp16a );
  4268. bytcclen = scale_expansion_zeroelim( 4, cc, bdytail, bytcc );
  4269. temp16blen = scale_expansion_zeroelim( bytcclen, bytcc, adx, temp16b );
  4270. bytaalen = scale_expansion_zeroelim( 4, aa, bdytail, bytaa );
  4271. temp16clen = scale_expansion_zeroelim( bytaalen, bytaa, -cdx, temp16c );
  4272. temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4273. temp16blen, temp16b, temp32a );
  4274. temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c,
  4275. temp32alen, temp32a, temp48 );
  4276. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4277. temp48, finother );
  4278. finswap = finnow; finnow = finother; finother = finswap;
  4279. }
  4280. if ( cdxtail != 0.0 ) {
  4281. cxtablen = scale_expansion_zeroelim( 4, ab, cdxtail, cxtab );
  4282. temp16alen = scale_expansion_zeroelim( cxtablen, cxtab, 2.0 * cdx,
  4283. temp16a );
  4284. cxtbblen = scale_expansion_zeroelim( 4, bb, cdxtail, cxtbb );
  4285. temp16blen = scale_expansion_zeroelim( cxtbblen, cxtbb, ady, temp16b );
  4286. cxtaalen = scale_expansion_zeroelim( 4, aa, cdxtail, cxtaa );
  4287. temp16clen = scale_expansion_zeroelim( cxtaalen, cxtaa, -bdy, temp16c );
  4288. temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4289. temp16blen, temp16b, temp32a );
  4290. temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c,
  4291. temp32alen, temp32a, temp48 );
  4292. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4293. temp48, finother );
  4294. finswap = finnow; finnow = finother; finother = finswap;
  4295. }
  4296. if ( cdytail != 0.0 ) {
  4297. cytablen = scale_expansion_zeroelim( 4, ab, cdytail, cytab );
  4298. temp16alen = scale_expansion_zeroelim( cytablen, cytab, 2.0 * cdy,
  4299. temp16a );
  4300. cytaalen = scale_expansion_zeroelim( 4, aa, cdytail, cytaa );
  4301. temp16blen = scale_expansion_zeroelim( cytaalen, cytaa, bdx, temp16b );
  4302. cytbblen = scale_expansion_zeroelim( 4, bb, cdytail, cytbb );
  4303. temp16clen = scale_expansion_zeroelim( cytbblen, cytbb, -adx, temp16c );
  4304. temp32alen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4305. temp16blen, temp16b, temp32a );
  4306. temp48len = fast_expansion_sum_zeroelim( temp16clen, temp16c,
  4307. temp32alen, temp32a, temp48 );
  4308. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4309. temp48, finother );
  4310. finswap = finnow; finnow = finother; finother = finswap;
  4311. }
  4312. if ( ( adxtail != 0.0 ) || ( adytail != 0.0 ) ) {
  4313. if ( ( bdxtail != 0.0 ) || ( bdytail != 0.0 )
  4314. || ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) ) {
  4315. Two_Product( bdxtail, cdy, ti1, ti0 );
  4316. Two_Product( bdx, cdytail, tj1, tj0 );
  4317. Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] );
  4318. u[3] = u3;
  4319. negate = -bdy;
  4320. Two_Product( cdxtail, negate, ti1, ti0 );
  4321. negate = -bdytail;
  4322. Two_Product( cdx, negate, tj1, tj0 );
  4323. Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] );
  4324. v[3] = v3;
  4325. bctlen = fast_expansion_sum_zeroelim( 4, u, 4, v, bct );
  4326. Two_Product( bdxtail, cdytail, ti1, ti0 );
  4327. Two_Product( cdxtail, bdytail, tj1, tj0 );
  4328. Two_Two_Diff( ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0] );
  4329. bctt[3] = bctt3;
  4330. bcttlen = 4;
  4331. }
  4332. else {
  4333. bct[0] = 0.0;
  4334. bctlen = 1;
  4335. bctt[0] = 0.0;
  4336. bcttlen = 1;
  4337. }
  4338. if ( adxtail != 0.0 ) {
  4339. temp16alen = scale_expansion_zeroelim( axtbclen, axtbc, adxtail, temp16a );
  4340. axtbctlen = scale_expansion_zeroelim( bctlen, bct, adxtail, axtbct );
  4341. temp32alen = scale_expansion_zeroelim( axtbctlen, axtbct, 2.0 * adx,
  4342. temp32a );
  4343. temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4344. temp32alen, temp32a, temp48 );
  4345. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4346. temp48, finother );
  4347. finswap = finnow; finnow = finother; finother = finswap;
  4348. if ( bdytail != 0.0 ) {
  4349. temp8len = scale_expansion_zeroelim( 4, cc, adxtail, temp8 );
  4350. temp16alen = scale_expansion_zeroelim( temp8len, temp8, bdytail,
  4351. temp16a );
  4352. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen,
  4353. temp16a, finother );
  4354. finswap = finnow; finnow = finother; finother = finswap;
  4355. }
  4356. if ( cdytail != 0.0 ) {
  4357. temp8len = scale_expansion_zeroelim( 4, bb, -adxtail, temp8 );
  4358. temp16alen = scale_expansion_zeroelim( temp8len, temp8, cdytail,
  4359. temp16a );
  4360. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen,
  4361. temp16a, finother );
  4362. finswap = finnow; finnow = finother; finother = finswap;
  4363. }
  4364. temp32alen = scale_expansion_zeroelim( axtbctlen, axtbct, adxtail,
  4365. temp32a );
  4366. axtbcttlen = scale_expansion_zeroelim( bcttlen, bctt, adxtail, axtbctt );
  4367. temp16alen = scale_expansion_zeroelim( axtbcttlen, axtbctt, 2.0 * adx,
  4368. temp16a );
  4369. temp16blen = scale_expansion_zeroelim( axtbcttlen, axtbctt, adxtail,
  4370. temp16b );
  4371. temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4372. temp16blen, temp16b, temp32b );
  4373. temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a,
  4374. temp32blen, temp32b, temp64 );
  4375. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len,
  4376. temp64, finother );
  4377. finswap = finnow; finnow = finother; finother = finswap;
  4378. }
  4379. if ( adytail != 0.0 ) {
  4380. temp16alen = scale_expansion_zeroelim( aytbclen, aytbc, adytail, temp16a );
  4381. aytbctlen = scale_expansion_zeroelim( bctlen, bct, adytail, aytbct );
  4382. temp32alen = scale_expansion_zeroelim( aytbctlen, aytbct, 2.0 * ady,
  4383. temp32a );
  4384. temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4385. temp32alen, temp32a, temp48 );
  4386. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4387. temp48, finother );
  4388. finswap = finnow; finnow = finother; finother = finswap;
  4389. temp32alen = scale_expansion_zeroelim( aytbctlen, aytbct, adytail,
  4390. temp32a );
  4391. aytbcttlen = scale_expansion_zeroelim( bcttlen, bctt, adytail, aytbctt );
  4392. temp16alen = scale_expansion_zeroelim( aytbcttlen, aytbctt, 2.0 * ady,
  4393. temp16a );
  4394. temp16blen = scale_expansion_zeroelim( aytbcttlen, aytbctt, adytail,
  4395. temp16b );
  4396. temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4397. temp16blen, temp16b, temp32b );
  4398. temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a,
  4399. temp32blen, temp32b, temp64 );
  4400. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len,
  4401. temp64, finother );
  4402. finswap = finnow; finnow = finother; finother = finswap;
  4403. }
  4404. }
  4405. if ( ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) ) {
  4406. if ( ( cdxtail != 0.0 ) || ( cdytail != 0.0 )
  4407. || ( adxtail != 0.0 ) || ( adytail != 0.0 ) ) {
  4408. Two_Product( cdxtail, ady, ti1, ti0 );
  4409. Two_Product( cdx, adytail, tj1, tj0 );
  4410. Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] );
  4411. u[3] = u3;
  4412. negate = -cdy;
  4413. Two_Product( adxtail, negate, ti1, ti0 );
  4414. negate = -cdytail;
  4415. Two_Product( adx, negate, tj1, tj0 );
  4416. Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] );
  4417. v[3] = v3;
  4418. catlen = fast_expansion_sum_zeroelim( 4, u, 4, v, cat );
  4419. Two_Product( cdxtail, adytail, ti1, ti0 );
  4420. Two_Product( adxtail, cdytail, tj1, tj0 );
  4421. Two_Two_Diff( ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0] );
  4422. catt[3] = catt3;
  4423. cattlen = 4;
  4424. }
  4425. else {
  4426. cat[0] = 0.0;
  4427. catlen = 1;
  4428. catt[0] = 0.0;
  4429. cattlen = 1;
  4430. }
  4431. if ( bdxtail != 0.0 ) {
  4432. temp16alen = scale_expansion_zeroelim( bxtcalen, bxtca, bdxtail, temp16a );
  4433. bxtcatlen = scale_expansion_zeroelim( catlen, cat, bdxtail, bxtcat );
  4434. temp32alen = scale_expansion_zeroelim( bxtcatlen, bxtcat, 2.0 * bdx,
  4435. temp32a );
  4436. temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4437. temp32alen, temp32a, temp48 );
  4438. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4439. temp48, finother );
  4440. finswap = finnow; finnow = finother; finother = finswap;
  4441. if ( cdytail != 0.0 ) {
  4442. temp8len = scale_expansion_zeroelim( 4, aa, bdxtail, temp8 );
  4443. temp16alen = scale_expansion_zeroelim( temp8len, temp8, cdytail,
  4444. temp16a );
  4445. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen,
  4446. temp16a, finother );
  4447. finswap = finnow; finnow = finother; finother = finswap;
  4448. }
  4449. if ( adytail != 0.0 ) {
  4450. temp8len = scale_expansion_zeroelim( 4, cc, -bdxtail, temp8 );
  4451. temp16alen = scale_expansion_zeroelim( temp8len, temp8, adytail,
  4452. temp16a );
  4453. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen,
  4454. temp16a, finother );
  4455. finswap = finnow; finnow = finother; finother = finswap;
  4456. }
  4457. temp32alen = scale_expansion_zeroelim( bxtcatlen, bxtcat, bdxtail,
  4458. temp32a );
  4459. bxtcattlen = scale_expansion_zeroelim( cattlen, catt, bdxtail, bxtcatt );
  4460. temp16alen = scale_expansion_zeroelim( bxtcattlen, bxtcatt, 2.0 * bdx,
  4461. temp16a );
  4462. temp16blen = scale_expansion_zeroelim( bxtcattlen, bxtcatt, bdxtail,
  4463. temp16b );
  4464. temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4465. temp16blen, temp16b, temp32b );
  4466. temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a,
  4467. temp32blen, temp32b, temp64 );
  4468. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len,
  4469. temp64, finother );
  4470. finswap = finnow; finnow = finother; finother = finswap;
  4471. }
  4472. if ( bdytail != 0.0 ) {
  4473. temp16alen = scale_expansion_zeroelim( bytcalen, bytca, bdytail, temp16a );
  4474. bytcatlen = scale_expansion_zeroelim( catlen, cat, bdytail, bytcat );
  4475. temp32alen = scale_expansion_zeroelim( bytcatlen, bytcat, 2.0 * bdy,
  4476. temp32a );
  4477. temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4478. temp32alen, temp32a, temp48 );
  4479. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4480. temp48, finother );
  4481. finswap = finnow; finnow = finother; finother = finswap;
  4482. temp32alen = scale_expansion_zeroelim( bytcatlen, bytcat, bdytail,
  4483. temp32a );
  4484. bytcattlen = scale_expansion_zeroelim( cattlen, catt, bdytail, bytcatt );
  4485. temp16alen = scale_expansion_zeroelim( bytcattlen, bytcatt, 2.0 * bdy,
  4486. temp16a );
  4487. temp16blen = scale_expansion_zeroelim( bytcattlen, bytcatt, bdytail,
  4488. temp16b );
  4489. temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4490. temp16blen, temp16b, temp32b );
  4491. temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a,
  4492. temp32blen, temp32b, temp64 );
  4493. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len,
  4494. temp64, finother );
  4495. finswap = finnow; finnow = finother; finother = finswap;
  4496. }
  4497. }
  4498. if ( ( cdxtail != 0.0 ) || ( cdytail != 0.0 ) ) {
  4499. if ( ( adxtail != 0.0 ) || ( adytail != 0.0 )
  4500. || ( bdxtail != 0.0 ) || ( bdytail != 0.0 ) ) {
  4501. Two_Product( adxtail, bdy, ti1, ti0 );
  4502. Two_Product( adx, bdytail, tj1, tj0 );
  4503. Two_Two_Sum( ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0] );
  4504. u[3] = u3;
  4505. negate = -ady;
  4506. Two_Product( bdxtail, negate, ti1, ti0 );
  4507. negate = -adytail;
  4508. Two_Product( bdx, negate, tj1, tj0 );
  4509. Two_Two_Sum( ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0] );
  4510. v[3] = v3;
  4511. abtlen = fast_expansion_sum_zeroelim( 4, u, 4, v, abt );
  4512. Two_Product( adxtail, bdytail, ti1, ti0 );
  4513. Two_Product( bdxtail, adytail, tj1, tj0 );
  4514. Two_Two_Diff( ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0] );
  4515. abtt[3] = abtt3;
  4516. abttlen = 4;
  4517. }
  4518. else {
  4519. abt[0] = 0.0;
  4520. abtlen = 1;
  4521. abtt[0] = 0.0;
  4522. abttlen = 1;
  4523. }
  4524. if ( cdxtail != 0.0 ) {
  4525. temp16alen = scale_expansion_zeroelim( cxtablen, cxtab, cdxtail, temp16a );
  4526. cxtabtlen = scale_expansion_zeroelim( abtlen, abt, cdxtail, cxtabt );
  4527. temp32alen = scale_expansion_zeroelim( cxtabtlen, cxtabt, 2.0 * cdx,
  4528. temp32a );
  4529. temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4530. temp32alen, temp32a, temp48 );
  4531. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4532. temp48, finother );
  4533. finswap = finnow; finnow = finother; finother = finswap;
  4534. if ( adytail != 0.0 ) {
  4535. temp8len = scale_expansion_zeroelim( 4, bb, cdxtail, temp8 );
  4536. temp16alen = scale_expansion_zeroelim( temp8len, temp8, adytail,
  4537. temp16a );
  4538. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen,
  4539. temp16a, finother );
  4540. finswap = finnow; finnow = finother; finother = finswap;
  4541. }
  4542. if ( bdytail != 0.0 ) {
  4543. temp8len = scale_expansion_zeroelim( 4, aa, -cdxtail, temp8 );
  4544. temp16alen = scale_expansion_zeroelim( temp8len, temp8, bdytail,
  4545. temp16a );
  4546. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp16alen,
  4547. temp16a, finother );
  4548. finswap = finnow; finnow = finother; finother = finswap;
  4549. }
  4550. temp32alen = scale_expansion_zeroelim( cxtabtlen, cxtabt, cdxtail,
  4551. temp32a );
  4552. cxtabttlen = scale_expansion_zeroelim( abttlen, abtt, cdxtail, cxtabtt );
  4553. temp16alen = scale_expansion_zeroelim( cxtabttlen, cxtabtt, 2.0 * cdx,
  4554. temp16a );
  4555. temp16blen = scale_expansion_zeroelim( cxtabttlen, cxtabtt, cdxtail,
  4556. temp16b );
  4557. temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4558. temp16blen, temp16b, temp32b );
  4559. temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a,
  4560. temp32blen, temp32b, temp64 );
  4561. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len,
  4562. temp64, finother );
  4563. finswap = finnow; finnow = finother; finother = finswap;
  4564. }
  4565. if ( cdytail != 0.0 ) {
  4566. temp16alen = scale_expansion_zeroelim( cytablen, cytab, cdytail, temp16a );
  4567. cytabtlen = scale_expansion_zeroelim( abtlen, abt, cdytail, cytabt );
  4568. temp32alen = scale_expansion_zeroelim( cytabtlen, cytabt, 2.0 * cdy,
  4569. temp32a );
  4570. temp48len = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4571. temp32alen, temp32a, temp48 );
  4572. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp48len,
  4573. temp48, finother );
  4574. finswap = finnow; finnow = finother; finother = finswap;
  4575. temp32alen = scale_expansion_zeroelim( cytabtlen, cytabt, cdytail,
  4576. temp32a );
  4577. cytabttlen = scale_expansion_zeroelim( abttlen, abtt, cdytail, cytabtt );
  4578. temp16alen = scale_expansion_zeroelim( cytabttlen, cytabtt, 2.0 * cdy,
  4579. temp16a );
  4580. temp16blen = scale_expansion_zeroelim( cytabttlen, cytabtt, cdytail,
  4581. temp16b );
  4582. temp32blen = fast_expansion_sum_zeroelim( temp16alen, temp16a,
  4583. temp16blen, temp16b, temp32b );
  4584. temp64len = fast_expansion_sum_zeroelim( temp32alen, temp32a,
  4585. temp32blen, temp32b, temp64 );
  4586. finlength = fast_expansion_sum_zeroelim( finlength, finnow, temp64len,
  4587. temp64, finother );
  4588. finswap = finnow; finnow = finother; finother = finswap;
  4589. }
  4590. }
  4591. return finnow[finlength - 1];
  4592. }
  4593. REAL incircle( pa, pb, pc, pd )
  4594. point pa;
  4595. point pb;
  4596. point pc;
  4597. point pd;
  4598. {
  4599. REAL adx, bdx, cdx, ady, bdy, cdy;
  4600. REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
  4601. REAL alift, blift, clift;
  4602. REAL det;
  4603. REAL permanent, errbound;
  4604. incirclecount++;
  4605. adx = pa[0] - pd[0];
  4606. bdx = pb[0] - pd[0];
  4607. cdx = pc[0] - pd[0];
  4608. ady = pa[1] - pd[1];
  4609. bdy = pb[1] - pd[1];
  4610. cdy = pc[1] - pd[1];
  4611. bdxcdy = bdx * cdy;
  4612. cdxbdy = cdx * bdy;
  4613. alift = adx * adx + ady * ady;
  4614. cdxady = cdx * ady;
  4615. adxcdy = adx * cdy;
  4616. blift = bdx * bdx + bdy * bdy;
  4617. adxbdy = adx * bdy;
  4618. bdxady = bdx * ady;
  4619. clift = cdx * cdx + cdy * cdy;
  4620. det = alift * ( bdxcdy - cdxbdy )
  4621. + blift * ( cdxady - adxcdy )
  4622. + clift * ( adxbdy - bdxady );
  4623. if ( noexact ) {
  4624. return det;
  4625. }
  4626. permanent = ( Absolute( bdxcdy ) + Absolute( cdxbdy ) ) * alift
  4627. + ( Absolute( cdxady ) + Absolute( adxcdy ) ) * blift
  4628. + ( Absolute( adxbdy ) + Absolute( bdxady ) ) * clift;
  4629. errbound = iccerrboundA * permanent;
  4630. if ( ( det > errbound ) || ( -det > errbound ) ) {
  4631. return det;
  4632. }
  4633. return incircleadapt( pa, pb, pc, pd, permanent );
  4634. }
  4635. /** **/
  4636. /** **/
  4637. /********* Determinant evaluation routines end here *********/
  4638. /*****************************************************************************/
  4639. /* */
  4640. /* triangleinit() Initialize some variables. */
  4641. /* */
  4642. /*****************************************************************************/
  4643. void triangleinit(){
  4644. points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems =
  4645. badsegments.maxitems = badtriangles.maxitems = splaynodes.maxitems = 0l;
  4646. points.itembytes = triangles.itembytes = shelles.itembytes = viri.itembytes =
  4647. badsegments.itembytes = badtriangles.itembytes = splaynodes.itembytes = 0;
  4648. recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */
  4649. samples = 1; /* Point location should take at least one sample. */
  4650. checksegments = 0; /* There are no segments in the triangulation yet. */
  4651. incirclecount = counterclockcount = hyperbolacount = 0;
  4652. circumcentercount = circletopcount = 0;
  4653. randomseed = 1;
  4654. exactinit(); /* Initialize exact arithmetic constants. */
  4655. }
  4656. /*****************************************************************************/
  4657. /* */
  4658. /* randomnation() Generate a random number between 0 and `choices' - 1. */
  4659. /* */
  4660. /* This is a simple linear congruential random number generator. Hence, it */
  4661. /* is a bad random number generator, but good enough for most randomized */
  4662. /* geometric algorithms. */
  4663. /* */
  4664. /*****************************************************************************/
  4665. unsigned long randomnation( choices )
  4666. unsigned int choices;
  4667. {
  4668. randomseed = ( randomseed * 1366l + 150889l ) % 714025l;
  4669. return randomseed / ( 714025l / choices + 1 );
  4670. }
  4671. /********* Mesh quality testing routines begin here *********/
  4672. /** **/
  4673. /** **/
  4674. /*****************************************************************************/
  4675. /* */
  4676. /* checkmesh() Test the mesh for topological consistency. */
  4677. /* */
  4678. /*****************************************************************************/
  4679. #ifndef REDUCED
  4680. void checkmesh(){
  4681. struct triedge triangleloop;
  4682. struct triedge oppotri, oppooppotri;
  4683. point triorg, tridest, triapex;
  4684. point oppoorg, oppodest;
  4685. int horrors;
  4686. int saveexact;
  4687. triangle ptr; /* Temporary variable used by sym(). */
  4688. /* Temporarily turn on exact arithmetic if it's off. */
  4689. saveexact = noexact;
  4690. noexact = 0;
  4691. if ( !quiet ) {
  4692. printf( " Checking consistency of mesh...\n" );
  4693. }
  4694. horrors = 0;
  4695. /* Run through the list of triangles, checking each one. */
  4696. traversalinit( &triangles );
  4697. triangleloop.tri = triangletraverse();
  4698. while ( triangleloop.tri != (triangle *) NULL ) {
  4699. /* Check all three edges of the triangle. */
  4700. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  4701. triangleloop.orient++ ) {
  4702. org( triangleloop, triorg );
  4703. dest( triangleloop, tridest );
  4704. if ( triangleloop.orient == 0 ) { /* Only test for inversion once. */
  4705. /* Test if the triangle is flat or inverted. */
  4706. apex( triangleloop, triapex );
  4707. if ( counterclockwise( triorg, tridest, triapex ) <= 0.0 ) {
  4708. printf( " !! !! Inverted " );
  4709. printtriangle( &triangleloop );
  4710. horrors++;
  4711. }
  4712. }
  4713. /* Find the neighboring triangle on this edge. */
  4714. sym( triangleloop, oppotri );
  4715. if ( oppotri.tri != dummytri ) {
  4716. /* Check that the triangle's neighbor knows it's a neighbor. */
  4717. sym( oppotri, oppooppotri );
  4718. if ( ( triangleloop.tri != oppooppotri.tri )
  4719. || ( triangleloop.orient != oppooppotri.orient ) ) {
  4720. printf( " !! !! Asymmetric triangle-triangle bond:\n" );
  4721. if ( triangleloop.tri == oppooppotri.tri ) {
  4722. printf( " (Right triangle, wrong orientation)\n" );
  4723. }
  4724. printf( " First " );
  4725. printtriangle( &triangleloop );
  4726. printf( " Second (nonreciprocating) " );
  4727. printtriangle( &oppotri );
  4728. horrors++;
  4729. }
  4730. /* Check that both triangles agree on the identities */
  4731. /* of their shared vertices. */
  4732. org( oppotri, oppoorg );
  4733. dest( oppotri, oppodest );
  4734. if ( ( triorg != oppodest ) || ( tridest != oppoorg ) ) {
  4735. printf( " !! !! Mismatched edge coordinates between two triangles:\n"
  4736. );
  4737. printf( " First mismatched " );
  4738. printtriangle( &triangleloop );
  4739. printf( " Second mismatched " );
  4740. printtriangle( &oppotri );
  4741. horrors++;
  4742. }
  4743. }
  4744. }
  4745. triangleloop.tri = triangletraverse();
  4746. }
  4747. if ( horrors == 0 ) {
  4748. if ( !quiet ) {
  4749. printf( " In my studied opinion, the mesh appears to be consistent.\n" );
  4750. }
  4751. }
  4752. else if ( horrors == 1 ) {
  4753. printf( " !! !! !! !! Precisely one festering wound discovered.\n" );
  4754. }
  4755. else {
  4756. printf( " !! !! !! !! %d abominations witnessed.\n", horrors );
  4757. }
  4758. /* Restore the status of exact arithmetic. */
  4759. noexact = saveexact;
  4760. }
  4761. #endif /* not REDUCED */
  4762. /*****************************************************************************/
  4763. /* */
  4764. /* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */
  4765. /* */
  4766. /*****************************************************************************/
  4767. #ifndef REDUCED
  4768. void checkdelaunay(){
  4769. struct triedge triangleloop;
  4770. struct triedge oppotri;
  4771. struct edge opposhelle;
  4772. point triorg, tridest, triapex;
  4773. point oppoapex;
  4774. int shouldbedelaunay;
  4775. int horrors;
  4776. int saveexact;
  4777. triangle ptr; /* Temporary variable used by sym(). */
  4778. shelle sptr; /* Temporary variable used by tspivot(). */
  4779. /* Temporarily turn on exact arithmetic if it's off. */
  4780. saveexact = noexact;
  4781. noexact = 0;
  4782. if ( !quiet ) {
  4783. printf( " Checking Delaunay property of mesh...\n" );
  4784. }
  4785. horrors = 0;
  4786. /* Run through the list of triangles, checking each one. */
  4787. traversalinit( &triangles );
  4788. triangleloop.tri = triangletraverse();
  4789. while ( triangleloop.tri != (triangle *) NULL ) {
  4790. /* Check all three edges of the triangle. */
  4791. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  4792. triangleloop.orient++ ) {
  4793. org( triangleloop, triorg );
  4794. dest( triangleloop, tridest );
  4795. apex( triangleloop, triapex );
  4796. sym( triangleloop, oppotri );
  4797. apex( oppotri, oppoapex );
  4798. /* Only test that the edge is locally Delaunay if there is an */
  4799. /* adjoining triangle whose pointer is larger (to ensure that */
  4800. /* each pair isn't tested twice). */
  4801. shouldbedelaunay = ( oppotri.tri != dummytri )
  4802. && ( triapex != (point) NULL ) && ( oppoapex != (point) NULL )
  4803. && ( triangleloop.tri < oppotri.tri );
  4804. if ( checksegments && shouldbedelaunay ) {
  4805. /* If a shell edge separates the triangles, then the edge is */
  4806. /* constrained, so no local Delaunay test should be done. */
  4807. tspivot( triangleloop, opposhelle );
  4808. if ( opposhelle.sh != dummysh ) {
  4809. shouldbedelaunay = 0;
  4810. }
  4811. }
  4812. if ( shouldbedelaunay ) {
  4813. if ( incircle( triorg, tridest, triapex, oppoapex ) > 0.0 ) {
  4814. printf( " !! !! Non-Delaunay pair of triangles:\n" );
  4815. printf( " First non-Delaunay " );
  4816. printtriangle( &triangleloop );
  4817. printf( " Second non-Delaunay " );
  4818. printtriangle( &oppotri );
  4819. horrors++;
  4820. }
  4821. }
  4822. }
  4823. triangleloop.tri = triangletraverse();
  4824. }
  4825. if ( horrors == 0 ) {
  4826. if ( !quiet ) {
  4827. printf(
  4828. " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n" );
  4829. }
  4830. }
  4831. else if ( horrors == 1 ) {
  4832. printf(
  4833. " !! !! !! !! Precisely one terrifying transgression identified.\n" );
  4834. }
  4835. else {
  4836. printf( " !! !! !! !! %d obscenities viewed with horror.\n", horrors );
  4837. }
  4838. /* Restore the status of exact arithmetic. */
  4839. noexact = saveexact;
  4840. }
  4841. #endif /* not REDUCED */
  4842. /*****************************************************************************/
  4843. /* */
  4844. /* enqueuebadtri() Add a bad triangle to the end of a queue. */
  4845. /* */
  4846. /* The queue is actually a set of 64 queues. I use multiple queues to give */
  4847. /* priority to smaller angles. I originally implemented a heap, but the */
  4848. /* queues are (to my surprise) much faster. */
  4849. /* */
  4850. /*****************************************************************************/
  4851. #ifndef CDT_ONLY
  4852. void enqueuebadtri( instri, angle, insapex, insorg, insdest )
  4853. struct triedge *instri;
  4854. REAL angle;
  4855. point insapex;
  4856. point insorg;
  4857. point insdest;
  4858. {
  4859. struct badface *newface;
  4860. int queuenumber;
  4861. if ( verbose > 2 ) {
  4862. printf( " Queueing bad triangle:\n" );
  4863. printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", insorg[0],
  4864. insorg[1], insdest[0], insdest[1], insapex[0], insapex[1] );
  4865. }
  4866. /* Allocate space for the bad triangle. */
  4867. newface = (struct badface *) poolalloc( &badtriangles );
  4868. triedgecopy( *instri, newface->badfacetri );
  4869. newface->key = angle;
  4870. newface->faceapex = insapex;
  4871. newface->faceorg = insorg;
  4872. newface->facedest = insdest;
  4873. newface->nextface = (struct badface *) NULL;
  4874. /* Determine the appropriate queue to put the bad triangle into. */
  4875. if ( angle > 0.6 ) {
  4876. queuenumber = (int) ( 160.0 * ( angle - 0.6 ) );
  4877. if ( queuenumber > 63 ) {
  4878. queuenumber = 63;
  4879. }
  4880. }
  4881. else {
  4882. /* It's not a bad angle; put the triangle in the lowest-priority queue. */
  4883. queuenumber = 0;
  4884. }
  4885. /* Add the triangle to the end of a queue. */
  4886. *queuetail[queuenumber] = newface;
  4887. /* Maintain a pointer to the NULL pointer at the end of the queue. */
  4888. queuetail[queuenumber] = &newface->nextface;
  4889. }
  4890. #endif /* not CDT_ONLY */
  4891. /*****************************************************************************/
  4892. /* */
  4893. /* dequeuebadtri() Remove a triangle from the front of the queue. */
  4894. /* */
  4895. /*****************************************************************************/
  4896. #ifndef CDT_ONLY
  4897. struct badface *dequeuebadtri(){
  4898. struct badface *result;
  4899. int queuenumber;
  4900. /* Look for a nonempty queue. */
  4901. for ( queuenumber = 63; queuenumber >= 0; queuenumber-- ) {
  4902. result = queuefront[queuenumber];
  4903. if ( result != (struct badface *) NULL ) {
  4904. /* Remove the triangle from the queue. */
  4905. queuefront[queuenumber] = result->nextface;
  4906. /* Maintain a pointer to the NULL pointer at the end of the queue. */
  4907. if ( queuefront[queuenumber] == (struct badface *) NULL ) {
  4908. queuetail[queuenumber] = &queuefront[queuenumber];
  4909. }
  4910. return result;
  4911. }
  4912. }
  4913. return (struct badface *) NULL;
  4914. }
  4915. #endif /* not CDT_ONLY */
  4916. /*****************************************************************************/
  4917. /* */
  4918. /* checkedge4encroach() Check a segment to see if it is encroached; add */
  4919. /* it to the list if it is. */
  4920. /* */
  4921. /* An encroached segment is an unflippable edge that has a point in its */
  4922. /* diametral circle (that is, it faces an angle greater than 90 degrees). */
  4923. /* This definition is due to Ruppert. */
  4924. /* */
  4925. /* Returns a nonzero value if the edge is encroached. */
  4926. /* */
  4927. /*****************************************************************************/
  4928. #ifndef CDT_ONLY
  4929. int checkedge4encroach( testedge )
  4930. struct edge *testedge;
  4931. {
  4932. struct triedge neighbortri;
  4933. struct edge testsym;
  4934. struct edge *badedge;
  4935. int addtolist;
  4936. int sides;
  4937. point eorg, edest, eapex;
  4938. triangle ptr; /* Temporary variable used by stpivot(). */
  4939. addtolist = 0;
  4940. sides = 0;
  4941. sorg( *testedge, eorg );
  4942. sdest( *testedge, edest );
  4943. /* Check one neighbor of the shell edge. */
  4944. stpivot( *testedge, neighbortri );
  4945. /* Does the neighbor exist, or is this a boundary edge? */
  4946. if ( neighbortri.tri != dummytri ) {
  4947. sides++;
  4948. /* Find a vertex opposite this edge. */
  4949. apex( neighbortri, eapex );
  4950. /* Check whether the vertex is inside the diametral circle of the */
  4951. /* shell edge. Pythagoras' Theorem is used to check whether the */
  4952. /* angle at the vertex is greater than 90 degrees. */
  4953. if ( eapex[0] * ( eorg[0] + edest[0] ) + eapex[1] * ( eorg[1] + edest[1] ) >
  4954. eapex[0] * eapex[0] + eorg[0] * edest[0] +
  4955. eapex[1] * eapex[1] + eorg[1] * edest[1] ) {
  4956. addtolist = 1;
  4957. }
  4958. }
  4959. /* Check the other neighbor of the shell edge. */
  4960. ssym( *testedge, testsym );
  4961. stpivot( testsym, neighbortri );
  4962. /* Does the neighbor exist, or is this a boundary edge? */
  4963. if ( neighbortri.tri != dummytri ) {
  4964. sides++;
  4965. /* Find the other vertex opposite this edge. */
  4966. apex( neighbortri, eapex );
  4967. /* Check whether the vertex is inside the diametral circle of the */
  4968. /* shell edge. Pythagoras' Theorem is used to check whether the */
  4969. /* angle at the vertex is greater than 90 degrees. */
  4970. if ( eapex[0] * ( eorg[0] + edest[0] ) +
  4971. eapex[1] * ( eorg[1] + edest[1] ) >
  4972. eapex[0] * eapex[0] + eorg[0] * edest[0] +
  4973. eapex[1] * eapex[1] + eorg[1] * edest[1] ) {
  4974. addtolist += 2;
  4975. }
  4976. }
  4977. if ( addtolist && ( !nobisect || ( ( nobisect == 1 ) && ( sides == 2 ) ) ) ) {
  4978. if ( verbose > 2 ) {
  4979. printf( " Queueing encroached segment (%.12g, %.12g) (%.12g, %.12g).\n",
  4980. eorg[0], eorg[1], edest[0], edest[1] );
  4981. }
  4982. /* Add the shell edge to the list of encroached segments. */
  4983. /* Be sure to get the orientation right. */
  4984. badedge = (struct edge *) poolalloc( &badsegments );
  4985. if ( addtolist == 1 ) {
  4986. shellecopy( *testedge, *badedge );
  4987. }
  4988. else {
  4989. shellecopy( testsym, *badedge );
  4990. }
  4991. }
  4992. return addtolist;
  4993. }
  4994. #endif /* not CDT_ONLY */
  4995. /*****************************************************************************/
  4996. /* */
  4997. /* testtriangle() Test a face for quality measures. */
  4998. /* */
  4999. /* Tests a triangle to see if it satisfies the minimum angle condition and */
  5000. /* the maximum area condition. Triangles that aren't up to spec are added */
  5001. /* to the bad triangle queue. */
  5002. /* */
  5003. /*****************************************************************************/
  5004. #ifndef CDT_ONLY
  5005. void testtriangle( testtri )
  5006. struct triedge *testtri;
  5007. {
  5008. struct triedge sametesttri;
  5009. struct edge edge1, edge2;
  5010. point torg, tdest, tapex;
  5011. point anglevertex;
  5012. REAL dxod, dyod, dxda, dyda, dxao, dyao;
  5013. REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
  5014. REAL apexlen, orglen, destlen;
  5015. REAL angle;
  5016. REAL area;
  5017. shelle sptr; /* Temporary variable used by tspivot(). */
  5018. org( *testtri, torg );
  5019. dest( *testtri, tdest );
  5020. apex( *testtri, tapex );
  5021. dxod = torg[0] - tdest[0];
  5022. dyod = torg[1] - tdest[1];
  5023. dxda = tdest[0] - tapex[0];
  5024. dyda = tdest[1] - tapex[1];
  5025. dxao = tapex[0] - torg[0];
  5026. dyao = tapex[1] - torg[1];
  5027. dxod2 = dxod * dxod;
  5028. dyod2 = dyod * dyod;
  5029. dxda2 = dxda * dxda;
  5030. dyda2 = dyda * dyda;
  5031. dxao2 = dxao * dxao;
  5032. dyao2 = dyao * dyao;
  5033. /* Find the lengths of the triangle's three edges. */
  5034. apexlen = dxod2 + dyod2;
  5035. orglen = dxda2 + dyda2;
  5036. destlen = dxao2 + dyao2;
  5037. if ( ( apexlen < orglen ) && ( apexlen < destlen ) ) {
  5038. /* The edge opposite the apex is shortest. */
  5039. /* Find the square of the cosine of the angle at the apex. */
  5040. angle = dxda * dxao + dyda * dyao;
  5041. angle = angle * angle / ( orglen * destlen );
  5042. anglevertex = tapex;
  5043. lnext( *testtri, sametesttri );
  5044. tspivot( sametesttri, edge1 );
  5045. lnextself( sametesttri );
  5046. tspivot( sametesttri, edge2 );
  5047. }
  5048. else if ( orglen < destlen ) {
  5049. /* The edge opposite the origin is shortest. */
  5050. /* Find the square of the cosine of the angle at the origin. */
  5051. angle = dxod * dxao + dyod * dyao;
  5052. angle = angle * angle / ( apexlen * destlen );
  5053. anglevertex = torg;
  5054. tspivot( *testtri, edge1 );
  5055. lprev( *testtri, sametesttri );
  5056. tspivot( sametesttri, edge2 );
  5057. }
  5058. else {
  5059. /* The edge opposite the destination is shortest. */
  5060. /* Find the square of the cosine of the angle at the destination. */
  5061. angle = dxod * dxda + dyod * dyda;
  5062. angle = angle * angle / ( apexlen * orglen );
  5063. anglevertex = tdest;
  5064. tspivot( *testtri, edge1 );
  5065. lnext( *testtri, sametesttri );
  5066. tspivot( sametesttri, edge2 );
  5067. }
  5068. /* Check if both edges that form the angle are segments. */
  5069. if ( ( edge1.sh != dummysh ) && ( edge2.sh != dummysh ) ) {
  5070. /* The angle is a segment intersection. */
  5071. if ( ( angle > 0.9924 ) && !quiet ) { /* Roughly 5 degrees. */
  5072. if ( angle > 1.0 ) {
  5073. /* Beware of a floating exception in acos(). */
  5074. angle = 1.0;
  5075. }
  5076. /* Find the actual angle in degrees, for printing. */
  5077. angle = acos( sqrt( angle ) ) * ( 180.0 / PI );
  5078. printf(
  5079. "Warning: Small angle (%.4g degrees) between segments at point\n",
  5080. angle );
  5081. printf( " (%.12g, %.12g)\n", anglevertex[0], anglevertex[1] );
  5082. }
  5083. /* Don't add this bad triangle to the list; there's nothing that */
  5084. /* can be done about a small angle between two segments. */
  5085. angle = 0.0;
  5086. }
  5087. /* Check whether the angle is smaller than permitted. */
  5088. if ( angle > goodangle ) {
  5089. /* Add this triangle to the list of bad triangles. */
  5090. enqueuebadtri( testtri, angle, tapex, torg, tdest );
  5091. return;
  5092. }
  5093. if ( vararea || fixedarea ) {
  5094. /* Check whether the area is larger than permitted. */
  5095. area = 0.5 * ( dxod * dyda - dyod * dxda );
  5096. if ( fixedarea && ( area > maxarea ) ) {
  5097. /* Add this triangle to the list of bad triangles. */
  5098. enqueuebadtri( testtri, angle, tapex, torg, tdest );
  5099. }
  5100. else if ( vararea ) {
  5101. /* Nonpositive area constraints are treated as unconstrained. */
  5102. if ( ( area > areabound( *testtri ) ) && ( areabound( *testtri ) > 0.0 ) ) {
  5103. /* Add this triangle to the list of bad triangles. */
  5104. enqueuebadtri( testtri, angle, tapex, torg, tdest );
  5105. }
  5106. }
  5107. }
  5108. }
  5109. #endif /* not CDT_ONLY */
  5110. /** **/
  5111. /** **/
  5112. /********* Mesh quality testing routines end here *********/
  5113. /********* Point location routines begin here *********/
  5114. /** **/
  5115. /** **/
  5116. /*****************************************************************************/
  5117. /* */
  5118. /* makepointmap() Construct a mapping from points to triangles to improve */
  5119. /* the speed of point location for segment insertion. */
  5120. /* */
  5121. /* Traverses all the triangles, and provides each corner of each triangle */
  5122. /* with a pointer to that triangle. Of course, pointers will be */
  5123. /* overwritten by other pointers because (almost) each point is a corner */
  5124. /* of several triangles, but in the end every point will point to some */
  5125. /* triangle that contains it. */
  5126. /* */
  5127. /*****************************************************************************/
  5128. void makepointmap(){
  5129. struct triedge triangleloop;
  5130. point triorg;
  5131. if ( verbose ) {
  5132. printf( " Constructing mapping from points to triangles.\n" );
  5133. }
  5134. traversalinit( &triangles );
  5135. triangleloop.tri = triangletraverse();
  5136. while ( triangleloop.tri != (triangle *) NULL ) {
  5137. /* Check all three points of the triangle. */
  5138. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  5139. triangleloop.orient++ ) {
  5140. org( triangleloop, triorg );
  5141. setpoint2tri( triorg, encode( triangleloop ) );
  5142. }
  5143. triangleloop.tri = triangletraverse();
  5144. }
  5145. }
  5146. /*****************************************************************************/
  5147. /* */
  5148. /* preciselocate() Find a triangle or edge containing a given point. */
  5149. /* */
  5150. /* Begins its search from `searchtri'. It is important that `searchtri' */
  5151. /* be a handle with the property that `searchpoint' is strictly to the left */
  5152. /* of the edge denoted by `searchtri', or is collinear with that edge and */
  5153. /* does not intersect that edge. (In particular, `searchpoint' should not */
  5154. /* be the origin or destination of that edge.) */
  5155. /* */
  5156. /* These conditions are imposed because preciselocate() is normally used in */
  5157. /* one of two situations: */
  5158. /* */
  5159. /* (1) To try to find the location to insert a new point. Normally, we */
  5160. /* know an edge that the point is strictly to the left of. In the */
  5161. /* incremental Delaunay algorithm, that edge is a bounding box edge. */
  5162. /* In Ruppert's Delaunay refinement algorithm for quality meshing, */
  5163. /* that edge is the shortest edge of the triangle whose circumcenter */
  5164. /* is being inserted. */
  5165. /* */
  5166. /* (2) To try to find an existing point. In this case, any edge on the */
  5167. /* convex hull is a good starting edge. The possibility that the */
  5168. /* vertex one seeks is an endpoint of the starting edge must be */
  5169. /* screened out before preciselocate() is called. */
  5170. /* */
  5171. /* On completion, `searchtri' is a triangle that contains `searchpoint'. */
  5172. /* */
  5173. /* This implementation differs from that given by Guibas and Stolfi. It */
  5174. /* walks from triangle to triangle, crossing an edge only if `searchpoint' */
  5175. /* is on the other side of the line containing that edge. After entering */
  5176. /* a triangle, there are two edges by which one can leave that triangle. */
  5177. /* If both edges are valid (`searchpoint' is on the other side of both */
  5178. /* edges), one of the two is chosen by drawing a line perpendicular to */
  5179. /* the entry edge (whose endpoints are `forg' and `fdest') passing through */
  5180. /* `fapex'. Depending on which side of this perpendicular `searchpoint' */
  5181. /* falls on, an exit edge is chosen. */
  5182. /* */
  5183. /* This implementation is empirically faster than the Guibas and Stolfi */
  5184. /* point location routine (which I originally used), which tends to spiral */
  5185. /* in toward its target. */
  5186. /* */
  5187. /* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
  5188. /* is a handle whose origin is the existing vertex. */
  5189. /* */
  5190. /* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
  5191. /* handle whose primary edge is the edge on which the point lies. */
  5192. /* */
  5193. /* Returns INTRIANGLE if the point lies strictly within a triangle. */
  5194. /* `searchtri' is a handle on the triangle that contains the point. */
  5195. /* */
  5196. /* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
  5197. /* handle whose primary edge the point is to the right of. This might */
  5198. /* occur when the circumcenter of a triangle falls just slightly outside */
  5199. /* the mesh due to floating-point roundoff error. It also occurs when */
  5200. /* seeking a hole or region point that a foolish user has placed outside */
  5201. /* the mesh. */
  5202. /* */
  5203. /* WARNING: This routine is designed for convex triangulations, and will */
  5204. /* not generally work after the holes and concavities have been carved. */
  5205. /* However, it can still be used to find the circumcenter of a triangle, as */
  5206. /* long as the search is begun from the triangle in question. */
  5207. /* */
  5208. /*****************************************************************************/
  5209. enum locateresult preciselocate( searchpoint, searchtri )
  5210. point searchpoint;
  5211. struct triedge *searchtri;
  5212. {
  5213. struct triedge backtracktri;
  5214. point forg, fdest, fapex;
  5215. point swappoint;
  5216. REAL orgorient, destorient;
  5217. int moveleft;
  5218. triangle ptr; /* Temporary variable used by sym(). */
  5219. if ( verbose > 2 ) {
  5220. printf( " Searching for point (%.12g, %.12g).\n",
  5221. searchpoint[0], searchpoint[1] );
  5222. }
  5223. /* Where are we? */
  5224. org( *searchtri, forg );
  5225. dest( *searchtri, fdest );
  5226. apex( *searchtri, fapex );
  5227. while ( 1 ) {
  5228. if ( verbose > 2 ) {
  5229. printf( " At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
  5230. forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1] );
  5231. }
  5232. /* Check whether the apex is the point we seek. */
  5233. if ( ( fapex[0] == searchpoint[0] ) && ( fapex[1] == searchpoint[1] ) ) {
  5234. lprevself( *searchtri );
  5235. return ONVERTEX;
  5236. }
  5237. /* Does the point lie on the other side of the line defined by the */
  5238. /* triangle edge opposite the triangle's destination? */
  5239. destorient = counterclockwise( forg, fapex, searchpoint );
  5240. /* Does the point lie on the other side of the line defined by the */
  5241. /* triangle edge opposite the triangle's origin? */
  5242. orgorient = counterclockwise( fapex, fdest, searchpoint );
  5243. if ( destorient > 0.0 ) {
  5244. if ( orgorient > 0.0 ) {
  5245. /* Move left if the inner product of (fapex - searchpoint) and */
  5246. /* (fdest - forg) is positive. This is equivalent to drawing */
  5247. /* a line perpendicular to the line (forg, fdest) passing */
  5248. /* through `fapex', and determining which side of this line */
  5249. /* `searchpoint' falls on. */
  5250. moveleft = ( fapex[0] - searchpoint[0] ) * ( fdest[0] - forg[0] ) +
  5251. ( fapex[1] - searchpoint[1] ) * ( fdest[1] - forg[1] ) > 0.0;
  5252. }
  5253. else {
  5254. moveleft = 1;
  5255. }
  5256. }
  5257. else {
  5258. if ( orgorient > 0.0 ) {
  5259. moveleft = 0;
  5260. }
  5261. else {
  5262. /* The point we seek must be on the boundary of or inside this */
  5263. /* triangle. */
  5264. if ( destorient == 0.0 ) {
  5265. lprevself( *searchtri );
  5266. return ONEDGE;
  5267. }
  5268. if ( orgorient == 0.0 ) {
  5269. lnextself( *searchtri );
  5270. return ONEDGE;
  5271. }
  5272. return INTRIANGLE;
  5273. }
  5274. }
  5275. /* Move to another triangle. Leave a trace `backtracktri' in case */
  5276. /* floating-point roundoff or some such bogey causes us to walk */
  5277. /* off a boundary of the triangulation. We can just bounce off */
  5278. /* the boundary as if it were an elastic band. */
  5279. if ( moveleft ) {
  5280. lprev( *searchtri, backtracktri );
  5281. fdest = fapex;
  5282. }
  5283. else {
  5284. lnext( *searchtri, backtracktri );
  5285. forg = fapex;
  5286. }
  5287. sym( backtracktri, *searchtri );
  5288. /* Check for walking off the edge. */
  5289. if ( searchtri->tri == dummytri ) {
  5290. /* Turn around. */
  5291. triedgecopy( backtracktri, *searchtri );
  5292. swappoint = forg;
  5293. forg = fdest;
  5294. fdest = swappoint;
  5295. apex( *searchtri, fapex );
  5296. /* Check if the point really is beyond the triangulation boundary. */
  5297. destorient = counterclockwise( forg, fapex, searchpoint );
  5298. orgorient = counterclockwise( fapex, fdest, searchpoint );
  5299. if ( ( orgorient < 0.0 ) && ( destorient < 0.0 ) ) {
  5300. return OUTSIDE;
  5301. }
  5302. }
  5303. else {
  5304. apex( *searchtri, fapex );
  5305. }
  5306. }
  5307. }
  5308. /*****************************************************************************/
  5309. /* */
  5310. /* locate() Find a triangle or edge containing a given point. */
  5311. /* */
  5312. /* Searching begins from one of: the input `searchtri', a recently */
  5313. /* encountered triangle `recenttri', or from a triangle chosen from a */
  5314. /* random sample. The choice is made by determining which triangle's */
  5315. /* origin is closest to the point we are searcing for. Normally, */
  5316. /* `searchtri' should be a handle on the convex hull of the triangulation. */
  5317. /* */
  5318. /* Details on the random sampling method can be found in the Mucke, Saias, */
  5319. /* and Zhu paper cited in the header of this code. */
  5320. /* */
  5321. /* On completion, `searchtri' is a triangle that contains `searchpoint'. */
  5322. /* */
  5323. /* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */
  5324. /* is a handle whose origin is the existing vertex. */
  5325. /* */
  5326. /* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */
  5327. /* handle whose primary edge is the edge on which the point lies. */
  5328. /* */
  5329. /* Returns INTRIANGLE if the point lies strictly within a triangle. */
  5330. /* `searchtri' is a handle on the triangle that contains the point. */
  5331. /* */
  5332. /* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */
  5333. /* handle whose primary edge the point is to the right of. This might */
  5334. /* occur when the circumcenter of a triangle falls just slightly outside */
  5335. /* the mesh due to floating-point roundoff error. It also occurs when */
  5336. /* seeking a hole or region point that a foolish user has placed outside */
  5337. /* the mesh. */
  5338. /* */
  5339. /* WARNING: This routine is designed for convex triangulations, and will */
  5340. /* not generally work after the holes and concavities have been carved. */
  5341. /* */
  5342. /*****************************************************************************/
  5343. enum locateresult locate( searchpoint, searchtri )
  5344. point searchpoint;
  5345. struct triedge *searchtri;
  5346. {
  5347. VOID **sampleblock;
  5348. triangle *firsttri;
  5349. struct triedge sampletri;
  5350. point torg, tdest;
  5351. unsigned long alignptr;
  5352. REAL searchdist, dist;
  5353. REAL ahead;
  5354. long sampleblocks, samplesperblock, samplenum;
  5355. long triblocks;
  5356. long i, j;
  5357. triangle ptr; /* Temporary variable used by sym(). */
  5358. if ( verbose > 2 ) {
  5359. printf( " Randomly sampling for a triangle near point (%.12g, %.12g).\n",
  5360. searchpoint[0], searchpoint[1] );
  5361. }
  5362. /* Record the distance from the suggested starting triangle to the */
  5363. /* point we seek. */
  5364. org( *searchtri, torg );
  5365. searchdist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] )
  5366. + ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] );
  5367. if ( verbose > 2 ) {
  5368. printf( " Boundary triangle has origin (%.12g, %.12g).\n",
  5369. torg[0], torg[1] );
  5370. }
  5371. /* If a recently encountered triangle has been recorded and has not been */
  5372. /* deallocated, test it as a good starting point. */
  5373. if ( recenttri.tri != (triangle *) NULL ) {
  5374. if ( recenttri.tri[3] != (triangle) NULL ) {
  5375. org( recenttri, torg );
  5376. if ( ( torg[0] == searchpoint[0] ) && ( torg[1] == searchpoint[1] ) ) {
  5377. triedgecopy( recenttri, *searchtri );
  5378. return ONVERTEX;
  5379. }
  5380. dist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] )
  5381. + ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] );
  5382. if ( dist < searchdist ) {
  5383. triedgecopy( recenttri, *searchtri );
  5384. searchdist = dist;
  5385. if ( verbose > 2 ) {
  5386. printf( " Choosing recent triangle with origin (%.12g, %.12g).\n",
  5387. torg[0], torg[1] );
  5388. }
  5389. }
  5390. }
  5391. }
  5392. /* The number of random samples taken is proportional to the cube root of */
  5393. /* the number of triangles in the mesh. The next bit of code assumes */
  5394. /* that the number of triangles increases monotonically. */
  5395. while ( SAMPLEFACTOR * samples * samples * samples < triangles.items ) {
  5396. samples++;
  5397. }
  5398. triblocks = ( triangles.maxitems + TRIPERBLOCK - 1 ) / TRIPERBLOCK;
  5399. samplesperblock = 1 + ( samples / triblocks );
  5400. sampleblocks = samples / samplesperblock;
  5401. sampleblock = triangles.firstblock;
  5402. sampletri.orient = 0;
  5403. for ( i = 0; i < sampleblocks; i++ ) {
  5404. alignptr = (unsigned long) ( sampleblock + 1 );
  5405. firsttri = (triangle *) ( alignptr + (unsigned long) triangles.alignbytes
  5406. - ( alignptr % (unsigned long) triangles.alignbytes ) );
  5407. for ( j = 0; j < samplesperblock; j++ ) {
  5408. if ( i == triblocks - 1 ) {
  5409. samplenum = randomnation( (int)
  5410. ( triangles.maxitems - ( i * TRIPERBLOCK ) ) );
  5411. }
  5412. else {
  5413. samplenum = randomnation( TRIPERBLOCK );
  5414. }
  5415. sampletri.tri = (triangle *)
  5416. ( firsttri + ( samplenum * triangles.itemwords ) );
  5417. if ( sampletri.tri[3] != (triangle) NULL ) {
  5418. org( sampletri, torg );
  5419. dist = ( searchpoint[0] - torg[0] ) * ( searchpoint[0] - torg[0] )
  5420. + ( searchpoint[1] - torg[1] ) * ( searchpoint[1] - torg[1] );
  5421. if ( dist < searchdist ) {
  5422. triedgecopy( sampletri, *searchtri );
  5423. searchdist = dist;
  5424. if ( verbose > 2 ) {
  5425. printf( " Choosing triangle with origin (%.12g, %.12g).\n",
  5426. torg[0], torg[1] );
  5427. }
  5428. }
  5429. }
  5430. }
  5431. sampleblock = (VOID **) *sampleblock;
  5432. }
  5433. /* Where are we? */
  5434. org( *searchtri, torg );
  5435. dest( *searchtri, tdest );
  5436. /* Check the starting triangle's vertices. */
  5437. if ( ( torg[0] == searchpoint[0] ) && ( torg[1] == searchpoint[1] ) ) {
  5438. return ONVERTEX;
  5439. }
  5440. if ( ( tdest[0] == searchpoint[0] ) && ( tdest[1] == searchpoint[1] ) ) {
  5441. lnextself( *searchtri );
  5442. return ONVERTEX;
  5443. }
  5444. /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
  5445. ahead = counterclockwise( torg, tdest, searchpoint );
  5446. if ( ahead < 0.0 ) {
  5447. /* Turn around so that `searchpoint' is to the left of the */
  5448. /* edge specified by `searchtri'. */
  5449. symself( *searchtri );
  5450. }
  5451. else if ( ahead == 0.0 ) {
  5452. /* Check if `searchpoint' is between `torg' and `tdest'. */
  5453. if ( ( ( torg[0] < searchpoint[0] ) == ( searchpoint[0] < tdest[0] ) )
  5454. && ( ( torg[1] < searchpoint[1] ) == ( searchpoint[1] < tdest[1] ) ) ) {
  5455. return ONEDGE;
  5456. }
  5457. }
  5458. return preciselocate( searchpoint, searchtri );
  5459. }
  5460. /** **/
  5461. /** **/
  5462. /********* Point location routines end here *********/
  5463. /********* Mesh transformation routines begin here *********/
  5464. /** **/
  5465. /** **/
  5466. /*****************************************************************************/
  5467. /* */
  5468. /* insertshelle() Create a new shell edge and insert it between two */
  5469. /* triangles. */
  5470. /* */
  5471. /* The new shell edge is inserted at the edge described by the handle */
  5472. /* `tri'. Its vertices are properly initialized. The marker `shellemark' */
  5473. /* is applied to the shell edge and, if appropriate, its vertices. */
  5474. /* */
  5475. /*****************************************************************************/
  5476. void insertshelle( tri, shellemark )
  5477. struct triedge *tri; /* Edge at which to insert the new shell edge. */
  5478. int shellemark; /* Marker for the new shell edge. */
  5479. {
  5480. struct triedge oppotri;
  5481. struct edge newshelle;
  5482. point triorg, tridest;
  5483. triangle ptr; /* Temporary variable used by sym(). */
  5484. shelle sptr; /* Temporary variable used by tspivot(). */
  5485. /* Mark points if possible. */
  5486. org( *tri, triorg );
  5487. dest( *tri, tridest );
  5488. if ( pointmark( triorg ) == 0 ) {
  5489. setpointmark( triorg, shellemark );
  5490. }
  5491. if ( pointmark( tridest ) == 0 ) {
  5492. setpointmark( tridest, shellemark );
  5493. }
  5494. /* Check if there's already a shell edge here. */
  5495. tspivot( *tri, newshelle );
  5496. if ( newshelle.sh == dummysh ) {
  5497. /* Make new shell edge and initialize its vertices. */
  5498. makeshelle( &newshelle );
  5499. setsorg( newshelle, tridest );
  5500. setsdest( newshelle, triorg );
  5501. /* Bond new shell edge to the two triangles it is sandwiched between. */
  5502. /* Note that the facing triangle `oppotri' might be equal to */
  5503. /* `dummytri' (outer space), but the new shell edge is bonded to it */
  5504. /* all the same. */
  5505. tsbond( *tri, newshelle );
  5506. sym( *tri, oppotri );
  5507. ssymself( newshelle );
  5508. tsbond( oppotri, newshelle );
  5509. setmark( newshelle, shellemark );
  5510. if ( verbose > 2 ) {
  5511. printf( " Inserting new " );
  5512. printshelle( &newshelle );
  5513. }
  5514. }
  5515. else {
  5516. if ( mark( newshelle ) == 0 ) {
  5517. setmark( newshelle, shellemark );
  5518. }
  5519. }
  5520. }
  5521. /*****************************************************************************/
  5522. /* */
  5523. /* Terminology */
  5524. /* */
  5525. /* A "local transformation" replaces a small set of triangles with another */
  5526. /* set of triangles. This may or may not involve inserting or deleting a */
  5527. /* point. */
  5528. /* */
  5529. /* The term "casing" is used to describe the set of triangles that are */
  5530. /* attached to the triangles being transformed, but are not transformed */
  5531. /* themselves. Think of the casing as a fixed hollow structure inside */
  5532. /* which all the action happens. A "casing" is only defined relative to */
  5533. /* a single transformation; each occurrence of a transformation will */
  5534. /* involve a different casing. */
  5535. /* */
  5536. /* A "shell" is similar to a "casing". The term "shell" describes the set */
  5537. /* of shell edges (if any) that are attached to the triangles being */
  5538. /* transformed. However, I sometimes use "shell" to refer to a single */
  5539. /* shell edge, so don't get confused. */
  5540. /* */
  5541. /*****************************************************************************/
  5542. /*****************************************************************************/
  5543. /* */
  5544. /* flip() Transform two triangles to two different triangles by flipping */
  5545. /* an edge within a quadrilateral. */
  5546. /* */
  5547. /* Imagine the original triangles, abc and bad, oriented so that the */
  5548. /* shared edge ab lies in a horizontal plane, with the point b on the left */
  5549. /* and the point a on the right. The point c lies below the edge, and the */
  5550. /* point d lies above the edge. The `flipedge' handle holds the edge ab */
  5551. /* of triangle abc, and is directed left, from vertex a to vertex b. */
  5552. /* */
  5553. /* The triangles abc and bad are deleted and replaced by the triangles cdb */
  5554. /* and dca. The triangles that represent abc and bad are NOT deallocated; */
  5555. /* they are reused for dca and cdb, respectively. Hence, any handles that */
  5556. /* may have held the original triangles are still valid, although not */
  5557. /* directed as they were before. */
  5558. /* */
  5559. /* Upon completion of this routine, the `flipedge' handle holds the edge */
  5560. /* dc of triangle dca, and is directed down, from vertex d to vertex c. */
  5561. /* (Hence, the two triangles have rotated counterclockwise.) */
  5562. /* */
  5563. /* WARNING: This transformation is geometrically valid only if the */
  5564. /* quadrilateral adbc is convex. Furthermore, this transformation is */
  5565. /* valid only if there is not a shell edge between the triangles abc and */
  5566. /* bad. This routine does not check either of these preconditions, and */
  5567. /* it is the responsibility of the calling routine to ensure that they are */
  5568. /* met. If they are not, the streets shall be filled with wailing and */
  5569. /* gnashing of teeth. */
  5570. /* */
  5571. /*****************************************************************************/
  5572. void flip( flipedge )
  5573. struct triedge *flipedge; /* Handle for the triangle abc. */
  5574. {
  5575. struct triedge botleft, botright;
  5576. struct triedge topleft, topright;
  5577. struct triedge top;
  5578. struct triedge botlcasing, botrcasing;
  5579. struct triedge toplcasing, toprcasing;
  5580. struct edge botlshelle, botrshelle;
  5581. struct edge toplshelle, toprshelle;
  5582. point leftpoint, rightpoint, botpoint;
  5583. point farpoint;
  5584. triangle ptr; /* Temporary variable used by sym(). */
  5585. shelle sptr; /* Temporary variable used by tspivot(). */
  5586. /* Identify the vertices of the quadrilateral. */
  5587. org( *flipedge, rightpoint );
  5588. dest( *flipedge, leftpoint );
  5589. apex( *flipedge, botpoint );
  5590. sym( *flipedge, top );
  5591. #ifdef SELF_CHECK
  5592. if ( top.tri == dummytri ) {
  5593. printf( "Internal error in flip(): Attempt to flip on boundary.\n" );
  5594. lnextself( *flipedge );
  5595. return;
  5596. }
  5597. if ( checksegments ) {
  5598. tspivot( *flipedge, toplshelle );
  5599. if ( toplshelle.sh != dummysh ) {
  5600. printf( "Internal error in flip(): Attempt to flip a segment.\n" );
  5601. lnextself( *flipedge );
  5602. return;
  5603. }
  5604. }
  5605. #endif /* SELF_CHECK */
  5606. apex( top, farpoint );
  5607. /* Identify the casing of the quadrilateral. */
  5608. lprev( top, topleft );
  5609. sym( topleft, toplcasing );
  5610. lnext( top, topright );
  5611. sym( topright, toprcasing );
  5612. lnext( *flipedge, botleft );
  5613. sym( botleft, botlcasing );
  5614. lprev( *flipedge, botright );
  5615. sym( botright, botrcasing );
  5616. /* Rotate the quadrilateral one-quarter turn counterclockwise. */
  5617. bond( topleft, botlcasing );
  5618. bond( botleft, botrcasing );
  5619. bond( botright, toprcasing );
  5620. bond( topright, toplcasing );
  5621. if ( checksegments ) {
  5622. /* Check for shell edges and rebond them to the quadrilateral. */
  5623. tspivot( topleft, toplshelle );
  5624. tspivot( botleft, botlshelle );
  5625. tspivot( botright, botrshelle );
  5626. tspivot( topright, toprshelle );
  5627. if ( toplshelle.sh == dummysh ) {
  5628. tsdissolve( topright );
  5629. }
  5630. else {
  5631. tsbond( topright, toplshelle );
  5632. }
  5633. if ( botlshelle.sh == dummysh ) {
  5634. tsdissolve( topleft );
  5635. }
  5636. else {
  5637. tsbond( topleft, botlshelle );
  5638. }
  5639. if ( botrshelle.sh == dummysh ) {
  5640. tsdissolve( botleft );
  5641. }
  5642. else {
  5643. tsbond( botleft, botrshelle );
  5644. }
  5645. if ( toprshelle.sh == dummysh ) {
  5646. tsdissolve( botright );
  5647. }
  5648. else {
  5649. tsbond( botright, toprshelle );
  5650. }
  5651. }
  5652. /* New point assignments for the rotated quadrilateral. */
  5653. setorg( *flipedge, farpoint );
  5654. setdest( *flipedge, botpoint );
  5655. setapex( *flipedge, rightpoint );
  5656. setorg( top, botpoint );
  5657. setdest( top, farpoint );
  5658. setapex( top, leftpoint );
  5659. if ( verbose > 2 ) {
  5660. printf( " Edge flip results in left " );
  5661. lnextself( topleft );
  5662. printtriangle( &topleft );
  5663. printf( " and right " );
  5664. printtriangle( flipedge );
  5665. }
  5666. }
  5667. /*****************************************************************************/
  5668. /* */
  5669. /* insertsite() Insert a vertex into a Delaunay triangulation, */
  5670. /* performing flips as necessary to maintain the Delaunay */
  5671. /* property. */
  5672. /* */
  5673. /* The point `insertpoint' is located. If `searchtri.tri' is not NULL, */
  5674. /* the search for the containing triangle begins from `searchtri'. If */
  5675. /* `searchtri.tri' is NULL, a full point location procedure is called. */
  5676. /* If `insertpoint' is found inside a triangle, the triangle is split into */
  5677. /* three; if `insertpoint' lies on an edge, the edge is split in two, */
  5678. /* thereby splitting the two adjacent triangles into four. Edge flips are */
  5679. /* used to restore the Delaunay property. If `insertpoint' lies on an */
  5680. /* existing vertex, no action is taken, and the value DUPLICATEPOINT is */
  5681. /* returned. On return, `searchtri' is set to a handle whose origin is the */
  5682. /* existing vertex. */
  5683. /* */
  5684. /* Normally, the parameter `splitedge' is set to NULL, implying that no */
  5685. /* segment should be split. In this case, if `insertpoint' is found to */
  5686. /* lie on a segment, no action is taken, and the value VIOLATINGPOINT is */
  5687. /* returned. On return, `searchtri' is set to a handle whose primary edge */
  5688. /* is the violated segment. */
  5689. /* */
  5690. /* If the calling routine wishes to split a segment by inserting a point in */
  5691. /* it, the parameter `splitedge' should be that segment. In this case, */
  5692. /* `searchtri' MUST be the triangle handle reached by pivoting from that */
  5693. /* segment; no point location is done. */
  5694. /* */
  5695. /* `segmentflaws' and `triflaws' are flags that indicate whether or not */
  5696. /* there should be checks for the creation of encroached segments or bad */
  5697. /* quality faces. If a newly inserted point encroaches upon segments, */
  5698. /* these segments are added to the list of segments to be split if */
  5699. /* `segmentflaws' is set. If bad triangles are created, these are added */
  5700. /* to the queue if `triflaws' is set. */
  5701. /* */
  5702. /* If a duplicate point or violated segment does not prevent the point */
  5703. /* from being inserted, the return value will be ENCROACHINGPOINT if the */
  5704. /* point encroaches upon a segment (and checking is enabled), or */
  5705. /* SUCCESSFULPOINT otherwise. In either case, `searchtri' is set to a */
  5706. /* handle whose origin is the newly inserted vertex. */
  5707. /* */
  5708. /* insertsite() does not use flip() for reasons of speed; some */
  5709. /* information can be reused from edge flip to edge flip, like the */
  5710. /* locations of shell edges. */
  5711. /* */
  5712. /*****************************************************************************/
  5713. enum insertsiteresult insertsite( insertpoint, searchtri, splitedge,
  5714. segmentflaws, triflaws )
  5715. point insertpoint;
  5716. struct triedge *searchtri;
  5717. struct edge *splitedge;
  5718. int segmentflaws;
  5719. int triflaws;
  5720. {
  5721. struct triedge horiz;
  5722. struct triedge top;
  5723. struct triedge botleft, botright;
  5724. struct triedge topleft, topright;
  5725. struct triedge newbotleft, newbotright;
  5726. struct triedge newtopright;
  5727. struct triedge botlcasing, botrcasing;
  5728. struct triedge toplcasing, toprcasing;
  5729. struct triedge testtri;
  5730. struct edge botlshelle, botrshelle;
  5731. struct edge toplshelle, toprshelle;
  5732. struct edge brokenshelle;
  5733. struct edge checkshelle;
  5734. struct edge rightedge;
  5735. struct edge newedge;
  5736. struct edge *encroached;
  5737. point first;
  5738. point leftpoint, rightpoint, botpoint, toppoint, farpoint;
  5739. REAL attrib;
  5740. REAL area;
  5741. enum insertsiteresult success;
  5742. enum locateresult intersect;
  5743. int doflip;
  5744. int mirrorflag;
  5745. int i;
  5746. triangle ptr; /* Temporary variable used by sym(). */
  5747. shelle sptr; /* Temporary variable used by spivot() and tspivot(). */
  5748. if ( verbose > 1 ) {
  5749. printf( " Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1] );
  5750. }
  5751. if ( splitedge == (struct edge *) NULL ) {
  5752. /* Find the location of the point to be inserted. Check if a good */
  5753. /* starting triangle has already been provided by the caller. */
  5754. if ( searchtri->tri == (triangle *) NULL ) {
  5755. /* Find a boundary triangle. */
  5756. horiz.tri = dummytri;
  5757. horiz.orient = 0;
  5758. symself( horiz );
  5759. /* Search for a triangle containing `insertpoint'. */
  5760. intersect = locate( insertpoint, &horiz );
  5761. }
  5762. else {
  5763. /* Start searching from the triangle provided by the caller. */
  5764. triedgecopy( *searchtri, horiz );
  5765. intersect = preciselocate( insertpoint, &horiz );
  5766. }
  5767. }
  5768. else {
  5769. /* The calling routine provides the edge in which the point is inserted. */
  5770. triedgecopy( *searchtri, horiz );
  5771. intersect = ONEDGE;
  5772. }
  5773. if ( intersect == ONVERTEX ) {
  5774. /* There's already a vertex there. Return in `searchtri' a triangle */
  5775. /* whose origin is the existing vertex. */
  5776. triedgecopy( horiz, *searchtri );
  5777. triedgecopy( horiz, recenttri );
  5778. return DUPLICATEPOINT;
  5779. }
  5780. if ( ( intersect == ONEDGE ) || ( intersect == OUTSIDE ) ) {
  5781. /* The vertex falls on an edge or boundary. */
  5782. if ( checksegments && ( splitedge == (struct edge *) NULL ) ) {
  5783. /* Check whether the vertex falls on a shell edge. */
  5784. tspivot( horiz, brokenshelle );
  5785. if ( brokenshelle.sh != dummysh ) {
  5786. /* The vertex falls on a shell edge. */
  5787. if ( segmentflaws ) {
  5788. if ( nobisect == 0 ) {
  5789. /* Add the shell edge to the list of encroached segments. */
  5790. encroached = (struct edge *) poolalloc( &badsegments );
  5791. shellecopy( brokenshelle, *encroached );
  5792. }
  5793. else if ( ( nobisect == 1 ) && ( intersect == ONEDGE ) ) {
  5794. /* This segment may be split only if it is an internal boundary. */
  5795. sym( horiz, testtri );
  5796. if ( testtri.tri != dummytri ) {
  5797. /* Add the shell edge to the list of encroached segments. */
  5798. encroached = (struct edge *) poolalloc( &badsegments );
  5799. shellecopy( brokenshelle, *encroached );
  5800. }
  5801. }
  5802. }
  5803. /* Return a handle whose primary edge contains the point, */
  5804. /* which has not been inserted. */
  5805. triedgecopy( horiz, *searchtri );
  5806. triedgecopy( horiz, recenttri );
  5807. return VIOLATINGPOINT;
  5808. }
  5809. }
  5810. /* Insert the point on an edge, dividing one triangle into two (if */
  5811. /* the edge lies on a boundary) or two triangles into four. */
  5812. lprev( horiz, botright );
  5813. sym( botright, botrcasing );
  5814. sym( horiz, topright );
  5815. /* Is there a second triangle? (Or does this edge lie on a boundary?) */
  5816. mirrorflag = topright.tri != dummytri;
  5817. if ( mirrorflag ) {
  5818. lnextself( topright );
  5819. sym( topright, toprcasing );
  5820. maketriangle( &newtopright );
  5821. }
  5822. else {
  5823. /* Splitting the boundary edge increases the number of boundary edges. */
  5824. hullsize++;
  5825. }
  5826. maketriangle( &newbotright );
  5827. /* Set the vertices of changed and new triangles. */
  5828. org( horiz, rightpoint );
  5829. dest( horiz, leftpoint );
  5830. apex( horiz, botpoint );
  5831. setorg( newbotright, botpoint );
  5832. setdest( newbotright, rightpoint );
  5833. setapex( newbotright, insertpoint );
  5834. setorg( horiz, insertpoint );
  5835. for ( i = 0; i < eextras; i++ ) {
  5836. /* Set the element attributes of a new triangle. */
  5837. setelemattribute( newbotright, i, elemattribute( botright, i ) );
  5838. }
  5839. if ( vararea ) {
  5840. /* Set the area constraint of a new triangle. */
  5841. setareabound( newbotright, areabound( botright ) );
  5842. }
  5843. if ( mirrorflag ) {
  5844. dest( topright, toppoint );
  5845. setorg( newtopright, rightpoint );
  5846. setdest( newtopright, toppoint );
  5847. setapex( newtopright, insertpoint );
  5848. setorg( topright, insertpoint );
  5849. for ( i = 0; i < eextras; i++ ) {
  5850. /* Set the element attributes of another new triangle. */
  5851. setelemattribute( newtopright, i, elemattribute( topright, i ) );
  5852. }
  5853. if ( vararea ) {
  5854. /* Set the area constraint of another new triangle. */
  5855. setareabound( newtopright, areabound( topright ) );
  5856. }
  5857. }
  5858. /* There may be shell edges that need to be bonded */
  5859. /* to the new triangle(s). */
  5860. if ( checksegments ) {
  5861. tspivot( botright, botrshelle );
  5862. if ( botrshelle.sh != dummysh ) {
  5863. tsdissolve( botright );
  5864. tsbond( newbotright, botrshelle );
  5865. }
  5866. if ( mirrorflag ) {
  5867. tspivot( topright, toprshelle );
  5868. if ( toprshelle.sh != dummysh ) {
  5869. tsdissolve( topright );
  5870. tsbond( newtopright, toprshelle );
  5871. }
  5872. }
  5873. }
  5874. /* Bond the new triangle(s) to the surrounding triangles. */
  5875. bond( newbotright, botrcasing );
  5876. lprevself( newbotright );
  5877. bond( newbotright, botright );
  5878. lprevself( newbotright );
  5879. if ( mirrorflag ) {
  5880. bond( newtopright, toprcasing );
  5881. lnextself( newtopright );
  5882. bond( newtopright, topright );
  5883. lnextself( newtopright );
  5884. bond( newtopright, newbotright );
  5885. }
  5886. if ( splitedge != (struct edge *) NULL ) {
  5887. /* Split the shell edge into two. */
  5888. setsdest( *splitedge, insertpoint );
  5889. ssymself( *splitedge );
  5890. spivot( *splitedge, rightedge );
  5891. insertshelle( &newbotright, mark( *splitedge ) );
  5892. tspivot( newbotright, newedge );
  5893. sbond( *splitedge, newedge );
  5894. ssymself( newedge );
  5895. sbond( newedge, rightedge );
  5896. ssymself( *splitedge );
  5897. }
  5898. #ifdef SELF_CHECK
  5899. if ( counterclockwise( rightpoint, leftpoint, botpoint ) < 0.0 ) {
  5900. printf( "Internal error in insertsite():\n" );
  5901. printf( " Clockwise triangle prior to edge point insertion (bottom).\n" );
  5902. }
  5903. if ( mirrorflag ) {
  5904. if ( counterclockwise( leftpoint, rightpoint, toppoint ) < 0.0 ) {
  5905. printf( "Internal error in insertsite():\n" );
  5906. printf( " Clockwise triangle prior to edge point insertion (top).\n" );
  5907. }
  5908. if ( counterclockwise( rightpoint, toppoint, insertpoint ) < 0.0 ) {
  5909. printf( "Internal error in insertsite():\n" );
  5910. printf( " Clockwise triangle after edge point insertion (top right).\n"
  5911. );
  5912. }
  5913. if ( counterclockwise( toppoint, leftpoint, insertpoint ) < 0.0 ) {
  5914. printf( "Internal error in insertsite():\n" );
  5915. printf( " Clockwise triangle after edge point insertion (top left).\n"
  5916. );
  5917. }
  5918. }
  5919. if ( counterclockwise( leftpoint, botpoint, insertpoint ) < 0.0 ) {
  5920. printf( "Internal error in insertsite():\n" );
  5921. printf( " Clockwise triangle after edge point insertion (bottom left).\n"
  5922. );
  5923. }
  5924. if ( counterclockwise( botpoint, rightpoint, insertpoint ) < 0.0 ) {
  5925. printf( "Internal error in insertsite():\n" );
  5926. printf(
  5927. " Clockwise triangle after edge point insertion (bottom right).\n" );
  5928. }
  5929. #endif /* SELF_CHECK */
  5930. if ( verbose > 2 ) {
  5931. printf( " Updating bottom left " );
  5932. printtriangle( &botright );
  5933. if ( mirrorflag ) {
  5934. printf( " Updating top left " );
  5935. printtriangle( &topright );
  5936. printf( " Creating top right " );
  5937. printtriangle( &newtopright );
  5938. }
  5939. printf( " Creating bottom right " );
  5940. printtriangle( &newbotright );
  5941. }
  5942. /* Position `horiz' on the first edge to check for */
  5943. /* the Delaunay property. */
  5944. lnextself( horiz );
  5945. }
  5946. else {
  5947. /* Insert the point in a triangle, splitting it into three. */
  5948. lnext( horiz, botleft );
  5949. lprev( horiz, botright );
  5950. sym( botleft, botlcasing );
  5951. sym( botright, botrcasing );
  5952. maketriangle( &newbotleft );
  5953. maketriangle( &newbotright );
  5954. /* Set the vertices of changed and new triangles. */
  5955. org( horiz, rightpoint );
  5956. dest( horiz, leftpoint );
  5957. apex( horiz, botpoint );
  5958. setorg( newbotleft, leftpoint );
  5959. setdest( newbotleft, botpoint );
  5960. setapex( newbotleft, insertpoint );
  5961. setorg( newbotright, botpoint );
  5962. setdest( newbotright, rightpoint );
  5963. setapex( newbotright, insertpoint );
  5964. setapex( horiz, insertpoint );
  5965. for ( i = 0; i < eextras; i++ ) {
  5966. /* Set the element attributes of the new triangles. */
  5967. attrib = elemattribute( horiz, i );
  5968. setelemattribute( newbotleft, i, attrib );
  5969. setelemattribute( newbotright, i, attrib );
  5970. }
  5971. if ( vararea ) {
  5972. /* Set the area constraint of the new triangles. */
  5973. area = areabound( horiz );
  5974. setareabound( newbotleft, area );
  5975. setareabound( newbotright, area );
  5976. }
  5977. /* There may be shell edges that need to be bonded */
  5978. /* to the new triangles. */
  5979. if ( checksegments ) {
  5980. tspivot( botleft, botlshelle );
  5981. if ( botlshelle.sh != dummysh ) {
  5982. tsdissolve( botleft );
  5983. tsbond( newbotleft, botlshelle );
  5984. }
  5985. tspivot( botright, botrshelle );
  5986. if ( botrshelle.sh != dummysh ) {
  5987. tsdissolve( botright );
  5988. tsbond( newbotright, botrshelle );
  5989. }
  5990. }
  5991. /* Bond the new triangles to the surrounding triangles. */
  5992. bond( newbotleft, botlcasing );
  5993. bond( newbotright, botrcasing );
  5994. lnextself( newbotleft );
  5995. lprevself( newbotright );
  5996. bond( newbotleft, newbotright );
  5997. lnextself( newbotleft );
  5998. bond( botleft, newbotleft );
  5999. lprevself( newbotright );
  6000. bond( botright, newbotright );
  6001. #ifdef SELF_CHECK
  6002. if ( counterclockwise( rightpoint, leftpoint, botpoint ) < 0.0 ) {
  6003. printf( "Internal error in insertsite():\n" );
  6004. printf( " Clockwise triangle prior to point insertion.\n" );
  6005. }
  6006. if ( counterclockwise( rightpoint, leftpoint, insertpoint ) < 0.0 ) {
  6007. printf( "Internal error in insertsite():\n" );
  6008. printf( " Clockwise triangle after point insertion (top).\n" );
  6009. }
  6010. if ( counterclockwise( leftpoint, botpoint, insertpoint ) < 0.0 ) {
  6011. printf( "Internal error in insertsite():\n" );
  6012. printf( " Clockwise triangle after point insertion (left).\n" );
  6013. }
  6014. if ( counterclockwise( botpoint, rightpoint, insertpoint ) < 0.0 ) {
  6015. printf( "Internal error in insertsite():\n" );
  6016. printf( " Clockwise triangle after point insertion (right).\n" );
  6017. }
  6018. #endif /* SELF_CHECK */
  6019. if ( verbose > 2 ) {
  6020. printf( " Updating top " );
  6021. printtriangle( &horiz );
  6022. printf( " Creating left " );
  6023. printtriangle( &newbotleft );
  6024. printf( " Creating right " );
  6025. printtriangle( &newbotright );
  6026. }
  6027. }
  6028. /* The insertion is successful by default, unless an encroached */
  6029. /* edge is found. */
  6030. success = SUCCESSFULPOINT;
  6031. /* Circle around the newly inserted vertex, checking each edge opposite */
  6032. /* it for the Delaunay property. Non-Delaunay edges are flipped. */
  6033. /* `horiz' is always the edge being checked. `first' marks where to */
  6034. /* stop circling. */
  6035. org( horiz, first );
  6036. rightpoint = first;
  6037. dest( horiz, leftpoint );
  6038. /* Circle until finished. */
  6039. while ( 1 ) {
  6040. /* By default, the edge will be flipped. */
  6041. doflip = 1;
  6042. if ( checksegments ) {
  6043. /* Check for a segment, which cannot be flipped. */
  6044. tspivot( horiz, checkshelle );
  6045. if ( checkshelle.sh != dummysh ) {
  6046. /* The edge is a segment and cannot be flipped. */
  6047. doflip = 0;
  6048. #ifndef CDT_ONLY
  6049. if ( segmentflaws ) {
  6050. /* Does the new point encroach upon this segment? */
  6051. if ( checkedge4encroach( &checkshelle ) ) {
  6052. success = ENCROACHINGPOINT;
  6053. }
  6054. }
  6055. #endif /* not CDT_ONLY */
  6056. }
  6057. }
  6058. if ( doflip ) {
  6059. /* Check if the edge is a boundary edge. */
  6060. sym( horiz, top );
  6061. if ( top.tri == dummytri ) {
  6062. /* The edge is a boundary edge and cannot be flipped. */
  6063. doflip = 0;
  6064. }
  6065. else {
  6066. /* Find the point on the other side of the edge. */
  6067. apex( top, farpoint );
  6068. /* In the incremental Delaunay triangulation algorithm, any of */
  6069. /* `leftpoint', `rightpoint', and `farpoint' could be vertices */
  6070. /* of the triangular bounding box. These vertices must be */
  6071. /* treated as if they are infinitely distant, even though their */
  6072. /* "coordinates" are not. */
  6073. if ( ( leftpoint == infpoint1 ) || ( leftpoint == infpoint2 )
  6074. || ( leftpoint == infpoint3 ) ) {
  6075. /* `leftpoint' is infinitely distant. Check the convexity of */
  6076. /* the boundary of the triangulation. 'farpoint' might be */
  6077. /* infinite as well, but trust me, this same condition */
  6078. /* should be applied. */
  6079. doflip = counterclockwise( insertpoint, rightpoint, farpoint ) > 0.0;
  6080. }
  6081. else if ( ( rightpoint == infpoint1 ) || ( rightpoint == infpoint2 )
  6082. || ( rightpoint == infpoint3 ) ) {
  6083. /* `rightpoint' is infinitely distant. Check the convexity of */
  6084. /* the boundary of the triangulation. 'farpoint' might be */
  6085. /* infinite as well, but trust me, this same condition */
  6086. /* should be applied. */
  6087. doflip = counterclockwise( farpoint, leftpoint, insertpoint ) > 0.0;
  6088. }
  6089. else if ( ( farpoint == infpoint1 ) || ( farpoint == infpoint2 )
  6090. || ( farpoint == infpoint3 ) ) {
  6091. /* `farpoint' is infinitely distant and cannot be inside */
  6092. /* the circumcircle of the triangle `horiz'. */
  6093. doflip = 0;
  6094. }
  6095. else {
  6096. /* Test whether the edge is locally Delaunay. */
  6097. doflip = incircle( leftpoint, insertpoint, rightpoint, farpoint )
  6098. > 0.0;
  6099. }
  6100. if ( doflip ) {
  6101. /* We made it! Flip the edge `horiz' by rotating its containing */
  6102. /* quadrilateral (the two triangles adjacent to `horiz'). */
  6103. /* Identify the casing of the quadrilateral. */
  6104. lprev( top, topleft );
  6105. sym( topleft, toplcasing );
  6106. lnext( top, topright );
  6107. sym( topright, toprcasing );
  6108. lnext( horiz, botleft );
  6109. sym( botleft, botlcasing );
  6110. lprev( horiz, botright );
  6111. sym( botright, botrcasing );
  6112. /* Rotate the quadrilateral one-quarter turn counterclockwise. */
  6113. bond( topleft, botlcasing );
  6114. bond( botleft, botrcasing );
  6115. bond( botright, toprcasing );
  6116. bond( topright, toplcasing );
  6117. if ( checksegments ) {
  6118. /* Check for shell edges and rebond them to the quadrilateral. */
  6119. tspivot( topleft, toplshelle );
  6120. tspivot( botleft, botlshelle );
  6121. tspivot( botright, botrshelle );
  6122. tspivot( topright, toprshelle );
  6123. if ( toplshelle.sh == dummysh ) {
  6124. tsdissolve( topright );
  6125. }
  6126. else {
  6127. tsbond( topright, toplshelle );
  6128. }
  6129. if ( botlshelle.sh == dummysh ) {
  6130. tsdissolve( topleft );
  6131. }
  6132. else {
  6133. tsbond( topleft, botlshelle );
  6134. }
  6135. if ( botrshelle.sh == dummysh ) {
  6136. tsdissolve( botleft );
  6137. }
  6138. else {
  6139. tsbond( botleft, botrshelle );
  6140. }
  6141. if ( toprshelle.sh == dummysh ) {
  6142. tsdissolve( botright );
  6143. }
  6144. else {
  6145. tsbond( botright, toprshelle );
  6146. }
  6147. }
  6148. /* New point assignments for the rotated quadrilateral. */
  6149. setorg( horiz, farpoint );
  6150. setdest( horiz, insertpoint );
  6151. setapex( horiz, rightpoint );
  6152. setorg( top, insertpoint );
  6153. setdest( top, farpoint );
  6154. setapex( top, leftpoint );
  6155. for ( i = 0; i < eextras; i++ ) {
  6156. /* Take the average of the two triangles' attributes. */
  6157. attrib = (REAL)( 0.5 * ( elemattribute( top, i ) + elemattribute( horiz, i ) ) );
  6158. setelemattribute( top, i, attrib );
  6159. setelemattribute( horiz, i, attrib );
  6160. }
  6161. if ( vararea ) {
  6162. if ( ( areabound( top ) <= 0.0 ) || ( areabound( horiz ) <= 0.0 ) ) {
  6163. area = -1.0;
  6164. }
  6165. else {
  6166. /* Take the average of the two triangles' area constraints. */
  6167. /* This prevents small area constraints from migrating a */
  6168. /* long, long way from their original location due to flips. */
  6169. area = (REAL)( 0.5 * ( areabound( top ) + areabound( horiz ) ) );
  6170. }
  6171. setareabound( top, area );
  6172. setareabound( horiz, area );
  6173. }
  6174. #ifdef SELF_CHECK
  6175. if ( insertpoint != (point) NULL ) {
  6176. if ( counterclockwise( leftpoint, insertpoint, rightpoint ) < 0.0 ) {
  6177. printf( "Internal error in insertsite():\n" );
  6178. printf( " Clockwise triangle prior to edge flip (bottom).\n" );
  6179. }
  6180. /* The following test has been removed because constrainededge() */
  6181. /* sometimes generates inverted triangles that insertsite() */
  6182. /* removes. */
  6183. /*
  6184. if (counterclockwise(rightpoint, farpoint, leftpoint) < 0.0) {
  6185. printf("Internal error in insertsite():\n");
  6186. printf(" Clockwise triangle prior to edge flip (top).\n");
  6187. }
  6188. */
  6189. if ( counterclockwise( farpoint, leftpoint, insertpoint ) < 0.0 ) {
  6190. printf( "Internal error in insertsite():\n" );
  6191. printf( " Clockwise triangle after edge flip (left).\n" );
  6192. }
  6193. if ( counterclockwise( insertpoint, rightpoint, farpoint ) < 0.0 ) {
  6194. printf( "Internal error in insertsite():\n" );
  6195. printf( " Clockwise triangle after edge flip (right).\n" );
  6196. }
  6197. }
  6198. #endif /* SELF_CHECK */
  6199. if ( verbose > 2 ) {
  6200. printf( " Edge flip results in left " );
  6201. lnextself( topleft );
  6202. printtriangle( &topleft );
  6203. printf( " and right " );
  6204. printtriangle( &horiz );
  6205. }
  6206. /* On the next iterations, consider the two edges that were */
  6207. /* exposed (this is, are now visible to the newly inserted */
  6208. /* point) by the edge flip. */
  6209. lprevself( horiz );
  6210. leftpoint = farpoint;
  6211. }
  6212. }
  6213. }
  6214. if ( !doflip ) {
  6215. /* The handle `horiz' is accepted as locally Delaunay. */
  6216. #ifndef CDT_ONLY
  6217. if ( triflaws ) {
  6218. /* Check the triangle `horiz' for quality. */
  6219. testtriangle( &horiz );
  6220. }
  6221. #endif /* not CDT_ONLY */
  6222. /* Look for the next edge around the newly inserted point. */
  6223. lnextself( horiz );
  6224. sym( horiz, testtri );
  6225. /* Check for finishing a complete revolution about the new point, or */
  6226. /* falling off the edge of the triangulation. The latter will */
  6227. /* happen when a point is inserted at a boundary. */
  6228. if ( ( leftpoint == first ) || ( testtri.tri == dummytri ) ) {
  6229. /* We're done. Return a triangle whose origin is the new point. */
  6230. lnext( horiz, *searchtri );
  6231. lnext( horiz, recenttri );
  6232. return success;
  6233. }
  6234. /* Finish finding the next edge around the newly inserted point. */
  6235. lnext( testtri, horiz );
  6236. rightpoint = leftpoint;
  6237. dest( horiz, leftpoint );
  6238. }
  6239. }
  6240. }
  6241. /*****************************************************************************/
  6242. /* */
  6243. /* triangulatepolygon() Find the Delaunay triangulation of a polygon that */
  6244. /* has a certain "nice" shape. This includes the */
  6245. /* polygons that result from deletion of a point or */
  6246. /* insertion of a segment. */
  6247. /* */
  6248. /* This is a conceptually difficult routine. The starting assumption is */
  6249. /* that we have a polygon with n sides. n - 1 of these sides are currently */
  6250. /* represented as edges in the mesh. One side, called the "base", need not */
  6251. /* be. */
  6252. /* */
  6253. /* Inside the polygon is a structure I call a "fan", consisting of n - 1 */
  6254. /* triangles that share a common origin. For each of these triangles, the */
  6255. /* edge opposite the origin is one of the sides of the polygon. The */
  6256. /* primary edge of each triangle is the edge directed from the origin to */
  6257. /* the destination; note that this is not the same edge that is a side of */
  6258. /* the polygon. `firstedge' is the primary edge of the first triangle. */
  6259. /* From there, the triangles follow in counterclockwise order about the */
  6260. /* polygon, until `lastedge', the primary edge of the last triangle. */
  6261. /* `firstedge' and `lastedge' are probably connected to other triangles */
  6262. /* beyond the extremes of the fan, but their identity is not important, as */
  6263. /* long as the fan remains connected to them. */
  6264. /* */
  6265. /* Imagine the polygon oriented so that its base is at the bottom. This */
  6266. /* puts `firstedge' on the far right, and `lastedge' on the far left. */
  6267. /* The right vertex of the base is the destination of `firstedge', and the */
  6268. /* left vertex of the base is the apex of `lastedge'. */
  6269. /* */
  6270. /* The challenge now is to find the right sequence of edge flips to */
  6271. /* transform the fan into a Delaunay triangulation of the polygon. Each */
  6272. /* edge flip effectively removes one triangle from the fan, committing it */
  6273. /* to the polygon. The resulting polygon has one fewer edge. If `doflip' */
  6274. /* is set, the final flip will be performed, resulting in a fan of one */
  6275. /* (useless?) triangle. If `doflip' is not set, the final flip is not */
  6276. /* performed, resulting in a fan of two triangles, and an unfinished */
  6277. /* triangular polygon that is not yet filled out with a single triangle. */
  6278. /* On completion of the routine, `lastedge' is the last remaining triangle, */
  6279. /* or the leftmost of the last two. */
  6280. /* */
  6281. /* Although the flips are performed in the order described above, the */
  6282. /* decisions about what flips to perform are made in precisely the reverse */
  6283. /* order. The recursive triangulatepolygon() procedure makes a decision, */
  6284. /* uses up to two recursive calls to triangulate the "subproblems" */
  6285. /* (polygons with fewer edges), and then performs an edge flip. */
  6286. /* */
  6287. /* The "decision" it makes is which vertex of the polygon should be */
  6288. /* connected to the base. This decision is made by testing every possible */
  6289. /* vertex. Once the best vertex is found, the two edges that connect this */
  6290. /* vertex to the base become the bases for two smaller polygons. These */
  6291. /* are triangulated recursively. Unfortunately, this approach can take */
  6292. /* O(n^2) time not only in the worst case, but in many common cases. It's */
  6293. /* rarely a big deal for point deletion, where n is rarely larger than ten, */
  6294. /* but it could be a big deal for segment insertion, especially if there's */
  6295. /* a lot of long segments that each cut many triangles. I ought to code */
  6296. /* a faster algorithm some time. */
  6297. /* */
  6298. /* The `edgecount' parameter is the number of sides of the polygon, */
  6299. /* including its base. `triflaws' is a flag that determines whether the */
  6300. /* new triangles should be tested for quality, and enqueued if they are */
  6301. /* bad. */
  6302. /* */
  6303. /*****************************************************************************/
  6304. void triangulatepolygon( firstedge, lastedge, edgecount, doflip, triflaws )
  6305. struct triedge *firstedge;
  6306. struct triedge *lastedge;
  6307. int edgecount;
  6308. int doflip;
  6309. int triflaws;
  6310. {
  6311. struct triedge testtri;
  6312. struct triedge besttri;
  6313. struct triedge tempedge;
  6314. point leftbasepoint, rightbasepoint;
  6315. point testpoint;
  6316. point bestpoint;
  6317. int bestnumber;
  6318. int i;
  6319. triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
  6320. /* Identify the base vertices. */
  6321. apex( *lastedge, leftbasepoint );
  6322. dest( *firstedge, rightbasepoint );
  6323. if ( verbose > 2 ) {
  6324. printf( " Triangulating interior polygon at edge\n" );
  6325. printf( " (%.12g, %.12g) (%.12g, %.12g)\n", leftbasepoint[0],
  6326. leftbasepoint[1], rightbasepoint[0], rightbasepoint[1] );
  6327. }
  6328. /* Find the best vertex to connect the base to. */
  6329. onext( *firstedge, besttri );
  6330. dest( besttri, bestpoint );
  6331. triedgecopy( besttri, testtri );
  6332. bestnumber = 1;
  6333. for ( i = 2; i <= edgecount - 2; i++ ) {
  6334. onextself( testtri );
  6335. dest( testtri, testpoint );
  6336. /* Is this a better vertex? */
  6337. if ( incircle( leftbasepoint, rightbasepoint, bestpoint, testpoint ) > 0.0 ) {
  6338. triedgecopy( testtri, besttri );
  6339. bestpoint = testpoint;
  6340. bestnumber = i;
  6341. }
  6342. }
  6343. if ( verbose > 2 ) {
  6344. printf( " Connecting edge to (%.12g, %.12g)\n", bestpoint[0],
  6345. bestpoint[1] );
  6346. }
  6347. if ( bestnumber > 1 ) {
  6348. /* Recursively triangulate the smaller polygon on the right. */
  6349. oprev( besttri, tempedge );
  6350. triangulatepolygon( firstedge, &tempedge, bestnumber + 1, 1, triflaws );
  6351. }
  6352. if ( bestnumber < edgecount - 2 ) {
  6353. /* Recursively triangulate the smaller polygon on the left. */
  6354. sym( besttri, tempedge );
  6355. triangulatepolygon( &besttri, lastedge, edgecount - bestnumber, 1,
  6356. triflaws );
  6357. /* Find `besttri' again; it may have been lost to edge flips. */
  6358. sym( tempedge, besttri );
  6359. }
  6360. if ( doflip ) {
  6361. /* Do one final edge flip. */
  6362. flip( &besttri );
  6363. #ifndef CDT_ONLY
  6364. if ( triflaws ) {
  6365. /* Check the quality of the newly committed triangle. */
  6366. sym( besttri, testtri );
  6367. testtriangle( &testtri );
  6368. }
  6369. #endif /* not CDT_ONLY */
  6370. }
  6371. /* Return the base triangle. */
  6372. triedgecopy( besttri, *lastedge );
  6373. }
  6374. /*****************************************************************************/
  6375. /* */
  6376. /* deletesite() Delete a vertex from a Delaunay triangulation, ensuring */
  6377. /* that the triangulation remains Delaunay. */
  6378. /* */
  6379. /* The origin of `deltri' is deleted. The union of the triangles adjacent */
  6380. /* to this point is a polygon, for which the Delaunay triangulation is */
  6381. /* found. Two triangles are removed from the mesh. */
  6382. /* */
  6383. /* Only interior points that do not lie on segments (shell edges) or */
  6384. /* boundaries may be deleted. */
  6385. /* */
  6386. /*****************************************************************************/
  6387. #ifndef CDT_ONLY
  6388. void deletesite( deltri )
  6389. struct triedge *deltri;
  6390. {
  6391. struct triedge countingtri;
  6392. struct triedge firstedge, lastedge;
  6393. struct triedge deltriright;
  6394. struct triedge lefttri, righttri;
  6395. struct triedge leftcasing, rightcasing;
  6396. struct edge leftshelle, rightshelle;
  6397. point delpoint;
  6398. point neworg;
  6399. int edgecount;
  6400. triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
  6401. shelle sptr; /* Temporary variable used by tspivot(). */
  6402. org( *deltri, delpoint );
  6403. if ( verbose > 1 ) {
  6404. printf( " Deleting (%.12g, %.12g).\n", delpoint[0], delpoint[1] );
  6405. }
  6406. pointdealloc( delpoint );
  6407. /* Count the degree of the point being deleted. */
  6408. onext( *deltri, countingtri );
  6409. edgecount = 1;
  6410. while ( !triedgeequal( *deltri, countingtri ) ) {
  6411. #ifdef SELF_CHECK
  6412. if ( countingtri.tri == dummytri ) {
  6413. printf( "Internal error in deletesite():\n" );
  6414. printf( " Attempt to delete boundary point.\n" );
  6415. internalerror();
  6416. }
  6417. #endif /* SELF_CHECK */
  6418. edgecount++;
  6419. onextself( countingtri );
  6420. }
  6421. #ifdef SELF_CHECK
  6422. if ( edgecount < 3 ) {
  6423. printf( "Internal error in deletesite():\n Point has degree %d.\n",
  6424. edgecount );
  6425. internalerror();
  6426. }
  6427. #endif /* SELF_CHECK */
  6428. if ( edgecount > 3 ) {
  6429. /* Triangulate the polygon defined by the union of all triangles */
  6430. /* adjacent to the point being deleted. Check the quality of */
  6431. /* the resulting triangles. */
  6432. onext( *deltri, firstedge );
  6433. oprev( *deltri, lastedge );
  6434. triangulatepolygon( &firstedge, &lastedge, edgecount, 0, !nobisect );
  6435. }
  6436. /* Splice out two triangles. */
  6437. lprev( *deltri, deltriright );
  6438. dnext( *deltri, lefttri );
  6439. sym( lefttri, leftcasing );
  6440. oprev( deltriright, righttri );
  6441. sym( righttri, rightcasing );
  6442. bond( *deltri, leftcasing );
  6443. bond( deltriright, rightcasing );
  6444. tspivot( lefttri, leftshelle );
  6445. if ( leftshelle.sh != dummysh ) {
  6446. tsbond( *deltri, leftshelle );
  6447. }
  6448. tspivot( righttri, rightshelle );
  6449. if ( rightshelle.sh != dummysh ) {
  6450. tsbond( deltriright, rightshelle );
  6451. }
  6452. /* Set the new origin of `deltri' and check its quality. */
  6453. org( lefttri, neworg );
  6454. setorg( *deltri, neworg );
  6455. if ( !nobisect ) {
  6456. testtriangle( deltri );
  6457. }
  6458. /* Delete the two spliced-out triangles. */
  6459. triangledealloc( lefttri.tri );
  6460. triangledealloc( righttri.tri );
  6461. }
  6462. #endif /* not CDT_ONLY */
  6463. /** **/
  6464. /** **/
  6465. /********* Mesh transformation routines end here *********/
  6466. /********* Divide-and-conquer Delaunay triangulation begins here *********/
  6467. /** **/
  6468. /** **/
  6469. /*****************************************************************************/
  6470. /* */
  6471. /* The divide-and-conquer bounding box */
  6472. /* */
  6473. /* I originally implemented the divide-and-conquer and incremental Delaunay */
  6474. /* triangulations using the edge-based data structure presented by Guibas */
  6475. /* and Stolfi. Switching to a triangle-based data structure doubled the */
  6476. /* speed. However, I had to think of a few extra tricks to maintain the */
  6477. /* elegance of the original algorithms. */
  6478. /* */
  6479. /* The "bounding box" used by my variant of the divide-and-conquer */
  6480. /* algorithm uses one triangle for each edge of the convex hull of the */
  6481. /* triangulation. These bounding triangles all share a common apical */
  6482. /* vertex, which is represented by NULL and which represents nothing. */
  6483. /* The bounding triangles are linked in a circular fan about this NULL */
  6484. /* vertex, and the edges on the convex hull of the triangulation appear */
  6485. /* opposite the NULL vertex. You might find it easiest to imagine that */
  6486. /* the NULL vertex is a point in 3D space behind the center of the */
  6487. /* triangulation, and that the bounding triangles form a sort of cone. */
  6488. /* */
  6489. /* This bounding box makes it easy to represent degenerate cases. For */
  6490. /* instance, the triangulation of two vertices is a single edge. This edge */
  6491. /* is represented by two bounding box triangles, one on each "side" of the */
  6492. /* edge. These triangles are also linked together in a fan about the NULL */
  6493. /* vertex. */
  6494. /* */
  6495. /* The bounding box also makes it easy to traverse the convex hull, as the */
  6496. /* divide-and-conquer algorithm needs to do. */
  6497. /* */
  6498. /*****************************************************************************/
  6499. /*****************************************************************************/
  6500. /* */
  6501. /* pointsort() Sort an array of points by x-coordinate, using the */
  6502. /* y-coordinate as a secondary key. */
  6503. /* */
  6504. /* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */
  6505. /* the usual quicksort mistakes. */
  6506. /* */
  6507. /*****************************************************************************/
  6508. void pointsort( sortarray, arraysize )
  6509. point * sortarray;
  6510. int arraysize;
  6511. {
  6512. int left, right;
  6513. int pivot;
  6514. REAL pivotx, pivoty;
  6515. point temp;
  6516. if ( arraysize == 2 ) {
  6517. /* Recursive base case. */
  6518. if ( ( sortarray[0][0] > sortarray[1][0] ) ||
  6519. ( ( sortarray[0][0] == sortarray[1][0] ) &&
  6520. ( sortarray[0][1] > sortarray[1][1] ) ) ) {
  6521. temp = sortarray[1];
  6522. sortarray[1] = sortarray[0];
  6523. sortarray[0] = temp;
  6524. }
  6525. return;
  6526. }
  6527. /* Choose a random pivot to split the array. */
  6528. pivot = (int) randomnation( arraysize );
  6529. pivotx = sortarray[pivot][0];
  6530. pivoty = sortarray[pivot][1];
  6531. /* Split the array. */
  6532. left = -1;
  6533. right = arraysize;
  6534. while ( left < right ) {
  6535. /* Search for a point whose x-coordinate is too large for the left. */
  6536. do {
  6537. left++;
  6538. } while ( ( left <= right ) && ( ( sortarray[left][0] < pivotx ) ||
  6539. ( ( sortarray[left][0] == pivotx ) &&
  6540. ( sortarray[left][1] < pivoty ) ) ) );
  6541. /* Search for a point whose x-coordinate is too small for the right. */
  6542. do {
  6543. right--;
  6544. } while ( ( left <= right ) && ( ( sortarray[right][0] > pivotx ) ||
  6545. ( ( sortarray[right][0] == pivotx ) &&
  6546. ( sortarray[right][1] > pivoty ) ) ) );
  6547. if ( left < right ) {
  6548. /* Swap the left and right points. */
  6549. temp = sortarray[left];
  6550. sortarray[left] = sortarray[right];
  6551. sortarray[right] = temp;
  6552. }
  6553. }
  6554. if ( left > 1 ) {
  6555. /* Recursively sort the left subset. */
  6556. pointsort( sortarray, left );
  6557. }
  6558. if ( right < arraysize - 2 ) {
  6559. /* Recursively sort the right subset. */
  6560. pointsort( &sortarray[right + 1], arraysize - right - 1 );
  6561. }
  6562. }
  6563. /*****************************************************************************/
  6564. /* */
  6565. /* pointmedian() An order statistic algorithm, almost. Shuffles an array */
  6566. /* of points so that the first `median' points occur */
  6567. /* lexicographically before the remaining points. */
  6568. /* */
  6569. /* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */
  6570. /* if axis == 1. Very similar to the pointsort() procedure, but runs in */
  6571. /* randomized linear time. */
  6572. /* */
  6573. /*****************************************************************************/
  6574. void pointmedian( sortarray, arraysize, median, axis )
  6575. point * sortarray;
  6576. int arraysize;
  6577. int median;
  6578. int axis;
  6579. {
  6580. int left, right;
  6581. int pivot;
  6582. REAL pivot1, pivot2;
  6583. point temp;
  6584. if ( arraysize == 2 ) {
  6585. /* Recursive base case. */
  6586. if ( ( sortarray[0][axis] > sortarray[1][axis] ) ||
  6587. ( ( sortarray[0][axis] == sortarray[1][axis] ) &&
  6588. ( sortarray[0][1 - axis] > sortarray[1][1 - axis] ) ) ) {
  6589. temp = sortarray[1];
  6590. sortarray[1] = sortarray[0];
  6591. sortarray[0] = temp;
  6592. }
  6593. return;
  6594. }
  6595. /* Choose a random pivot to split the array. */
  6596. pivot = (int) randomnation( arraysize );
  6597. pivot1 = sortarray[pivot][axis];
  6598. pivot2 = sortarray[pivot][1 - axis];
  6599. /* Split the array. */
  6600. left = -1;
  6601. right = arraysize;
  6602. while ( left < right ) {
  6603. /* Search for a point whose x-coordinate is too large for the left. */
  6604. do {
  6605. left++;
  6606. } while ( ( left <= right ) && ( ( sortarray[left][axis] < pivot1 ) ||
  6607. ( ( sortarray[left][axis] == pivot1 ) &&
  6608. ( sortarray[left][1 - axis] < pivot2 ) ) ) );
  6609. /* Search for a point whose x-coordinate is too small for the right. */
  6610. do {
  6611. right--;
  6612. } while ( ( left <= right ) && ( ( sortarray[right][axis] > pivot1 ) ||
  6613. ( ( sortarray[right][axis] == pivot1 ) &&
  6614. ( sortarray[right][1 - axis] > pivot2 ) ) ) );
  6615. if ( left < right ) {
  6616. /* Swap the left and right points. */
  6617. temp = sortarray[left];
  6618. sortarray[left] = sortarray[right];
  6619. sortarray[right] = temp;
  6620. }
  6621. }
  6622. /* Unlike in pointsort(), at most one of the following */
  6623. /* conditionals is true. */
  6624. if ( left > median ) {
  6625. /* Recursively shuffle the left subset. */
  6626. pointmedian( sortarray, left, median, axis );
  6627. }
  6628. if ( right < median - 1 ) {
  6629. /* Recursively shuffle the right subset. */
  6630. pointmedian( &sortarray[right + 1], arraysize - right - 1,
  6631. median - right - 1, axis );
  6632. }
  6633. }
  6634. /*****************************************************************************/
  6635. /* */
  6636. /* alternateaxes() Sorts the points as appropriate for the divide-and- */
  6637. /* conquer algorithm with alternating cuts. */
  6638. /* */
  6639. /* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */
  6640. /* For the base case, subsets containing only two or three points are */
  6641. /* always sorted by x-coordinate. */
  6642. /* */
  6643. /*****************************************************************************/
  6644. void alternateaxes( sortarray, arraysize, axis )
  6645. point * sortarray;
  6646. int arraysize;
  6647. int axis;
  6648. {
  6649. int divider;
  6650. divider = arraysize >> 1;
  6651. if ( arraysize <= 3 ) {
  6652. /* Recursive base case: subsets of two or three points will be */
  6653. /* handled specially, and should always be sorted by x-coordinate. */
  6654. axis = 0;
  6655. }
  6656. /* Partition with a horizontal or vertical cut. */
  6657. pointmedian( sortarray, arraysize, divider, axis );
  6658. /* Recursively partition the subsets with a cross cut. */
  6659. if ( arraysize - divider >= 2 ) {
  6660. if ( divider >= 2 ) {
  6661. alternateaxes( sortarray, divider, 1 - axis );
  6662. }
  6663. alternateaxes( &sortarray[divider], arraysize - divider, 1 - axis );
  6664. }
  6665. }
  6666. /*****************************************************************************/
  6667. /* */
  6668. /* mergehulls() Merge two adjacent Delaunay triangulations into a */
  6669. /* single Delaunay triangulation. */
  6670. /* */
  6671. /* This is similar to the algorithm given by Guibas and Stolfi, but uses */
  6672. /* a triangle-based, rather than edge-based, data structure. */
  6673. /* */
  6674. /* The algorithm walks up the gap between the two triangulations, knitting */
  6675. /* them together. As they are merged, some of their bounding triangles */
  6676. /* are converted into real triangles of the triangulation. The procedure */
  6677. /* pulls each hull's bounding triangles apart, then knits them together */
  6678. /* like the teeth of two gears. The Delaunay property determines, at each */
  6679. /* step, whether the next "tooth" is a bounding triangle of the left hull */
  6680. /* or the right. When a bounding triangle becomes real, its apex is */
  6681. /* changed from NULL to a real point. */
  6682. /* */
  6683. /* Only two new triangles need to be allocated. These become new bounding */
  6684. /* triangles at the top and bottom of the seam. They are used to connect */
  6685. /* the remaining bounding triangles (those that have not been converted */
  6686. /* into real triangles) into a single fan. */
  6687. /* */
  6688. /* On entry, `farleft' and `innerleft' are bounding triangles of the left */
  6689. /* triangulation. The origin of `farleft' is the leftmost vertex, and */
  6690. /* the destination of `innerleft' is the rightmost vertex of the */
  6691. /* triangulation. Similarly, `innerright' and `farright' are bounding */
  6692. /* triangles of the right triangulation. The origin of `innerright' and */
  6693. /* destination of `farright' are the leftmost and rightmost vertices. */
  6694. /* */
  6695. /* On completion, the origin of `farleft' is the leftmost vertex of the */
  6696. /* merged triangulation, and the destination of `farright' is the rightmost */
  6697. /* vertex. */
  6698. /* */
  6699. /*****************************************************************************/
  6700. void mergehulls( farleft, innerleft, innerright, farright, axis )
  6701. struct triedge *farleft;
  6702. struct triedge *innerleft;
  6703. struct triedge *innerright;
  6704. struct triedge *farright;
  6705. int axis;
  6706. {
  6707. struct triedge leftcand, rightcand;
  6708. struct triedge baseedge;
  6709. struct triedge nextedge;
  6710. struct triedge sidecasing, topcasing, outercasing;
  6711. struct triedge checkedge;
  6712. point innerleftdest;
  6713. point innerrightorg;
  6714. point innerleftapex, innerrightapex;
  6715. point farleftpt, farrightpt;
  6716. point farleftapex, farrightapex;
  6717. point lowerleft, lowerright;
  6718. point upperleft, upperright;
  6719. point nextapex;
  6720. point checkvertex;
  6721. int changemade;
  6722. int badedge;
  6723. int leftfinished, rightfinished;
  6724. triangle ptr; /* Temporary variable used by sym(). */
  6725. dest( *innerleft, innerleftdest );
  6726. apex( *innerleft, innerleftapex );
  6727. org( *innerright, innerrightorg );
  6728. apex( *innerright, innerrightapex );
  6729. /* Special treatment for horizontal cuts. */
  6730. if ( dwyer && ( axis == 1 ) ) {
  6731. org( *farleft, farleftpt );
  6732. apex( *farleft, farleftapex );
  6733. dest( *farright, farrightpt );
  6734. apex( *farright, farrightapex );
  6735. /* The pointers to the extremal points are shifted to point to the */
  6736. /* topmost and bottommost point of each hull, rather than the */
  6737. /* leftmost and rightmost points. */
  6738. while ( farleftapex[1] < farleftpt[1] ) {
  6739. lnextself( *farleft );
  6740. symself( *farleft );
  6741. farleftpt = farleftapex;
  6742. apex( *farleft, farleftapex );
  6743. }
  6744. sym( *innerleft, checkedge );
  6745. apex( checkedge, checkvertex );
  6746. while ( checkvertex[1] > innerleftdest[1] ) {
  6747. lnext( checkedge, *innerleft );
  6748. innerleftapex = innerleftdest;
  6749. innerleftdest = checkvertex;
  6750. sym( *innerleft, checkedge );
  6751. apex( checkedge, checkvertex );
  6752. }
  6753. while ( innerrightapex[1] < innerrightorg[1] ) {
  6754. lnextself( *innerright );
  6755. symself( *innerright );
  6756. innerrightorg = innerrightapex;
  6757. apex( *innerright, innerrightapex );
  6758. }
  6759. sym( *farright, checkedge );
  6760. apex( checkedge, checkvertex );
  6761. while ( checkvertex[1] > farrightpt[1] ) {
  6762. lnext( checkedge, *farright );
  6763. farrightapex = farrightpt;
  6764. farrightpt = checkvertex;
  6765. sym( *farright, checkedge );
  6766. apex( checkedge, checkvertex );
  6767. }
  6768. }
  6769. /* Find a line tangent to and below both hulls. */
  6770. do {
  6771. changemade = 0;
  6772. /* Make innerleftdest the "bottommost" point of the left hull. */
  6773. if ( counterclockwise( innerleftdest, innerleftapex, innerrightorg ) > 0.0 ) {
  6774. lprevself( *innerleft );
  6775. symself( *innerleft );
  6776. innerleftdest = innerleftapex;
  6777. apex( *innerleft, innerleftapex );
  6778. changemade = 1;
  6779. }
  6780. /* Make innerrightorg the "bottommost" point of the right hull. */
  6781. if ( counterclockwise( innerrightapex, innerrightorg, innerleftdest ) > 0.0 ) {
  6782. lnextself( *innerright );
  6783. symself( *innerright );
  6784. innerrightorg = innerrightapex;
  6785. apex( *innerright, innerrightapex );
  6786. changemade = 1;
  6787. }
  6788. } while ( changemade );
  6789. /* Find the two candidates to be the next "gear tooth". */
  6790. sym( *innerleft, leftcand );
  6791. sym( *innerright, rightcand );
  6792. /* Create the bottom new bounding triangle. */
  6793. maketriangle( &baseedge );
  6794. /* Connect it to the bounding boxes of the left and right triangulations. */
  6795. bond( baseedge, *innerleft );
  6796. lnextself( baseedge );
  6797. bond( baseedge, *innerright );
  6798. lnextself( baseedge );
  6799. setorg( baseedge, innerrightorg );
  6800. setdest( baseedge, innerleftdest );
  6801. /* Apex is intentionally left NULL. */
  6802. if ( verbose > 2 ) {
  6803. printf( " Creating base bounding " );
  6804. printtriangle( &baseedge );
  6805. }
  6806. /* Fix the extreme triangles if necessary. */
  6807. org( *farleft, farleftpt );
  6808. if ( innerleftdest == farleftpt ) {
  6809. lnext( baseedge, *farleft );
  6810. }
  6811. dest( *farright, farrightpt );
  6812. if ( innerrightorg == farrightpt ) {
  6813. lprev( baseedge, *farright );
  6814. }
  6815. /* The vertices of the current knitting edge. */
  6816. lowerleft = innerleftdest;
  6817. lowerright = innerrightorg;
  6818. /* The candidate vertices for knitting. */
  6819. apex( leftcand, upperleft );
  6820. apex( rightcand, upperright );
  6821. /* Walk up the gap between the two triangulations, knitting them together. */
  6822. while ( 1 ) {
  6823. /* Have we reached the top? (This isn't quite the right question, */
  6824. /* because even though the left triangulation might seem finished now, */
  6825. /* moving up on the right triangulation might reveal a new point of */
  6826. /* the left triangulation. And vice-versa.) */
  6827. leftfinished = counterclockwise( upperleft, lowerleft, lowerright ) <= 0.0;
  6828. rightfinished = counterclockwise( upperright, lowerleft, lowerright ) <= 0.0;
  6829. if ( leftfinished && rightfinished ) {
  6830. /* Create the top new bounding triangle. */
  6831. maketriangle( &nextedge );
  6832. setorg( nextedge, lowerleft );
  6833. setdest( nextedge, lowerright );
  6834. /* Apex is intentionally left NULL. */
  6835. /* Connect it to the bounding boxes of the two triangulations. */
  6836. bond( nextedge, baseedge );
  6837. lnextself( nextedge );
  6838. bond( nextedge, rightcand );
  6839. lnextself( nextedge );
  6840. bond( nextedge, leftcand );
  6841. if ( verbose > 2 ) {
  6842. printf( " Creating top bounding " );
  6843. printtriangle( &baseedge );
  6844. }
  6845. /* Special treatment for horizontal cuts. */
  6846. if ( dwyer && ( axis == 1 ) ) {
  6847. org( *farleft, farleftpt );
  6848. apex( *farleft, farleftapex );
  6849. dest( *farright, farrightpt );
  6850. apex( *farright, farrightapex );
  6851. sym( *farleft, checkedge );
  6852. apex( checkedge, checkvertex );
  6853. /* The pointers to the extremal points are restored to the leftmost */
  6854. /* and rightmost points (rather than topmost and bottommost). */
  6855. while ( checkvertex[0] < farleftpt[0] ) {
  6856. lprev( checkedge, *farleft );
  6857. farleftapex = farleftpt;
  6858. farleftpt = checkvertex;
  6859. sym( *farleft, checkedge );
  6860. apex( checkedge, checkvertex );
  6861. }
  6862. while ( farrightapex[0] > farrightpt[0] ) {
  6863. lprevself( *farright );
  6864. symself( *farright );
  6865. farrightpt = farrightapex;
  6866. apex( *farright, farrightapex );
  6867. }
  6868. }
  6869. return;
  6870. }
  6871. /* Consider eliminating edges from the left triangulation. */
  6872. if ( !leftfinished ) {
  6873. /* What vertex would be exposed if an edge were deleted? */
  6874. lprev( leftcand, nextedge );
  6875. symself( nextedge );
  6876. apex( nextedge, nextapex );
  6877. /* If nextapex is NULL, then no vertex would be exposed; the */
  6878. /* triangulation would have been eaten right through. */
  6879. if ( nextapex != (point) NULL ) {
  6880. /* Check whether the edge is Delaunay. */
  6881. badedge = incircle( lowerleft, lowerright, upperleft, nextapex ) > 0.0;
  6882. while ( badedge ) {
  6883. /* Eliminate the edge with an edge flip. As a result, the */
  6884. /* left triangulation will have one more boundary triangle. */
  6885. lnextself( nextedge );
  6886. sym( nextedge, topcasing );
  6887. lnextself( nextedge );
  6888. sym( nextedge, sidecasing );
  6889. bond( nextedge, topcasing );
  6890. bond( leftcand, sidecasing );
  6891. lnextself( leftcand );
  6892. sym( leftcand, outercasing );
  6893. lprevself( nextedge );
  6894. bond( nextedge, outercasing );
  6895. /* Correct the vertices to reflect the edge flip. */
  6896. setorg( leftcand, lowerleft );
  6897. setdest( leftcand, NULL );
  6898. setapex( leftcand, nextapex );
  6899. setorg( nextedge, NULL );
  6900. setdest( nextedge, upperleft );
  6901. setapex( nextedge, nextapex );
  6902. /* Consider the newly exposed vertex. */
  6903. upperleft = nextapex;
  6904. /* What vertex would be exposed if another edge were deleted? */
  6905. triedgecopy( sidecasing, nextedge );
  6906. apex( nextedge, nextapex );
  6907. if ( nextapex != (point) NULL ) {
  6908. /* Check whether the edge is Delaunay. */
  6909. badedge = incircle( lowerleft, lowerright, upperleft, nextapex )
  6910. > 0.0;
  6911. }
  6912. else {
  6913. /* Avoid eating right through the triangulation. */
  6914. badedge = 0;
  6915. }
  6916. }
  6917. }
  6918. }
  6919. /* Consider eliminating edges from the right triangulation. */
  6920. if ( !rightfinished ) {
  6921. /* What vertex would be exposed if an edge were deleted? */
  6922. lnext( rightcand, nextedge );
  6923. symself( nextedge );
  6924. apex( nextedge, nextapex );
  6925. /* If nextapex is NULL, then no vertex would be exposed; the */
  6926. /* triangulation would have been eaten right through. */
  6927. if ( nextapex != (point) NULL ) {
  6928. /* Check whether the edge is Delaunay. */
  6929. badedge = incircle( lowerleft, lowerright, upperright, nextapex ) > 0.0;
  6930. while ( badedge ) {
  6931. /* Eliminate the edge with an edge flip. As a result, the */
  6932. /* right triangulation will have one more boundary triangle. */
  6933. lprevself( nextedge );
  6934. sym( nextedge, topcasing );
  6935. lprevself( nextedge );
  6936. sym( nextedge, sidecasing );
  6937. bond( nextedge, topcasing );
  6938. bond( rightcand, sidecasing );
  6939. lprevself( rightcand );
  6940. sym( rightcand, outercasing );
  6941. lnextself( nextedge );
  6942. bond( nextedge, outercasing );
  6943. /* Correct the vertices to reflect the edge flip. */
  6944. setorg( rightcand, NULL );
  6945. setdest( rightcand, lowerright );
  6946. setapex( rightcand, nextapex );
  6947. setorg( nextedge, upperright );
  6948. setdest( nextedge, NULL );
  6949. setapex( nextedge, nextapex );
  6950. /* Consider the newly exposed vertex. */
  6951. upperright = nextapex;
  6952. /* What vertex would be exposed if another edge were deleted? */
  6953. triedgecopy( sidecasing, nextedge );
  6954. apex( nextedge, nextapex );
  6955. if ( nextapex != (point) NULL ) {
  6956. /* Check whether the edge is Delaunay. */
  6957. badedge = incircle( lowerleft, lowerright, upperright, nextapex )
  6958. > 0.0;
  6959. }
  6960. else {
  6961. /* Avoid eating right through the triangulation. */
  6962. badedge = 0;
  6963. }
  6964. }
  6965. }
  6966. }
  6967. if ( leftfinished || ( !rightfinished &&
  6968. ( incircle( upperleft, lowerleft, lowerright, upperright ) > 0.0 ) ) ) {
  6969. /* Knit the triangulations, adding an edge from `lowerleft' */
  6970. /* to `upperright'. */
  6971. bond( baseedge, rightcand );
  6972. lprev( rightcand, baseedge );
  6973. setdest( baseedge, lowerleft );
  6974. lowerright = upperright;
  6975. sym( baseedge, rightcand );
  6976. apex( rightcand, upperright );
  6977. }
  6978. else {
  6979. /* Knit the triangulations, adding an edge from `upperleft' */
  6980. /* to `lowerright'. */
  6981. bond( baseedge, leftcand );
  6982. lnext( leftcand, baseedge );
  6983. setorg( baseedge, lowerright );
  6984. lowerleft = upperleft;
  6985. sym( baseedge, leftcand );
  6986. apex( leftcand, upperleft );
  6987. }
  6988. if ( verbose > 2 ) {
  6989. printf( " Connecting " );
  6990. printtriangle( &baseedge );
  6991. }
  6992. }
  6993. }
  6994. /*****************************************************************************/
  6995. /* */
  6996. /* divconqrecurse() Recursively form a Delaunay triangulation by the */
  6997. /* divide-and-conquer method. */
  6998. /* */
  6999. /* Recursively breaks down the problem into smaller pieces, which are */
  7000. /* knitted together by mergehulls(). The base cases (problems of two or */
  7001. /* three points) are handled specially here. */
  7002. /* */
  7003. /* On completion, `farleft' and `farright' are bounding triangles such that */
  7004. /* the origin of `farleft' is the leftmost vertex (breaking ties by */
  7005. /* choosing the highest leftmost vertex), and the destination of */
  7006. /* `farright' is the rightmost vertex (breaking ties by choosing the */
  7007. /* lowest rightmost vertex). */
  7008. /* */
  7009. /*****************************************************************************/
  7010. void divconqrecurse( sortarray, vertices, axis, farleft, farright )
  7011. point * sortarray;
  7012. int vertices;
  7013. int axis;
  7014. struct triedge *farleft;
  7015. struct triedge *farright;
  7016. {
  7017. struct triedge midtri, tri1, tri2, tri3;
  7018. struct triedge innerleft, innerright;
  7019. REAL area;
  7020. int divider;
  7021. if ( verbose > 2 ) {
  7022. printf( " Triangulating %d points.\n", vertices );
  7023. }
  7024. if ( vertices == 2 ) {
  7025. /* The triangulation of two vertices is an edge. An edge is */
  7026. /* represented by two bounding triangles. */
  7027. maketriangle( farleft );
  7028. setorg( *farleft, sortarray[0] );
  7029. setdest( *farleft, sortarray[1] );
  7030. /* The apex is intentionally left NULL. */
  7031. maketriangle( farright );
  7032. setorg( *farright, sortarray[1] );
  7033. setdest( *farright, sortarray[0] );
  7034. /* The apex is intentionally left NULL. */
  7035. bond( *farleft, *farright );
  7036. lprevself( *farleft );
  7037. lnextself( *farright );
  7038. bond( *farleft, *farright );
  7039. lprevself( *farleft );
  7040. lnextself( *farright );
  7041. bond( *farleft, *farright );
  7042. if ( verbose > 2 ) {
  7043. printf( " Creating " );
  7044. printtriangle( farleft );
  7045. printf( " Creating " );
  7046. printtriangle( farright );
  7047. }
  7048. /* Ensure that the origin of `farleft' is sortarray[0]. */
  7049. lprev( *farright, *farleft );
  7050. return;
  7051. }
  7052. else if ( vertices == 3 ) {
  7053. /* The triangulation of three vertices is either a triangle (with */
  7054. /* three bounding triangles) or two edges (with four bounding */
  7055. /* triangles). In either case, four triangles are created. */
  7056. maketriangle( &midtri );
  7057. maketriangle( &tri1 );
  7058. maketriangle( &tri2 );
  7059. maketriangle( &tri3 );
  7060. area = counterclockwise( sortarray[0], sortarray[1], sortarray[2] );
  7061. if ( area == 0.0 ) {
  7062. /* Three collinear points; the triangulation is two edges. */
  7063. setorg( midtri, sortarray[0] );
  7064. setdest( midtri, sortarray[1] );
  7065. setorg( tri1, sortarray[1] );
  7066. setdest( tri1, sortarray[0] );
  7067. setorg( tri2, sortarray[2] );
  7068. setdest( tri2, sortarray[1] );
  7069. setorg( tri3, sortarray[1] );
  7070. setdest( tri3, sortarray[2] );
  7071. /* All apices are intentionally left NULL. */
  7072. bond( midtri, tri1 );
  7073. bond( tri2, tri3 );
  7074. lnextself( midtri );
  7075. lprevself( tri1 );
  7076. lnextself( tri2 );
  7077. lprevself( tri3 );
  7078. bond( midtri, tri3 );
  7079. bond( tri1, tri2 );
  7080. lnextself( midtri );
  7081. lprevself( tri1 );
  7082. lnextself( tri2 );
  7083. lprevself( tri3 );
  7084. bond( midtri, tri1 );
  7085. bond( tri2, tri3 );
  7086. /* Ensure that the origin of `farleft' is sortarray[0]. */
  7087. triedgecopy( tri1, *farleft );
  7088. /* Ensure that the destination of `farright' is sortarray[2]. */
  7089. triedgecopy( tri2, *farright );
  7090. }
  7091. else {
  7092. /* The three points are not collinear; the triangulation is one */
  7093. /* triangle, namely `midtri'. */
  7094. setorg( midtri, sortarray[0] );
  7095. setdest( tri1, sortarray[0] );
  7096. setorg( tri3, sortarray[0] );
  7097. /* Apices of tri1, tri2, and tri3 are left NULL. */
  7098. if ( area > 0.0 ) {
  7099. /* The vertices are in counterclockwise order. */
  7100. setdest( midtri, sortarray[1] );
  7101. setorg( tri1, sortarray[1] );
  7102. setdest( tri2, sortarray[1] );
  7103. setapex( midtri, sortarray[2] );
  7104. setorg( tri2, sortarray[2] );
  7105. setdest( tri3, sortarray[2] );
  7106. }
  7107. else {
  7108. /* The vertices are in clockwise order. */
  7109. setdest( midtri, sortarray[2] );
  7110. setorg( tri1, sortarray[2] );
  7111. setdest( tri2, sortarray[2] );
  7112. setapex( midtri, sortarray[1] );
  7113. setorg( tri2, sortarray[1] );
  7114. setdest( tri3, sortarray[1] );
  7115. }
  7116. /* The topology does not depend on how the vertices are ordered. */
  7117. bond( midtri, tri1 );
  7118. lnextself( midtri );
  7119. bond( midtri, tri2 );
  7120. lnextself( midtri );
  7121. bond( midtri, tri3 );
  7122. lprevself( tri1 );
  7123. lnextself( tri2 );
  7124. bond( tri1, tri2 );
  7125. lprevself( tri1 );
  7126. lprevself( tri3 );
  7127. bond( tri1, tri3 );
  7128. lnextself( tri2 );
  7129. lprevself( tri3 );
  7130. bond( tri2, tri3 );
  7131. /* Ensure that the origin of `farleft' is sortarray[0]. */
  7132. triedgecopy( tri1, *farleft );
  7133. /* Ensure that the destination of `farright' is sortarray[2]. */
  7134. if ( area > 0.0 ) {
  7135. triedgecopy( tri2, *farright );
  7136. }
  7137. else {
  7138. lnext( *farleft, *farright );
  7139. }
  7140. }
  7141. if ( verbose > 2 ) {
  7142. printf( " Creating " );
  7143. printtriangle( &midtri );
  7144. printf( " Creating " );
  7145. printtriangle( &tri1 );
  7146. printf( " Creating " );
  7147. printtriangle( &tri2 );
  7148. printf( " Creating " );
  7149. printtriangle( &tri3 );
  7150. }
  7151. return;
  7152. }
  7153. else {
  7154. /* Split the vertices in half. */
  7155. divider = vertices >> 1;
  7156. /* Recursively triangulate each half. */
  7157. divconqrecurse( sortarray, divider, 1 - axis, farleft, &innerleft );
  7158. divconqrecurse( &sortarray[divider], vertices - divider, 1 - axis,
  7159. &innerright, farright );
  7160. if ( verbose > 1 ) {
  7161. printf( " Joining triangulations with %d and %d vertices.\n", divider,
  7162. vertices - divider );
  7163. }
  7164. /* Merge the two triangulations into one. */
  7165. mergehulls( farleft, &innerleft, &innerright, farright, axis );
  7166. }
  7167. }
  7168. long removeghosts( startghost )
  7169. struct triedge *startghost;
  7170. {
  7171. struct triedge searchedge;
  7172. struct triedge dissolveedge;
  7173. struct triedge deadtri;
  7174. point markorg;
  7175. long hullsize;
  7176. triangle ptr; /* Temporary variable used by sym(). */
  7177. if ( verbose ) {
  7178. printf( " Removing ghost triangles.\n" );
  7179. }
  7180. /* Find an edge on the convex hull to start point location from. */
  7181. lprev( *startghost, searchedge );
  7182. symself( searchedge );
  7183. dummytri[0] = encode( searchedge );
  7184. /* Remove the bounding box and count the convex hull edges. */
  7185. triedgecopy( *startghost, dissolveedge );
  7186. hullsize = 0;
  7187. do {
  7188. hullsize++;
  7189. lnext( dissolveedge, deadtri );
  7190. lprevself( dissolveedge );
  7191. symself( dissolveedge );
  7192. /* If no PSLG is involved, set the boundary markers of all the points */
  7193. /* on the convex hull. If a PSLG is used, this step is done later. */
  7194. if ( !poly ) {
  7195. /* Watch out for the case where all the input points are collinear. */
  7196. if ( dissolveedge.tri != dummytri ) {
  7197. org( dissolveedge, markorg );
  7198. if ( pointmark( markorg ) == 0 ) {
  7199. setpointmark( markorg, 1 );
  7200. }
  7201. }
  7202. }
  7203. /* Remove a bounding triangle from a convex hull triangle. */
  7204. dissolve( dissolveedge );
  7205. /* Find the next bounding triangle. */
  7206. sym( deadtri, dissolveedge );
  7207. /* Delete the bounding triangle. */
  7208. triangledealloc( deadtri.tri );
  7209. } while ( !triedgeequal( dissolveedge, *startghost ) );
  7210. return hullsize;
  7211. }
  7212. /*****************************************************************************/
  7213. /* */
  7214. /* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */
  7215. /* conquer method. */
  7216. /* */
  7217. /* Sorts the points, calls a recursive procedure to triangulate them, and */
  7218. /* removes the bounding box, setting boundary markers as appropriate. */
  7219. /* */
  7220. /*****************************************************************************/
  7221. long divconqdelaunay(){
  7222. point *sortarray;
  7223. struct triedge hullleft, hullright;
  7224. int divider;
  7225. int i, j;
  7226. /* Allocate an array of pointers to points for sorting. */
  7227. sortarray = (point *) malloc( inpoints * sizeof( point ) );
  7228. if ( sortarray == (point *) NULL ) {
  7229. printf( "Error: Out of memory.\n" );
  7230. exit( 1 );
  7231. }
  7232. traversalinit( &points );
  7233. for ( i = 0; i < inpoints; i++ ) {
  7234. sortarray[i] = pointtraverse();
  7235. }
  7236. if ( verbose ) {
  7237. printf( " Sorting points.\n" );
  7238. }
  7239. /* Sort the points. */
  7240. pointsort( sortarray, inpoints );
  7241. /* Discard duplicate points, which can really mess up the algorithm. */
  7242. i = 0;
  7243. for ( j = 1; j < inpoints; j++ ) {
  7244. if ( ( sortarray[i][0] == sortarray[j][0] )
  7245. && ( sortarray[i][1] == sortarray[j][1] ) ) {
  7246. if ( !quiet ) {
  7247. printf(
  7248. "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
  7249. sortarray[j][0], sortarray[j][1] );
  7250. }
  7251. /* Commented out - would eliminate point from output .node file, but causes
  7252. a failure if some segment has this point as an endpoint.
  7253. setpointmark(sortarray[j], DEADPOINT);
  7254. */
  7255. }
  7256. else {
  7257. i++;
  7258. sortarray[i] = sortarray[j];
  7259. }
  7260. }
  7261. i++;
  7262. if ( dwyer ) {
  7263. /* Re-sort the array of points to accommodate alternating cuts. */
  7264. divider = i >> 1;
  7265. if ( i - divider >= 2 ) {
  7266. if ( divider >= 2 ) {
  7267. alternateaxes( sortarray, divider, 1 );
  7268. }
  7269. alternateaxes( &sortarray[divider], i - divider, 1 );
  7270. }
  7271. }
  7272. if ( verbose ) {
  7273. printf( " Forming triangulation.\n" );
  7274. }
  7275. /* Form the Delaunay triangulation. */
  7276. divconqrecurse( sortarray, i, 0, &hullleft, &hullright );
  7277. free( sortarray );
  7278. return removeghosts( &hullleft );
  7279. }
  7280. /** **/
  7281. /** **/
  7282. /********* Divide-and-conquer Delaunay triangulation ends here *********/
  7283. /********* Incremental Delaunay triangulation begins here *********/
  7284. /** **/
  7285. /** **/
  7286. /*****************************************************************************/
  7287. /* */
  7288. /* boundingbox() Form an "infinite" bounding triangle to insert points */
  7289. /* into. */
  7290. /* */
  7291. /* The points at "infinity" are assigned finite coordinates, which are used */
  7292. /* by the point location routines, but (mostly) ignored by the Delaunay */
  7293. /* edge flip routines. */
  7294. /* */
  7295. /*****************************************************************************/
  7296. #ifndef REDUCED
  7297. void boundingbox(){
  7298. struct triedge inftri; /* Handle for the triangular bounding box. */
  7299. REAL width;
  7300. if ( verbose ) {
  7301. printf( " Creating triangular bounding box.\n" );
  7302. }
  7303. /* Find the width (or height, whichever is larger) of the triangulation. */
  7304. width = xmax - xmin;
  7305. if ( ymax - ymin > width ) {
  7306. width = ymax - ymin;
  7307. }
  7308. if ( width == 0.0 ) {
  7309. width = 1.0;
  7310. }
  7311. /* Create the vertices of the bounding box. */
  7312. infpoint1 = (point) malloc( points.itembytes );
  7313. infpoint2 = (point) malloc( points.itembytes );
  7314. infpoint3 = (point) malloc( points.itembytes );
  7315. if ( ( infpoint1 == (point) NULL ) || ( infpoint2 == (point) NULL )
  7316. || ( infpoint3 == (point) NULL ) ) {
  7317. printf( "Error: Out of memory.\n" );
  7318. exit( 1 );
  7319. }
  7320. infpoint1[0] = xmin - 50.0 * width;
  7321. infpoint1[1] = ymin - 40.0 * width;
  7322. infpoint2[0] = xmax + 50.0 * width;
  7323. infpoint2[1] = ymin - 40.0 * width;
  7324. infpoint3[0] = 0.5 * ( xmin + xmax );
  7325. infpoint3[1] = ymax + 60.0 * width;
  7326. /* Create the bounding box. */
  7327. maketriangle( &inftri );
  7328. setorg( inftri, infpoint1 );
  7329. setdest( inftri, infpoint2 );
  7330. setapex( inftri, infpoint3 );
  7331. /* Link dummytri to the bounding box so we can always find an */
  7332. /* edge to begin searching (point location) from. */
  7333. dummytri[0] = (triangle) inftri.tri;
  7334. if ( verbose > 2 ) {
  7335. printf( " Creating " );
  7336. printtriangle( &inftri );
  7337. }
  7338. }
  7339. #endif /* not REDUCED */
  7340. /*****************************************************************************/
  7341. /* */
  7342. /* removebox() Remove the "infinite" bounding triangle, setting boundary */
  7343. /* markers as appropriate. */
  7344. /* */
  7345. /* The triangular bounding box has three boundary triangles (one for each */
  7346. /* side of the bounding box), and a bunch of triangles fanning out from */
  7347. /* the three bounding box vertices (one triangle for each edge of the */
  7348. /* convex hull of the inner mesh). This routine removes these triangles. */
  7349. /* */
  7350. /*****************************************************************************/
  7351. #ifndef REDUCED
  7352. long removebox(){
  7353. struct triedge deadtri;
  7354. struct triedge searchedge;
  7355. struct triedge checkedge;
  7356. struct triedge nextedge, finaledge, dissolveedge;
  7357. point markorg;
  7358. long hullsize;
  7359. triangle ptr; /* Temporary variable used by sym(). */
  7360. if ( verbose ) {
  7361. printf( " Removing triangular bounding box.\n" );
  7362. }
  7363. /* Find a boundary triangle. */
  7364. nextedge.tri = dummytri;
  7365. nextedge.orient = 0;
  7366. symself( nextedge );
  7367. /* Mark a place to stop. */
  7368. lprev( nextedge, finaledge );
  7369. lnextself( nextedge );
  7370. symself( nextedge );
  7371. /* Find a triangle (on the boundary of the point set) that isn't */
  7372. /* a bounding box triangle. */
  7373. lprev( nextedge, searchedge );
  7374. symself( searchedge );
  7375. /* Check whether nextedge is another boundary triangle */
  7376. /* adjacent to the first one. */
  7377. lnext( nextedge, checkedge );
  7378. symself( checkedge );
  7379. if ( checkedge.tri == dummytri ) {
  7380. /* Go on to the next triangle. There are only three boundary */
  7381. /* triangles, and this next triangle cannot be the third one, */
  7382. /* so it's safe to stop here. */
  7383. lprevself( searchedge );
  7384. symself( searchedge );
  7385. }
  7386. /* Find a new boundary edge to search from, as the current search */
  7387. /* edge lies on a bounding box triangle and will be deleted. */
  7388. dummytri[0] = encode( searchedge );
  7389. hullsize = -2l;
  7390. while ( !triedgeequal( nextedge, finaledge ) ) {
  7391. hullsize++;
  7392. lprev( nextedge, dissolveedge );
  7393. symself( dissolveedge );
  7394. /* If not using a PSLG, the vertices should be marked now. */
  7395. /* (If using a PSLG, markhull() will do the job.) */
  7396. if ( !poly ) {
  7397. /* Be careful! One must check for the case where all the input */
  7398. /* points are collinear, and thus all the triangles are part of */
  7399. /* the bounding box. Otherwise, the setpointmark() call below */
  7400. /* will cause a bad pointer reference. */
  7401. if ( dissolveedge.tri != dummytri ) {
  7402. org( dissolveedge, markorg );
  7403. if ( pointmark( markorg ) == 0 ) {
  7404. setpointmark( markorg, 1 );
  7405. }
  7406. }
  7407. }
  7408. /* Disconnect the bounding box triangle from the mesh triangle. */
  7409. dissolve( dissolveedge );
  7410. lnext( nextedge, deadtri );
  7411. sym( deadtri, nextedge );
  7412. /* Get rid of the bounding box triangle. */
  7413. triangledealloc( deadtri.tri );
  7414. /* Do we need to turn the corner? */
  7415. if ( nextedge.tri == dummytri ) {
  7416. /* Turn the corner. */
  7417. triedgecopy( dissolveedge, nextedge );
  7418. }
  7419. }
  7420. triangledealloc( finaledge.tri );
  7421. free( infpoint1 ); /* Deallocate the bounding box vertices. */
  7422. free( infpoint2 );
  7423. free( infpoint3 );
  7424. return hullsize;
  7425. }
  7426. #endif /* not REDUCED */
  7427. /*****************************************************************************/
  7428. /* */
  7429. /* incrementaldelaunay() Form a Delaunay triangulation by incrementally */
  7430. /* adding vertices. */
  7431. /* */
  7432. /*****************************************************************************/
  7433. #ifndef REDUCED
  7434. long incrementaldelaunay(){
  7435. struct triedge starttri;
  7436. point pointloop;
  7437. int i;
  7438. /* Create a triangular bounding box. */
  7439. boundingbox();
  7440. if ( verbose ) {
  7441. printf( " Incrementally inserting points.\n" );
  7442. }
  7443. traversalinit( &points );
  7444. pointloop = pointtraverse();
  7445. i = 1;
  7446. while ( pointloop != (point) NULL ) {
  7447. /* Find a boundary triangle to search from. */
  7448. starttri.tri = (triangle *) NULL;
  7449. if ( insertsite( pointloop, &starttri, (struct edge *) NULL, 0, 0 ) ==
  7450. DUPLICATEPOINT ) {
  7451. if ( !quiet ) {
  7452. printf(
  7453. "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
  7454. pointloop[0], pointloop[1] );
  7455. }
  7456. /* Commented out - would eliminate point from output .node file.
  7457. setpointmark(pointloop, DEADPOINT);
  7458. */
  7459. }
  7460. pointloop = pointtraverse();
  7461. i++;
  7462. }
  7463. /* Remove the bounding box. */
  7464. return removebox();
  7465. }
  7466. #endif /* not REDUCED */
  7467. /** **/
  7468. /** **/
  7469. /********* Incremental Delaunay triangulation ends here *********/
  7470. /********* Sweepline Delaunay triangulation begins here *********/
  7471. /** **/
  7472. /** **/
  7473. #ifndef REDUCED
  7474. void eventheapinsert( heap, heapsize, newevent )
  7475. struct event **heap;
  7476. int heapsize;
  7477. struct event *newevent;
  7478. {
  7479. REAL eventx, eventy;
  7480. int eventnum;
  7481. int parent;
  7482. int notdone;
  7483. eventx = newevent->xkey;
  7484. eventy = newevent->ykey;
  7485. eventnum = heapsize;
  7486. notdone = eventnum > 0;
  7487. while ( notdone ) {
  7488. parent = ( eventnum - 1 ) >> 1;
  7489. if ( ( heap[parent]->ykey < eventy ) ||
  7490. ( ( heap[parent]->ykey == eventy )
  7491. && ( heap[parent]->xkey <= eventx ) ) ) {
  7492. notdone = 0;
  7493. }
  7494. else {
  7495. heap[eventnum] = heap[parent];
  7496. heap[eventnum]->heapposition = eventnum;
  7497. eventnum = parent;
  7498. notdone = eventnum > 0;
  7499. }
  7500. }
  7501. heap[eventnum] = newevent;
  7502. newevent->heapposition = eventnum;
  7503. }
  7504. #endif /* not REDUCED */
  7505. #ifndef REDUCED
  7506. void eventheapify( heap, heapsize, eventnum )
  7507. struct event **heap;
  7508. int heapsize;
  7509. int eventnum;
  7510. {
  7511. struct event *thisevent;
  7512. REAL eventx, eventy;
  7513. int leftchild, rightchild;
  7514. int smallest;
  7515. int notdone;
  7516. thisevent = heap[eventnum];
  7517. eventx = thisevent->xkey;
  7518. eventy = thisevent->ykey;
  7519. leftchild = 2 * eventnum + 1;
  7520. notdone = leftchild < heapsize;
  7521. while ( notdone ) {
  7522. if ( ( heap[leftchild]->ykey < eventy ) ||
  7523. ( ( heap[leftchild]->ykey == eventy )
  7524. && ( heap[leftchild]->xkey < eventx ) ) ) {
  7525. smallest = leftchild;
  7526. }
  7527. else {
  7528. smallest = eventnum;
  7529. }
  7530. rightchild = leftchild + 1;
  7531. if ( rightchild < heapsize ) {
  7532. if ( ( heap[rightchild]->ykey < heap[smallest]->ykey ) ||
  7533. ( ( heap[rightchild]->ykey == heap[smallest]->ykey )
  7534. && ( heap[rightchild]->xkey < heap[smallest]->xkey ) ) ) {
  7535. smallest = rightchild;
  7536. }
  7537. }
  7538. if ( smallest == eventnum ) {
  7539. notdone = 0;
  7540. }
  7541. else {
  7542. heap[eventnum] = heap[smallest];
  7543. heap[eventnum]->heapposition = eventnum;
  7544. heap[smallest] = thisevent;
  7545. thisevent->heapposition = smallest;
  7546. eventnum = smallest;
  7547. leftchild = 2 * eventnum + 1;
  7548. notdone = leftchild < heapsize;
  7549. }
  7550. }
  7551. }
  7552. #endif /* not REDUCED */
  7553. #ifndef REDUCED
  7554. void eventheapdelete( heap, heapsize, eventnum )
  7555. struct event **heap;
  7556. int heapsize;
  7557. int eventnum;
  7558. {
  7559. struct event *moveevent;
  7560. REAL eventx, eventy;
  7561. int parent;
  7562. int notdone;
  7563. moveevent = heap[heapsize - 1];
  7564. if ( eventnum > 0 ) {
  7565. eventx = moveevent->xkey;
  7566. eventy = moveevent->ykey;
  7567. do {
  7568. parent = ( eventnum - 1 ) >> 1;
  7569. if ( ( heap[parent]->ykey < eventy ) ||
  7570. ( ( heap[parent]->ykey == eventy )
  7571. && ( heap[parent]->xkey <= eventx ) ) ) {
  7572. notdone = 0;
  7573. }
  7574. else {
  7575. heap[eventnum] = heap[parent];
  7576. heap[eventnum]->heapposition = eventnum;
  7577. eventnum = parent;
  7578. notdone = eventnum > 0;
  7579. }
  7580. } while ( notdone );
  7581. }
  7582. heap[eventnum] = moveevent;
  7583. moveevent->heapposition = eventnum;
  7584. eventheapify( heap, heapsize - 1, eventnum );
  7585. }
  7586. #endif /* not REDUCED */
  7587. #ifndef REDUCED
  7588. void createeventheap( eventheap, events, freeevents )
  7589. struct event ***eventheap;
  7590. struct event **events;
  7591. struct event **freeevents;
  7592. {
  7593. point thispoint;
  7594. int maxevents;
  7595. int i;
  7596. maxevents = ( 3 * inpoints ) / 2;
  7597. *eventheap = (struct event **) malloc( maxevents * sizeof( struct event * ) );
  7598. if ( *eventheap == (struct event **) NULL ) {
  7599. printf( "Error: Out of memory.\n" );
  7600. exit( 1 );
  7601. }
  7602. *events = (struct event *) malloc( maxevents * sizeof( struct event ) );
  7603. if ( *events == (struct event *) NULL ) {
  7604. printf( "Error: Out of memory.\n" );
  7605. exit( 1 );
  7606. }
  7607. traversalinit( &points );
  7608. for ( i = 0; i < inpoints; i++ ) {
  7609. thispoint = pointtraverse();
  7610. ( *events )[i].eventptr = (VOID *) thispoint;
  7611. ( *events )[i].xkey = thispoint[0];
  7612. ( *events )[i].ykey = thispoint[1];
  7613. eventheapinsert( *eventheap, i, *events + i );
  7614. }
  7615. *freeevents = (struct event *) NULL;
  7616. for ( i = maxevents - 1; i >= inpoints; i-- ) {
  7617. ( *events )[i].eventptr = (VOID *) *freeevents;
  7618. *freeevents = *events + i;
  7619. }
  7620. }
  7621. #endif /* not REDUCED */
  7622. #ifndef REDUCED
  7623. int rightofhyperbola( fronttri, newsite )
  7624. struct triedge *fronttri;
  7625. point newsite;
  7626. {
  7627. point leftpoint, rightpoint;
  7628. REAL dxa, dya, dxb, dyb;
  7629. hyperbolacount++;
  7630. dest( *fronttri, leftpoint );
  7631. apex( *fronttri, rightpoint );
  7632. if ( ( leftpoint[1] < rightpoint[1] )
  7633. || ( ( leftpoint[1] == rightpoint[1] ) && ( leftpoint[0] < rightpoint[0] ) ) ) {
  7634. if ( newsite[0] >= rightpoint[0] ) {
  7635. return 1;
  7636. }
  7637. }
  7638. else {
  7639. if ( newsite[0] <= leftpoint[0] ) {
  7640. return 0;
  7641. }
  7642. }
  7643. dxa = leftpoint[0] - newsite[0];
  7644. dya = leftpoint[1] - newsite[1];
  7645. dxb = rightpoint[0] - newsite[0];
  7646. dyb = rightpoint[1] - newsite[1];
  7647. return dya * ( dxb * dxb + dyb * dyb ) > dyb * ( dxa * dxa + dya * dya );
  7648. }
  7649. #endif /* not REDUCED */
  7650. #ifndef REDUCED
  7651. REAL circletop( pa, pb, pc, ccwabc )
  7652. point pa;
  7653. point pb;
  7654. point pc;
  7655. REAL ccwabc;
  7656. {
  7657. REAL xac, yac, xbc, ybc, xab, yab;
  7658. REAL aclen2, bclen2, ablen2;
  7659. circletopcount++;
  7660. xac = pa[0] - pc[0];
  7661. yac = pa[1] - pc[1];
  7662. xbc = pb[0] - pc[0];
  7663. ybc = pb[1] - pc[1];
  7664. xab = pa[0] - pb[0];
  7665. yab = pa[1] - pb[1];
  7666. aclen2 = xac * xac + yac * yac;
  7667. bclen2 = xbc * xbc + ybc * ybc;
  7668. ablen2 = xab * xab + yab * yab;
  7669. return pc[1] + ( xac * bclen2 - xbc * aclen2 + sqrt( aclen2 * bclen2 * ablen2 ) )
  7670. / ( 2.0 * ccwabc );
  7671. }
  7672. #endif /* not REDUCED */
  7673. #ifndef REDUCED
  7674. void check4deadevent( checktri, freeevents, eventheap, heapsize )
  7675. struct triedge *checktri;
  7676. struct event **freeevents;
  7677. struct event **eventheap;
  7678. int *heapsize;
  7679. {
  7680. struct event *deadevent;
  7681. point eventpoint;
  7682. int eventnum;
  7683. org( *checktri, eventpoint );
  7684. if ( eventpoint != (point) NULL ) {
  7685. deadevent = (struct event *) eventpoint;
  7686. eventnum = deadevent->heapposition;
  7687. deadevent->eventptr = (VOID *) *freeevents;
  7688. *freeevents = deadevent;
  7689. eventheapdelete( eventheap, *heapsize, eventnum );
  7690. ( *heapsize )--;
  7691. setorg( *checktri, NULL );
  7692. }
  7693. }
  7694. #endif /* not REDUCED */
  7695. #ifndef REDUCED
  7696. struct splaynode *splay( splaytree, searchpoint, searchtri )
  7697. struct splaynode *splaytree;
  7698. point searchpoint;
  7699. struct triedge *searchtri;
  7700. {
  7701. struct splaynode *child, *grandchild;
  7702. struct splaynode *lefttree, *righttree;
  7703. struct splaynode *leftright;
  7704. point checkpoint;
  7705. int rightofroot, rightofchild;
  7706. if ( splaytree == (struct splaynode *) NULL ) {
  7707. return (struct splaynode *) NULL;
  7708. }
  7709. dest( splaytree->keyedge, checkpoint );
  7710. if ( checkpoint == splaytree->keydest ) {
  7711. rightofroot = rightofhyperbola( &splaytree->keyedge, searchpoint );
  7712. if ( rightofroot ) {
  7713. triedgecopy( splaytree->keyedge, *searchtri );
  7714. child = splaytree->rchild;
  7715. }
  7716. else {
  7717. child = splaytree->lchild;
  7718. }
  7719. if ( child == (struct splaynode *) NULL ) {
  7720. return splaytree;
  7721. }
  7722. dest( child->keyedge, checkpoint );
  7723. if ( checkpoint != child->keydest ) {
  7724. child = splay( child, searchpoint, searchtri );
  7725. if ( child == (struct splaynode *) NULL ) {
  7726. if ( rightofroot ) {
  7727. splaytree->rchild = (struct splaynode *) NULL;
  7728. }
  7729. else {
  7730. splaytree->lchild = (struct splaynode *) NULL;
  7731. }
  7732. return splaytree;
  7733. }
  7734. }
  7735. rightofchild = rightofhyperbola( &child->keyedge, searchpoint );
  7736. if ( rightofchild ) {
  7737. triedgecopy( child->keyedge, *searchtri );
  7738. grandchild = splay( child->rchild, searchpoint, searchtri );
  7739. child->rchild = grandchild;
  7740. }
  7741. else {
  7742. grandchild = splay( child->lchild, searchpoint, searchtri );
  7743. child->lchild = grandchild;
  7744. }
  7745. if ( grandchild == (struct splaynode *) NULL ) {
  7746. if ( rightofroot ) {
  7747. splaytree->rchild = child->lchild;
  7748. child->lchild = splaytree;
  7749. }
  7750. else {
  7751. splaytree->lchild = child->rchild;
  7752. child->rchild = splaytree;
  7753. }
  7754. return child;
  7755. }
  7756. if ( rightofchild ) {
  7757. if ( rightofroot ) {
  7758. splaytree->rchild = child->lchild;
  7759. child->lchild = splaytree;
  7760. }
  7761. else {
  7762. splaytree->lchild = grandchild->rchild;
  7763. grandchild->rchild = splaytree;
  7764. }
  7765. child->rchild = grandchild->lchild;
  7766. grandchild->lchild = child;
  7767. }
  7768. else {
  7769. if ( rightofroot ) {
  7770. splaytree->rchild = grandchild->lchild;
  7771. grandchild->lchild = splaytree;
  7772. }
  7773. else {
  7774. splaytree->lchild = child->rchild;
  7775. child->rchild = splaytree;
  7776. }
  7777. child->lchild = grandchild->rchild;
  7778. grandchild->rchild = child;
  7779. }
  7780. return grandchild;
  7781. }
  7782. else {
  7783. lefttree = splay( splaytree->lchild, searchpoint, searchtri );
  7784. righttree = splay( splaytree->rchild, searchpoint, searchtri );
  7785. pooldealloc( &splaynodes, (VOID *) splaytree );
  7786. if ( lefttree == (struct splaynode *) NULL ) {
  7787. return righttree;
  7788. }
  7789. else if ( righttree == (struct splaynode *) NULL ) {
  7790. return lefttree;
  7791. }
  7792. else if ( lefttree->rchild == (struct splaynode *) NULL ) {
  7793. lefttree->rchild = righttree->lchild;
  7794. righttree->lchild = lefttree;
  7795. return righttree;
  7796. }
  7797. else if ( righttree->lchild == (struct splaynode *) NULL ) {
  7798. righttree->lchild = lefttree->rchild;
  7799. lefttree->rchild = righttree;
  7800. return lefttree;
  7801. }
  7802. else {
  7803. /* printf("Holy Toledo!!!\n"); */
  7804. leftright = lefttree->rchild;
  7805. while ( leftright->rchild != (struct splaynode *) NULL ) {
  7806. leftright = leftright->rchild;
  7807. }
  7808. leftright->rchild = righttree;
  7809. return lefttree;
  7810. }
  7811. }
  7812. }
  7813. #endif /* not REDUCED */
  7814. #ifndef REDUCED
  7815. struct splaynode *splayinsert( splayroot, newkey, searchpoint )
  7816. struct splaynode *splayroot;
  7817. struct triedge *newkey;
  7818. point searchpoint;
  7819. {
  7820. struct splaynode *newsplaynode;
  7821. newsplaynode = (struct splaynode *) poolalloc( &splaynodes );
  7822. triedgecopy( *newkey, newsplaynode->keyedge );
  7823. dest( *newkey, newsplaynode->keydest );
  7824. if ( splayroot == (struct splaynode *) NULL ) {
  7825. newsplaynode->lchild = (struct splaynode *) NULL;
  7826. newsplaynode->rchild = (struct splaynode *) NULL;
  7827. }
  7828. else if ( rightofhyperbola( &splayroot->keyedge, searchpoint ) ) {
  7829. newsplaynode->lchild = splayroot;
  7830. newsplaynode->rchild = splayroot->rchild;
  7831. splayroot->rchild = (struct splaynode *) NULL;
  7832. }
  7833. else {
  7834. newsplaynode->lchild = splayroot->lchild;
  7835. newsplaynode->rchild = splayroot;
  7836. splayroot->lchild = (struct splaynode *) NULL;
  7837. }
  7838. return newsplaynode;
  7839. }
  7840. #endif /* not REDUCED */
  7841. #ifndef REDUCED
  7842. struct splaynode *circletopinsert( splayroot, newkey, pa, pb, pc, topy )
  7843. struct splaynode *splayroot;
  7844. struct triedge *newkey;
  7845. point pa;
  7846. point pb;
  7847. point pc;
  7848. REAL topy;
  7849. {
  7850. REAL ccwabc;
  7851. REAL xac, yac, xbc, ybc;
  7852. REAL aclen2, bclen2;
  7853. REAL searchpoint[2];
  7854. struct triedge dummytri;
  7855. ccwabc = counterclockwise( pa, pb, pc );
  7856. xac = pa[0] - pc[0];
  7857. yac = pa[1] - pc[1];
  7858. xbc = pb[0] - pc[0];
  7859. ybc = pb[1] - pc[1];
  7860. aclen2 = xac * xac + yac * yac;
  7861. bclen2 = xbc * xbc + ybc * ybc;
  7862. searchpoint[0] = pc[0] - ( yac * bclen2 - ybc * aclen2 ) / ( 2.0 * ccwabc );
  7863. searchpoint[1] = topy;
  7864. return splayinsert( splay( splayroot, (point) searchpoint, &dummytri ), newkey,
  7865. (point) searchpoint );
  7866. }
  7867. #endif /* not REDUCED */
  7868. #ifndef REDUCED
  7869. struct splaynode *frontlocate( splayroot, bottommost, searchpoint, searchtri,
  7870. farright )
  7871. struct splaynode *splayroot;
  7872. struct triedge *bottommost;
  7873. point searchpoint;
  7874. struct triedge *searchtri;
  7875. int *farright;
  7876. {
  7877. int farrightflag;
  7878. triangle ptr; /* Temporary variable used by onext(). */
  7879. triedgecopy( *bottommost, *searchtri );
  7880. splayroot = splay( splayroot, searchpoint, searchtri );
  7881. farrightflag = 0;
  7882. while ( !farrightflag && rightofhyperbola( searchtri, searchpoint ) ) {
  7883. onextself( *searchtri );
  7884. farrightflag = triedgeequal( *searchtri, *bottommost );
  7885. }
  7886. *farright = farrightflag;
  7887. return splayroot;
  7888. }
  7889. #endif /* not REDUCED */
  7890. #ifndef REDUCED
  7891. long sweeplinedelaunay(){
  7892. struct event **eventheap;
  7893. struct event *events;
  7894. struct event *freeevents;
  7895. struct event *nextevent;
  7896. struct event *newevent;
  7897. struct splaynode *splayroot;
  7898. struct triedge bottommost;
  7899. struct triedge searchtri;
  7900. struct triedge fliptri;
  7901. struct triedge lefttri, righttri, farlefttri, farrighttri;
  7902. struct triedge inserttri;
  7903. point firstpoint, secondpoint;
  7904. point nextpoint, lastpoint;
  7905. point connectpoint;
  7906. point leftpoint, midpoint, rightpoint;
  7907. REAL lefttest, righttest;
  7908. int heapsize;
  7909. int check4events, farrightflag;
  7910. triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
  7911. poolinit( &splaynodes, sizeof( struct splaynode ), SPLAYNODEPERBLOCK, POINTER,
  7912. 0 );
  7913. splayroot = (struct splaynode *) NULL;
  7914. if ( verbose ) {
  7915. printf( " Placing points in event heap.\n" );
  7916. }
  7917. createeventheap( &eventheap, &events, &freeevents );
  7918. heapsize = inpoints;
  7919. if ( verbose ) {
  7920. printf( " Forming triangulation.\n" );
  7921. }
  7922. maketriangle( &lefttri );
  7923. maketriangle( &righttri );
  7924. bond( lefttri, righttri );
  7925. lnextself( lefttri );
  7926. lprevself( righttri );
  7927. bond( lefttri, righttri );
  7928. lnextself( lefttri );
  7929. lprevself( righttri );
  7930. bond( lefttri, righttri );
  7931. firstpoint = (point) eventheap[0]->eventptr;
  7932. eventheap[0]->eventptr = (VOID *) freeevents;
  7933. freeevents = eventheap[0];
  7934. eventheapdelete( eventheap, heapsize, 0 );
  7935. heapsize--;
  7936. do {
  7937. if ( heapsize == 0 ) {
  7938. printf( "Error: Input points are all identical.\n" );
  7939. exit( 1 );
  7940. }
  7941. secondpoint = (point) eventheap[0]->eventptr;
  7942. eventheap[0]->eventptr = (VOID *) freeevents;
  7943. freeevents = eventheap[0];
  7944. eventheapdelete( eventheap, heapsize, 0 );
  7945. heapsize--;
  7946. if ( ( firstpoint[0] == secondpoint[0] )
  7947. && ( firstpoint[1] == secondpoint[1] ) ) {
  7948. printf(
  7949. "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
  7950. secondpoint[0], secondpoint[1] );
  7951. /* Commented out - would eliminate point from output .node file.
  7952. setpointmark(secondpoint, DEADPOINT);
  7953. */
  7954. }
  7955. } while ( ( firstpoint[0] == secondpoint[0] )
  7956. && ( firstpoint[1] == secondpoint[1] ) );
  7957. setorg( lefttri, firstpoint );
  7958. setdest( lefttri, secondpoint );
  7959. setorg( righttri, secondpoint );
  7960. setdest( righttri, firstpoint );
  7961. lprev( lefttri, bottommost );
  7962. lastpoint = secondpoint;
  7963. while ( heapsize > 0 ) {
  7964. nextevent = eventheap[0];
  7965. eventheapdelete( eventheap, heapsize, 0 );
  7966. heapsize--;
  7967. check4events = 1;
  7968. if ( nextevent->xkey < xmin ) {
  7969. decode( nextevent->eventptr, fliptri );
  7970. oprev( fliptri, farlefttri );
  7971. check4deadevent( &farlefttri, &freeevents, eventheap, &heapsize );
  7972. onext( fliptri, farrighttri );
  7973. check4deadevent( &farrighttri, &freeevents, eventheap, &heapsize );
  7974. if ( triedgeequal( farlefttri, bottommost ) ) {
  7975. lprev( fliptri, bottommost );
  7976. }
  7977. flip( &fliptri );
  7978. setapex( fliptri, NULL );
  7979. lprev( fliptri, lefttri );
  7980. lnext( fliptri, righttri );
  7981. sym( lefttri, farlefttri );
  7982. if ( randomnation( SAMPLERATE ) == 0 ) {
  7983. symself( fliptri );
  7984. dest( fliptri, leftpoint );
  7985. apex( fliptri, midpoint );
  7986. org( fliptri, rightpoint );
  7987. splayroot = circletopinsert( splayroot, &lefttri, leftpoint, midpoint,
  7988. rightpoint, nextevent->ykey );
  7989. }
  7990. }
  7991. else {
  7992. nextpoint = (point) nextevent->eventptr;
  7993. if ( ( nextpoint[0] == lastpoint[0] ) && ( nextpoint[1] == lastpoint[1] ) ) {
  7994. printf(
  7995. "Warning: A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
  7996. nextpoint[0], nextpoint[1] );
  7997. /* Commented out - would eliminate point from output .node file.
  7998. setpointmark(nextpoint, DEADPOINT);
  7999. */
  8000. check4events = 0;
  8001. }
  8002. else {
  8003. lastpoint = nextpoint;
  8004. splayroot = frontlocate( splayroot, &bottommost, nextpoint, &searchtri,
  8005. &farrightflag );
  8006. /*
  8007. triedgecopy(bottommost, searchtri);
  8008. farrightflag = 0;
  8009. while (!farrightflag && rightofhyperbola(&searchtri, nextpoint)) {
  8010. onextself(searchtri);
  8011. farrightflag = triedgeequal(searchtri, bottommost);
  8012. }
  8013. */
  8014. check4deadevent( &searchtri, &freeevents, eventheap, &heapsize );
  8015. triedgecopy( searchtri, farrighttri );
  8016. sym( searchtri, farlefttri );
  8017. maketriangle( &lefttri );
  8018. maketriangle( &righttri );
  8019. dest( farrighttri, connectpoint );
  8020. setorg( lefttri, connectpoint );
  8021. setdest( lefttri, nextpoint );
  8022. setorg( righttri, nextpoint );
  8023. setdest( righttri, connectpoint );
  8024. bond( lefttri, righttri );
  8025. lnextself( lefttri );
  8026. lprevself( righttri );
  8027. bond( lefttri, righttri );
  8028. lnextself( lefttri );
  8029. lprevself( righttri );
  8030. bond( lefttri, farlefttri );
  8031. bond( righttri, farrighttri );
  8032. if ( !farrightflag && triedgeequal( farrighttri, bottommost ) ) {
  8033. triedgecopy( lefttri, bottommost );
  8034. }
  8035. if ( randomnation( SAMPLERATE ) == 0 ) {
  8036. splayroot = splayinsert( splayroot, &lefttri, nextpoint );
  8037. }
  8038. else if ( randomnation( SAMPLERATE ) == 0 ) {
  8039. lnext( righttri, inserttri );
  8040. splayroot = splayinsert( splayroot, &inserttri, nextpoint );
  8041. }
  8042. }
  8043. }
  8044. nextevent->eventptr = (VOID *) freeevents;
  8045. freeevents = nextevent;
  8046. if ( check4events ) {
  8047. apex( farlefttri, leftpoint );
  8048. dest( lefttri, midpoint );
  8049. apex( lefttri, rightpoint );
  8050. lefttest = counterclockwise( leftpoint, midpoint, rightpoint );
  8051. if ( lefttest > 0.0 ) {
  8052. newevent = freeevents;
  8053. freeevents = (struct event *) freeevents->eventptr;
  8054. newevent->xkey = xminextreme;
  8055. newevent->ykey = circletop( leftpoint, midpoint, rightpoint,
  8056. lefttest );
  8057. newevent->eventptr = (VOID *) encode( lefttri );
  8058. eventheapinsert( eventheap, heapsize, newevent );
  8059. heapsize++;
  8060. setorg( lefttri, newevent );
  8061. }
  8062. apex( righttri, leftpoint );
  8063. org( righttri, midpoint );
  8064. apex( farrighttri, rightpoint );
  8065. righttest = counterclockwise( leftpoint, midpoint, rightpoint );
  8066. if ( righttest > 0.0 ) {
  8067. newevent = freeevents;
  8068. freeevents = (struct event *) freeevents->eventptr;
  8069. newevent->xkey = xminextreme;
  8070. newevent->ykey = circletop( leftpoint, midpoint, rightpoint,
  8071. righttest );
  8072. newevent->eventptr = (VOID *) encode( farrighttri );
  8073. eventheapinsert( eventheap, heapsize, newevent );
  8074. heapsize++;
  8075. setorg( farrighttri, newevent );
  8076. }
  8077. }
  8078. }
  8079. pooldeinit( &splaynodes );
  8080. lprevself( bottommost );
  8081. return removeghosts( &bottommost );
  8082. }
  8083. #endif /* not REDUCED */
  8084. /** **/
  8085. /** **/
  8086. /********* Sweepline Delaunay triangulation ends here *********/
  8087. /********* General mesh construction routines begin here *********/
  8088. /** **/
  8089. /** **/
  8090. /*****************************************************************************/
  8091. /* */
  8092. /* delaunay() Form a Delaunay triangulation. */
  8093. /* */
  8094. /*****************************************************************************/
  8095. long delaunay(){
  8096. eextras = 0;
  8097. initializetrisegpools();
  8098. #ifdef REDUCED
  8099. if ( !quiet ) {
  8100. printf(
  8101. "Constructing Delaunay triangulation by divide-and-conquer method.\n" );
  8102. }
  8103. return divconqdelaunay();
  8104. #else /* not REDUCED */
  8105. if ( !quiet ) {
  8106. printf( "Constructing Delaunay triangulation " );
  8107. if ( incremental ) {
  8108. printf( "by incremental method.\n" );
  8109. }
  8110. else if ( sweepline ) {
  8111. printf( "by sweepline method.\n" );
  8112. }
  8113. else {
  8114. printf( "by divide-and-conquer method.\n" );
  8115. }
  8116. }
  8117. if ( incremental ) {
  8118. return incrementaldelaunay();
  8119. }
  8120. else if ( sweepline ) {
  8121. return sweeplinedelaunay();
  8122. }
  8123. else {
  8124. return divconqdelaunay();
  8125. }
  8126. #endif /* not REDUCED */
  8127. }
  8128. /*****************************************************************************/
  8129. /* */
  8130. /* reconstruct() Reconstruct a triangulation from its .ele (and possibly */
  8131. /* .poly) file. Used when the -r switch is used. */
  8132. /* */
  8133. /* Reads an .ele file and reconstructs the original mesh. If the -p switch */
  8134. /* is used, this procedure will also read a .poly file and reconstruct the */
  8135. /* shell edges of the original mesh. If the -a switch is used, this */
  8136. /* procedure will also read an .area file and set a maximum area constraint */
  8137. /* on each triangle. */
  8138. /* */
  8139. /* Points that are not corners of triangles, such as nodes on edges of */
  8140. /* subparametric elements, are discarded. */
  8141. /* */
  8142. /* This routine finds the adjacencies between triangles (and shell edges) */
  8143. /* by forming one stack of triangles for each vertex. Each triangle is on */
  8144. /* three different stacks simultaneously. Each triangle's shell edge */
  8145. /* pointers are used to link the items in each stack. This memory-saving */
  8146. /* feature makes the code harder to read. The most important thing to keep */
  8147. /* in mind is that each triangle is removed from a stack precisely when */
  8148. /* the corresponding pointer is adjusted to refer to a shell edge rather */
  8149. /* than the next triangle of the stack. */
  8150. /* */
  8151. /*****************************************************************************/
  8152. #ifndef CDT_ONLY
  8153. #ifdef TRILIBRARY
  8154. int reconstruct( trianglelist, triangleattriblist, trianglearealist, elements,
  8155. corners, attribs, segmentlist, segmentmarkerlist,
  8156. numberofsegments )
  8157. int *trianglelist;
  8158. REAL *triangleattriblist;
  8159. REAL *trianglearealist;
  8160. int elements;
  8161. int corners;
  8162. int attribs;
  8163. int *segmentlist;
  8164. int *segmentmarkerlist;
  8165. int numberofsegments;
  8166. #else /* not TRILIBRARY */
  8167. long reconstruct( elefilename, areafilename, polyfilename, polyfile )
  8168. char *elefilename;
  8169. char *areafilename;
  8170. char *polyfilename;
  8171. FILE *polyfile;
  8172. #endif /* not TRILIBRARY */
  8173. {
  8174. #ifdef TRILIBRARY
  8175. int pointindex;
  8176. int attribindex;
  8177. #else /* not TRILIBRARY */
  8178. FILE *elefile;
  8179. FILE *areafile;
  8180. char inputline[INPUTLINESIZE];
  8181. char *stringptr;
  8182. int areaelements;
  8183. #endif /* not TRILIBRARY */
  8184. struct triedge triangleloop;
  8185. struct triedge triangleleft;
  8186. struct triedge checktri;
  8187. struct triedge checkleft;
  8188. struct triedge checkneighbor;
  8189. struct edge shelleloop;
  8190. triangle *vertexarray;
  8191. triangle *prevlink;
  8192. triangle nexttri;
  8193. point tdest, tapex;
  8194. point checkdest, checkapex;
  8195. point shorg;
  8196. point killpoint;
  8197. REAL area;
  8198. int corner[3];
  8199. int end[2];
  8200. int killpointindex;
  8201. int incorners;
  8202. int segmentmarkers;
  8203. int boundmarker;
  8204. int aroundpoint;
  8205. long hullsize;
  8206. int notfound;
  8207. int elementnumber, segmentnumber;
  8208. int i, j;
  8209. triangle ptr; /* Temporary variable used by sym(). */
  8210. #ifdef TRILIBRARY
  8211. inelements = elements;
  8212. incorners = corners;
  8213. if ( incorners < 3 ) {
  8214. printf( "Error: Triangles must have at least 3 points.\n" );
  8215. exit( 1 );
  8216. }
  8217. eextras = attribs;
  8218. #else /* not TRILIBRARY */
  8219. /* Read the triangles from an .ele file. */
  8220. if ( !quiet ) {
  8221. printf( "Opening %s.\n", elefilename );
  8222. }
  8223. elefile = fopen( elefilename, "r" );
  8224. if ( elefile == (FILE *) NULL ) {
  8225. printf( " Error: Cannot access file %s.\n", elefilename );
  8226. exit( 1 );
  8227. }
  8228. /* Read number of triangles, number of points per triangle, and */
  8229. /* number of triangle attributes from .ele file. */
  8230. stringptr = readline( inputline, elefile, elefilename );
  8231. inelements = (int) strtol( stringptr, &stringptr, 0 );
  8232. stringptr = findfield( stringptr );
  8233. if ( *stringptr == '\0' ) {
  8234. incorners = 3;
  8235. }
  8236. else {
  8237. incorners = (int) strtol( stringptr, &stringptr, 0 );
  8238. if ( incorners < 3 ) {
  8239. printf( "Error: Triangles in %s must have at least 3 points.\n",
  8240. elefilename );
  8241. exit( 1 );
  8242. }
  8243. }
  8244. stringptr = findfield( stringptr );
  8245. if ( *stringptr == '\0' ) {
  8246. eextras = 0;
  8247. }
  8248. else {
  8249. eextras = (int) strtol( stringptr, &stringptr, 0 );
  8250. }
  8251. #endif /* not TRILIBRARY */
  8252. initializetrisegpools();
  8253. /* Create the triangles. */
  8254. for ( elementnumber = 1; elementnumber <= inelements; elementnumber++ ) {
  8255. maketriangle( &triangleloop );
  8256. /* Mark the triangle as living. */
  8257. triangleloop.tri[3] = (triangle) triangleloop.tri;
  8258. }
  8259. if ( poly ) {
  8260. #ifdef TRILIBRARY
  8261. insegments = numberofsegments;
  8262. segmentmarkers = segmentmarkerlist != (int *) NULL;
  8263. #else /* not TRILIBRARY */
  8264. /* Read number of segments and number of segment */
  8265. /* boundary markers from .poly file. */
  8266. stringptr = readline( inputline, polyfile, inpolyfilename );
  8267. insegments = (int) strtol( stringptr, &stringptr, 0 );
  8268. stringptr = findfield( stringptr );
  8269. if ( *stringptr == '\0' ) {
  8270. segmentmarkers = 0;
  8271. }
  8272. else {
  8273. segmentmarkers = (int) strtol( stringptr, &stringptr, 0 );
  8274. }
  8275. #endif /* not TRILIBRARY */
  8276. /* Create the shell edges. */
  8277. for ( segmentnumber = 1; segmentnumber <= insegments; segmentnumber++ ) {
  8278. makeshelle( &shelleloop );
  8279. /* Mark the shell edge as living. */
  8280. shelleloop.sh[2] = (shelle) shelleloop.sh;
  8281. }
  8282. }
  8283. #ifdef TRILIBRARY
  8284. pointindex = 0;
  8285. attribindex = 0;
  8286. #else /* not TRILIBRARY */
  8287. if ( vararea ) {
  8288. /* Open an .area file, check for consistency with the .ele file. */
  8289. if ( !quiet ) {
  8290. printf( "Opening %s.\n", areafilename );
  8291. }
  8292. areafile = fopen( areafilename, "r" );
  8293. if ( areafile == (FILE *) NULL ) {
  8294. printf( " Error: Cannot access file %s.\n", areafilename );
  8295. exit( 1 );
  8296. }
  8297. stringptr = readline( inputline, areafile, areafilename );
  8298. areaelements = (int) strtol( stringptr, &stringptr, 0 );
  8299. if ( areaelements != inelements ) {
  8300. printf( "Error: %s and %s disagree on number of triangles.\n",
  8301. elefilename, areafilename );
  8302. exit( 1 );
  8303. }
  8304. }
  8305. #endif /* not TRILIBRARY */
  8306. if ( !quiet ) {
  8307. printf( "Reconstructing mesh.\n" );
  8308. }
  8309. /* Allocate a temporary array that maps each point to some adjacent */
  8310. /* triangle. I took care to allocate all the permanent memory for */
  8311. /* triangles and shell edges first. */
  8312. vertexarray = (triangle *) malloc( points.items * sizeof( triangle ) );
  8313. if ( vertexarray == (triangle *) NULL ) {
  8314. printf( "Error: Out of memory.\n" );
  8315. exit( 1 );
  8316. }
  8317. /* Each point is initially unrepresented. */
  8318. for ( i = 0; i < points.items; i++ ) {
  8319. vertexarray[i] = (triangle) dummytri;
  8320. }
  8321. if ( verbose ) {
  8322. printf( " Assembling triangles.\n" );
  8323. }
  8324. /* Read the triangles from the .ele file, and link */
  8325. /* together those that share an edge. */
  8326. traversalinit( &triangles );
  8327. triangleloop.tri = triangletraverse();
  8328. elementnumber = firstnumber;
  8329. while ( triangleloop.tri != (triangle *) NULL ) {
  8330. #ifdef TRILIBRARY
  8331. /* Copy the triangle's three corners. */
  8332. for ( j = 0; j < 3; j++ ) {
  8333. corner[j] = trianglelist[pointindex++];
  8334. if ( ( corner[j] < firstnumber ) || ( corner[j] >= firstnumber + inpoints ) ) {
  8335. printf( "Error: Triangle %d has an invalid vertex index.\n",
  8336. elementnumber );
  8337. exit( 1 );
  8338. }
  8339. }
  8340. #else /* not TRILIBRARY */
  8341. /* Read triangle number and the triangle's three corners. */
  8342. stringptr = readline( inputline, elefile, elefilename );
  8343. for ( j = 0; j < 3; j++ ) {
  8344. stringptr = findfield( stringptr );
  8345. if ( *stringptr == '\0' ) {
  8346. printf( "Error: Triangle %d is missing point %d in %s.\n",
  8347. elementnumber, j + 1, elefilename );
  8348. exit( 1 );
  8349. }
  8350. else {
  8351. corner[j] = (int) strtol( stringptr, &stringptr, 0 );
  8352. if ( ( corner[j] < firstnumber ) ||
  8353. ( corner[j] >= firstnumber + inpoints ) ) {
  8354. printf( "Error: Triangle %d has an invalid vertex index.\n",
  8355. elementnumber );
  8356. exit( 1 );
  8357. }
  8358. }
  8359. }
  8360. #endif /* not TRILIBRARY */
  8361. /* Find out about (and throw away) extra nodes. */
  8362. for ( j = 3; j < incorners; j++ ) {
  8363. #ifdef TRILIBRARY
  8364. killpointindex = trianglelist[pointindex++];
  8365. #else /* not TRILIBRARY */
  8366. stringptr = findfield( stringptr );
  8367. if ( *stringptr != '\0' ) {
  8368. killpointindex = (int) strtol( stringptr, &stringptr, 0 );
  8369. #endif /* not TRILIBRARY */
  8370. if ( ( killpointindex >= firstnumber ) &&
  8371. ( killpointindex < firstnumber + inpoints ) ) {
  8372. /* Delete the non-corner point if it's not already deleted. */
  8373. killpoint = getpoint( killpointindex );
  8374. if ( pointmark( killpoint ) != DEADPOINT ) {
  8375. pointdealloc( killpoint );
  8376. }
  8377. }
  8378. #ifndef TRILIBRARY
  8379. }
  8380. #endif /* not TRILIBRARY */
  8381. }
  8382. /* Read the triangle's attributes. */
  8383. for ( j = 0; j < eextras; j++ ) {
  8384. #ifdef TRILIBRARY
  8385. setelemattribute( triangleloop, j, triangleattriblist[attribindex++] );
  8386. #else /* not TRILIBRARY */
  8387. stringptr = findfield( stringptr );
  8388. if ( *stringptr == '\0' ) {
  8389. setelemattribute( triangleloop, j, 0 );
  8390. }
  8391. else {
  8392. setelemattribute( triangleloop, j,
  8393. (REAL) strtod( stringptr, &stringptr ) );
  8394. }
  8395. #endif /* not TRILIBRARY */
  8396. }
  8397. if ( vararea ) {
  8398. #ifdef TRILIBRARY
  8399. area = trianglearealist[elementnumber - firstnumber];
  8400. #else /* not TRILIBRARY */
  8401. /* Read an area constraint from the .area file. */
  8402. stringptr = readline( inputline, areafile, areafilename );
  8403. stringptr = findfield( stringptr );
  8404. if ( *stringptr == '\0' ) {
  8405. area = -1.0; /* No constraint on this triangle. */
  8406. }
  8407. else {
  8408. area = (REAL) strtod( stringptr, &stringptr );
  8409. }
  8410. #endif /* not TRILIBRARY */
  8411. setareabound( triangleloop, area );
  8412. }
  8413. /* Set the triangle's vertices. */
  8414. triangleloop.orient = 0;
  8415. setorg( triangleloop, getpoint( corner[0] ) );
  8416. setdest( triangleloop, getpoint( corner[1] ) );
  8417. setapex( triangleloop, getpoint( corner[2] ) );
  8418. /* Try linking the triangle to others that share these vertices. */
  8419. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  8420. triangleloop.orient++ ) {
  8421. /* Take the number for the origin of triangleloop. */
  8422. aroundpoint = corner[triangleloop.orient];
  8423. /* Look for other triangles having this vertex. */
  8424. nexttri = vertexarray[aroundpoint - firstnumber];
  8425. /* Link the current triangle to the next one in the stack. */
  8426. triangleloop.tri[6 + triangleloop.orient] = nexttri;
  8427. /* Push the current triangle onto the stack. */
  8428. vertexarray[aroundpoint - firstnumber] = encode( triangleloop );
  8429. decode( nexttri, checktri );
  8430. if ( checktri.tri != dummytri ) {
  8431. dest( triangleloop, tdest );
  8432. apex( triangleloop, tapex );
  8433. /* Look for other triangles that share an edge. */
  8434. do {
  8435. dest( checktri, checkdest );
  8436. apex( checktri, checkapex );
  8437. if ( tapex == checkdest ) {
  8438. /* The two triangles share an edge; bond them together. */
  8439. lprev( triangleloop, triangleleft );
  8440. bond( triangleleft, checktri );
  8441. }
  8442. if ( tdest == checkapex ) {
  8443. /* The two triangles share an edge; bond them together. */
  8444. lprev( checktri, checkleft );
  8445. bond( triangleloop, checkleft );
  8446. }
  8447. /* Find the next triangle in the stack. */
  8448. nexttri = checktri.tri[6 + checktri.orient];
  8449. decode( nexttri, checktri );
  8450. } while ( checktri.tri != dummytri );
  8451. }
  8452. }
  8453. triangleloop.tri = triangletraverse();
  8454. elementnumber++;
  8455. }
  8456. #ifdef TRILIBRARY
  8457. pointindex = 0;
  8458. #else /* not TRILIBRARY */
  8459. fclose( elefile );
  8460. if ( vararea ) {
  8461. fclose( areafile );
  8462. }
  8463. #endif /* not TRILIBRARY */
  8464. hullsize = 0; /* Prepare to count the boundary edges. */
  8465. if ( poly ) {
  8466. if ( verbose ) {
  8467. printf( " Marking segments in triangulation.\n" );
  8468. }
  8469. /* Read the segments from the .poly file, and link them */
  8470. /* to their neighboring triangles. */
  8471. boundmarker = 0;
  8472. traversalinit( &shelles );
  8473. shelleloop.sh = shelletraverse();
  8474. segmentnumber = firstnumber;
  8475. while ( shelleloop.sh != (shelle *) NULL ) {
  8476. #ifdef TRILIBRARY
  8477. end[0] = segmentlist[pointindex++];
  8478. end[1] = segmentlist[pointindex++];
  8479. if ( segmentmarkers ) {
  8480. boundmarker = segmentmarkerlist[segmentnumber - firstnumber];
  8481. }
  8482. #else /* not TRILIBRARY */
  8483. /* Read the endpoints of each segment, and possibly a boundary marker. */
  8484. stringptr = readline( inputline, polyfile, inpolyfilename );
  8485. /* Skip the first (segment number) field. */
  8486. stringptr = findfield( stringptr );
  8487. if ( *stringptr == '\0' ) {
  8488. printf( "Error: Segment %d has no endpoints in %s.\n", segmentnumber,
  8489. polyfilename );
  8490. exit( 1 );
  8491. }
  8492. else {
  8493. end[0] = (int) strtol( stringptr, &stringptr, 0 );
  8494. }
  8495. stringptr = findfield( stringptr );
  8496. if ( *stringptr == '\0' ) {
  8497. printf( "Error: Segment %d is missing its second endpoint in %s.\n",
  8498. segmentnumber, polyfilename );
  8499. exit( 1 );
  8500. }
  8501. else {
  8502. end[1] = (int) strtol( stringptr, &stringptr, 0 );
  8503. }
  8504. if ( segmentmarkers ) {
  8505. stringptr = findfield( stringptr );
  8506. if ( *stringptr == '\0' ) {
  8507. boundmarker = 0;
  8508. }
  8509. else {
  8510. boundmarker = (int) strtol( stringptr, &stringptr, 0 );
  8511. }
  8512. }
  8513. #endif /* not TRILIBRARY */
  8514. for ( j = 0; j < 2; j++ ) {
  8515. if ( ( end[j] < firstnumber ) || ( end[j] >= firstnumber + inpoints ) ) {
  8516. printf( "Error: Segment %d has an invalid vertex index.\n",
  8517. segmentnumber );
  8518. exit( 1 );
  8519. }
  8520. }
  8521. /* set the shell edge's vertices. */
  8522. shelleloop.shorient = 0;
  8523. setsorg( shelleloop, getpoint( end[0] ) );
  8524. setsdest( shelleloop, getpoint( end[1] ) );
  8525. setmark( shelleloop, boundmarker );
  8526. /* Try linking the shell edge to triangles that share these vertices. */
  8527. for ( shelleloop.shorient = 0; shelleloop.shorient < 2;
  8528. shelleloop.shorient++ ) {
  8529. /* Take the number for the destination of shelleloop. */
  8530. aroundpoint = end[1 - shelleloop.shorient];
  8531. /* Look for triangles having this vertex. */
  8532. prevlink = &vertexarray[aroundpoint - firstnumber];
  8533. nexttri = vertexarray[aroundpoint - firstnumber];
  8534. decode( nexttri, checktri );
  8535. sorg( shelleloop, shorg );
  8536. notfound = 1;
  8537. /* Look for triangles having this edge. Note that I'm only */
  8538. /* comparing each triangle's destination with the shell edge; */
  8539. /* each triangle's apex is handled through a different vertex. */
  8540. /* Because each triangle appears on three vertices' lists, each */
  8541. /* occurrence of a triangle on a list can (and does) represent */
  8542. /* an edge. In this way, most edges are represented twice, and */
  8543. /* every triangle-segment bond is represented once. */
  8544. while ( notfound && ( checktri.tri != dummytri ) ) {
  8545. dest( checktri, checkdest );
  8546. if ( shorg == checkdest ) {
  8547. /* We have a match. Remove this triangle from the list. */
  8548. *prevlink = checktri.tri[6 + checktri.orient];
  8549. /* Bond the shell edge to the triangle. */
  8550. tsbond( checktri, shelleloop );
  8551. /* Check if this is a boundary edge. */
  8552. sym( checktri, checkneighbor );
  8553. if ( checkneighbor.tri == dummytri ) {
  8554. /* The next line doesn't insert a shell edge (because there's */
  8555. /* already one there), but it sets the boundary markers of */
  8556. /* the existing shell edge and its vertices. */
  8557. insertshelle( &checktri, 1 );
  8558. hullsize++;
  8559. }
  8560. notfound = 0;
  8561. }
  8562. /* Find the next triangle in the stack. */
  8563. prevlink = &checktri.tri[6 + checktri.orient];
  8564. nexttri = checktri.tri[6 + checktri.orient];
  8565. decode( nexttri, checktri );
  8566. }
  8567. }
  8568. shelleloop.sh = shelletraverse();
  8569. segmentnumber++;
  8570. }
  8571. }
  8572. /* Mark the remaining edges as not being attached to any shell edge. */
  8573. /* Also, count the (yet uncounted) boundary edges. */
  8574. for ( i = 0; i < points.items; i++ ) {
  8575. /* Search the stack of triangles adjacent to a point. */
  8576. nexttri = vertexarray[i];
  8577. decode( nexttri, checktri );
  8578. while ( checktri.tri != dummytri ) {
  8579. /* Find the next triangle in the stack before this */
  8580. /* information gets overwritten. */
  8581. nexttri = checktri.tri[6 + checktri.orient];
  8582. /* No adjacent shell edge. (This overwrites the stack info.) */
  8583. tsdissolve( checktri );
  8584. sym( checktri, checkneighbor );
  8585. if ( checkneighbor.tri == dummytri ) {
  8586. insertshelle( &checktri, 1 );
  8587. hullsize++;
  8588. }
  8589. decode( nexttri, checktri );
  8590. }
  8591. }
  8592. free( vertexarray );
  8593. return hullsize;
  8594. }
  8595. #endif /* not CDT_ONLY */
  8596. /** **/
  8597. /** **/
  8598. /********* General mesh construction routines end here *********/
  8599. /********* Segment (shell edge) insertion begins here *********/
  8600. /** **/
  8601. /** **/
  8602. /*****************************************************************************/
  8603. /* */
  8604. /* finddirection() Find the first triangle on the path from one point */
  8605. /* to another. */
  8606. /* */
  8607. /* Finds the triangle that intersects a line segment drawn from the */
  8608. /* origin of `searchtri' to the point `endpoint', and returns the result */
  8609. /* in `searchtri'. The origin of `searchtri' does not change, even though */
  8610. /* the triangle returned may differ from the one passed in. This routine */
  8611. /* is used to find the direction to move in to get from one point to */
  8612. /* another. */
  8613. /* */
  8614. /* The return value notes whether the destination or apex of the found */
  8615. /* triangle is collinear with the two points in question. */
  8616. /* */
  8617. /*****************************************************************************/
  8618. enum finddirectionresult finddirection( searchtri, endpoint )
  8619. struct triedge *searchtri;
  8620. point endpoint;
  8621. {
  8622. struct triedge checktri;
  8623. point startpoint;
  8624. point leftpoint, rightpoint;
  8625. REAL leftccw, rightccw;
  8626. int leftflag, rightflag;
  8627. triangle ptr; /* Temporary variable used by onext() and oprev(). */
  8628. org( *searchtri, startpoint );
  8629. dest( *searchtri, rightpoint );
  8630. apex( *searchtri, leftpoint );
  8631. /* Is `endpoint' to the left? */
  8632. leftccw = counterclockwise( endpoint, startpoint, leftpoint );
  8633. leftflag = leftccw > 0.0;
  8634. /* Is `endpoint' to the right? */
  8635. rightccw = counterclockwise( startpoint, endpoint, rightpoint );
  8636. rightflag = rightccw > 0.0;
  8637. if ( leftflag && rightflag ) {
  8638. /* `searchtri' faces directly away from `endpoint'. We could go */
  8639. /* left or right. Ask whether it's a triangle or a boundary */
  8640. /* on the left. */
  8641. onext( *searchtri, checktri );
  8642. if ( checktri.tri == dummytri ) {
  8643. leftflag = 0;
  8644. }
  8645. else {
  8646. rightflag = 0;
  8647. }
  8648. }
  8649. while ( leftflag ) {
  8650. /* Turn left until satisfied. */
  8651. onextself( *searchtri );
  8652. if ( searchtri->tri == dummytri ) {
  8653. printf( "Internal error in finddirection(): Unable to find a\n" );
  8654. printf( " triangle leading from (%.12g, %.12g) to", startpoint[0],
  8655. startpoint[1] );
  8656. printf( " (%.12g, %.12g).\n", endpoint[0], endpoint[1] );
  8657. internalerror();
  8658. }
  8659. apex( *searchtri, leftpoint );
  8660. rightccw = leftccw;
  8661. leftccw = counterclockwise( endpoint, startpoint, leftpoint );
  8662. leftflag = leftccw > 0.0;
  8663. }
  8664. while ( rightflag ) {
  8665. /* Turn right until satisfied. */
  8666. oprevself( *searchtri );
  8667. if ( searchtri->tri == dummytri ) {
  8668. printf( "Internal error in finddirection(): Unable to find a\n" );
  8669. printf( " triangle leading from (%.12g, %.12g) to", startpoint[0],
  8670. startpoint[1] );
  8671. printf( " (%.12g, %.12g).\n", endpoint[0], endpoint[1] );
  8672. internalerror();
  8673. }
  8674. dest( *searchtri, rightpoint );
  8675. leftccw = rightccw;
  8676. rightccw = counterclockwise( startpoint, endpoint, rightpoint );
  8677. rightflag = rightccw > 0.0;
  8678. }
  8679. if ( leftccw == 0.0 ) {
  8680. return LEFTCOLLINEAR;
  8681. }
  8682. else if ( rightccw == 0.0 ) {
  8683. return RIGHTCOLLINEAR;
  8684. }
  8685. else {
  8686. return WITHIN;
  8687. }
  8688. }
  8689. /*****************************************************************************/
  8690. /* */
  8691. /* segmentintersection() Find the intersection of an existing segment */
  8692. /* and a segment that is being inserted. Insert */
  8693. /* a point at the intersection, splitting an */
  8694. /* existing shell edge. */
  8695. /* */
  8696. /* The segment being inserted connects the apex of splittri to endpoint2. */
  8697. /* splitshelle is the shell edge being split, and MUST be opposite */
  8698. /* splittri. Hence, the edge being split connects the origin and */
  8699. /* destination of splittri. */
  8700. /* */
  8701. /* On completion, splittri is a handle having the newly inserted */
  8702. /* intersection point as its origin, and endpoint1 as its destination. */
  8703. /* */
  8704. /*****************************************************************************/
  8705. void segmentintersection( splittri, splitshelle, endpoint2 )
  8706. struct triedge *splittri;
  8707. struct edge *splitshelle;
  8708. point endpoint2;
  8709. {
  8710. point endpoint1;
  8711. point torg, tdest;
  8712. point leftpoint, rightpoint;
  8713. point newpoint;
  8714. enum insertsiteresult success;
  8715. enum finddirectionresult collinear;
  8716. REAL ex, ey;
  8717. REAL tx, ty;
  8718. REAL etx, ety;
  8719. REAL split, denom;
  8720. int i;
  8721. triangle ptr; /* Temporary variable used by onext(). */
  8722. /* Find the other three segment endpoints. */
  8723. apex( *splittri, endpoint1 );
  8724. org( *splittri, torg );
  8725. dest( *splittri, tdest );
  8726. /* Segment intersection formulae; see the Antonio reference. */
  8727. tx = tdest[0] - torg[0];
  8728. ty = tdest[1] - torg[1];
  8729. ex = endpoint2[0] - endpoint1[0];
  8730. ey = endpoint2[1] - endpoint1[1];
  8731. etx = torg[0] - endpoint2[0];
  8732. ety = torg[1] - endpoint2[1];
  8733. denom = ty * ex - tx * ey;
  8734. if ( denom == 0.0 ) {
  8735. printf( "Internal error in segmentintersection():" );
  8736. printf( " Attempt to find intersection of parallel segments.\n" );
  8737. internalerror();
  8738. }
  8739. split = ( ey * etx - ex * ety ) / denom;
  8740. /* Create the new point. */
  8741. newpoint = (point) poolalloc( &points );
  8742. /* Interpolate its coordinate and attributes. */
  8743. for ( i = 0; i < 2 + nextras; i++ ) {
  8744. newpoint[i] = torg[i] + split * ( tdest[i] - torg[i] );
  8745. }
  8746. setpointmark( newpoint, mark( *splitshelle ) );
  8747. if ( verbose > 1 ) {
  8748. printf(
  8749. " Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
  8750. torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1] );
  8751. }
  8752. /* Insert the intersection point. This should always succeed. */
  8753. success = insertsite( newpoint, splittri, splitshelle, 0, 0 );
  8754. if ( success != SUCCESSFULPOINT ) {
  8755. printf( "Internal error in segmentintersection():\n" );
  8756. printf( " Failure to split a segment.\n" );
  8757. internalerror();
  8758. }
  8759. if ( steinerleft > 0 ) {
  8760. steinerleft--;
  8761. }
  8762. /* Inserting the point may have caused edge flips. We wish to rediscover */
  8763. /* the edge connecting endpoint1 to the new intersection point. */
  8764. collinear = finddirection( splittri, endpoint1 );
  8765. dest( *splittri, rightpoint );
  8766. apex( *splittri, leftpoint );
  8767. if ( ( leftpoint[0] == endpoint1[0] ) && ( leftpoint[1] == endpoint1[1] ) ) {
  8768. onextself( *splittri );
  8769. }
  8770. else if ( ( rightpoint[0] != endpoint1[0] ) ||
  8771. ( rightpoint[1] != endpoint1[1] ) ) {
  8772. printf( "Internal error in segmentintersection():\n" );
  8773. printf( " Topological inconsistency after splitting a segment.\n" );
  8774. internalerror();
  8775. }
  8776. /* `splittri' should have destination endpoint1. */
  8777. }
  8778. /*****************************************************************************/
  8779. /* */
  8780. /* scoutsegment() Scout the first triangle on the path from one endpoint */
  8781. /* to another, and check for completion (reaching the */
  8782. /* second endpoint), a collinear point, and the */
  8783. /* intersection of two segments. */
  8784. /* */
  8785. /* Returns one if the entire segment is successfully inserted, and zero if */
  8786. /* the job must be finished by conformingedge() or constrainededge(). */
  8787. /* */
  8788. /* If the first triangle on the path has the second endpoint as its */
  8789. /* destination or apex, a shell edge is inserted and the job is done. */
  8790. /* */
  8791. /* If the first triangle on the path has a destination or apex that lies on */
  8792. /* the segment, a shell edge is inserted connecting the first endpoint to */
  8793. /* the collinear point, and the search is continued from the collinear */
  8794. /* point. */
  8795. /* */
  8796. /* If the first triangle on the path has a shell edge opposite its origin, */
  8797. /* then there is a segment that intersects the segment being inserted. */
  8798. /* Their intersection point is inserted, splitting the shell edge. */
  8799. /* */
  8800. /* Otherwise, return zero. */
  8801. /* */
  8802. /*****************************************************************************/
  8803. int scoutsegment( searchtri, endpoint2, newmark )
  8804. struct triedge *searchtri;
  8805. point endpoint2;
  8806. int newmark;
  8807. {
  8808. struct triedge crosstri;
  8809. struct edge crossedge;
  8810. point leftpoint, rightpoint;
  8811. point endpoint1;
  8812. enum finddirectionresult collinear;
  8813. shelle sptr; /* Temporary variable used by tspivot(). */
  8814. collinear = finddirection( searchtri, endpoint2 );
  8815. dest( *searchtri, rightpoint );
  8816. apex( *searchtri, leftpoint );
  8817. if ( ( ( leftpoint[0] == endpoint2[0] ) && ( leftpoint[1] == endpoint2[1] ) ) ||
  8818. ( ( rightpoint[0] == endpoint2[0] ) && ( rightpoint[1] == endpoint2[1] ) ) ) {
  8819. /* The segment is already an edge in the mesh. */
  8820. if ( ( leftpoint[0] == endpoint2[0] ) && ( leftpoint[1] == endpoint2[1] ) ) {
  8821. lprevself( *searchtri );
  8822. }
  8823. /* Insert a shell edge, if there isn't already one there. */
  8824. insertshelle( searchtri, newmark );
  8825. return 1;
  8826. }
  8827. else if ( collinear == LEFTCOLLINEAR ) {
  8828. /* We've collided with a point between the segment's endpoints. */
  8829. /* Make the collinear point be the triangle's origin. */
  8830. lprevself( *searchtri );
  8831. insertshelle( searchtri, newmark );
  8832. /* Insert the remainder of the segment. */
  8833. return scoutsegment( searchtri, endpoint2, newmark );
  8834. }
  8835. else if ( collinear == RIGHTCOLLINEAR ) {
  8836. /* We've collided with a point between the segment's endpoints. */
  8837. insertshelle( searchtri, newmark );
  8838. /* Make the collinear point be the triangle's origin. */
  8839. lnextself( *searchtri );
  8840. /* Insert the remainder of the segment. */
  8841. return scoutsegment( searchtri, endpoint2, newmark );
  8842. }
  8843. else {
  8844. lnext( *searchtri, crosstri );
  8845. tspivot( crosstri, crossedge );
  8846. /* Check for a crossing segment. */
  8847. if ( crossedge.sh == dummysh ) {
  8848. return 0;
  8849. }
  8850. else {
  8851. org( *searchtri, endpoint1 );
  8852. /* Insert a point at the intersection. */
  8853. segmentintersection( &crosstri, &crossedge, endpoint2 );
  8854. triedgecopy( crosstri, *searchtri );
  8855. insertshelle( searchtri, newmark );
  8856. /* Insert the remainder of the segment. */
  8857. return scoutsegment( searchtri, endpoint2, newmark );
  8858. }
  8859. }
  8860. }
  8861. /*****************************************************************************/
  8862. /* */
  8863. /* conformingedge() Force a segment into a conforming Delaunay */
  8864. /* triangulation by inserting a point at its midpoint, */
  8865. /* and recursively forcing in the two half-segments if */
  8866. /* necessary. */
  8867. /* */
  8868. /* Generates a sequence of edges connecting `endpoint1' to `endpoint2'. */
  8869. /* `newmark' is the boundary marker of the segment, assigned to each new */
  8870. /* splitting point and shell edge. */
  8871. /* */
  8872. /* Note that conformingedge() does not always maintain the conforming */
  8873. /* Delaunay property. Once inserted, segments are locked into place; */
  8874. /* points inserted later (to force other segments in) may render these */
  8875. /* fixed segments non-Delaunay. The conforming Delaunay property will be */
  8876. /* restored by enforcequality() by splitting encroached segments. */
  8877. /* */
  8878. /*****************************************************************************/
  8879. #ifndef REDUCED
  8880. #ifndef CDT_ONLY
  8881. void conformingedge( endpoint1, endpoint2, newmark )
  8882. point endpoint1;
  8883. point endpoint2;
  8884. int newmark;
  8885. {
  8886. struct triedge searchtri1, searchtri2;
  8887. struct edge brokenshelle;
  8888. point newpoint;
  8889. point midpoint1, midpoint2;
  8890. enum insertsiteresult success;
  8891. int result1, result2;
  8892. int i;
  8893. shelle sptr; /* Temporary variable used by tspivot(). */
  8894. if ( verbose > 2 ) {
  8895. printf( "Forcing segment into triangulation by recursive splitting:\n" );
  8896. printf( " (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
  8897. endpoint2[0], endpoint2[1] );
  8898. }
  8899. /* Create a new point to insert in the middle of the segment. */
  8900. newpoint = (point) poolalloc( &points );
  8901. /* Interpolate coordinates and attributes. */
  8902. for ( i = 0; i < 2 + nextras; i++ ) {
  8903. newpoint[i] = 0.5 * ( endpoint1[i] + endpoint2[i] );
  8904. }
  8905. setpointmark( newpoint, newmark );
  8906. /* Find a boundary triangle to search from. */
  8907. searchtri1.tri = (triangle *) NULL;
  8908. /* Attempt to insert the new point. */
  8909. success = insertsite( newpoint, &searchtri1, (struct edge *) NULL, 0, 0 );
  8910. if ( success == DUPLICATEPOINT ) {
  8911. if ( verbose > 2 ) {
  8912. printf( " Segment intersects existing point (%.12g, %.12g).\n",
  8913. newpoint[0], newpoint[1] );
  8914. }
  8915. /* Use the point that's already there. */
  8916. pointdealloc( newpoint );
  8917. org( searchtri1, newpoint );
  8918. }
  8919. else {
  8920. if ( success == VIOLATINGPOINT ) {
  8921. if ( verbose > 2 ) {
  8922. printf( " Two segments intersect at (%.12g, %.12g).\n",
  8923. newpoint[0], newpoint[1] );
  8924. }
  8925. /* By fluke, we've landed right on another segment. Split it. */
  8926. tspivot( searchtri1, brokenshelle );
  8927. success = insertsite( newpoint, &searchtri1, &brokenshelle, 0, 0 );
  8928. if ( success != SUCCESSFULPOINT ) {
  8929. printf( "Internal error in conformingedge():\n" );
  8930. printf( " Failure to split a segment.\n" );
  8931. internalerror();
  8932. }
  8933. }
  8934. /* The point has been inserted successfully. */
  8935. if ( steinerleft > 0 ) {
  8936. steinerleft--;
  8937. }
  8938. }
  8939. triedgecopy( searchtri1, searchtri2 );
  8940. result1 = scoutsegment( &searchtri1, endpoint1, newmark );
  8941. result2 = scoutsegment( &searchtri2, endpoint2, newmark );
  8942. if ( !result1 ) {
  8943. /* The origin of searchtri1 may have changed if a collision with an */
  8944. /* intervening vertex on the segment occurred. */
  8945. org( searchtri1, midpoint1 );
  8946. conformingedge( midpoint1, endpoint1, newmark );
  8947. }
  8948. if ( !result2 ) {
  8949. /* The origin of searchtri2 may have changed if a collision with an */
  8950. /* intervening vertex on the segment occurred. */
  8951. org( searchtri2, midpoint2 );
  8952. conformingedge( midpoint2, endpoint2, newmark );
  8953. }
  8954. }
  8955. #endif /* not CDT_ONLY */
  8956. #endif /* not REDUCED */
  8957. /*****************************************************************************/
  8958. /* */
  8959. /* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */
  8960. /* recursively from an existing point. Pay special */
  8961. /* attention to stacking inverted triangles. */
  8962. /* */
  8963. /* This is a support routine for inserting segments into a constrained */
  8964. /* Delaunay triangulation. */
  8965. /* */
  8966. /* The origin of fixuptri is treated as if it has just been inserted, and */
  8967. /* the local Delaunay condition needs to be enforced. It is only enforced */
  8968. /* in one sector, however, that being the angular range defined by */
  8969. /* fixuptri. */
  8970. /* */
  8971. /* This routine also needs to make decisions regarding the "stacking" of */
  8972. /* triangles. (Read the description of constrainededge() below before */
  8973. /* reading on here, so you understand the algorithm.) If the position of */
  8974. /* the new point (the origin of fixuptri) indicates that the vertex before */
  8975. /* it on the polygon is a reflex vertex, then "stack" the triangle by */
  8976. /* doing nothing. (fixuptri is an inverted triangle, which is how stacked */
  8977. /* triangles are identified.) */
  8978. /* */
  8979. /* Otherwise, check whether the vertex before that was a reflex vertex. */
  8980. /* If so, perform an edge flip, thereby eliminating an inverted triangle */
  8981. /* (popping it off the stack). The edge flip may result in the creation */
  8982. /* of a new inverted triangle, depending on whether or not the new vertex */
  8983. /* is visible to the vertex three edges behind on the polygon. */
  8984. /* */
  8985. /* If neither of the two vertices behind the new vertex are reflex */
  8986. /* vertices, fixuptri and fartri, the triangle opposite it, are not */
  8987. /* inverted; hence, ensure that the edge between them is locally Delaunay. */
  8988. /* */
  8989. /* `leftside' indicates whether or not fixuptri is to the left of the */
  8990. /* segment being inserted. (Imagine that the segment is pointing up from */
  8991. /* endpoint1 to endpoint2.) */
  8992. /* */
  8993. /*****************************************************************************/
  8994. void delaunayfixup( fixuptri, leftside )
  8995. struct triedge *fixuptri;
  8996. int leftside;
  8997. {
  8998. struct triedge neartri;
  8999. struct triedge fartri;
  9000. struct edge faredge;
  9001. point nearpoint, leftpoint, rightpoint, farpoint;
  9002. triangle ptr; /* Temporary variable used by sym(). */
  9003. shelle sptr; /* Temporary variable used by tspivot(). */
  9004. lnext( *fixuptri, neartri );
  9005. sym( neartri, fartri );
  9006. /* Check if the edge opposite the origin of fixuptri can be flipped. */
  9007. if ( fartri.tri == dummytri ) {
  9008. return;
  9009. }
  9010. tspivot( neartri, faredge );
  9011. if ( faredge.sh != dummysh ) {
  9012. return;
  9013. }
  9014. /* Find all the relevant vertices. */
  9015. apex( neartri, nearpoint );
  9016. org( neartri, leftpoint );
  9017. dest( neartri, rightpoint );
  9018. apex( fartri, farpoint );
  9019. /* Check whether the previous polygon vertex is a reflex vertex. */
  9020. if ( leftside ) {
  9021. if ( counterclockwise( nearpoint, leftpoint, farpoint ) <= 0.0 ) {
  9022. /* leftpoint is a reflex vertex too. Nothing can */
  9023. /* be done until a convex section is found. */
  9024. return;
  9025. }
  9026. }
  9027. else {
  9028. if ( counterclockwise( farpoint, rightpoint, nearpoint ) <= 0.0 ) {
  9029. /* rightpoint is a reflex vertex too. Nothing can */
  9030. /* be done until a convex section is found. */
  9031. return;
  9032. }
  9033. }
  9034. if ( counterclockwise( rightpoint, leftpoint, farpoint ) > 0.0 ) {
  9035. /* fartri is not an inverted triangle, and farpoint is not a reflex */
  9036. /* vertex. As there are no reflex vertices, fixuptri isn't an */
  9037. /* inverted triangle, either. Hence, test the edge between the */
  9038. /* triangles to ensure it is locally Delaunay. */
  9039. if ( incircle( leftpoint, farpoint, rightpoint, nearpoint ) <= 0.0 ) {
  9040. return;
  9041. }
  9042. /* Not locally Delaunay; go on to an edge flip. */
  9043. } /* else fartri is inverted; remove it from the stack by flipping. */
  9044. flip( &neartri );
  9045. lprevself( *fixuptri ); /* Restore the origin of fixuptri after the flip. */
  9046. /* Recursively process the two triangles that result from the flip. */
  9047. delaunayfixup( fixuptri, leftside );
  9048. delaunayfixup( &fartri, leftside );
  9049. }
  9050. /*****************************************************************************/
  9051. /* */
  9052. /* constrainededge() Force a segment into a constrained Delaunay */
  9053. /* triangulation by deleting the triangles it */
  9054. /* intersects, and triangulating the polygons that */
  9055. /* form on each side of it. */
  9056. /* */
  9057. /* Generates a single edge connecting `endpoint1' to `endpoint2'. The */
  9058. /* triangle `starttri' has `endpoint1' as its origin. `newmark' is the */
  9059. /* boundary marker of the segment. */
  9060. /* */
  9061. /* To insert a segment, every triangle whose interior intersects the */
  9062. /* segment is deleted. The union of these deleted triangles is a polygon */
  9063. /* (which is not necessarily monotone, but is close enough), which is */
  9064. /* divided into two polygons by the new segment. This routine's task is */
  9065. /* to generate the Delaunay triangulation of these two polygons. */
  9066. /* */
  9067. /* You might think of this routine's behavior as a two-step process. The */
  9068. /* first step is to walk from endpoint1 to endpoint2, flipping each edge */
  9069. /* encountered. This step creates a fan of edges connected to endpoint1, */
  9070. /* including the desired edge to endpoint2. The second step enforces the */
  9071. /* Delaunay condition on each side of the segment in an incremental manner: */
  9072. /* proceeding along the polygon from endpoint1 to endpoint2 (this is done */
  9073. /* independently on each side of the segment), each vertex is "enforced" */
  9074. /* as if it had just been inserted, but affecting only the previous */
  9075. /* vertices. The result is the same as if the vertices had been inserted */
  9076. /* in the order they appear on the polygon, so the result is Delaunay. */
  9077. /* */
  9078. /* In truth, constrainededge() interleaves these two steps. The procedure */
  9079. /* walks from endpoint1 to endpoint2, and each time an edge is encountered */
  9080. /* and flipped, the newly exposed vertex (at the far end of the flipped */
  9081. /* edge) is "enforced" upon the previously flipped edges, usually affecting */
  9082. /* only one side of the polygon (depending upon which side of the segment */
  9083. /* the vertex falls on). */
  9084. /* */
  9085. /* The algorithm is complicated by the need to handle polygons that are not */
  9086. /* convex. Although the polygon is not necessarily monotone, it can be */
  9087. /* triangulated in a manner similar to the stack-based algorithms for */
  9088. /* monotone polygons. For each reflex vertex (local concavity) of the */
  9089. /* polygon, there will be an inverted triangle formed by one of the edge */
  9090. /* flips. (An inverted triangle is one with negative area - that is, its */
  9091. /* vertices are arranged in clockwise order - and is best thought of as a */
  9092. /* wrinkle in the fabric of the mesh.) Each inverted triangle can be */
  9093. /* thought of as a reflex vertex pushed on the stack, waiting to be fixed */
  9094. /* later. */
  9095. /* */
  9096. /* A reflex vertex is popped from the stack when a vertex is inserted that */
  9097. /* is visible to the reflex vertex. (However, if the vertex behind the */
  9098. /* reflex vertex is not visible to the reflex vertex, a new inverted */
  9099. /* triangle will take its place on the stack.) These details are handled */
  9100. /* by the delaunayfixup() routine above. */
  9101. /* */
  9102. /*****************************************************************************/
  9103. void constrainededge( starttri, endpoint2, newmark )
  9104. struct triedge *starttri;
  9105. point endpoint2;
  9106. int newmark;
  9107. {
  9108. struct triedge fixuptri, fixuptri2;
  9109. struct edge fixupedge;
  9110. point endpoint1;
  9111. point farpoint;
  9112. REAL area;
  9113. int collision;
  9114. int done;
  9115. triangle ptr; /* Temporary variable used by sym() and oprev(). */
  9116. shelle sptr; /* Temporary variable used by tspivot(). */
  9117. org( *starttri, endpoint1 );
  9118. lnext( *starttri, fixuptri );
  9119. flip( &fixuptri );
  9120. /* `collision' indicates whether we have found a point directly */
  9121. /* between endpoint1 and endpoint2. */
  9122. collision = 0;
  9123. done = 0;
  9124. do {
  9125. org( fixuptri, farpoint );
  9126. /* `farpoint' is the extreme point of the polygon we are "digging" */
  9127. /* to get from endpoint1 to endpoint2. */
  9128. if ( ( farpoint[0] == endpoint2[0] ) && ( farpoint[1] == endpoint2[1] ) ) {
  9129. oprev( fixuptri, fixuptri2 );
  9130. /* Enforce the Delaunay condition around endpoint2. */
  9131. delaunayfixup( &fixuptri, 0 );
  9132. delaunayfixup( &fixuptri2, 1 );
  9133. done = 1;
  9134. }
  9135. else {
  9136. /* Check whether farpoint is to the left or right of the segment */
  9137. /* being inserted, to decide which edge of fixuptri to dig */
  9138. /* through next. */
  9139. area = counterclockwise( endpoint1, endpoint2, farpoint );
  9140. if ( area == 0.0 ) {
  9141. /* We've collided with a point between endpoint1 and endpoint2. */
  9142. collision = 1;
  9143. oprev( fixuptri, fixuptri2 );
  9144. /* Enforce the Delaunay condition around farpoint. */
  9145. delaunayfixup( &fixuptri, 0 );
  9146. delaunayfixup( &fixuptri2, 1 );
  9147. done = 1;
  9148. }
  9149. else {
  9150. if ( area > 0.0 ) { /* farpoint is to the left of the segment. */
  9151. oprev( fixuptri, fixuptri2 );
  9152. /* Enforce the Delaunay condition around farpoint, on the */
  9153. /* left side of the segment only. */
  9154. delaunayfixup( &fixuptri2, 1 );
  9155. /* Flip the edge that crosses the segment. After the edge is */
  9156. /* flipped, one of its endpoints is the fan vertex, and the */
  9157. /* destination of fixuptri is the fan vertex. */
  9158. lprevself( fixuptri );
  9159. }
  9160. else { /* farpoint is to the right of the segment. */
  9161. delaunayfixup( &fixuptri, 0 );
  9162. /* Flip the edge that crosses the segment. After the edge is */
  9163. /* flipped, one of its endpoints is the fan vertex, and the */
  9164. /* destination of fixuptri is the fan vertex. */
  9165. oprevself( fixuptri );
  9166. }
  9167. /* Check for two intersecting segments. */
  9168. tspivot( fixuptri, fixupedge );
  9169. if ( fixupedge.sh == dummysh ) {
  9170. flip( &fixuptri ); /* May create an inverted triangle on the left. */
  9171. }
  9172. else {
  9173. /* We've collided with a segment between endpoint1 and endpoint2. */
  9174. collision = 1;
  9175. /* Insert a point at the intersection. */
  9176. segmentintersection( &fixuptri, &fixupedge, endpoint2 );
  9177. done = 1;
  9178. }
  9179. }
  9180. }
  9181. } while ( !done );
  9182. /* Insert a shell edge to make the segment permanent. */
  9183. insertshelle( &fixuptri, newmark );
  9184. /* If there was a collision with an interceding vertex, install another */
  9185. /* segment connecting that vertex with endpoint2. */
  9186. if ( collision ) {
  9187. /* Insert the remainder of the segment. */
  9188. if ( !scoutsegment( &fixuptri, endpoint2, newmark ) ) {
  9189. constrainededge( &fixuptri, endpoint2, newmark );
  9190. }
  9191. }
  9192. }
  9193. /*****************************************************************************/
  9194. /* */
  9195. /* insertsegment() Insert a PSLG segment into a triangulation. */
  9196. /* */
  9197. /*****************************************************************************/
  9198. void insertsegment( endpoint1, endpoint2, newmark )
  9199. point endpoint1;
  9200. point endpoint2;
  9201. int newmark;
  9202. {
  9203. struct triedge searchtri1, searchtri2;
  9204. triangle encodedtri;
  9205. point checkpoint;
  9206. triangle ptr; /* Temporary variable used by sym(). */
  9207. if ( verbose > 1 ) {
  9208. printf( " Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
  9209. endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1] );
  9210. }
  9211. /* Find a triangle whose origin is the segment's first endpoint. */
  9212. checkpoint = (point) NULL;
  9213. encodedtri = point2tri( endpoint1 );
  9214. if ( encodedtri != (triangle) NULL ) {
  9215. decode( encodedtri, searchtri1 );
  9216. org( searchtri1, checkpoint );
  9217. }
  9218. if ( checkpoint != endpoint1 ) {
  9219. /* Find a boundary triangle to search from. */
  9220. searchtri1.tri = dummytri;
  9221. searchtri1.orient = 0;
  9222. symself( searchtri1 );
  9223. /* Search for the segment's first endpoint by point location. */
  9224. if ( locate( endpoint1, &searchtri1 ) != ONVERTEX ) {
  9225. printf(
  9226. "Internal error in insertsegment(): Unable to locate PSLG point\n" );
  9227. printf( " (%.12g, %.12g) in triangulation.\n",
  9228. endpoint1[0], endpoint1[1] );
  9229. internalerror();
  9230. }
  9231. }
  9232. /* Remember this triangle to improve subsequent point location. */
  9233. triedgecopy( searchtri1, recenttri );
  9234. /* Scout the beginnings of a path from the first endpoint */
  9235. /* toward the second. */
  9236. if ( scoutsegment( &searchtri1, endpoint2, newmark ) ) {
  9237. /* The segment was easily inserted. */
  9238. return;
  9239. }
  9240. /* The first endpoint may have changed if a collision with an intervening */
  9241. /* vertex on the segment occurred. */
  9242. org( searchtri1, endpoint1 );
  9243. /* Find a triangle whose origin is the segment's second endpoint. */
  9244. checkpoint = (point) NULL;
  9245. encodedtri = point2tri( endpoint2 );
  9246. if ( encodedtri != (triangle) NULL ) {
  9247. decode( encodedtri, searchtri2 );
  9248. org( searchtri2, checkpoint );
  9249. }
  9250. if ( checkpoint != endpoint2 ) {
  9251. /* Find a boundary triangle to search from. */
  9252. searchtri2.tri = dummytri;
  9253. searchtri2.orient = 0;
  9254. symself( searchtri2 );
  9255. /* Search for the segment's second endpoint by point location. */
  9256. if ( locate( endpoint2, &searchtri2 ) != ONVERTEX ) {
  9257. printf(
  9258. "Internal error in insertsegment(): Unable to locate PSLG point\n" );
  9259. printf( " (%.12g, %.12g) in triangulation.\n",
  9260. endpoint2[0], endpoint2[1] );
  9261. internalerror();
  9262. }
  9263. }
  9264. /* Remember this triangle to improve subsequent point location. */
  9265. triedgecopy( searchtri2, recenttri );
  9266. /* Scout the beginnings of a path from the second endpoint */
  9267. /* toward the first. */
  9268. if ( scoutsegment( &searchtri2, endpoint1, newmark ) ) {
  9269. /* The segment was easily inserted. */
  9270. return;
  9271. }
  9272. /* The second endpoint may have changed if a collision with an intervening */
  9273. /* vertex on the segment occurred. */
  9274. org( searchtri2, endpoint2 );
  9275. #ifndef REDUCED
  9276. #ifndef CDT_ONLY
  9277. if ( splitseg ) {
  9278. /* Insert vertices to force the segment into the triangulation. */
  9279. conformingedge( endpoint1, endpoint2, newmark );
  9280. }
  9281. else {
  9282. #endif /* not CDT_ONLY */
  9283. #endif /* not REDUCED */
  9284. /* Insert the segment directly into the triangulation. */
  9285. constrainededge( &searchtri1, endpoint2, newmark );
  9286. #ifndef REDUCED
  9287. #ifndef CDT_ONLY
  9288. }
  9289. #endif /* not CDT_ONLY */
  9290. #endif /* not REDUCED */
  9291. }
  9292. /*****************************************************************************/
  9293. /* */
  9294. /* markhull() Cover the convex hull of a triangulation with shell edges. */
  9295. /* */
  9296. /*****************************************************************************/
  9297. void markhull(){
  9298. struct triedge hulltri;
  9299. struct triedge nexttri;
  9300. struct triedge starttri;
  9301. triangle ptr; /* Temporary variable used by sym() and oprev(). */
  9302. /* Find a triangle handle on the hull. */
  9303. hulltri.tri = dummytri;
  9304. hulltri.orient = 0;
  9305. symself( hulltri );
  9306. /* Remember where we started so we know when to stop. */
  9307. triedgecopy( hulltri, starttri );
  9308. /* Go once counterclockwise around the convex hull. */
  9309. do {
  9310. /* Create a shell edge if there isn't already one here. */
  9311. insertshelle( &hulltri, 1 );
  9312. /* To find the next hull edge, go clockwise around the next vertex. */
  9313. lnextself( hulltri );
  9314. oprev( hulltri, nexttri );
  9315. while ( nexttri.tri != dummytri ) {
  9316. triedgecopy( nexttri, hulltri );
  9317. oprev( hulltri, nexttri );
  9318. }
  9319. } while ( !triedgeequal( hulltri, starttri ) );
  9320. }
  9321. /*****************************************************************************/
  9322. /* */
  9323. /* formskeleton() Create the shell edges of a triangulation, including */
  9324. /* PSLG edges and edges on the convex hull. */
  9325. /* */
  9326. /* The PSLG edges are read from a .poly file. The return value is the */
  9327. /* number of segments in the file. */
  9328. /* */
  9329. /*****************************************************************************/
  9330. #ifdef TRILIBRARY
  9331. int formskeleton( segmentlist, segmentmarkerlist, numberofsegments )
  9332. int *segmentlist;
  9333. int *segmentmarkerlist;
  9334. int numberofsegments;
  9335. #else /* not TRILIBRARY */
  9336. int formskeleton( polyfile, polyfilename )
  9337. FILE * polyfile;
  9338. char *polyfilename;
  9339. #endif /* not TRILIBRARY */
  9340. {
  9341. #ifdef TRILIBRARY
  9342. char polyfilename[6];
  9343. int index;
  9344. #else /* not TRILIBRARY */
  9345. char inputline[INPUTLINESIZE];
  9346. char *stringptr;
  9347. #endif /* not TRILIBRARY */
  9348. point endpoint1, endpoint2;
  9349. int segments;
  9350. int segmentmarkers;
  9351. int end1, end2;
  9352. int boundmarker;
  9353. int i;
  9354. if ( poly ) {
  9355. if ( !quiet ) {
  9356. printf( "Inserting segments into Delaunay triangulation.\n" );
  9357. }
  9358. #ifdef TRILIBRARY
  9359. strcpy( polyfilename, "input" );
  9360. segments = numberofsegments;
  9361. segmentmarkers = segmentmarkerlist != (int *) NULL;
  9362. index = 0;
  9363. #else /* not TRILIBRARY */
  9364. /* Read the segments from a .poly file. */
  9365. /* Read number of segments and number of boundary markers. */
  9366. stringptr = readline( inputline, polyfile, polyfilename );
  9367. segments = (int) strtol( stringptr, &stringptr, 0 );
  9368. stringptr = findfield( stringptr );
  9369. if ( *stringptr == '\0' ) {
  9370. segmentmarkers = 0;
  9371. }
  9372. else {
  9373. segmentmarkers = (int) strtol( stringptr, &stringptr, 0 );
  9374. }
  9375. #endif /* not TRILIBRARY */
  9376. /* If segments are to be inserted, compute a mapping */
  9377. /* from points to triangles. */
  9378. if ( segments > 0 ) {
  9379. if ( verbose ) {
  9380. printf( " Inserting PSLG segments.\n" );
  9381. }
  9382. makepointmap();
  9383. }
  9384. boundmarker = 0;
  9385. /* Read and insert the segments. */
  9386. for ( i = 1; i <= segments; i++ ) {
  9387. #ifdef TRILIBRARY
  9388. end1 = segmentlist[index++];
  9389. end2 = segmentlist[index++];
  9390. if ( segmentmarkers ) {
  9391. boundmarker = segmentmarkerlist[i - 1];
  9392. }
  9393. #else /* not TRILIBRARY */
  9394. stringptr = readline( inputline, polyfile, inpolyfilename );
  9395. stringptr = findfield( stringptr );
  9396. if ( *stringptr == '\0' ) {
  9397. printf( "Error: Segment %d has no endpoints in %s.\n", i,
  9398. polyfilename );
  9399. exit( 1 );
  9400. }
  9401. else {
  9402. end1 = (int) strtol( stringptr, &stringptr, 0 );
  9403. }
  9404. stringptr = findfield( stringptr );
  9405. if ( *stringptr == '\0' ) {
  9406. printf( "Error: Segment %d is missing its second endpoint in %s.\n", i,
  9407. polyfilename );
  9408. exit( 1 );
  9409. }
  9410. else {
  9411. end2 = (int) strtol( stringptr, &stringptr, 0 );
  9412. }
  9413. if ( segmentmarkers ) {
  9414. stringptr = findfield( stringptr );
  9415. if ( *stringptr == '\0' ) {
  9416. boundmarker = 0;
  9417. }
  9418. else {
  9419. boundmarker = (int) strtol( stringptr, &stringptr, 0 );
  9420. }
  9421. }
  9422. #endif /* not TRILIBRARY */
  9423. if ( ( end1 < firstnumber ) || ( end1 >= firstnumber + inpoints ) ) {
  9424. if ( !quiet ) {
  9425. printf( "Warning: Invalid first endpoint of segment %d in %s.\n", i,
  9426. polyfilename );
  9427. }
  9428. }
  9429. else if ( ( end2 < firstnumber ) || ( end2 >= firstnumber + inpoints ) ) {
  9430. if ( !quiet ) {
  9431. printf( "Warning: Invalid second endpoint of segment %d in %s.\n", i,
  9432. polyfilename );
  9433. }
  9434. }
  9435. else {
  9436. endpoint1 = getpoint( end1 );
  9437. endpoint2 = getpoint( end2 );
  9438. if ( ( endpoint1[0] == endpoint2[0] ) && ( endpoint1[1] == endpoint2[1] ) ) {
  9439. if ( !quiet ) {
  9440. printf( "Warning: Endpoints of segment %d are coincident in %s.\n",
  9441. i, polyfilename );
  9442. }
  9443. }
  9444. else {
  9445. insertsegment( endpoint1, endpoint2, boundmarker );
  9446. }
  9447. }
  9448. }
  9449. }
  9450. else {
  9451. segments = 0;
  9452. }
  9453. if ( convex || !poly ) {
  9454. /* Enclose the convex hull with shell edges. */
  9455. if ( verbose ) {
  9456. printf( " Enclosing convex hull with segments.\n" );
  9457. }
  9458. markhull();
  9459. }
  9460. return segments;
  9461. }
  9462. /** **/
  9463. /** **/
  9464. /********* Segment (shell edge) insertion ends here *********/
  9465. /********* Carving out holes and concavities begins here *********/
  9466. /** **/
  9467. /** **/
  9468. /*****************************************************************************/
  9469. /* */
  9470. /* infecthull() Virally infect all of the triangles of the convex hull */
  9471. /* that are not protected by shell edges. Where there are */
  9472. /* shell edges, set boundary markers as appropriate. */
  9473. /* */
  9474. /*****************************************************************************/
  9475. void infecthull(){
  9476. struct triedge hulltri;
  9477. struct triedge nexttri;
  9478. struct triedge starttri;
  9479. struct edge hulledge;
  9480. triangle **deadtri;
  9481. point horg, hdest;
  9482. triangle ptr; /* Temporary variable used by sym(). */
  9483. shelle sptr; /* Temporary variable used by tspivot(). */
  9484. if ( verbose ) {
  9485. printf( " Marking concavities (external triangles) for elimination.\n" );
  9486. }
  9487. /* Find a triangle handle on the hull. */
  9488. hulltri.tri = dummytri;
  9489. hulltri.orient = 0;
  9490. symself( hulltri );
  9491. /* Remember where we started so we know when to stop. */
  9492. triedgecopy( hulltri, starttri );
  9493. /* Go once counterclockwise around the convex hull. */
  9494. do {
  9495. /* Ignore triangles that are already infected. */
  9496. if ( !infected( hulltri ) ) {
  9497. /* Is the triangle protected by a shell edge? */
  9498. tspivot( hulltri, hulledge );
  9499. if ( hulledge.sh == dummysh ) {
  9500. /* The triangle is not protected; infect it. */
  9501. infect( hulltri );
  9502. deadtri = (triangle **) poolalloc( &viri );
  9503. *deadtri = hulltri.tri;
  9504. }
  9505. else {
  9506. /* The triangle is protected; set boundary markers if appropriate. */
  9507. if ( mark( hulledge ) == 0 ) {
  9508. setmark( hulledge, 1 );
  9509. org( hulltri, horg );
  9510. dest( hulltri, hdest );
  9511. if ( pointmark( horg ) == 0 ) {
  9512. setpointmark( horg, 1 );
  9513. }
  9514. if ( pointmark( hdest ) == 0 ) {
  9515. setpointmark( hdest, 1 );
  9516. }
  9517. }
  9518. }
  9519. }
  9520. /* To find the next hull edge, go clockwise around the next vertex. */
  9521. lnextself( hulltri );
  9522. oprev( hulltri, nexttri );
  9523. while ( nexttri.tri != dummytri ) {
  9524. triedgecopy( nexttri, hulltri );
  9525. oprev( hulltri, nexttri );
  9526. }
  9527. } while ( !triedgeequal( hulltri, starttri ) );
  9528. }
  9529. /*****************************************************************************/
  9530. /* */
  9531. /* plague() Spread the virus from all infected triangles to any neighbors */
  9532. /* not protected by shell edges. Delete all infected triangles. */
  9533. /* */
  9534. /* This is the procedure that actually creates holes and concavities. */
  9535. /* */
  9536. /* This procedure operates in two phases. The first phase identifies all */
  9537. /* the triangles that will die, and marks them as infected. They are */
  9538. /* marked to ensure that each triangle is added to the virus pool only */
  9539. /* once, so the procedure will terminate. */
  9540. /* */
  9541. /* The second phase actually eliminates the infected triangles. It also */
  9542. /* eliminates orphaned points. */
  9543. /* */
  9544. /*****************************************************************************/
  9545. void plague(){
  9546. struct triedge testtri;
  9547. struct triedge neighbor;
  9548. triangle **virusloop;
  9549. triangle **deadtri;
  9550. struct edge neighborshelle;
  9551. point testpoint;
  9552. point norg, ndest;
  9553. point deadorg, deaddest, deadapex;
  9554. int killorg;
  9555. triangle ptr; /* Temporary variable used by sym() and onext(). */
  9556. shelle sptr; /* Temporary variable used by tspivot(). */
  9557. if ( verbose ) {
  9558. printf( " Marking neighbors of marked triangles.\n" );
  9559. }
  9560. /* Loop through all the infected triangles, spreading the virus to */
  9561. /* their neighbors, then to their neighbors' neighbors. */
  9562. traversalinit( &viri );
  9563. virusloop = (triangle **) traverse( &viri );
  9564. while ( virusloop != (triangle **) NULL ) {
  9565. testtri.tri = *virusloop;
  9566. /* A triangle is marked as infected by messing with one of its shell */
  9567. /* edges, setting it to an illegal value. Hence, we have to */
  9568. /* temporarily uninfect this triangle so that we can examine its */
  9569. /* adjacent shell edges. */
  9570. uninfect( testtri );
  9571. if ( verbose > 2 ) {
  9572. /* Assign the triangle an orientation for convenience in */
  9573. /* checking its points. */
  9574. testtri.orient = 0;
  9575. org( testtri, deadorg );
  9576. dest( testtri, deaddest );
  9577. apex( testtri, deadapex );
  9578. printf( " Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
  9579. deadorg[0], deadorg[1], deaddest[0], deaddest[1],
  9580. deadapex[0], deadapex[1] );
  9581. }
  9582. /* Check each of the triangle's three neighbors. */
  9583. for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) {
  9584. /* Find the neighbor. */
  9585. sym( testtri, neighbor );
  9586. /* Check for a shell between the triangle and its neighbor. */
  9587. tspivot( testtri, neighborshelle );
  9588. /* Check if the neighbor is nonexistent or already infected. */
  9589. if ( ( neighbor.tri == dummytri ) || infected( neighbor ) ) {
  9590. if ( neighborshelle.sh != dummysh ) {
  9591. /* There is a shell edge separating the triangle from its */
  9592. /* neighbor, but both triangles are dying, so the shell */
  9593. /* edge dies too. */
  9594. shelledealloc( neighborshelle.sh );
  9595. if ( neighbor.tri != dummytri ) {
  9596. /* Make sure the shell edge doesn't get deallocated again */
  9597. /* later when the infected neighbor is visited. */
  9598. uninfect( neighbor );
  9599. tsdissolve( neighbor );
  9600. infect( neighbor );
  9601. }
  9602. }
  9603. }
  9604. else { /* The neighbor exists and is not infected. */
  9605. if ( neighborshelle.sh == dummysh ) {
  9606. /* There is no shell edge protecting the neighbor, so */
  9607. /* the neighbor becomes infected. */
  9608. if ( verbose > 2 ) {
  9609. org( neighbor, deadorg );
  9610. dest( neighbor, deaddest );
  9611. apex( neighbor, deadapex );
  9612. printf(
  9613. " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
  9614. deadorg[0], deadorg[1], deaddest[0], deaddest[1],
  9615. deadapex[0], deadapex[1] );
  9616. }
  9617. infect( neighbor );
  9618. /* Ensure that the neighbor's neighbors will be infected. */
  9619. deadtri = (triangle **) poolalloc( &viri );
  9620. *deadtri = neighbor.tri;
  9621. }
  9622. else { /* The neighbor is protected by a shell edge. */
  9623. /* Remove this triangle from the shell edge. */
  9624. stdissolve( neighborshelle );
  9625. /* The shell edge becomes a boundary. Set markers accordingly. */
  9626. if ( mark( neighborshelle ) == 0 ) {
  9627. setmark( neighborshelle, 1 );
  9628. }
  9629. org( neighbor, norg );
  9630. dest( neighbor, ndest );
  9631. if ( pointmark( norg ) == 0 ) {
  9632. setpointmark( norg, 1 );
  9633. }
  9634. if ( pointmark( ndest ) == 0 ) {
  9635. setpointmark( ndest, 1 );
  9636. }
  9637. }
  9638. }
  9639. }
  9640. /* Remark the triangle as infected, so it doesn't get added to the */
  9641. /* virus pool again. */
  9642. infect( testtri );
  9643. virusloop = (triangle **) traverse( &viri );
  9644. }
  9645. if ( verbose ) {
  9646. printf( " Deleting marked triangles.\n" );
  9647. }
  9648. traversalinit( &viri );
  9649. virusloop = (triangle **) traverse( &viri );
  9650. while ( virusloop != (triangle **) NULL ) {
  9651. testtri.tri = *virusloop;
  9652. /* Check each of the three corners of the triangle for elimination. */
  9653. /* This is done by walking around each point, checking if it is */
  9654. /* still connected to at least one live triangle. */
  9655. for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) {
  9656. org( testtri, testpoint );
  9657. /* Check if the point has already been tested. */
  9658. if ( testpoint != (point) NULL ) {
  9659. killorg = 1;
  9660. /* Mark the corner of the triangle as having been tested. */
  9661. setorg( testtri, NULL );
  9662. /* Walk counterclockwise about the point. */
  9663. onext( testtri, neighbor );
  9664. /* Stop upon reaching a boundary or the starting triangle. */
  9665. while ( ( neighbor.tri != dummytri )
  9666. && ( !triedgeequal( neighbor, testtri ) ) ) {
  9667. if ( infected( neighbor ) ) {
  9668. /* Mark the corner of this triangle as having been tested. */
  9669. setorg( neighbor, NULL );
  9670. }
  9671. else {
  9672. /* A live triangle. The point survives. */
  9673. killorg = 0;
  9674. }
  9675. /* Walk counterclockwise about the point. */
  9676. onextself( neighbor );
  9677. }
  9678. /* If we reached a boundary, we must walk clockwise as well. */
  9679. if ( neighbor.tri == dummytri ) {
  9680. /* Walk clockwise about the point. */
  9681. oprev( testtri, neighbor );
  9682. /* Stop upon reaching a boundary. */
  9683. while ( neighbor.tri != dummytri ) {
  9684. if ( infected( neighbor ) ) {
  9685. /* Mark the corner of this triangle as having been tested. */
  9686. setorg( neighbor, NULL );
  9687. }
  9688. else {
  9689. /* A live triangle. The point survives. */
  9690. killorg = 0;
  9691. }
  9692. /* Walk clockwise about the point. */
  9693. oprevself( neighbor );
  9694. }
  9695. }
  9696. if ( killorg ) {
  9697. if ( verbose > 1 ) {
  9698. printf( " Deleting point (%.12g, %.12g)\n",
  9699. testpoint[0], testpoint[1] );
  9700. }
  9701. pointdealloc( testpoint );
  9702. }
  9703. }
  9704. }
  9705. /* Record changes in the number of boundary edges, and disconnect */
  9706. /* dead triangles from their neighbors. */
  9707. for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) {
  9708. sym( testtri, neighbor );
  9709. if ( neighbor.tri == dummytri ) {
  9710. /* There is no neighboring triangle on this edge, so this edge */
  9711. /* is a boundary edge. This triangle is being deleted, so this */
  9712. /* boundary edge is deleted. */
  9713. hullsize--;
  9714. }
  9715. else {
  9716. /* Disconnect the triangle from its neighbor. */
  9717. dissolve( neighbor );
  9718. /* There is a neighboring triangle on this edge, so this edge */
  9719. /* becomes a boundary edge when this triangle is deleted. */
  9720. hullsize++;
  9721. }
  9722. }
  9723. /* Return the dead triangle to the pool of triangles. */
  9724. triangledealloc( testtri.tri );
  9725. virusloop = (triangle **) traverse( &viri );
  9726. }
  9727. /* Empty the virus pool. */
  9728. poolrestart( &viri );
  9729. }
  9730. /*****************************************************************************/
  9731. /* */
  9732. /* regionplague() Spread regional attributes and/or area constraints */
  9733. /* (from a .poly file) throughout the mesh. */
  9734. /* */
  9735. /* This procedure operates in two phases. The first phase spreads an */
  9736. /* attribute and/or an area constraint through a (segment-bounded) region. */
  9737. /* The triangles are marked to ensure that each triangle is added to the */
  9738. /* virus pool only once, so the procedure will terminate. */
  9739. /* */
  9740. /* The second phase uninfects all infected triangles, returning them to */
  9741. /* normal. */
  9742. /* */
  9743. /*****************************************************************************/
  9744. void regionplague( attribute, area )
  9745. REAL attribute;
  9746. REAL area;
  9747. {
  9748. struct triedge testtri;
  9749. struct triedge neighbor;
  9750. triangle **virusloop;
  9751. triangle **regiontri;
  9752. struct edge neighborshelle;
  9753. point regionorg, regiondest, regionapex;
  9754. triangle ptr; /* Temporary variable used by sym() and onext(). */
  9755. shelle sptr; /* Temporary variable used by tspivot(). */
  9756. if ( verbose > 1 ) {
  9757. printf( " Marking neighbors of marked triangles.\n" );
  9758. }
  9759. /* Loop through all the infected triangles, spreading the attribute */
  9760. /* and/or area constraint to their neighbors, then to their neighbors' */
  9761. /* neighbors. */
  9762. traversalinit( &viri );
  9763. virusloop = (triangle **) traverse( &viri );
  9764. while ( virusloop != (triangle **) NULL ) {
  9765. testtri.tri = *virusloop;
  9766. /* A triangle is marked as infected by messing with one of its shell */
  9767. /* edges, setting it to an illegal value. Hence, we have to */
  9768. /* temporarily uninfect this triangle so that we can examine its */
  9769. /* adjacent shell edges. */
  9770. uninfect( testtri );
  9771. if ( regionattrib ) {
  9772. /* Set an attribute. */
  9773. setelemattribute( testtri, eextras, attribute );
  9774. }
  9775. if ( vararea ) {
  9776. /* Set an area constraint. */
  9777. setareabound( testtri, area );
  9778. }
  9779. if ( verbose > 2 ) {
  9780. /* Assign the triangle an orientation for convenience in */
  9781. /* checking its points. */
  9782. testtri.orient = 0;
  9783. org( testtri, regionorg );
  9784. dest( testtri, regiondest );
  9785. apex( testtri, regionapex );
  9786. printf( " Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
  9787. regionorg[0], regionorg[1], regiondest[0], regiondest[1],
  9788. regionapex[0], regionapex[1] );
  9789. }
  9790. /* Check each of the triangle's three neighbors. */
  9791. for ( testtri.orient = 0; testtri.orient < 3; testtri.orient++ ) {
  9792. /* Find the neighbor. */
  9793. sym( testtri, neighbor );
  9794. /* Check for a shell between the triangle and its neighbor. */
  9795. tspivot( testtri, neighborshelle );
  9796. /* Make sure the neighbor exists, is not already infected, and */
  9797. /* isn't protected by a shell edge. */
  9798. if ( ( neighbor.tri != dummytri ) && !infected( neighbor )
  9799. && ( neighborshelle.sh == dummysh ) ) {
  9800. if ( verbose > 2 ) {
  9801. org( neighbor, regionorg );
  9802. dest( neighbor, regiondest );
  9803. apex( neighbor, regionapex );
  9804. printf( " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
  9805. regionorg[0], regionorg[1], regiondest[0], regiondest[1],
  9806. regionapex[0], regionapex[1] );
  9807. }
  9808. /* Infect the neighbor. */
  9809. infect( neighbor );
  9810. /* Ensure that the neighbor's neighbors will be infected. */
  9811. regiontri = (triangle **) poolalloc( &viri );
  9812. *regiontri = neighbor.tri;
  9813. }
  9814. }
  9815. /* Remark the triangle as infected, so it doesn't get added to the */
  9816. /* virus pool again. */
  9817. infect( testtri );
  9818. virusloop = (triangle **) traverse( &viri );
  9819. }
  9820. /* Uninfect all triangles. */
  9821. if ( verbose > 1 ) {
  9822. printf( " Unmarking marked triangles.\n" );
  9823. }
  9824. traversalinit( &viri );
  9825. virusloop = (triangle **) traverse( &viri );
  9826. while ( virusloop != (triangle **) NULL ) {
  9827. testtri.tri = *virusloop;
  9828. uninfect( testtri );
  9829. virusloop = (triangle **) traverse( &viri );
  9830. }
  9831. /* Empty the virus pool. */
  9832. poolrestart( &viri );
  9833. }
  9834. /*****************************************************************************/
  9835. /* */
  9836. /* carveholes() Find the holes and infect them. Find the area */
  9837. /* constraints and infect them. Infect the convex hull. */
  9838. /* Spread the infection and kill triangles. Spread the */
  9839. /* area constraints. */
  9840. /* */
  9841. /* This routine mainly calls other routines to carry out all these */
  9842. /* functions. */
  9843. /* */
  9844. /*****************************************************************************/
  9845. void carveholes( holelist, holes, regionlist, regions )
  9846. REAL * holelist;
  9847. int holes;
  9848. REAL *regionlist;
  9849. int regions;
  9850. {
  9851. struct triedge searchtri;
  9852. struct triedge triangleloop;
  9853. struct triedge *regiontris;
  9854. triangle **holetri;
  9855. triangle **regiontri;
  9856. point searchorg, searchdest;
  9857. enum locateresult intersect;
  9858. int i;
  9859. triangle ptr; /* Temporary variable used by sym(). */
  9860. if ( !( quiet || ( noholes && convex ) ) ) {
  9861. printf( "Removing unwanted triangles.\n" );
  9862. if ( verbose && ( holes > 0 ) ) {
  9863. printf( " Marking holes for elimination.\n" );
  9864. }
  9865. }
  9866. if ( regions > 0 ) {
  9867. /* Allocate storage for the triangles in which region points fall. */
  9868. regiontris = (struct triedge *) malloc( regions * sizeof( struct triedge ) );
  9869. if ( regiontris == (struct triedge *) NULL ) {
  9870. printf( "Error: Out of memory.\n" );
  9871. exit( 1 );
  9872. }
  9873. }
  9874. if ( ( ( holes > 0 ) && !noholes ) || !convex || ( regions > 0 ) ) {
  9875. /* Initialize a pool of viri to be used for holes, concavities, */
  9876. /* regional attributes, and/or regional area constraints. */
  9877. poolinit( &viri, sizeof( triangle * ), VIRUSPERBLOCK, POINTER, 0 );
  9878. }
  9879. if ( !convex ) {
  9880. /* Mark as infected any unprotected triangles on the boundary. */
  9881. /* This is one way by which concavities are created. */
  9882. infecthull();
  9883. }
  9884. if ( ( holes > 0 ) && !noholes ) {
  9885. /* Infect each triangle in which a hole lies. */
  9886. for ( i = 0; i < 2 * holes; i += 2 ) {
  9887. /* Ignore holes that aren't within the bounds of the mesh. */
  9888. if ( ( holelist[i] >= xmin ) && ( holelist[i] <= xmax )
  9889. && ( holelist[i + 1] >= ymin ) && ( holelist[i + 1] <= ymax ) ) {
  9890. /* Start searching from some triangle on the outer boundary. */
  9891. searchtri.tri = dummytri;
  9892. searchtri.orient = 0;
  9893. symself( searchtri );
  9894. /* Ensure that the hole is to the left of this boundary edge; */
  9895. /* otherwise, locate() will falsely report that the hole */
  9896. /* falls within the starting triangle. */
  9897. org( searchtri, searchorg );
  9898. dest( searchtri, searchdest );
  9899. if ( counterclockwise( searchorg, searchdest, &holelist[i] ) > 0.0 ) {
  9900. /* Find a triangle that contains the hole. */
  9901. intersect = locate( &holelist[i], &searchtri );
  9902. if ( ( intersect != OUTSIDE ) && ( !infected( searchtri ) ) ) {
  9903. /* Infect the triangle. This is done by marking the triangle */
  9904. /* as infect and including the triangle in the virus pool. */
  9905. infect( searchtri );
  9906. holetri = (triangle **) poolalloc( &viri );
  9907. *holetri = searchtri.tri;
  9908. }
  9909. }
  9910. }
  9911. }
  9912. }
  9913. /* Now, we have to find all the regions BEFORE we carve the holes, because */
  9914. /* locate() won't work when the triangulation is no longer convex. */
  9915. /* (Incidentally, this is the reason why regional attributes and area */
  9916. /* constraints can't be used when refining a preexisting mesh, which */
  9917. /* might not be convex; they can only be used with a freshly */
  9918. /* triangulated PSLG.) */
  9919. if ( regions > 0 ) {
  9920. /* Find the starting triangle for each region. */
  9921. for ( i = 0; i < regions; i++ ) {
  9922. regiontris[i].tri = dummytri;
  9923. /* Ignore region points that aren't within the bounds of the mesh. */
  9924. if ( ( regionlist[4 * i] >= xmin ) && ( regionlist[4 * i] <= xmax ) &&
  9925. ( regionlist[4 * i + 1] >= ymin ) && ( regionlist[4 * i + 1] <= ymax ) ) {
  9926. /* Start searching from some triangle on the outer boundary. */
  9927. searchtri.tri = dummytri;
  9928. searchtri.orient = 0;
  9929. symself( searchtri );
  9930. /* Ensure that the region point is to the left of this boundary */
  9931. /* edge; otherwise, locate() will falsely report that the */
  9932. /* region point falls within the starting triangle. */
  9933. org( searchtri, searchorg );
  9934. dest( searchtri, searchdest );
  9935. if ( counterclockwise( searchorg, searchdest, &regionlist[4 * i] ) >
  9936. 0.0 ) {
  9937. /* Find a triangle that contains the region point. */
  9938. intersect = locate( &regionlist[4 * i], &searchtri );
  9939. if ( ( intersect != OUTSIDE ) && ( !infected( searchtri ) ) ) {
  9940. /* Record the triangle for processing after the */
  9941. /* holes have been carved. */
  9942. triedgecopy( searchtri, regiontris[i] );
  9943. }
  9944. }
  9945. }
  9946. }
  9947. }
  9948. if ( viri.items > 0 ) {
  9949. /* Carve the holes and concavities. */
  9950. plague();
  9951. }
  9952. /* The virus pool should be empty now. */
  9953. if ( regions > 0 ) {
  9954. if ( !quiet ) {
  9955. if ( regionattrib ) {
  9956. if ( vararea ) {
  9957. printf( "Spreading regional attributes and area constraints.\n" );
  9958. }
  9959. else {
  9960. printf( "Spreading regional attributes.\n" );
  9961. }
  9962. }
  9963. else {
  9964. printf( "Spreading regional area constraints.\n" );
  9965. }
  9966. }
  9967. if ( regionattrib && !refine ) {
  9968. /* Assign every triangle a regional attribute of zero. */
  9969. traversalinit( &triangles );
  9970. triangleloop.orient = 0;
  9971. triangleloop.tri = triangletraverse();
  9972. while ( triangleloop.tri != (triangle *) NULL ) {
  9973. setelemattribute( triangleloop, eextras, 0.0 );
  9974. triangleloop.tri = triangletraverse();
  9975. }
  9976. }
  9977. for ( i = 0; i < regions; i++ ) {
  9978. if ( regiontris[i].tri != dummytri ) {
  9979. /* Make sure the triangle under consideration still exists. */
  9980. /* It may have been eaten by the virus. */
  9981. if ( regiontris[i].tri[3] != (triangle) NULL ) {
  9982. /* Put one triangle in the virus pool. */
  9983. infect( regiontris[i] );
  9984. regiontri = (triangle **) poolalloc( &viri );
  9985. *regiontri = regiontris[i].tri;
  9986. /* Apply one region's attribute and/or area constraint. */
  9987. regionplague( regionlist[4 * i + 2], regionlist[4 * i + 3] );
  9988. /* The virus pool should be empty now. */
  9989. }
  9990. }
  9991. }
  9992. if ( regionattrib && !refine ) {
  9993. /* Note the fact that each triangle has an additional attribute. */
  9994. eextras++;
  9995. }
  9996. }
  9997. /* Free up memory. */
  9998. if ( ( ( holes > 0 ) && !noholes ) || !convex || ( regions > 0 ) ) {
  9999. pooldeinit( &viri );
  10000. }
  10001. if ( regions > 0 ) {
  10002. free( regiontris );
  10003. }
  10004. }
  10005. /** **/
  10006. /** **/
  10007. /********* Carving out holes and concavities ends here *********/
  10008. /********* Mesh quality maintenance begins here *********/
  10009. /** **/
  10010. /** **/
  10011. /*****************************************************************************/
  10012. /* */
  10013. /* tallyencs() Traverse the entire list of shell edges, check each edge */
  10014. /* to see if it is encroached. If so, add it to the list. */
  10015. /* */
  10016. /*****************************************************************************/
  10017. #ifndef CDT_ONLY
  10018. void tallyencs(){
  10019. struct edge edgeloop;
  10020. int dummy;
  10021. traversalinit( &shelles );
  10022. edgeloop.shorient = 0;
  10023. edgeloop.sh = shelletraverse();
  10024. while ( edgeloop.sh != (shelle *) NULL ) {
  10025. /* If the segment is encroached, add it to the list. */
  10026. dummy = checkedge4encroach( &edgeloop );
  10027. edgeloop.sh = shelletraverse();
  10028. }
  10029. }
  10030. #endif /* not CDT_ONLY */
  10031. /*****************************************************************************/
  10032. /* */
  10033. /* precisionerror() Print an error message for precision problems. */
  10034. /* */
  10035. /*****************************************************************************/
  10036. #ifndef CDT_ONLY
  10037. void precisionerror(){
  10038. printf( "Try increasing the area criterion and/or reducing the minimum\n" );
  10039. printf( " allowable angle so that tiny triangles are not created.\n" );
  10040. #ifdef SINGLE
  10041. printf( "Alternatively, try recompiling me with double precision\n" );
  10042. printf( " arithmetic (by removing \"#define SINGLE\" from the\n" );
  10043. printf( " source file or \"-DSINGLE\" from the makefile).\n" );
  10044. #endif /* SINGLE */
  10045. }
  10046. #endif /* not CDT_ONLY */
  10047. /*****************************************************************************/
  10048. /* */
  10049. /* repairencs() Find and repair all the encroached segments. */
  10050. /* */
  10051. /* Encroached segments are repaired by splitting them by inserting a point */
  10052. /* at or near their centers. */
  10053. /* */
  10054. /* `flaws' is a flag that specifies whether one should take note of new */
  10055. /* encroached segments and bad triangles that result from inserting points */
  10056. /* to repair existing encroached segments. */
  10057. /* */
  10058. /* When a segment is split, the two resulting subsegments are always */
  10059. /* tested to see if they are encroached upon, regardless of the value */
  10060. /* of `flaws'. */
  10061. /* */
  10062. /*****************************************************************************/
  10063. #ifndef CDT_ONLY
  10064. void repairencs( flaws )
  10065. int flaws;
  10066. {
  10067. struct triedge enctri;
  10068. struct triedge testtri;
  10069. struct edge *encloop;
  10070. struct edge testsh;
  10071. point eorg, edest;
  10072. point newpoint;
  10073. enum insertsiteresult success;
  10074. REAL segmentlength, nearestpoweroftwo;
  10075. REAL split;
  10076. int acuteorg, acutedest;
  10077. int dummy;
  10078. int i;
  10079. triangle ptr; /* Temporary variable used by stpivot(). */
  10080. shelle sptr; /* Temporary variable used by snext(). */
  10081. while ( ( badsegments.items > 0 ) && ( steinerleft != 0 ) ) {
  10082. traversalinit( &badsegments );
  10083. encloop = badsegmenttraverse();
  10084. while ( ( encloop != (struct edge *) NULL ) && ( steinerleft != 0 ) ) {
  10085. /* To decide where to split a segment, we need to know if the */
  10086. /* segment shares an endpoint with an adjacent segment. */
  10087. /* The concern is that, if we simply split every encroached */
  10088. /* segment in its center, two adjacent segments with a small */
  10089. /* angle between them might lead to an infinite loop; each */
  10090. /* point added to split one segment will encroach upon the */
  10091. /* other segment, which must then be split with a point that */
  10092. /* will encroach upon the first segment, and so on forever. */
  10093. /* To avoid this, imagine a set of concentric circles, whose */
  10094. /* radii are powers of two, about each segment endpoint. */
  10095. /* These concentric circles determine where the segment is */
  10096. /* split. (If both endpoints are shared with adjacent */
  10097. /* segments, split the segment in the middle, and apply the */
  10098. /* concentric shells for later splittings.) */
  10099. /* Is the origin shared with another segment? */
  10100. stpivot( *encloop, enctri );
  10101. lnext( enctri, testtri );
  10102. tspivot( testtri, testsh );
  10103. acuteorg = testsh.sh != dummysh;
  10104. /* Is the destination shared with another segment? */
  10105. lnextself( testtri );
  10106. tspivot( testtri, testsh );
  10107. acutedest = testsh.sh != dummysh;
  10108. /* Now, check the other side of the segment, if there's a triangle */
  10109. /* there. */
  10110. sym( enctri, testtri );
  10111. if ( testtri.tri != dummytri ) {
  10112. /* Is the destination shared with another segment? */
  10113. lnextself( testtri );
  10114. tspivot( testtri, testsh );
  10115. acutedest = acutedest || ( testsh.sh != dummysh );
  10116. /* Is the origin shared with another segment? */
  10117. lnextself( testtri );
  10118. tspivot( testtri, testsh );
  10119. acuteorg = acuteorg || ( testsh.sh != dummysh );
  10120. }
  10121. sorg( *encloop, eorg );
  10122. sdest( *encloop, edest );
  10123. /* Use the concentric circles if exactly one endpoint is shared */
  10124. /* with another adjacent segment. */
  10125. if ( acuteorg ^ acutedest ) {
  10126. segmentlength = sqrt( ( edest[0] - eorg[0] ) * ( edest[0] - eorg[0] )
  10127. + ( edest[1] - eorg[1] ) * ( edest[1] - eorg[1] ) );
  10128. /* Find the power of two nearest the segment's length. */
  10129. nearestpoweroftwo = 1.0;
  10130. while ( segmentlength > SQUAREROOTTWO * nearestpoweroftwo ) {
  10131. nearestpoweroftwo *= 2.0;
  10132. }
  10133. while ( segmentlength < ( 0.5 * SQUAREROOTTWO ) * nearestpoweroftwo ) {
  10134. nearestpoweroftwo *= 0.5;
  10135. }
  10136. /* Where do we split the segment? */
  10137. split = 0.5 * nearestpoweroftwo / segmentlength;
  10138. if ( acutedest ) {
  10139. split = 1.0 - split;
  10140. }
  10141. }
  10142. else {
  10143. /* If we're not worried about adjacent segments, split */
  10144. /* this segment in the middle. */
  10145. split = 0.5;
  10146. }
  10147. /* Create the new point. */
  10148. newpoint = (point) poolalloc( &points );
  10149. /* Interpolate its coordinate and attributes. */
  10150. for ( i = 0; i < 2 + nextras; i++ ) {
  10151. newpoint[i] = ( 1.0 - split ) * eorg[i] + split * edest[i];
  10152. }
  10153. setpointmark( newpoint, mark( *encloop ) );
  10154. if ( verbose > 1 ) {
  10155. printf(
  10156. " Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
  10157. eorg[0], eorg[1], edest[0], edest[1], newpoint[0], newpoint[1] );
  10158. }
  10159. /* Check whether the new point lies on an endpoint. */
  10160. if ( ( ( newpoint[0] == eorg[0] ) && ( newpoint[1] == eorg[1] ) )
  10161. || ( ( newpoint[0] == edest[0] ) && ( newpoint[1] == edest[1] ) ) ) {
  10162. printf( "Error: Ran out of precision at (%.12g, %.12g).\n",
  10163. newpoint[0], newpoint[1] );
  10164. printf( "I attempted to split a segment to a smaller size than can\n" );
  10165. printf( " be accommodated by the finite precision of floating point\n"
  10166. );
  10167. printf( " arithmetic.\n" );
  10168. precisionerror();
  10169. exit( 1 );
  10170. }
  10171. /* Insert the splitting point. This should always succeed. */
  10172. success = insertsite( newpoint, &enctri, encloop, flaws, flaws );
  10173. if ( ( success != SUCCESSFULPOINT ) && ( success != ENCROACHINGPOINT ) ) {
  10174. printf( "Internal error in repairencs():\n" );
  10175. printf( " Failure to split a segment.\n" );
  10176. internalerror();
  10177. }
  10178. if ( steinerleft > 0 ) {
  10179. steinerleft--;
  10180. }
  10181. /* Check the two new subsegments to see if they're encroached. */
  10182. dummy = checkedge4encroach( encloop );
  10183. snextself( *encloop );
  10184. dummy = checkedge4encroach( encloop );
  10185. badsegmentdealloc( encloop );
  10186. encloop = badsegmenttraverse();
  10187. }
  10188. }
  10189. }
  10190. #endif /* not CDT_ONLY */
  10191. /*****************************************************************************/
  10192. /* */
  10193. /* tallyfaces() Test every triangle in the mesh for quality measures. */
  10194. /* */
  10195. /*****************************************************************************/
  10196. #ifndef CDT_ONLY
  10197. void tallyfaces(){
  10198. struct triedge triangleloop;
  10199. if ( verbose ) {
  10200. printf( " Making a list of bad triangles.\n" );
  10201. }
  10202. traversalinit( &triangles );
  10203. triangleloop.orient = 0;
  10204. triangleloop.tri = triangletraverse();
  10205. while ( triangleloop.tri != (triangle *) NULL ) {
  10206. /* If the triangle is bad, enqueue it. */
  10207. testtriangle( &triangleloop );
  10208. triangleloop.tri = triangletraverse();
  10209. }
  10210. }
  10211. #endif /* not CDT_ONLY */
  10212. /*****************************************************************************/
  10213. /* */
  10214. /* findcircumcenter() Find the circumcenter of a triangle. */
  10215. /* */
  10216. /* The result is returned both in terms of x-y coordinates and xi-eta */
  10217. /* coordinates. The xi-eta coordinate system is defined in terms of the */
  10218. /* triangle: the origin of the triangle is the origin of the coordinate */
  10219. /* system; the destination of the triangle is one unit along the xi axis; */
  10220. /* and the apex of the triangle is one unit along the eta axis. */
  10221. /* */
  10222. /* The return value indicates which edge of the triangle is shortest. */
  10223. /* */
  10224. /*****************************************************************************/
  10225. enum circumcenterresult findcircumcenter( torg, tdest, tapex, circumcenter,
  10226. xi, eta )
  10227. point torg;
  10228. point tdest;
  10229. point tapex;
  10230. point circumcenter;
  10231. REAL *xi;
  10232. REAL *eta;
  10233. {
  10234. REAL xdo, ydo, xao, yao, xad, yad;
  10235. REAL dodist, aodist, addist;
  10236. REAL denominator;
  10237. REAL dx, dy;
  10238. circumcentercount++;
  10239. /* Compute the circumcenter of the triangle. */
  10240. xdo = tdest[0] - torg[0];
  10241. ydo = tdest[1] - torg[1];
  10242. xao = tapex[0] - torg[0];
  10243. yao = tapex[1] - torg[1];
  10244. dodist = xdo * xdo + ydo * ydo;
  10245. aodist = xao * xao + yao * yao;
  10246. if ( noexact ) {
  10247. denominator = (REAL)( 0.5 / ( xdo * yao - xao * ydo ) );
  10248. }
  10249. else {
  10250. /* Use the counterclockwise() routine to ensure a positive (and */
  10251. /* reasonably accurate) result, avoiding any possibility of */
  10252. /* division by zero. */
  10253. denominator = (REAL)( 0.5 / counterclockwise( tdest, tapex, torg ) );
  10254. /* Don't count the above as an orientation test. */
  10255. counterclockcount--;
  10256. }
  10257. circumcenter[0] = torg[0] - ( ydo * aodist - yao * dodist ) * denominator;
  10258. circumcenter[1] = torg[1] + ( xdo * aodist - xao * dodist ) * denominator;
  10259. /* To interpolate point attributes for the new point inserted at */
  10260. /* the circumcenter, define a coordinate system with a xi-axis, */
  10261. /* directed from the triangle's origin to its destination, and */
  10262. /* an eta-axis, directed from its origin to its apex. */
  10263. /* Calculate the xi and eta coordinates of the circumcenter. */
  10264. dx = circumcenter[0] - torg[0];
  10265. dy = circumcenter[1] - torg[1];
  10266. *xi = (REAL)( ( dx * yao - xao * dy ) * ( 2.0 * denominator ) );
  10267. *eta = (REAL)( ( xdo * dy - dx * ydo ) * ( 2.0 * denominator ) );
  10268. xad = tapex[0] - tdest[0];
  10269. yad = tapex[1] - tdest[1];
  10270. addist = xad * xad + yad * yad;
  10271. if ( ( addist < dodist ) && ( addist < aodist ) ) {
  10272. return OPPOSITEORG;
  10273. }
  10274. else if ( dodist < aodist ) {
  10275. return OPPOSITEAPEX;
  10276. }
  10277. else {
  10278. return OPPOSITEDEST;
  10279. }
  10280. }
  10281. /*****************************************************************************/
  10282. /* */
  10283. /* splittriangle() Inserts a point at the circumcenter of a triangle. */
  10284. /* Deletes the newly inserted point if it encroaches upon */
  10285. /* a segment. */
  10286. /* */
  10287. /*****************************************************************************/
  10288. #ifndef CDT_ONLY
  10289. void splittriangle( badtri )
  10290. struct badface *badtri;
  10291. {
  10292. point borg, bdest, bapex;
  10293. point newpoint;
  10294. REAL xi, eta;
  10295. enum insertsiteresult success;
  10296. enum circumcenterresult shortedge;
  10297. int errorflag;
  10298. int i;
  10299. org( badtri->badfacetri, borg );
  10300. dest( badtri->badfacetri, bdest );
  10301. apex( badtri->badfacetri, bapex );
  10302. /* Make sure that this triangle is still the same triangle it was */
  10303. /* when it was tested and determined to be of bad quality. */
  10304. /* Subsequent transformations may have made it a different triangle. */
  10305. if ( ( borg == badtri->faceorg ) && ( bdest == badtri->facedest ) &&
  10306. ( bapex == badtri->faceapex ) ) {
  10307. if ( verbose > 1 ) {
  10308. printf( " Splitting this triangle at its circumcenter:\n" );
  10309. printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
  10310. borg[1], bdest[0], bdest[1], bapex[0], bapex[1] );
  10311. }
  10312. errorflag = 0;
  10313. /* Create a new point at the triangle's circumcenter. */
  10314. newpoint = (point) poolalloc( &points );
  10315. shortedge = findcircumcenter( borg, bdest, bapex, newpoint, &xi, &eta );
  10316. /* Check whether the new point lies on a triangle vertex. */
  10317. if ( ( ( newpoint[0] == borg[0] ) && ( newpoint[1] == borg[1] ) )
  10318. || ( ( newpoint[0] == bdest[0] ) && ( newpoint[1] == bdest[1] ) )
  10319. || ( ( newpoint[0] == bapex[0] ) && ( newpoint[1] == bapex[1] ) ) ) {
  10320. if ( !quiet ) {
  10321. printf( "Warning: New point (%.12g, %.12g) falls on existing vertex.\n"
  10322. , newpoint[0], newpoint[1] );
  10323. errorflag = 1;
  10324. }
  10325. pointdealloc( newpoint );
  10326. }
  10327. else {
  10328. for ( i = 2; i < 2 + nextras; i++ ) {
  10329. /* Interpolate the point attributes at the circumcenter. */
  10330. newpoint[i] = borg[i] + xi * ( bdest[i] - borg[i] )
  10331. + eta * ( bapex[i] - borg[i] );
  10332. }
  10333. /* The new point must be in the interior, and have a marker of zero. */
  10334. setpointmark( newpoint, 0 );
  10335. /* Ensure that the handle `badtri->badfacetri' represents the shortest */
  10336. /* edge of the triangle. This ensures that the circumcenter must */
  10337. /* fall to the left of this edge, so point location will work. */
  10338. if ( shortedge == OPPOSITEORG ) {
  10339. lnextself( badtri->badfacetri );
  10340. }
  10341. else if ( shortedge == OPPOSITEDEST ) {
  10342. lprevself( badtri->badfacetri );
  10343. }
  10344. /* Insert the circumcenter, searching from the edge of the triangle, */
  10345. /* and maintain the Delaunay property of the triangulation. */
  10346. success = insertsite( newpoint, &( badtri->badfacetri ),
  10347. (struct edge *) NULL, 1, 1 );
  10348. if ( success == SUCCESSFULPOINT ) {
  10349. if ( steinerleft > 0 ) {
  10350. steinerleft--;
  10351. }
  10352. }
  10353. else if ( success == ENCROACHINGPOINT ) {
  10354. /* If the newly inserted point encroaches upon a segment, delete it. */
  10355. deletesite( &( badtri->badfacetri ) );
  10356. }
  10357. else if ( success == VIOLATINGPOINT ) {
  10358. /* Failed to insert the new point, but some segment was */
  10359. /* marked as being encroached. */
  10360. pointdealloc( newpoint );
  10361. }
  10362. else { /* success == DUPLICATEPOINT */
  10363. /* Failed to insert the new point because a vertex is already there. */
  10364. if ( !quiet ) {
  10365. printf(
  10366. "Warning: New point (%.12g, %.12g) falls on existing vertex.\n"
  10367. , newpoint[0], newpoint[1] );
  10368. errorflag = 1;
  10369. }
  10370. pointdealloc( newpoint );
  10371. }
  10372. }
  10373. if ( errorflag ) {
  10374. if ( verbose ) {
  10375. printf( " The new point is at the circumcenter of triangle\n" );
  10376. printf( " (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
  10377. borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1] );
  10378. }
  10379. printf( "This probably means that I am trying to refine triangles\n" );
  10380. printf( " to a smaller size than can be accommodated by the finite\n" );
  10381. printf( " precision of floating point arithmetic. (You can be\n" );
  10382. printf( " sure of this if I fail to terminate.)\n" );
  10383. precisionerror();
  10384. }
  10385. }
  10386. /* Return the bad triangle to the pool. */
  10387. pooldealloc( &badtriangles, (VOID *) badtri );
  10388. }
  10389. #endif /* not CDT_ONLY */
  10390. /*****************************************************************************/
  10391. /* */
  10392. /* enforcequality() Remove all the encroached edges and bad triangles */
  10393. /* from the triangulation. */
  10394. /* */
  10395. /*****************************************************************************/
  10396. #ifndef CDT_ONLY
  10397. void enforcequality(){
  10398. int i;
  10399. if ( !quiet ) {
  10400. printf( "Adding Steiner points to enforce quality.\n" );
  10401. }
  10402. /* Initialize the pool of encroached segments. */
  10403. poolinit( &badsegments, sizeof( struct edge ), BADSEGMENTPERBLOCK, POINTER, 0 );
  10404. if ( verbose ) {
  10405. printf( " Looking for encroached segments.\n" );
  10406. }
  10407. /* Test all segments to see if they're encroached. */
  10408. tallyencs();
  10409. if ( verbose && ( badsegments.items > 0 ) ) {
  10410. printf( " Splitting encroached segments.\n" );
  10411. }
  10412. /* Note that steinerleft == -1 if an unlimited number */
  10413. /* of Steiner points is allowed. */
  10414. while ( ( badsegments.items > 0 ) && ( steinerleft != 0 ) ) {
  10415. /* Fix the segments without noting newly encroached segments or */
  10416. /* bad triangles. The reason we don't want to note newly */
  10417. /* encroached segments is because some encroached segments are */
  10418. /* likely to be noted multiple times, and would then be blindly */
  10419. /* split multiple times. I should fix that some time. */
  10420. repairencs( 0 );
  10421. /* Now, find all the segments that became encroached while adding */
  10422. /* points to split encroached segments. */
  10423. tallyencs();
  10424. }
  10425. /* At this point, if we haven't run out of Steiner points, the */
  10426. /* triangulation should be (conforming) Delaunay. */
  10427. /* Next, we worry about enforcing triangle quality. */
  10428. if ( ( minangle > 0.0 ) || vararea || fixedarea ) {
  10429. /* Initialize the pool of bad triangles. */
  10430. poolinit( &badtriangles, sizeof( struct badface ), BADTRIPERBLOCK, POINTER,
  10431. 0 );
  10432. /* Initialize the queues of bad triangles. */
  10433. for ( i = 0; i < 64; i++ ) {
  10434. queuefront[i] = (struct badface *) NULL;
  10435. queuetail[i] = &queuefront[i];
  10436. }
  10437. /* Test all triangles to see if they're bad. */
  10438. tallyfaces();
  10439. if ( verbose ) {
  10440. printf( " Splitting bad triangles.\n" );
  10441. }
  10442. while ( ( badtriangles.items > 0 ) && ( steinerleft != 0 ) ) {
  10443. /* Fix one bad triangle by inserting a point at its circumcenter. */
  10444. splittriangle( dequeuebadtri() );
  10445. /* Fix any encroached segments that may have resulted. Record */
  10446. /* any new bad triangles or encroached segments that result. */
  10447. if ( badsegments.items > 0 ) {
  10448. repairencs( 1 );
  10449. }
  10450. }
  10451. }
  10452. /* At this point, if we haven't run out of Steiner points, the */
  10453. /* triangulation should be (conforming) Delaunay and have no */
  10454. /* low-quality triangles. */
  10455. /* Might we have run out of Steiner points too soon? */
  10456. if ( !quiet && ( badsegments.items > 0 ) && ( steinerleft == 0 ) ) {
  10457. printf( "\nWarning: I ran out of Steiner points, but the mesh has\n" );
  10458. if ( badsegments.items == 1 ) {
  10459. printf( " an encroached segment, and therefore might not be truly\n" );
  10460. }
  10461. else {
  10462. printf( " %ld encroached segments, and therefore might not be truly\n",
  10463. badsegments.items );
  10464. }
  10465. printf( " Delaunay. If the Delaunay property is important to you,\n" );
  10466. printf( " try increasing the number of Steiner points (controlled by\n" );
  10467. printf( " the -S switch) slightly and try again.\n\n" );
  10468. }
  10469. }
  10470. #endif /* not CDT_ONLY */
  10471. /** **/
  10472. /** **/
  10473. /********* Mesh quality maintenance ends here *********/
  10474. /*****************************************************************************/
  10475. /* */
  10476. /* highorder() Create extra nodes for quadratic subparametric elements. */
  10477. /* */
  10478. /*****************************************************************************/
  10479. void highorder(){
  10480. struct triedge triangleloop, trisym;
  10481. struct edge checkmark;
  10482. point newpoint;
  10483. point torg, tdest;
  10484. int i;
  10485. triangle ptr; /* Temporary variable used by sym(). */
  10486. shelle sptr; /* Temporary variable used by tspivot(). */
  10487. if ( !quiet ) {
  10488. printf( "Adding vertices for second-order triangles.\n" );
  10489. }
  10490. /* The following line ensures that dead items in the pool of nodes */
  10491. /* cannot be allocated for the extra nodes associated with high */
  10492. /* order elements. This ensures that the primary nodes (at the */
  10493. /* corners of elements) will occur earlier in the output files, and */
  10494. /* have lower indices, than the extra nodes. */
  10495. points.deaditemstack = (VOID *) NULL;
  10496. traversalinit( &triangles );
  10497. triangleloop.tri = triangletraverse();
  10498. /* To loop over the set of edges, loop over all triangles, and look at */
  10499. /* the three edges of each triangle. If there isn't another triangle */
  10500. /* adjacent to the edge, operate on the edge. If there is another */
  10501. /* adjacent triangle, operate on the edge only if the current triangle */
  10502. /* has a smaller pointer than its neighbor. This way, each edge is */
  10503. /* considered only once. */
  10504. while ( triangleloop.tri != (triangle *) NULL ) {
  10505. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  10506. triangleloop.orient++ ) {
  10507. sym( triangleloop, trisym );
  10508. if ( ( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri ) ) {
  10509. org( triangleloop, torg );
  10510. dest( triangleloop, tdest );
  10511. /* Create a new node in the middle of the edge. Interpolate */
  10512. /* its attributes. */
  10513. newpoint = (point) poolalloc( &points );
  10514. for ( i = 0; i < 2 + nextras; i++ ) {
  10515. newpoint[i] = (REAL)( 0.5 * ( torg[i] + tdest[i] ) );
  10516. }
  10517. /* Set the new node's marker to zero or one, depending on */
  10518. /* whether it lies on a boundary. */
  10519. setpointmark( newpoint, trisym.tri == dummytri );
  10520. if ( useshelles ) {
  10521. tspivot( triangleloop, checkmark );
  10522. /* If this edge is a segment, transfer the marker to the new node. */
  10523. if ( checkmark.sh != dummysh ) {
  10524. setpointmark( newpoint, mark( checkmark ) );
  10525. }
  10526. }
  10527. if ( verbose > 1 ) {
  10528. printf( " Creating (%.12g, %.12g).\n", newpoint[0], newpoint[1] );
  10529. }
  10530. /* Record the new node in the (one or two) adjacent elements. */
  10531. triangleloop.tri[highorderindex + triangleloop.orient] =
  10532. (triangle) newpoint;
  10533. if ( trisym.tri != dummytri ) {
  10534. trisym.tri[highorderindex + trisym.orient] = (triangle) newpoint;
  10535. }
  10536. }
  10537. }
  10538. triangleloop.tri = triangletraverse();
  10539. }
  10540. }
  10541. /********* File I/O routines begin here *********/
  10542. /** **/
  10543. /** **/
  10544. /*****************************************************************************/
  10545. /* */
  10546. /* readline() Read a nonempty line from a file. */
  10547. /* */
  10548. /* A line is considered "nonempty" if it contains something that looks like */
  10549. /* a number. */
  10550. /* */
  10551. /*****************************************************************************/
  10552. #ifndef TRILIBRARY
  10553. char *readline( string, infile, infilename )
  10554. char *string;
  10555. FILE *infile;
  10556. char *infilename;
  10557. {
  10558. char *result;
  10559. /* Search for something that looks like a number. */
  10560. do {
  10561. result = fgets( string, INPUTLINESIZE, infile );
  10562. if ( result == (char *) NULL ) {
  10563. printf( " Error: Unexpected end of file in %s.\n", infilename );
  10564. exit( 1 );
  10565. }
  10566. /* Skip anything that doesn't look like a number, a comment, */
  10567. /* or the end of a line. */
  10568. while ( ( *result != '\0' ) && ( *result != '#' )
  10569. && ( *result != '.' ) && ( *result != '+' ) && ( *result != '-' )
  10570. && ( ( *result < '0' ) || ( *result > '9' ) ) ) {
  10571. result++;
  10572. }
  10573. /* If it's a comment or end of line, read another line and try again. */
  10574. } while ( ( *result == '#' ) || ( *result == '\0' ) );
  10575. return result;
  10576. }
  10577. #endif /* not TRILIBRARY */
  10578. /*****************************************************************************/
  10579. /* */
  10580. /* findfield() Find the next field of a string. */
  10581. /* */
  10582. /* Jumps past the current field by searching for whitespace, then jumps */
  10583. /* past the whitespace to find the next field. */
  10584. /* */
  10585. /*****************************************************************************/
  10586. #ifndef TRILIBRARY
  10587. char *findfield( string )
  10588. char *string;
  10589. {
  10590. char *result;
  10591. result = string;
  10592. /* Skip the current field. Stop upon reaching whitespace. */
  10593. while ( ( *result != '\0' ) && ( *result != '#' )
  10594. && ( *result != ' ' ) && ( *result != '\t' ) ) {
  10595. result++;
  10596. }
  10597. /* Now skip the whitespace and anything else that doesn't look like a */
  10598. /* number, a comment, or the end of a line. */
  10599. while ( ( *result != '\0' ) && ( *result != '#' )
  10600. && ( *result != '.' ) && ( *result != '+' ) && ( *result != '-' )
  10601. && ( ( *result < '0' ) || ( *result > '9' ) ) ) {
  10602. result++;
  10603. }
  10604. /* Check for a comment (prefixed with `#'). */
  10605. if ( *result == '#' ) {
  10606. *result = '\0';
  10607. }
  10608. return result;
  10609. }
  10610. #endif /* not TRILIBRARY */
  10611. /*****************************************************************************/
  10612. /* */
  10613. /* readnodes() Read the points from a file, which may be a .node or .poly */
  10614. /* file. */
  10615. /* */
  10616. /*****************************************************************************/
  10617. #ifndef TRILIBRARY
  10618. void readnodes( nodefilename, polyfilename, polyfile )
  10619. char *nodefilename;
  10620. char *polyfilename;
  10621. FILE **polyfile;
  10622. {
  10623. FILE *infile;
  10624. point pointloop;
  10625. char inputline[INPUTLINESIZE];
  10626. char *stringptr;
  10627. char *infilename;
  10628. REAL x, y;
  10629. int firstnode;
  10630. int nodemarkers;
  10631. int currentmarker;
  10632. int i, j;
  10633. if ( poly ) {
  10634. /* Read the points from a .poly file. */
  10635. if ( !quiet ) {
  10636. printf( "Opening %s.\n", polyfilename );
  10637. }
  10638. *polyfile = fopen( polyfilename, "r" );
  10639. if ( *polyfile == (FILE *) NULL ) {
  10640. printf( " Error: Cannot access file %s.\n", polyfilename );
  10641. exit( 1 );
  10642. }
  10643. /* Read number of points, number of dimensions, number of point */
  10644. /* attributes, and number of boundary markers. */
  10645. stringptr = readline( inputline, *polyfile, polyfilename );
  10646. inpoints = (int) strtol( stringptr, &stringptr, 0 );
  10647. stringptr = findfield( stringptr );
  10648. if ( *stringptr == '\0' ) {
  10649. mesh_dim = 2;
  10650. }
  10651. else {
  10652. mesh_dim = (int) strtol( stringptr, &stringptr, 0 );
  10653. }
  10654. stringptr = findfield( stringptr );
  10655. if ( *stringptr == '\0' ) {
  10656. nextras = 0;
  10657. }
  10658. else {
  10659. nextras = (int) strtol( stringptr, &stringptr, 0 );
  10660. }
  10661. stringptr = findfield( stringptr );
  10662. if ( *stringptr == '\0' ) {
  10663. nodemarkers = 0;
  10664. }
  10665. else {
  10666. nodemarkers = (int) strtol( stringptr, &stringptr, 0 );
  10667. }
  10668. if ( inpoints > 0 ) {
  10669. infile = *polyfile;
  10670. infilename = polyfilename;
  10671. readnodefile = 0;
  10672. }
  10673. else {
  10674. /* If the .poly file claims there are zero points, that means that */
  10675. /* the points should be read from a separate .node file. */
  10676. readnodefile = 1;
  10677. infilename = innodefilename;
  10678. }
  10679. }
  10680. else {
  10681. readnodefile = 1;
  10682. infilename = innodefilename;
  10683. *polyfile = (FILE *) NULL;
  10684. }
  10685. if ( readnodefile ) {
  10686. /* Read the points from a .node file. */
  10687. if ( !quiet ) {
  10688. printf( "Opening %s.\n", innodefilename );
  10689. }
  10690. infile = fopen( innodefilename, "r" );
  10691. if ( infile == (FILE *) NULL ) {
  10692. printf( " Error: Cannot access file %s.\n", innodefilename );
  10693. exit( 1 );
  10694. }
  10695. /* Read number of points, number of dimensions, number of point */
  10696. /* attributes, and number of boundary markers. */
  10697. stringptr = readline( inputline, infile, innodefilename );
  10698. inpoints = (int) strtol( stringptr, &stringptr, 0 );
  10699. stringptr = findfield( stringptr );
  10700. if ( *stringptr == '\0' ) {
  10701. mesh_dim = 2;
  10702. }
  10703. else {
  10704. mesh_dim = (int) strtol( stringptr, &stringptr, 0 );
  10705. }
  10706. stringptr = findfield( stringptr );
  10707. if ( *stringptr == '\0' ) {
  10708. nextras = 0;
  10709. }
  10710. else {
  10711. nextras = (int) strtol( stringptr, &stringptr, 0 );
  10712. }
  10713. stringptr = findfield( stringptr );
  10714. if ( *stringptr == '\0' ) {
  10715. nodemarkers = 0;
  10716. }
  10717. else {
  10718. nodemarkers = (int) strtol( stringptr, &stringptr, 0 );
  10719. }
  10720. }
  10721. if ( inpoints < 3 ) {
  10722. printf( "Error: Input must have at least three input points.\n" );
  10723. exit( 1 );
  10724. }
  10725. if ( mesh_dim != 2 ) {
  10726. printf( "Error: Triangle only works with two-dimensional meshes.\n" );
  10727. exit( 1 );
  10728. }
  10729. initializepointpool();
  10730. /* Read the points. */
  10731. for ( i = 0; i < inpoints; i++ ) {
  10732. pointloop = (point) poolalloc( &points );
  10733. stringptr = readline( inputline, infile, infilename );
  10734. if ( i == 0 ) {
  10735. firstnode = (int) strtol( stringptr, &stringptr, 0 );
  10736. if ( ( firstnode == 0 ) || ( firstnode == 1 ) ) {
  10737. firstnumber = firstnode;
  10738. }
  10739. }
  10740. stringptr = findfield( stringptr );
  10741. if ( *stringptr == '\0' ) {
  10742. printf( "Error: Point %d has no x coordinate.\n", firstnumber + i );
  10743. exit( 1 );
  10744. }
  10745. x = (REAL) strtod( stringptr, &stringptr );
  10746. stringptr = findfield( stringptr );
  10747. if ( *stringptr == '\0' ) {
  10748. printf( "Error: Point %d has no y coordinate.\n", firstnumber + i );
  10749. exit( 1 );
  10750. }
  10751. y = (REAL) strtod( stringptr, &stringptr );
  10752. pointloop[0] = x;
  10753. pointloop[1] = y;
  10754. /* Read the point attributes. */
  10755. for ( j = 2; j < 2 + nextras; j++ ) {
  10756. stringptr = findfield( stringptr );
  10757. if ( *stringptr == '\0' ) {
  10758. pointloop[j] = 0.0;
  10759. }
  10760. else {
  10761. pointloop[j] = (REAL) strtod( stringptr, &stringptr );
  10762. }
  10763. }
  10764. if ( nodemarkers ) {
  10765. /* Read a point marker. */
  10766. stringptr = findfield( stringptr );
  10767. if ( *stringptr == '\0' ) {
  10768. setpointmark( pointloop, 0 );
  10769. }
  10770. else {
  10771. currentmarker = (int) strtol( stringptr, &stringptr, 0 );
  10772. setpointmark( pointloop, currentmarker );
  10773. }
  10774. }
  10775. else {
  10776. /* If no markers are specified in the file, they default to zero. */
  10777. setpointmark( pointloop, 0 );
  10778. }
  10779. /* Determine the smallest and largest x and y coordinates. */
  10780. if ( i == 0 ) {
  10781. xmin = xmax = x;
  10782. ymin = ymax = y;
  10783. }
  10784. else {
  10785. xmin = ( x < xmin ) ? x : xmin;
  10786. xmax = ( x > xmax ) ? x : xmax;
  10787. ymin = ( y < ymin ) ? y : ymin;
  10788. ymax = ( y > ymax ) ? y : ymax;
  10789. }
  10790. }
  10791. if ( readnodefile ) {
  10792. fclose( infile );
  10793. }
  10794. /* Nonexistent x value used as a flag to mark circle events in sweepline */
  10795. /* Delaunay algorithm. */
  10796. xminextreme = 10 * xmin - 9 * xmax;
  10797. }
  10798. #endif /* not TRILIBRARY */
  10799. /*****************************************************************************/
  10800. /* */
  10801. /* transfernodes() Read the points from memory. */
  10802. /* */
  10803. /*****************************************************************************/
  10804. #ifdef TRILIBRARY
  10805. void transfernodes( pointlist, pointattriblist, pointmarkerlist, numberofpoints,
  10806. numberofpointattribs )
  10807. REAL * pointlist;
  10808. REAL *pointattriblist;
  10809. int *pointmarkerlist;
  10810. int numberofpoints;
  10811. int numberofpointattribs;
  10812. {
  10813. point pointloop;
  10814. REAL x, y;
  10815. int i, j;
  10816. int coordindex;
  10817. int attribindex;
  10818. inpoints = numberofpoints;
  10819. mesh_dim = 2;
  10820. nextras = numberofpointattribs;
  10821. readnodefile = 0;
  10822. if ( inpoints < 3 ) {
  10823. printf( "Error: Input must have at least three input points.\n" );
  10824. exit( 1 );
  10825. }
  10826. initializepointpool();
  10827. /* Read the points. */
  10828. coordindex = 0;
  10829. attribindex = 0;
  10830. for ( i = 0; i < inpoints; i++ ) {
  10831. pointloop = (point) poolalloc( &points );
  10832. /* Read the point coordinates. */
  10833. x = pointloop[0] = pointlist[coordindex++];
  10834. y = pointloop[1] = pointlist[coordindex++];
  10835. /* Read the point attributes. */
  10836. for ( j = 0; j < numberofpointattribs; j++ ) {
  10837. pointloop[2 + j] = pointattriblist[attribindex++];
  10838. }
  10839. if ( pointmarkerlist != (int *) NULL ) {
  10840. /* Read a point marker. */
  10841. setpointmark( pointloop, pointmarkerlist[i] );
  10842. }
  10843. else {
  10844. /* If no markers are specified, they default to zero. */
  10845. setpointmark( pointloop, 0 );
  10846. }
  10847. x = pointloop[0];
  10848. y = pointloop[1];
  10849. /* Determine the smallest and largest x and y coordinates. */
  10850. if ( i == 0 ) {
  10851. xmin = xmax = x;
  10852. ymin = ymax = y;
  10853. }
  10854. else {
  10855. xmin = ( x < xmin ) ? x : xmin;
  10856. xmax = ( x > xmax ) ? x : xmax;
  10857. ymin = ( y < ymin ) ? y : ymin;
  10858. ymax = ( y > ymax ) ? y : ymax;
  10859. }
  10860. }
  10861. /* Nonexistent x value used as a flag to mark circle events in sweepline */
  10862. /* Delaunay algorithm. */
  10863. xminextreme = 10 * xmin - 9 * xmax;
  10864. }
  10865. #endif /* TRILIBRARY */
  10866. /*****************************************************************************/
  10867. /* */
  10868. /* readholes() Read the holes, and possibly regional attributes and area */
  10869. /* constraints, from a .poly file. */
  10870. /* */
  10871. /*****************************************************************************/
  10872. #ifndef TRILIBRARY
  10873. void readholes( polyfile, polyfilename, hlist, holes, rlist, regions )
  10874. FILE * polyfile;
  10875. char *polyfilename;
  10876. REAL **hlist;
  10877. int *holes;
  10878. REAL **rlist;
  10879. int *regions;
  10880. {
  10881. REAL *holelist;
  10882. REAL *regionlist;
  10883. char inputline[INPUTLINESIZE];
  10884. char *stringptr;
  10885. int index;
  10886. int i;
  10887. /* Read the holes. */
  10888. stringptr = readline( inputline, polyfile, polyfilename );
  10889. *holes = (int) strtol( stringptr, &stringptr, 0 );
  10890. if ( *holes > 0 ) {
  10891. holelist = (REAL *) malloc( 2 * *holes * sizeof( REAL ) );
  10892. *hlist = holelist;
  10893. if ( holelist == (REAL *) NULL ) {
  10894. printf( "Error: Out of memory.\n" );
  10895. exit( 1 );
  10896. }
  10897. for ( i = 0; i < 2 * *holes; i += 2 ) {
  10898. stringptr = readline( inputline, polyfile, polyfilename );
  10899. stringptr = findfield( stringptr );
  10900. if ( *stringptr == '\0' ) {
  10901. printf( "Error: Hole %d has no x coordinate.\n",
  10902. firstnumber + ( i >> 1 ) );
  10903. exit( 1 );
  10904. }
  10905. else {
  10906. holelist[i] = (REAL) strtod( stringptr, &stringptr );
  10907. }
  10908. stringptr = findfield( stringptr );
  10909. if ( *stringptr == '\0' ) {
  10910. printf( "Error: Hole %d has no y coordinate.\n",
  10911. firstnumber + ( i >> 1 ) );
  10912. exit( 1 );
  10913. }
  10914. else {
  10915. holelist[i + 1] = (REAL) strtod( stringptr, &stringptr );
  10916. }
  10917. }
  10918. }
  10919. else {
  10920. *hlist = (REAL *) NULL;
  10921. }
  10922. #ifndef CDT_ONLY
  10923. if ( ( regionattrib || vararea ) && !refine ) {
  10924. /* Read the area constraints. */
  10925. stringptr = readline( inputline, polyfile, polyfilename );
  10926. *regions = (int) strtol( stringptr, &stringptr, 0 );
  10927. if ( *regions > 0 ) {
  10928. regionlist = (REAL *) malloc( 4 * *regions * sizeof( REAL ) );
  10929. *rlist = regionlist;
  10930. if ( regionlist == (REAL *) NULL ) {
  10931. printf( "Error: Out of memory.\n" );
  10932. exit( 1 );
  10933. }
  10934. index = 0;
  10935. for ( i = 0; i < *regions; i++ ) {
  10936. stringptr = readline( inputline, polyfile, polyfilename );
  10937. stringptr = findfield( stringptr );
  10938. if ( *stringptr == '\0' ) {
  10939. printf( "Error: Region %d has no x coordinate.\n",
  10940. firstnumber + i );
  10941. exit( 1 );
  10942. }
  10943. else {
  10944. regionlist[index++] = (REAL) strtod( stringptr, &stringptr );
  10945. }
  10946. stringptr = findfield( stringptr );
  10947. if ( *stringptr == '\0' ) {
  10948. printf( "Error: Region %d has no y coordinate.\n",
  10949. firstnumber + i );
  10950. exit( 1 );
  10951. }
  10952. else {
  10953. regionlist[index++] = (REAL) strtod( stringptr, &stringptr );
  10954. }
  10955. stringptr = findfield( stringptr );
  10956. if ( *stringptr == '\0' ) {
  10957. printf(
  10958. "Error: Region %d has no region attribute or area constraint.\n",
  10959. firstnumber + i );
  10960. exit( 1 );
  10961. }
  10962. else {
  10963. regionlist[index++] = (REAL) strtod( stringptr, &stringptr );
  10964. }
  10965. stringptr = findfield( stringptr );
  10966. if ( *stringptr == '\0' ) {
  10967. regionlist[index] = regionlist[index - 1];
  10968. }
  10969. else {
  10970. regionlist[index] = (REAL) strtod( stringptr, &stringptr );
  10971. }
  10972. index++;
  10973. }
  10974. }
  10975. }
  10976. else {
  10977. /* Set `*regions' to zero to avoid an accidental free() later. */
  10978. *regions = 0;
  10979. *rlist = (REAL *) NULL;
  10980. }
  10981. #endif /* not CDT_ONLY */
  10982. fclose( polyfile );
  10983. }
  10984. #endif /* not TRILIBRARY */
  10985. /*****************************************************************************/
  10986. /* */
  10987. /* finishfile() Write the command line to the output file so the user */
  10988. /* can remember how the file was generated. Close the file. */
  10989. /* */
  10990. /*****************************************************************************/
  10991. #ifndef TRILIBRARY
  10992. void finishfile( outfile, argc, argv )
  10993. FILE * outfile;
  10994. int argc;
  10995. char **argv;
  10996. {
  10997. int i;
  10998. fprintf( outfile, "# Generated by" );
  10999. for ( i = 0; i < argc; i++ ) {
  11000. fprintf( outfile, " " );
  11001. fputs( argv[i], outfile );
  11002. }
  11003. fprintf( outfile, "\n" );
  11004. fclose( outfile );
  11005. }
  11006. #endif /* not TRILIBRARY */
  11007. /*****************************************************************************/
  11008. /* */
  11009. /* writenodes() Number the points and write them to a .node file. */
  11010. /* */
  11011. /* To save memory, the point numbers are written over the shell markers */
  11012. /* after the points are written to a file. */
  11013. /* */
  11014. /*****************************************************************************/
  11015. #ifdef TRILIBRARY
  11016. void writenodes( pointlist, pointattriblist, pointmarkerlist )
  11017. REAL * *pointlist;
  11018. REAL **pointattriblist;
  11019. int **pointmarkerlist;
  11020. #else /* not TRILIBRARY */
  11021. void writenodes( nodefilename, argc, argv )
  11022. char *nodefilename;
  11023. int argc;
  11024. char **argv;
  11025. #endif /* not TRILIBRARY */
  11026. {
  11027. #ifdef TRILIBRARY
  11028. REAL *plist;
  11029. REAL *palist;
  11030. int *pmlist;
  11031. int coordindex;
  11032. int attribindex;
  11033. #else /* not TRILIBRARY */
  11034. FILE *outfile;
  11035. #endif /* not TRILIBRARY */
  11036. point pointloop;
  11037. int pointnumber;
  11038. int i;
  11039. #ifdef TRILIBRARY
  11040. if ( !quiet ) {
  11041. printf( "Writing points.\n" );
  11042. }
  11043. /* Allocate memory for output points if necessary. */
  11044. if ( *pointlist == (REAL *) NULL ) {
  11045. *pointlist = (REAL *) malloc( points.items * 2 * sizeof( REAL ) );
  11046. if ( *pointlist == (REAL *) NULL ) {
  11047. printf( "Error: Out of memory.\n" );
  11048. exit( 1 );
  11049. }
  11050. }
  11051. /* Allocate memory for output point attributes if necessary. */
  11052. if ( ( nextras > 0 ) && ( *pointattriblist == (REAL *) NULL ) ) {
  11053. *pointattriblist = (REAL *) malloc( points.items * nextras * sizeof( REAL ) );
  11054. if ( *pointattriblist == (REAL *) NULL ) {
  11055. printf( "Error: Out of memory.\n" );
  11056. exit( 1 );
  11057. }
  11058. }
  11059. /* Allocate memory for output point markers if necessary. */
  11060. if ( !nobound && ( *pointmarkerlist == (int *) NULL ) ) {
  11061. *pointmarkerlist = (int *) malloc( points.items * sizeof( int ) );
  11062. if ( *pointmarkerlist == (int *) NULL ) {
  11063. printf( "Error: Out of memory.\n" );
  11064. exit( 1 );
  11065. }
  11066. }
  11067. plist = *pointlist;
  11068. palist = *pointattriblist;
  11069. pmlist = *pointmarkerlist;
  11070. coordindex = 0;
  11071. attribindex = 0;
  11072. #else /* not TRILIBRARY */
  11073. if ( !quiet ) {
  11074. printf( "Writing %s.\n", nodefilename );
  11075. }
  11076. outfile = fopen( nodefilename, "w" );
  11077. if ( outfile == (FILE *) NULL ) {
  11078. printf( " Error: Cannot create file %s.\n", nodefilename );
  11079. exit( 1 );
  11080. }
  11081. /* Number of points, number of dimensions, number of point attributes, */
  11082. /* and number of boundary markers (zero or one). */
  11083. fprintf( outfile, "%ld %d %d %d\n", points.items, mesh_dim, nextras,
  11084. 1 - nobound );
  11085. #endif /* not TRILIBRARY */
  11086. traversalinit( &points );
  11087. pointloop = pointtraverse();
  11088. pointnumber = firstnumber;
  11089. while ( pointloop != (point) NULL ) {
  11090. #ifdef TRILIBRARY
  11091. /* X and y coordinates. */
  11092. plist[coordindex++] = pointloop[0];
  11093. plist[coordindex++] = pointloop[1];
  11094. /* Point attributes. */
  11095. for ( i = 0; i < nextras; i++ ) {
  11096. palist[attribindex++] = pointloop[2 + i];
  11097. }
  11098. if ( !nobound ) {
  11099. /* Copy the boundary marker. */
  11100. pmlist[pointnumber - firstnumber] = pointmark( pointloop );
  11101. }
  11102. #else /* not TRILIBRARY */
  11103. /* Point number, x and y coordinates. */
  11104. fprintf( outfile, "%4d %.17g %.17g", pointnumber, pointloop[0],
  11105. pointloop[1] );
  11106. for ( i = 0; i < nextras; i++ ) {
  11107. /* Write an attribute. */
  11108. fprintf( outfile, " %.17g", pointloop[i + 2] );
  11109. }
  11110. if ( nobound ) {
  11111. fprintf( outfile, "\n" );
  11112. }
  11113. else {
  11114. /* Write the boundary marker. */
  11115. fprintf( outfile, " %d\n", pointmark( pointloop ) );
  11116. }
  11117. #endif /* not TRILIBRARY */
  11118. setpointmark( pointloop, pointnumber );
  11119. pointloop = pointtraverse();
  11120. pointnumber++;
  11121. }
  11122. #ifndef TRILIBRARY
  11123. finishfile( outfile, argc, argv );
  11124. #endif /* not TRILIBRARY */
  11125. }
  11126. /*****************************************************************************/
  11127. /* */
  11128. /* numbernodes() Number the points. */
  11129. /* */
  11130. /* Each point is assigned a marker equal to its number. */
  11131. /* */
  11132. /* Used when writenodes() is not called because no .node file is written. */
  11133. /* */
  11134. /*****************************************************************************/
  11135. void numbernodes(){
  11136. point pointloop;
  11137. int pointnumber;
  11138. traversalinit( &points );
  11139. pointloop = pointtraverse();
  11140. pointnumber = firstnumber;
  11141. while ( pointloop != (point) NULL ) {
  11142. setpointmark( pointloop, pointnumber );
  11143. pointloop = pointtraverse();
  11144. pointnumber++;
  11145. }
  11146. }
  11147. /*****************************************************************************/
  11148. /* */
  11149. /* writeelements() Write the triangles to an .ele file. */
  11150. /* */
  11151. /*****************************************************************************/
  11152. #ifdef TRILIBRARY
  11153. void writeelements( trianglelist, triangleattriblist )
  11154. int **trianglelist;
  11155. REAL **triangleattriblist;
  11156. #else /* not TRILIBRARY */
  11157. void writeelements( elefilename, argc, argv )
  11158. char *elefilename;
  11159. int argc;
  11160. char **argv;
  11161. #endif /* not TRILIBRARY */
  11162. {
  11163. #ifdef TRILIBRARY
  11164. int *tlist;
  11165. REAL *talist;
  11166. int pointindex;
  11167. int attribindex;
  11168. #else /* not TRILIBRARY */
  11169. FILE *outfile;
  11170. #endif /* not TRILIBRARY */
  11171. struct triedge triangleloop;
  11172. point p1, p2, p3;
  11173. point mid1, mid2, mid3;
  11174. int elementnumber;
  11175. int i;
  11176. #ifdef TRILIBRARY
  11177. if ( !quiet ) {
  11178. printf( "Writing triangles.\n" );
  11179. }
  11180. /* Allocate memory for output triangles if necessary. */
  11181. if ( *trianglelist == (int *) NULL ) {
  11182. *trianglelist = (int *) malloc( triangles.items *
  11183. ( ( order + 1 ) * ( order + 2 ) / 2 ) * sizeof( int ) );
  11184. if ( *trianglelist == (int *) NULL ) {
  11185. printf( "Error: Out of memory.\n" );
  11186. exit( 1 );
  11187. }
  11188. }
  11189. /* Allocate memory for output triangle attributes if necessary. */
  11190. if ( ( eextras > 0 ) && ( *triangleattriblist == (REAL *) NULL ) ) {
  11191. *triangleattriblist = (REAL *) malloc( triangles.items * eextras *
  11192. sizeof( REAL ) );
  11193. if ( *triangleattriblist == (REAL *) NULL ) {
  11194. printf( "Error: Out of memory.\n" );
  11195. exit( 1 );
  11196. }
  11197. }
  11198. tlist = *trianglelist;
  11199. talist = *triangleattriblist;
  11200. pointindex = 0;
  11201. attribindex = 0;
  11202. #else /* not TRILIBRARY */
  11203. if ( !quiet ) {
  11204. printf( "Writing %s.\n", elefilename );
  11205. }
  11206. outfile = fopen( elefilename, "w" );
  11207. if ( outfile == (FILE *) NULL ) {
  11208. printf( " Error: Cannot create file %s.\n", elefilename );
  11209. exit( 1 );
  11210. }
  11211. /* Number of triangles, points per triangle, attributes per triangle. */
  11212. fprintf( outfile, "%ld %d %d\n", triangles.items,
  11213. ( order + 1 ) * ( order + 2 ) / 2, eextras );
  11214. #endif /* not TRILIBRARY */
  11215. traversalinit( &triangles );
  11216. triangleloop.tri = triangletraverse();
  11217. triangleloop.orient = 0;
  11218. elementnumber = firstnumber;
  11219. while ( triangleloop.tri != (triangle *) NULL ) {
  11220. org( triangleloop, p1 );
  11221. dest( triangleloop, p2 );
  11222. apex( triangleloop, p3 );
  11223. if ( order == 1 ) {
  11224. #ifdef TRILIBRARY
  11225. tlist[pointindex++] = pointmark( p1 );
  11226. tlist[pointindex++] = pointmark( p2 );
  11227. tlist[pointindex++] = pointmark( p3 );
  11228. #else /* not TRILIBRARY */
  11229. /* Triangle number, indices for three points. */
  11230. fprintf( outfile, "%4d %4d %4d %4d", elementnumber,
  11231. pointmark( p1 ), pointmark( p2 ), pointmark( p3 ) );
  11232. #endif /* not TRILIBRARY */
  11233. }
  11234. else {
  11235. mid1 = (point) triangleloop.tri[highorderindex + 1];
  11236. mid2 = (point) triangleloop.tri[highorderindex + 2];
  11237. mid3 = (point) triangleloop.tri[highorderindex];
  11238. #ifdef TRILIBRARY
  11239. tlist[pointindex++] = pointmark( p1 );
  11240. tlist[pointindex++] = pointmark( p2 );
  11241. tlist[pointindex++] = pointmark( p3 );
  11242. tlist[pointindex++] = pointmark( mid1 );
  11243. tlist[pointindex++] = pointmark( mid2 );
  11244. tlist[pointindex++] = pointmark( mid3 );
  11245. #else /* not TRILIBRARY */
  11246. /* Triangle number, indices for six points. */
  11247. fprintf( outfile, "%4d %4d %4d %4d %4d %4d %4d", elementnumber,
  11248. pointmark( p1 ), pointmark( p2 ), pointmark( p3 ), pointmark( mid1 ),
  11249. pointmark( mid2 ), pointmark( mid3 ) );
  11250. #endif /* not TRILIBRARY */
  11251. }
  11252. #ifdef TRILIBRARY
  11253. for ( i = 0; i < eextras; i++ ) {
  11254. talist[attribindex++] = elemattribute( triangleloop, i );
  11255. }
  11256. #else /* not TRILIBRARY */
  11257. for ( i = 0; i < eextras; i++ ) {
  11258. fprintf( outfile, " %.17g", elemattribute( triangleloop, i ) );
  11259. }
  11260. fprintf( outfile, "\n" );
  11261. #endif /* not TRILIBRARY */
  11262. triangleloop.tri = triangletraverse();
  11263. elementnumber++;
  11264. }
  11265. #ifndef TRILIBRARY
  11266. finishfile( outfile, argc, argv );
  11267. #endif /* not TRILIBRARY */
  11268. }
  11269. /*****************************************************************************/
  11270. /* */
  11271. /* writepoly() Write the segments and holes to a .poly file. */
  11272. /* */
  11273. /*****************************************************************************/
  11274. #ifdef TRILIBRARY
  11275. void writepoly( segmentlist, segmentmarkerlist )
  11276. int **segmentlist;
  11277. int **segmentmarkerlist;
  11278. #else /* not TRILIBRARY */
  11279. void writepoly( polyfilename, holelist, holes, regionlist, regions, argc, argv )
  11280. char *polyfilename;
  11281. REAL *holelist;
  11282. int holes;
  11283. REAL *regionlist;
  11284. int regions;
  11285. int argc;
  11286. char **argv;
  11287. #endif /* not TRILIBRARY */
  11288. {
  11289. #ifdef TRILIBRARY
  11290. int *slist;
  11291. int *smlist;
  11292. int index;
  11293. #else /* not TRILIBRARY */
  11294. FILE *outfile;
  11295. int i;
  11296. #endif /* not TRILIBRARY */
  11297. struct edge shelleloop;
  11298. point endpoint1, endpoint2;
  11299. int shellenumber;
  11300. #ifdef TRILIBRARY
  11301. if ( !quiet ) {
  11302. printf( "Writing segments.\n" );
  11303. }
  11304. /* Allocate memory for output segments if necessary. */
  11305. if ( *segmentlist == (int *) NULL ) {
  11306. *segmentlist = (int *) malloc( shelles.items * 2 * sizeof( int ) );
  11307. if ( *segmentlist == (int *) NULL ) {
  11308. printf( "Error: Out of memory.\n" );
  11309. exit( 1 );
  11310. }
  11311. }
  11312. /* Allocate memory for output segment markers if necessary. */
  11313. if ( !nobound && ( *segmentmarkerlist == (int *) NULL ) ) {
  11314. *segmentmarkerlist = (int *) malloc( shelles.items * sizeof( int ) );
  11315. if ( *segmentmarkerlist == (int *) NULL ) {
  11316. printf( "Error: Out of memory.\n" );
  11317. exit( 1 );
  11318. }
  11319. }
  11320. slist = *segmentlist;
  11321. smlist = *segmentmarkerlist;
  11322. index = 0;
  11323. #else /* not TRILIBRARY */
  11324. if ( !quiet ) {
  11325. printf( "Writing %s.\n", polyfilename );
  11326. }
  11327. outfile = fopen( polyfilename, "w" );
  11328. if ( outfile == (FILE *) NULL ) {
  11329. printf( " Error: Cannot create file %s.\n", polyfilename );
  11330. exit( 1 );
  11331. }
  11332. /* The zero indicates that the points are in a separate .node file. */
  11333. /* Followed by number of dimensions, number of point attributes, */
  11334. /* and number of boundary markers (zero or one). */
  11335. fprintf( outfile, "%d %d %d %d\n", 0, mesh_dim, nextras, 1 - nobound );
  11336. /* Number of segments, number of boundary markers (zero or one). */
  11337. fprintf( outfile, "%ld %d\n", shelles.items, 1 - nobound );
  11338. #endif /* not TRILIBRARY */
  11339. traversalinit( &shelles );
  11340. shelleloop.sh = shelletraverse();
  11341. shelleloop.shorient = 0;
  11342. shellenumber = firstnumber;
  11343. while ( shelleloop.sh != (shelle *) NULL ) {
  11344. sorg( shelleloop, endpoint1 );
  11345. sdest( shelleloop, endpoint2 );
  11346. #ifdef TRILIBRARY
  11347. /* Copy indices of the segment's two endpoints. */
  11348. slist[index++] = pointmark( endpoint1 );
  11349. slist[index++] = pointmark( endpoint2 );
  11350. if ( !nobound ) {
  11351. /* Copy the boundary marker. */
  11352. smlist[shellenumber - firstnumber] = mark( shelleloop );
  11353. }
  11354. #else /* not TRILIBRARY */
  11355. /* Segment number, indices of its two endpoints, and possibly a marker. */
  11356. if ( nobound ) {
  11357. fprintf( outfile, "%4d %4d %4d\n", shellenumber,
  11358. pointmark( endpoint1 ), pointmark( endpoint2 ) );
  11359. }
  11360. else {
  11361. fprintf( outfile, "%4d %4d %4d %4d\n", shellenumber,
  11362. pointmark( endpoint1 ), pointmark( endpoint2 ), mark( shelleloop ) );
  11363. }
  11364. #endif /* not TRILIBRARY */
  11365. shelleloop.sh = shelletraverse();
  11366. shellenumber++;
  11367. }
  11368. #ifndef TRILIBRARY
  11369. #ifndef CDT_ONLY
  11370. fprintf( outfile, "%d\n", holes );
  11371. if ( holes > 0 ) {
  11372. for ( i = 0; i < holes; i++ ) {
  11373. /* Hole number, x and y coordinates. */
  11374. fprintf( outfile, "%4d %.17g %.17g\n", firstnumber + i,
  11375. holelist[2 * i], holelist[2 * i + 1] );
  11376. }
  11377. }
  11378. if ( regions > 0 ) {
  11379. fprintf( outfile, "%d\n", regions );
  11380. for ( i = 0; i < regions; i++ ) {
  11381. /* Region number, x and y coordinates, attribute, maximum area. */
  11382. fprintf( outfile, "%4d %.17g %.17g %.17g %.17g\n", firstnumber + i,
  11383. regionlist[4 * i], regionlist[4 * i + 1],
  11384. regionlist[4 * i + 2], regionlist[4 * i + 3] );
  11385. }
  11386. }
  11387. #endif /* not CDT_ONLY */
  11388. finishfile( outfile, argc, argv );
  11389. #endif /* not TRILIBRARY */
  11390. }
  11391. /*****************************************************************************/
  11392. /* */
  11393. /* writeedges() Write the edges to a .edge file. */
  11394. /* */
  11395. /*****************************************************************************/
  11396. #ifdef TRILIBRARY
  11397. void writeedges( edgelist, edgemarkerlist )
  11398. int **edgelist;
  11399. int **edgemarkerlist;
  11400. #else /* not TRILIBRARY */
  11401. void writeedges( edgefilename, argc, argv )
  11402. char *edgefilename;
  11403. int argc;
  11404. char **argv;
  11405. #endif /* not TRILIBRARY */
  11406. {
  11407. #ifdef TRILIBRARY
  11408. int *elist;
  11409. int *emlist;
  11410. int index;
  11411. #else /* not TRILIBRARY */
  11412. FILE *outfile;
  11413. #endif /* not TRILIBRARY */
  11414. struct triedge triangleloop, trisym;
  11415. struct edge checkmark;
  11416. point p1, p2;
  11417. int edgenumber;
  11418. triangle ptr; /* Temporary variable used by sym(). */
  11419. shelle sptr; /* Temporary variable used by tspivot(). */
  11420. #ifdef TRILIBRARY
  11421. if ( !quiet ) {
  11422. printf( "Writing edges.\n" );
  11423. }
  11424. /* Allocate memory for edges if necessary. */
  11425. if ( *edgelist == (int *) NULL ) {
  11426. *edgelist = (int *) malloc( edges * 2 * sizeof( int ) );
  11427. if ( *edgelist == (int *) NULL ) {
  11428. printf( "Error: Out of memory.\n" );
  11429. exit( 1 );
  11430. }
  11431. }
  11432. /* Allocate memory for edge markers if necessary. */
  11433. if ( !nobound && ( *edgemarkerlist == (int *) NULL ) ) {
  11434. *edgemarkerlist = (int *) malloc( edges * sizeof( int ) );
  11435. if ( *edgemarkerlist == (int *) NULL ) {
  11436. printf( "Error: Out of memory.\n" );
  11437. exit( 1 );
  11438. }
  11439. }
  11440. elist = *edgelist;
  11441. emlist = *edgemarkerlist;
  11442. index = 0;
  11443. #else /* not TRILIBRARY */
  11444. if ( !quiet ) {
  11445. printf( "Writing %s.\n", edgefilename );
  11446. }
  11447. outfile = fopen( edgefilename, "w" );
  11448. if ( outfile == (FILE *) NULL ) {
  11449. printf( " Error: Cannot create file %s.\n", edgefilename );
  11450. exit( 1 );
  11451. }
  11452. /* Number of edges, number of boundary markers (zero or one). */
  11453. fprintf( outfile, "%ld %d\n", edges, 1 - nobound );
  11454. #endif /* not TRILIBRARY */
  11455. traversalinit( &triangles );
  11456. triangleloop.tri = triangletraverse();
  11457. edgenumber = firstnumber;
  11458. /* To loop over the set of edges, loop over all triangles, and look at */
  11459. /* the three edges of each triangle. If there isn't another triangle */
  11460. /* adjacent to the edge, operate on the edge. If there is another */
  11461. /* adjacent triangle, operate on the edge only if the current triangle */
  11462. /* has a smaller pointer than its neighbor. This way, each edge is */
  11463. /* considered only once. */
  11464. while ( triangleloop.tri != (triangle *) NULL ) {
  11465. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  11466. triangleloop.orient++ ) {
  11467. sym( triangleloop, trisym );
  11468. if ( ( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri ) ) {
  11469. org( triangleloop, p1 );
  11470. dest( triangleloop, p2 );
  11471. #ifdef TRILIBRARY
  11472. elist[index++] = pointmark( p1 );
  11473. elist[index++] = pointmark( p2 );
  11474. #endif /* TRILIBRARY */
  11475. if ( nobound ) {
  11476. #ifndef TRILIBRARY
  11477. /* Edge number, indices of two endpoints. */
  11478. fprintf( outfile, "%4d %d %d\n", edgenumber,
  11479. pointmark( p1 ), pointmark( p2 ) );
  11480. #endif /* not TRILIBRARY */
  11481. }
  11482. else {
  11483. /* Edge number, indices of two endpoints, and a boundary marker. */
  11484. /* If there's no shell edge, the boundary marker is zero. */
  11485. if ( useshelles ) {
  11486. tspivot( triangleloop, checkmark );
  11487. if ( checkmark.sh == dummysh ) {
  11488. #ifdef TRILIBRARY
  11489. emlist[edgenumber - firstnumber] = 0;
  11490. #else /* not TRILIBRARY */
  11491. fprintf( outfile, "%4d %d %d %d\n", edgenumber,
  11492. pointmark( p1 ), pointmark( p2 ), 0 );
  11493. #endif /* not TRILIBRARY */
  11494. }
  11495. else {
  11496. #ifdef TRILIBRARY
  11497. emlist[edgenumber - firstnumber] = mark( checkmark );
  11498. #else /* not TRILIBRARY */
  11499. fprintf( outfile, "%4d %d %d %d\n", edgenumber,
  11500. pointmark( p1 ), pointmark( p2 ), mark( checkmark ) );
  11501. #endif /* not TRILIBRARY */
  11502. }
  11503. }
  11504. else {
  11505. #ifdef TRILIBRARY
  11506. emlist[edgenumber - firstnumber] = trisym.tri == dummytri;
  11507. #else /* not TRILIBRARY */
  11508. fprintf( outfile, "%4d %d %d %d\n", edgenumber,
  11509. pointmark( p1 ), pointmark( p2 ), trisym.tri == dummytri );
  11510. #endif /* not TRILIBRARY */
  11511. }
  11512. }
  11513. edgenumber++;
  11514. }
  11515. }
  11516. triangleloop.tri = triangletraverse();
  11517. }
  11518. #ifndef TRILIBRARY
  11519. finishfile( outfile, argc, argv );
  11520. #endif /* not TRILIBRARY */
  11521. }
  11522. /*****************************************************************************/
  11523. /* */
  11524. /* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */
  11525. /* file. */
  11526. /* */
  11527. /* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
  11528. /* Hence, the Voronoi vertices are listed by traversing the Delaunay */
  11529. /* triangles, and the Voronoi edges are listed by traversing the Delaunay */
  11530. /* edges. */
  11531. /* */
  11532. /* WARNING: In order to assign numbers to the Voronoi vertices, this */
  11533. /* procedure messes up the shell edges or the extra nodes of every */
  11534. /* element. Hence, you should call this procedure last. */
  11535. /* */
  11536. /*****************************************************************************/
  11537. #ifdef TRILIBRARY
  11538. void writevoronoi( vpointlist, vpointattriblist, vpointmarkerlist, vedgelist,
  11539. vedgemarkerlist, vnormlist )
  11540. REAL * *vpointlist;
  11541. REAL **vpointattriblist;
  11542. int **vpointmarkerlist;
  11543. int **vedgelist;
  11544. int **vedgemarkerlist;
  11545. REAL **vnormlist;
  11546. #else /* not TRILIBRARY */
  11547. void writevoronoi( vnodefilename, vedgefilename, argc, argv )
  11548. char *vnodefilename;
  11549. char *vedgefilename;
  11550. int argc;
  11551. char **argv;
  11552. #endif /* not TRILIBRARY */
  11553. {
  11554. #ifdef TRILIBRARY
  11555. REAL *plist;
  11556. REAL *palist;
  11557. int *elist;
  11558. REAL *normlist;
  11559. int coordindex;
  11560. int attribindex;
  11561. #else /* not TRILIBRARY */
  11562. FILE *outfile;
  11563. #endif /* not TRILIBRARY */
  11564. struct triedge triangleloop, trisym;
  11565. point torg, tdest, tapex;
  11566. REAL circumcenter[2];
  11567. REAL xi, eta;
  11568. int vnodenumber, vedgenumber;
  11569. int p1, p2;
  11570. int i;
  11571. triangle ptr; /* Temporary variable used by sym(). */
  11572. #ifdef TRILIBRARY
  11573. if ( !quiet ) {
  11574. printf( "Writing Voronoi vertices.\n" );
  11575. }
  11576. /* Allocate memory for Voronoi vertices if necessary. */
  11577. if ( *vpointlist == (REAL *) NULL ) {
  11578. *vpointlist = (REAL *) malloc( triangles.items * 2 * sizeof( REAL ) );
  11579. if ( *vpointlist == (REAL *) NULL ) {
  11580. printf( "Error: Out of memory.\n" );
  11581. exit( 1 );
  11582. }
  11583. }
  11584. /* Allocate memory for Voronoi vertex attributes if necessary. */
  11585. if ( *vpointattriblist == (REAL *) NULL ) {
  11586. *vpointattriblist = (REAL *) malloc( triangles.items * nextras *
  11587. sizeof( REAL ) );
  11588. if ( *vpointattriblist == (REAL *) NULL ) {
  11589. printf( "Error: Out of memory.\n" );
  11590. exit( 1 );
  11591. }
  11592. }
  11593. *vpointmarkerlist = (int *) NULL;
  11594. plist = *vpointlist;
  11595. palist = *vpointattriblist;
  11596. coordindex = 0;
  11597. attribindex = 0;
  11598. #else /* not TRILIBRARY */
  11599. if ( !quiet ) {
  11600. printf( "Writing %s.\n", vnodefilename );
  11601. }
  11602. outfile = fopen( vnodefilename, "w" );
  11603. if ( outfile == (FILE *) NULL ) {
  11604. printf( " Error: Cannot create file %s.\n", vnodefilename );
  11605. exit( 1 );
  11606. }
  11607. /* Number of triangles, two dimensions, number of point attributes, */
  11608. /* zero markers. */
  11609. fprintf( outfile, "%ld %d %d %d\n", triangles.items, 2, nextras, 0 );
  11610. #endif /* not TRILIBRARY */
  11611. traversalinit( &triangles );
  11612. triangleloop.tri = triangletraverse();
  11613. triangleloop.orient = 0;
  11614. vnodenumber = firstnumber;
  11615. while ( triangleloop.tri != (triangle *) NULL ) {
  11616. org( triangleloop, torg );
  11617. dest( triangleloop, tdest );
  11618. apex( triangleloop, tapex );
  11619. findcircumcenter( torg, tdest, tapex, circumcenter, &xi, &eta );
  11620. #ifdef TRILIBRARY
  11621. /* X and y coordinates. */
  11622. plist[coordindex++] = circumcenter[0];
  11623. plist[coordindex++] = circumcenter[1];
  11624. for ( i = 2; i < 2 + nextras; i++ ) {
  11625. /* Interpolate the point attributes at the circumcenter. */
  11626. palist[attribindex++] = torg[i] + xi * ( tdest[i] - torg[i] )
  11627. + eta * ( tapex[i] - torg[i] );
  11628. }
  11629. #else /* not TRILIBRARY */
  11630. /* Voronoi vertex number, x and y coordinates. */
  11631. fprintf( outfile, "%4d %.17g %.17g", vnodenumber, circumcenter[0],
  11632. circumcenter[1] );
  11633. for ( i = 2; i < 2 + nextras; i++ ) {
  11634. /* Interpolate the point attributes at the circumcenter. */
  11635. fprintf( outfile, " %.17g", torg[i] + xi * ( tdest[i] - torg[i] )
  11636. + eta * ( tapex[i] - torg[i] ) );
  11637. }
  11638. fprintf( outfile, "\n" );
  11639. #endif /* not TRILIBRARY */
  11640. *(int *) ( triangleloop.tri + 6 ) = vnodenumber;
  11641. triangleloop.tri = triangletraverse();
  11642. vnodenumber++;
  11643. }
  11644. #ifndef TRILIBRARY
  11645. finishfile( outfile, argc, argv );
  11646. #endif /* not TRILIBRARY */
  11647. #ifdef TRILIBRARY
  11648. if ( !quiet ) {
  11649. printf( "Writing Voronoi edges.\n" );
  11650. }
  11651. /* Allocate memory for output Voronoi edges if necessary. */
  11652. if ( *vedgelist == (int *) NULL ) {
  11653. *vedgelist = (int *) malloc( edges * 2 * sizeof( int ) );
  11654. if ( *vedgelist == (int *) NULL ) {
  11655. printf( "Error: Out of memory.\n" );
  11656. exit( 1 );
  11657. }
  11658. }
  11659. *vedgemarkerlist = (int *) NULL;
  11660. /* Allocate memory for output Voronoi norms if necessary. */
  11661. if ( *vnormlist == (REAL *) NULL ) {
  11662. *vnormlist = (REAL *) malloc( edges * 2 * sizeof( REAL ) );
  11663. if ( *vnormlist == (REAL *) NULL ) {
  11664. printf( "Error: Out of memory.\n" );
  11665. exit( 1 );
  11666. }
  11667. }
  11668. elist = *vedgelist;
  11669. normlist = *vnormlist;
  11670. coordindex = 0;
  11671. #else /* not TRILIBRARY */
  11672. if ( !quiet ) {
  11673. printf( "Writing %s.\n", vedgefilename );
  11674. }
  11675. outfile = fopen( vedgefilename, "w" );
  11676. if ( outfile == (FILE *) NULL ) {
  11677. printf( " Error: Cannot create file %s.\n", vedgefilename );
  11678. exit( 1 );
  11679. }
  11680. /* Number of edges, zero boundary markers. */
  11681. fprintf( outfile, "%ld %d\n", edges, 0 );
  11682. #endif /* not TRILIBRARY */
  11683. traversalinit( &triangles );
  11684. triangleloop.tri = triangletraverse();
  11685. vedgenumber = firstnumber;
  11686. /* To loop over the set of edges, loop over all triangles, and look at */
  11687. /* the three edges of each triangle. If there isn't another triangle */
  11688. /* adjacent to the edge, operate on the edge. If there is another */
  11689. /* adjacent triangle, operate on the edge only if the current triangle */
  11690. /* has a smaller pointer than its neighbor. This way, each edge is */
  11691. /* considered only once. */
  11692. while ( triangleloop.tri != (triangle *) NULL ) {
  11693. for ( triangleloop.orient = 0; triangleloop.orient < 3;
  11694. triangleloop.orient++ ) {
  11695. sym( triangleloop, trisym );
  11696. if ( ( triangleloop.tri < trisym.tri ) || ( trisym.tri == dummytri ) ) {
  11697. /* Find the number of this triangle (and Voronoi vertex). */
  11698. p1 = *(int *) ( triangleloop.tri + 6 );
  11699. if ( trisym.tri == dummytri ) {
  11700. org( triangleloop, torg );
  11701. dest( triangleloop, tdest );
  11702. #ifdef TRILIBRARY
  11703. /* Copy an infinite ray. Index of one endpoint, and -1. */
  11704. elist[coordindex] = p1;
  11705. normlist[coordindex++] = tdest[1] - torg[1];
  11706. elist[coordindex] = -1;
  11707. normlist[coordindex++] = torg[0] - tdest[0];
  11708. #else /* not TRILIBRARY */
  11709. /* Write an infinite ray. Edge number, index of one endpoint, -1, */
  11710. /* and x and y coordinates of a vector representing the */
  11711. /* direction of the ray. */
  11712. fprintf( outfile, "%4d %d %d %.17g %.17g\n", vedgenumber,
  11713. p1, -1, tdest[1] - torg[1], torg[0] - tdest[0] );
  11714. #endif /* not TRILIBRARY */
  11715. }
  11716. else {
  11717. /* Find the number of the adjacent triangle (and Voronoi vertex). */
  11718. p2 = *(int *) ( trisym.tri + 6 );
  11719. /* Finite edge. Write indices of two endpoints. */
  11720. #ifdef TRILIBRARY
  11721. elist[coordindex] = p1;
  11722. normlist[coordindex++] = 0.0;
  11723. elist[coordindex] = p2;
  11724. normlist[coordindex++] = 0.0;
  11725. #else /* not TRILIBRARY */
  11726. fprintf( outfile, "%4d %d %d\n", vedgenumber, p1, p2 );
  11727. #endif /* not TRILIBRARY */
  11728. }
  11729. vedgenumber++;
  11730. }
  11731. }
  11732. triangleloop.tri = triangletraverse();
  11733. }
  11734. #ifndef TRILIBRARY
  11735. finishfile( outfile, argc, argv );
  11736. #endif /* not TRILIBRARY */
  11737. }
  11738. #ifdef TRILIBRARY
  11739. void writeneighbors( neighborlist )
  11740. int **neighborlist;
  11741. #else /* not TRILIBRARY */
  11742. void writeneighbors( neighborfilename, argc, argv )
  11743. char *neighborfilename;
  11744. int argc;
  11745. char **argv;
  11746. #endif /* not TRILIBRARY */
  11747. {
  11748. #ifdef TRILIBRARY
  11749. int *nlist;
  11750. int index;
  11751. #else /* not TRILIBRARY */
  11752. FILE *outfile;
  11753. #endif /* not TRILIBRARY */
  11754. struct triedge triangleloop, trisym;
  11755. int elementnumber;
  11756. int neighbor1, neighbor2, neighbor3;
  11757. triangle ptr; /* Temporary variable used by sym(). */