Chaste Release::3.1
|
00001 00008 /*****************************************************************************/ 00009 /* */ 00010 /* 888888888 ,o, / 888 */ 00011 /* 888 88o88o " o8888o 88o8888o o88888o 888 o88888o */ 00012 /* 888 888 888 88b 888 888 888 888 888 d888 88b */ 00013 /* 888 888 888 o88^o888 888 888 "88888" 888 8888oo888 */ 00014 /* 888 888 888 C888 888 888 888 / 888 q888 */ 00015 /* 888 888 888 "88o^888 888 888 Cb 888 "88oooo" */ 00016 /* "8oo8D */ 00017 /* */ 00018 /* A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator. */ 00019 /* (triangle.c) */ 00020 /* */ 00021 /* Version 1.6 */ 00022 /* July 28, 2005 */ 00023 /* */ 00024 /* Copyright 1993, 1995, 1997, 1998, 2002, 2005 */ 00025 /* Jonathan Richard Shewchuk */ 00026 /* 2360 Woolsey #H */ 00027 /* Berkeley, California 94705-1927 */ 00028 /* jrs@cs.berkeley.edu */ 00029 /* */ 00030 /* This program may be freely redistributed under the condition that the */ 00031 /* copyright notices (including this entire header and the copyright */ 00032 /* notice printed when the `-h' switch is selected) are not removed, and */ 00033 /* no compensation is received. Private, research, and institutional */ 00034 /* use is free. You may distribute modified versions of this code UNDER */ 00035 /* THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE */ 00036 /* SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE */ 00037 /* AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR */ 00038 /* NOTICE IS GIVEN OF THE MODIFICATIONS. Distribution of this code as */ 00039 /* part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT */ 00040 /* WITH THE AUTHOR. (If you are not directly supplying this code to a */ 00041 /* customer, and you are instead telling them how they can obtain it for */ 00042 /* free, then you are not required to make any arrangement with me.) */ 00043 /* */ 00044 /* Hypertext instructions for Triangle are available on the Web at */ 00045 /* */ 00046 /* http://www.cs.cmu.edu/~quake/triangle.html */ 00047 /* */ 00048 /* Disclaimer: Neither I nor Carnegie Mellon warrant this code in any way */ 00049 /* whatsoever. This code is provided "as-is". Use at your own risk. */ 00050 /* */ 00051 /* Some of the references listed below are marked with an asterisk. [*] */ 00052 /* These references are available for downloading from the Web page */ 00053 /* */ 00054 /* http://www.cs.cmu.edu/~quake/triangle.research.html */ 00055 /* */ 00056 /* Three papers discussing aspects of Triangle are available. A short */ 00057 /* overview appears in "Triangle: Engineering a 2D Quality Mesh */ 00058 /* Generator and Delaunay Triangulator," in Applied Computational */ 00059 /* Geometry: Towards Geometric Engineering, Ming C. Lin and Dinesh */ 00060 /* Manocha, editors, Lecture Notes in Computer Science volume 1148, */ 00061 /* pages 203-222, Springer-Verlag, Berlin, May 1996 (from the First ACM */ 00062 /* Workshop on Applied Computational Geometry). [*] */ 00063 /* */ 00064 /* The algorithms are discussed in the greatest detail in "Delaunay */ 00065 /* Refinement Algorithms for Triangular Mesh Generation," Computational */ 00066 /* Geometry: Theory and Applications 22(1-3):21-74, May 2002. [*] */ 00067 /* */ 00068 /* More detail about the data structures may be found in my dissertation: */ 00069 /* "Delaunay Refinement Mesh Generation," Ph.D. thesis, Technical Report */ 00070 /* CMU-CS-97-137, School of Computer Science, Carnegie Mellon University, */ 00071 /* Pittsburgh, Pennsylvania, 18 May 1997. [*] */ 00072 /* */ 00073 /* Triangle was created as part of the Quake Project in the School of */ 00074 /* Computer Science at Carnegie Mellon University. For further */ 00075 /* information, see Hesheng Bao, Jacobo Bielak, Omar Ghattas, Loukas F. */ 00076 /* Kallivokas, David R. O'Hallaron, Jonathan R. Shewchuk, and Jifeng Xu, */ 00077 /* "Large-scale Simulation of Elastic Wave Propagation in Heterogeneous */ 00078 /* Media on Parallel Computers," Computer Methods in Applied Mechanics */ 00079 /* and Engineering 152(1-2):85-102, 22 January 1998. */ 00080 /* */ 00081 /* Triangle's Delaunay refinement algorithm for quality mesh generation is */ 00082 /* a hybrid of one due to Jim Ruppert, "A Delaunay Refinement Algorithm */ 00083 /* for Quality 2-Dimensional Mesh Generation," Journal of Algorithms */ 00084 /* 18(3):548-585, May 1995 [*], and one due to L. Paul Chew, "Guaranteed- */ 00085 /* Quality Mesh Generation for Curved Surfaces," Proceedings of the Ninth */ 00086 /* Annual Symposium on Computational Geometry (San Diego, California), */ 00087 /* pages 274-280, Association for Computing Machinery, May 1993, */ 00088 /* http://portal.acm.org/citation.cfm?id=161150 . */ 00089 /* */ 00090 /* The Delaunay refinement algorithm has been modified so that it meshes */ 00091 /* domains with small input angles well, as described in Gary L. Miller, */ 00092 /* Steven E. Pav, and Noel J. Walkington, "When and Why Ruppert's */ 00093 /* Algorithm Works," Twelfth International Meshing Roundtable, pages */ 00094 /* 91-102, Sandia National Laboratories, September 2003. [*] */ 00095 /* */ 00096 /* My implementation of the divide-and-conquer and incremental Delaunay */ 00097 /* triangulation algorithms follows closely the presentation of Guibas */ 00098 /* and Stolfi, even though I use a triangle-based data structure instead */ 00099 /* of their quad-edge data structure. (In fact, I originally implemented */ 00100 /* Triangle using the quad-edge data structure, but the switch to a */ 00101 /* triangle-based data structure sped Triangle by a factor of two.) The */ 00102 /* mesh manipulation primitives and the two aforementioned Delaunay */ 00103 /* triangulation algorithms are described by Leonidas J. Guibas and Jorge */ 00104 /* Stolfi, "Primitives for the Manipulation of General Subdivisions and */ 00105 /* the Computation of Voronoi Diagrams," ACM Transactions on Graphics */ 00106 /* 4(2):74-123, April 1985, http://portal.acm.org/citation.cfm?id=282923 .*/ 00107 /* */ 00108 /* Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai */ 00109 /* Lee and Bruce J. Schachter, "Two Algorithms for Constructing the */ 00110 /* Delaunay Triangulation," International Journal of Computer and */ 00111 /* Information Science 9(3):219-242, 1980. Triangle's improvement of the */ 00112 /* divide-and-conquer algorithm by alternating between vertical and */ 00113 /* horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and- */ 00114 /* Conquer Algorithm for Constructing Delaunay Triangulations," */ 00115 /* Algorithmica 2(2):137-151, 1987. */ 00116 /* */ 00117 /* The incremental insertion algorithm was first proposed by C. L. Lawson, */ 00118 /* "Software for C1 Surface Interpolation," in Mathematical Software III, */ 00119 /* John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977. */ 00120 /* For point location, I use the algorithm of Ernst P. Mucke, Isaac */ 00121 /* Saias, and Binhai Zhu, "Fast Randomized Point Location Without */ 00122 /* Preprocessing in Two- and Three-Dimensional Delaunay Triangulations," */ 00123 /* Proceedings of the Twelfth Annual Symposium on Computational Geometry, */ 00124 /* ACM, May 1996. [*] If I were to randomize the order of vertex */ 00125 /* insertion (I currently don't bother), their result combined with the */ 00126 /* result of Kenneth L. Clarkson and Peter W. Shor, "Applications of */ 00127 /* Random Sampling in Computational Geometry II," Discrete & */ 00128 /* Computational Geometry 4(1):387-421, 1989, would yield an expected */ 00129 /* O(n^{4/3}) bound on running time. */ 00130 /* */ 00131 /* The O(n log n) sweepline Delaunay triangulation algorithm is taken from */ 00132 /* Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams", */ 00133 /* Algorithmica 2(2):153-174, 1987. A random sample of edges on the */ 00134 /* boundary of the triangulation are maintained in a splay tree for the */ 00135 /* purpose of point location. Splay trees are described by Daniel */ 00136 /* Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */ 00137 /* Trees," Journal of the ACM 32(3):652-686, July 1985, */ 00138 /* http://portal.acm.org/citation.cfm?id=3835 . */ 00139 /* */ 00140 /* The algorithms for exact computation of the signs of determinants are */ 00141 /* described in Jonathan Richard Shewchuk, "Adaptive Precision Floating- */ 00142 /* Point Arithmetic and Fast Robust Geometric Predicates," Discrete & */ 00143 /* Computational Geometry 18(3):305-363, October 1997. (Also available */ 00144 /* as Technical Report CMU-CS-96-140, School of Computer Science, */ 00145 /* Carnegie Mellon University, Pittsburgh, Pennsylvania, May 1996.) [*] */ 00146 /* An abbreviated version appears as Jonathan Richard Shewchuk, "Robust */ 00147 /* Adaptive Floating-Point Geometric Predicates," Proceedings of the */ 00148 /* Twelfth Annual Symposium on Computational Geometry, ACM, May 1996. [*] */ 00149 /* Many of the ideas for my exact arithmetic routines originate with */ 00150 /* Douglas M. Priest, "Algorithms for Arbitrary Precision Floating Point */ 00151 /* Arithmetic," Tenth Symposium on Computer Arithmetic, pp. 132-143, IEEE */ 00152 /* Computer Society Press, 1991. [*] Many of the ideas for the correct */ 00153 /* evaluation of the signs of determinants are taken from Steven Fortune */ 00154 /* and Christopher J. Van Wyk, "Efficient Exact Arithmetic for Computa- */ 00155 /* tional Geometry," Proceedings of the Ninth Annual Symposium on */ 00156 /* Computational Geometry, ACM, pp. 163-172, May 1993, and from Steven */ 00157 /* Fortune, "Numerical Stability of Algorithms for 2D Delaunay Triangu- */ 00158 /* lations," International Journal of Computational Geometry & Applica- */ 00159 /* tions 5(1-2):193-213, March-June 1995. */ 00160 /* */ 00161 /* The method of inserting new vertices off-center (not precisely at the */ 00162 /* circumcenter of every poor-quality triangle) is from Alper Ungor, */ 00163 /* "Off-centers: A New Type of Steiner Points for Computing Size-Optimal */ 00164 /* Quality-Guaranteed Delaunay Triangulations," Proceedings of LATIN */ 00165 /* 2004 (Buenos Aires, Argentina), April 2004. */ 00166 /* */ 00167 /* For definitions of and results involving Delaunay triangulations, */ 00168 /* constrained and conforming versions thereof, and other aspects of */ 00169 /* triangular mesh generation, see the excellent survey by Marshall Bern */ 00170 /* and David Eppstein, "Mesh Generation and Optimal Triangulation," in */ 00171 /* Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang, */ 00172 /* editors, World Scientific, Singapore, pp. 23-90, 1992. [*] */ 00173 /* */ 00174 /* The time for incrementally adding PSLG (planar straight line graph) */ 00175 /* segments to create a constrained Delaunay triangulation is probably */ 00176 /* O(t^2) per segment in the worst case and O(t) per segment in the */ 00177 /* common case, where t is the number of triangles that intersect the */ 00178 /* segment before it is inserted. This doesn't count point location, */ 00179 /* which can be much more expensive. I could improve this to O(d log d) */ 00180 /* time, but d is usually quite small, so it's not worth the bother. */ 00181 /* (This note does not apply when the -s switch is used, invoking a */ 00182 /* different method is used to insert segments.) */ 00183 /* */ 00184 /* The time for deleting a vertex from a Delaunay triangulation is O(d^2) */ 00185 /* in the worst case and O(d) in the common case, where d is the degree */ 00186 /* of the vertex being deleted. I could improve this to O(d log d) time, */ 00187 /* but d is usually quite small, so it's not worth the bother. */ 00188 /* */ 00189 /* Ruppert's Delaunay refinement algorithm typically generates triangles */ 00190 /* at a linear rate (constant time per triangle) after the initial */ 00191 /* triangulation is formed. There may be pathological cases where */ 00192 /* quadratic time is required, but these never arise in practice. */ 00193 /* */ 00194 /* The geometric predicates (circumcenter calculations, segment */ 00195 /* intersection formulae, etc.) appear in my "Lecture Notes on Geometric */ 00196 /* Robustness" at http://www.cs.berkeley.edu/~jrs/mesh . */ 00197 /* */ 00198 /* If you make any improvements to this code, please please please let me */ 00199 /* know, so that I may obtain the improvements. Even if you don't change */ 00200 /* the code, I'd still love to hear what it's being used for. */ 00201 /* */ 00202 /*****************************************************************************/ 00203 00204 /* For single precision (which will save some memory and reduce paging), */ 00205 /* define the symbol SINGLE by using the -DSINGLE compiler switch or by */ 00206 /* writing "#define SINGLE" below. */ 00207 /* */ 00208 /* For double precision (which will allow you to refine meshes to a smaller */ 00209 /* edge length), leave SINGLE undefined. */ 00210 /* */ 00211 /* Double precision uses more memory, but improves the resolution of the */ 00212 /* meshes you can generate with Triangle. It also reduces the likelihood */ 00213 /* of a floating exception due to overflow. Finally, it is much faster */ 00214 /* than single precision on 64-bit architectures like the DEC Alpha. I */ 00215 /* recommend double precision unless you want to generate a mesh for which */ 00216 /* you do not have enough memory. */ 00217 00218 /* #define SINGLE */ 00219 00220 #ifdef SINGLE 00221 #define REAL float 00222 #else /* not SINGLE */ 00223 #define REAL double 00224 #endif /* not SINGLE */ 00225 00226 /* If yours is not a Unix system, define the NO_TIMER compiler switch to */ 00227 /* remove the Unix-specific timing code. */ 00228 00229 /* #define NO_TIMER */ 00230 00231 /* To insert lots of self-checks for internal errors, define the SELF_CHECK */ 00232 /* symbol. This will slow down the program significantly. It is best to */ 00233 /* define the symbol using the -DSELF_CHECK compiler switch, but you could */ 00234 /* write "#define SELF_CHECK" below. If you are modifying this code, I */ 00235 /* recommend you turn self-checks on until your work is debugged. */ 00236 00237 /* #define SELF_CHECK */ 00238 00239 /* To compile Triangle as a callable object library (triangle.o), define the */ 00240 /* TRILIBRARY symbol. Read the file triangle.h for details on how to call */ 00241 /* the procedure triangulate() that results. */ 00242 00243 /* #define TRILIBRARY */ 00244 00245 /* It is possible to generate a smaller version of Triangle using one or */ 00246 /* both of the following symbols. Define the REDUCED symbol to eliminate */ 00247 /* all features that are primarily of research interest; specifically, the */ 00248 /* -i, -F, -s, and -C switches. Define the CDT_ONLY symbol to eliminate */ 00249 /* all meshing algorithms above and beyond constrained Delaunay */ 00250 /* triangulation; specifically, the -r, -q, -a, -u, -D, -S, and -s */ 00251 /* switches. These reductions are most likely to be useful when */ 00252 /* generating an object library (triangle.o) by defining the TRILIBRARY */ 00253 /* symbol. */ 00254 00255 /* #define REDUCED */ 00256 /* #define CDT_ONLY */ 00257 00258 /* On some machines, my exact arithmetic routines might be defeated by the */ 00259 /* use of internal extended precision floating-point registers. The best */ 00260 /* way to solve this problem is to set the floating-point registers to use */ 00261 /* single or double precision internally. On 80x86 processors, this may */ 00262 /* be accomplished by setting the CPU86 symbol for the Microsoft C */ 00263 /* compiler, or the LINUX symbol for the gcc compiler running on Linux. */ 00264 /* */ 00265 /* An inferior solution is to declare certain values as `volatile', thus */ 00266 /* forcing them to be stored to memory and rounded off. Unfortunately, */ 00267 /* this solution might slow Triangle down quite a bit. To use volatile */ 00268 /* values, write "#define INEXACT volatile" below. Normally, however, */ 00269 /* INEXACT should be defined to be nothing. ("#define INEXACT".) */ 00270 /* */ 00271 /* For more discussion, see http://www.cs.cmu.edu/~quake/robust.pc.html . */ 00272 /* For yet more discussion, see Section 5 of my paper, "Adaptive Precision */ 00273 /* Floating-Point Arithmetic and Fast Robust Geometric Predicates" (also */ 00274 /* available as Section 6.6 of my dissertation). */ 00275 00276 /* #define CPU86 */ 00277 /* #define LINUX */ 00278 00279 #define INEXACT /* Nothing */ 00280 /* #define INEXACT volatile */ 00281 00282 /* Maximum number of characters in a file name (including the null). */ 00283 00284 #define FILENAMESIZE 2048 00285 00286 /* Maximum number of characters in a line read from a file (including the */ 00287 /* null). */ 00288 00289 #define INPUTLINESIZE 1024 00290 00291 /* For efficiency, a variety of data structures are allocated in bulk. The */ 00292 /* following constants determine how many of each structure is allocated */ 00293 /* at once. */ 00294 00295 #define TRIPERBLOCK 4092 /* Number of triangles allocated at once. */ 00296 #define SUBSEGPERBLOCK 508 /* Number of subsegments allocated at once. */ 00297 #define VERTEXPERBLOCK 4092 /* Number of vertices allocated at once. */ 00298 #define VIRUSPERBLOCK 1020 /* Number of virus triangles allocated at once. */ 00299 /* Number of encroached subsegments allocated at once. */ 00300 #define BADSUBSEGPERBLOCK 252 00301 /* Number of skinny triangles allocated at once. */ 00302 #define BADTRIPERBLOCK 4092 00303 /* Number of flipped triangles allocated at once. */ 00304 #define FLIPSTACKERPERBLOCK 252 00305 /* Number of splay tree nodes allocated at once. */ 00306 #define SPLAYNODEPERBLOCK 508 00307 00308 /* The vertex types. A DEADVERTEX has been deleted entirely. An */ 00309 /* UNDEADVERTEX is not part of the mesh, but is written to the output */ 00310 /* .node file and affects the node indexing in the other output files. */ 00311 00312 #define INPUTVERTEX 0 00313 #define SEGMENTVERTEX 1 00314 #define FREEVERTEX 2 00315 #define DEADVERTEX -32768 00316 #define UNDEADVERTEX -32767 00317 00318 /* The next line is used to outsmart some very stupid compilers. If your */ 00319 /* compiler is smarter, feel free to replace the "int" with "void". */ 00320 /* Not that it matters. */ 00321 00322 #define VOID int 00323 00324 /* Two constants for algorithms based on random sampling. Both constants */ 00325 /* have been chosen empirically to optimize their respective algorithms. */ 00326 00327 /* Used for the point location scheme of Mucke, Saias, and Zhu, to decide */ 00328 /* how large a random sample of triangles to inspect. */ 00329 00330 #define SAMPLEFACTOR 11 00331 00332 /* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */ 00333 /* of boundary edges should be maintained in the splay tree for point */ 00334 /* location on the front. */ 00335 00336 #define SAMPLERATE 10 00337 00338 /* A number that speaks for itself, every kissable digit. */ 00339 00340 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308 00341 00342 /* Another fave. */ 00343 00344 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732 00345 00346 /* And here's one for those of you who are intimidated by math. */ 00347 00348 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333 00349 00350 #include <stdio.h> 00351 #include <stdlib.h> 00352 #include <string.h> 00353 #include <math.h> 00354 #ifndef NO_TIMER 00355 #include <sys/time.h> 00356 #endif /* not NO_TIMER */ 00357 #ifdef CPU86 00358 #include <float.h> 00359 #endif /* CPU86 */ 00360 #ifdef LINUX 00361 #include <fpu_control.h> 00362 #endif /* LINUX */ 00363 #ifdef TRILIBRARY 00364 #include "triangle.h" 00365 #endif /* TRILIBRARY */ 00366 00367 /* A few forward declarations. */ 00368 00369 #ifndef TRILIBRARY 00370 char *readline(); 00371 char *findfield(); 00372 #endif /* not TRILIBRARY */ 00373 00374 /* Labels that signify the result of point location. The result of a */ 00375 /* search indicates that the point falls in the interior of a triangle, on */ 00376 /* an edge, on a vertex, or outside the mesh. */ 00377 00378 enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE}; 00379 00380 /* Labels that signify the result of vertex insertion. The result indicates */ 00381 /* that the vertex was inserted with complete success, was inserted but */ 00382 /* encroaches upon a subsegment, was not inserted because it lies on a */ 00383 /* segment, or was not inserted because another vertex occupies the same */ 00384 /* location. */ 00385 00386 enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX, 00387 DUPLICATEVERTEX}; 00388 00389 /* Labels that signify the result of direction finding. The result */ 00390 /* indicates that a segment connecting the two query points falls within */ 00391 /* the direction triangle, along the left edge of the direction triangle, */ 00392 /* or along the right edge of the direction triangle. */ 00393 00394 enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR}; 00395 00396 /*****************************************************************************/ 00397 /* */ 00398 /* The basic mesh data structures */ 00399 /* */ 00400 /* There are three: vertices, triangles, and subsegments (abbreviated */ 00401 /* `subseg'). These three data structures, linked by pointers, comprise */ 00402 /* the mesh. A vertex simply represents a mesh vertex and its properties. */ 00403 /* A triangle is a triangle. A subsegment is a special data structure used */ 00404 /* to represent an impenetrable edge of the mesh (perhaps on the outer */ 00405 /* boundary, on the boundary of a hole, or part of an internal boundary */ 00406 /* separating two triangulated regions). Subsegments represent boundaries, */ 00407 /* defined by the user, that triangles may not lie across. */ 00408 /* */ 00409 /* A triangle consists of a list of three vertices, a list of three */ 00410 /* adjoining triangles, a list of three adjoining subsegments (when */ 00411 /* segments exist), an arbitrary number of optional user-defined */ 00412 /* floating-point attributes, and an optional area constraint. The latter */ 00413 /* is an upper bound on the permissible area of each triangle in a region, */ 00414 /* used for mesh refinement. */ 00415 /* */ 00416 /* For a triangle on a boundary of the mesh, some or all of the neighboring */ 00417 /* triangles may not be present. For a triangle in the interior of the */ 00418 /* mesh, often no neighboring subsegments are present. Such absent */ 00419 /* triangles and subsegments are never represented by NULL pointers; they */ 00420 /* are represented by two special records: `dummytri', the triangle that */ 00421 /* fills "outer space", and `dummysub', the omnipresent subsegment. */ 00422 /* `dummytri' and `dummysub' are used for several reasons; for instance, */ 00423 /* they can be dereferenced and their contents examined without violating */ 00424 /* protected memory. */ 00425 /* */ 00426 /* However, it is important to understand that a triangle includes other */ 00427 /* information as well. The pointers to adjoining vertices, triangles, and */ 00428 /* subsegments are ordered in a way that indicates their geometric relation */ 00429 /* to each other. Furthermore, each of these pointers contains orientation */ 00430 /* information. Each pointer to an adjoining triangle indicates which face */ 00431 /* of that triangle is contacted. Similarly, each pointer to an adjoining */ 00432 /* subsegment indicates which side of that subsegment is contacted, and how */ 00433 /* the subsegment is oriented relative to the triangle. */ 00434 /* */ 00435 /* The data structure representing a subsegment may be thought to be */ 00436 /* abutting the edge of one or two triangle data structures: either */ 00437 /* sandwiched between two triangles, or resting against one triangle on an */ 00438 /* exterior boundary or hole boundary. */ 00439 /* */ 00440 /* A subsegment consists of a list of four vertices--the vertices of the */ 00441 /* subsegment, and the vertices of the segment it is a part of--a list of */ 00442 /* two adjoining subsegments, and a list of two adjoining triangles. One */ 00443 /* of the two adjoining triangles may not be present (though there should */ 00444 /* always be one), and neighboring subsegments might not be present. */ 00445 /* Subsegments also store a user-defined integer "boundary marker". */ 00446 /* Typically, this integer is used to indicate what boundary conditions are */ 00447 /* to be applied at that location in a finite element simulation. */ 00448 /* */ 00449 /* Like triangles, subsegments maintain information about the relative */ 00450 /* orientation of neighboring objects. */ 00451 /* */ 00452 /* Vertices are relatively simple. A vertex is a list of floating-point */ 00453 /* numbers, starting with the x, and y coordinates, followed by an */ 00454 /* arbitrary number of optional user-defined floating-point attributes, */ 00455 /* followed by an integer boundary marker. During the segment insertion */ 00456 /* phase, there is also a pointer from each vertex to a triangle that may */ 00457 /* contain it. Each pointer is not always correct, but when one is, it */ 00458 /* speeds up segment insertion. These pointers are assigned values once */ 00459 /* at the beginning of the segment insertion phase, and are not used or */ 00460 /* updated except during this phase. Edge flipping during segment */ 00461 /* insertion will render some of them incorrect. Hence, don't rely upon */ 00462 /* them for anything. */ 00463 /* */ 00464 /* Other than the exception mentioned above, vertices have no information */ 00465 /* about what triangles, subfacets, or subsegments they are linked to. */ 00466 /* */ 00467 /*****************************************************************************/ 00468 00469 /*****************************************************************************/ 00470 /* */ 00471 /* Handles */ 00472 /* */ 00473 /* The oriented triangle (`otri') and oriented subsegment (`osub') data */ 00474 /* structures defined below do not themselves store any part of the mesh. */ 00475 /* The mesh itself is made of `triangle's, `subseg's, and `vertex's. */ 00476 /* */ 00477 /* Oriented triangles and oriented subsegments will usually be referred to */ 00478 /* as "handles." A handle is essentially a pointer into the mesh; it */ 00479 /* allows you to "hold" one particular part of the mesh. Handles are used */ 00480 /* to specify the regions in which one is traversing and modifying the mesh.*/ 00481 /* A single `triangle' may be held by many handles, or none at all. (The */ 00482 /* latter case is not a memory leak, because the triangle is still */ 00483 /* connected to other triangles in the mesh.) */ 00484 /* */ 00485 /* An `otri' is a handle that holds a triangle. It holds a specific edge */ 00486 /* of the triangle. An `osub' is a handle that holds a subsegment. It */ 00487 /* holds either the left or right side of the subsegment. */ 00488 /* */ 00489 /* Navigation about the mesh is accomplished through a set of mesh */ 00490 /* manipulation primitives, further below. Many of these primitives take */ 00491 /* a handle and produce a new handle that holds the mesh near the first */ 00492 /* handle. Other primitives take two handles and glue the corresponding */ 00493 /* parts of the mesh together. The orientation of the handles is */ 00494 /* important. For instance, when two triangles are glued together by the */ 00495 /* bond() primitive, they are glued at the edges on which the handles lie. */ 00496 /* */ 00497 /* Because vertices have no information about which triangles they are */ 00498 /* attached to, I commonly represent a vertex by use of a handle whose */ 00499 /* origin is the vertex. A single handle can simultaneously represent a */ 00500 /* triangle, an edge, and a vertex. */ 00501 /* */ 00502 /*****************************************************************************/ 00503 00504 /* The triangle data structure. Each triangle contains three pointers to */ 00505 /* adjoining triangles, plus three pointers to vertices, plus three */ 00506 /* pointers to subsegments (declared below; these pointers are usually */ 00507 /* `dummysub'). It may or may not also contain user-defined attributes */ 00508 /* and/or a floating-point "area constraint." It may also contain extra */ 00509 /* pointers for nodes, when the user asks for high-order elements. */ 00510 /* Because the size and structure of a `triangle' is not decided until */ 00511 /* runtime, I haven't simply declared the type `triangle' as a struct. */ 00512 00513 typedef REAL **triangle; /* Really: typedef triangle *triangle */ 00514 00515 /* An oriented triangle: includes a pointer to a triangle and orientation. */ 00516 /* The orientation denotes an edge of the triangle. Hence, there are */ 00517 /* three possible orientations. By convention, each edge always points */ 00518 /* counterclockwise about the corresponding triangle. */ 00519 00520 struct otri { 00521 triangle *tri; 00522 int orient; /* Ranges from 0 to 2. */ 00523 }; 00524 00525 /* The subsegment data structure. Each subsegment contains two pointers to */ 00526 /* adjoining subsegments, plus four pointers to vertices, plus two */ 00527 /* pointers to adjoining triangles, plus one boundary marker, plus one */ 00528 /* segment number. */ 00529 00530 typedef REAL **subseg; /* Really: typedef subseg *subseg */ 00531 00532 /* An oriented subsegment: includes a pointer to a subsegment and an */ 00533 /* orientation. The orientation denotes a side of the edge. Hence, there */ 00534 /* are two possible orientations. By convention, the edge is always */ 00535 /* directed so that the "side" denoted is the right side of the edge. */ 00536 00537 struct osub { 00538 subseg *ss; 00539 int ssorient; /* Ranges from 0 to 1. */ 00540 }; 00541 00542 /* The vertex data structure. Each vertex is actually an array of REALs. */ 00543 /* The number of REALs is unknown until runtime. An integer boundary */ 00544 /* marker, and sometimes a pointer to a triangle, is appended after the */ 00545 /* REALs. */ 00546 00547 typedef REAL *vertex; 00548 00549 /* A queue used to store encroached subsegments. Each subsegment's vertices */ 00550 /* are stored so that we can check whether a subsegment is still the same. */ 00551 00552 struct badsubseg { 00553 subseg encsubseg; /* An encroached subsegment. */ 00554 vertex subsegorg, subsegdest; /* Its two vertices. */ 00555 }; 00556 00557 /* A queue used to store bad triangles. The key is the square of the cosine */ 00558 /* of the smallest angle of the triangle. Each triangle's vertices are */ 00559 /* stored so that one can check whether a triangle is still the same. */ 00560 00561 struct badtriang { 00562 triangle poortri; /* A skinny or too-large triangle. */ 00563 REAL key; /* cos^2 of smallest (apical) angle. */ 00564 vertex triangorg, triangdest, triangapex; /* Its three vertices. */ 00565 struct badtriang *nexttriang; /* Pointer to next bad triangle. */ 00566 }; 00567 00568 /* A stack of triangles flipped during the most recent vertex insertion. */ 00569 /* The stack is used to undo the vertex insertion if the vertex encroaches */ 00570 /* upon a subsegment. */ 00571 00572 struct flipstacker { 00573 triangle flippedtri; /* A recently flipped triangle. */ 00574 struct flipstacker* prevflip; /* Previous flip in the stack. */ 00575 }; 00576 00577 /* A node in a heap used to store events for the sweepline Delaunay */ 00578 /* algorithm. Nodes do not point directly to their parents or children in */ 00579 /* the heap. Instead, each node knows its position in the heap, and can */ 00580 /* look up its parent and children in a separate array. The `eventptr' */ 00581 /* points either to a `vertex' or to a triangle (in encoded format, so */ 00582 /* that an orientation is included). In the latter case, the origin of */ 00583 /* the oriented triangle is the apex of a "circle event" of the sweepline */ 00584 /* algorithm. To distinguish site events from circle events, all circle */ 00585 /* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */ 00586 00587 struct event { 00588 REAL xkey, ykey; /* Coordinates of the event. */ 00589 VOID *eventptr; /* Can be a vertex or the location of a circle event. */ 00590 int heapposition; /* Marks this event's position in the heap. */ 00591 }; 00592 00593 /* A node in the splay tree. Each node holds an oriented ghost triangle */ 00594 /* that represents a boundary edge of the growing triangulation. When a */ 00595 /* circle event covers two boundary edges with a triangle, so that they */ 00596 /* are no longer boundary edges, those edges are not immediately deleted */ 00597 /* from the tree; rather, they are lazily deleted when they are next */ 00598 /* encountered. (Since only a random sample of boundary edges are kept */ 00599 /* in the tree, lazy deletion is faster.) `keydest' is used to verify */ 00600 /* that a triangle is still the same as when it entered the splay tree; if */ 00601 /* it has been rotated (due to a circle event), it no longer represents a */ 00602 /* boundary edge and should be deleted. */ 00603 00604 struct splaynode { 00605 struct otri keyedge; /* Lprev of an edge on the front. */ 00606 vertex keydest; /* Used to verify that splay node is still live. */ 00607 struct splaynode *lchild, *rchild; /* Children in splay tree. */ 00608 }; 00609 00610 /* A type used to allocate memory. firstblock is the first block of items. */ 00611 /* nowblock is the block from which items are currently being allocated. */ 00612 /* nextitem points to the next slab of free memory for an item. */ 00613 /* deaditemstack is the head of a linked list (stack) of deallocated items */ 00614 /* that can be recycled. unallocateditems is the number of items that */ 00615 /* remain to be allocated from nowblock. */ 00616 /* */ 00617 /* Traversal is the process of walking through the entire list of items, and */ 00618 /* is separate from allocation. Note that a traversal will visit items on */ 00619 /* the "deaditemstack" stack as well as live items. pathblock points to */ 00620 /* the block currently being traversed. pathitem points to the next item */ 00621 /* to be traversed. pathitemsleft is the number of items that remain to */ 00622 /* be traversed in pathblock. */ 00623 /* */ 00624 /* alignbytes determines how new records should be aligned in memory. */ 00625 /* itembytes is the length of a record in bytes (after rounding up). */ 00626 /* itemsperblock is the number of items allocated at once in a single */ 00627 /* block. itemsfirstblock is the number of items in the first block, */ 00628 /* which can vary from the others. items is the number of currently */ 00629 /* allocated items. maxitems is the maximum number of items that have */ 00630 /* been allocated at once; it is the current number of items plus the */ 00631 /* number of records kept on deaditemstack. */ 00632 00633 struct memorypool { 00634 VOID **firstblock, **nowblock; 00635 VOID *nextitem; 00636 VOID *deaditemstack; 00637 VOID **pathblock; 00638 VOID* pathitem; 00639 int alignbytes; 00640 int itembytes; 00641 int itemsperblock; 00642 int itemsfirstblock; 00643 long items, maxitems; 00644 int unallocateditems; 00645 int pathitemsleft; 00646 }; 00647 00648 00649 /* Global constants. */ 00650 00651 REAL splitter; /* Used to split REAL factors for exact multiplication. */ 00652 REAL epsilon; /* Floating-point machine epsilon. */ 00653 REAL resulterrbound; 00654 REAL ccwerrboundA, ccwerrboundB, ccwerrboundC; 00655 REAL iccerrboundA, iccerrboundB, iccerrboundC; 00656 REAL o3derrboundA, o3derrboundB, o3derrboundC; 00657 00658 /* Random number seed is not constant, but I've made it global anyway. */ 00659 00660 unsigned long randomseed; /* Current random number seed. */ 00661 00662 00663 /* Mesh data structure. Triangle operates on only one mesh, but the mesh */ 00664 /* structure is used (instead of global variables) to allow reentrancy. */ 00665 00666 struct mesh { 00667 00668 /* Variables used to allocate memory for triangles, subsegments, vertices, */ 00669 /* viri (triangles being eaten), encroached segments, bad (skinny or too */ 00670 /* large) triangles, and splay tree nodes. */ 00671 00672 struct memorypool triangles; 00673 struct memorypool subsegs; 00674 struct memorypool vertices; 00675 struct memorypool viri; 00676 struct memorypool badsubsegs; 00677 struct memorypool badtriangles; 00678 struct memorypool flipstackers; 00679 struct memorypool splaynodes; 00680 00681 /* Variables that maintain the bad triangle queues. The queues are */ 00682 /* ordered from 4095 (highest priority) to 0 (lowest priority). */ 00683 00684 struct badtriang *queuefront[4096]; 00685 struct badtriang *queuetail[4096]; 00686 int nextnonemptyq[4096]; 00687 int firstnonemptyq; 00688 00689 /* Variable that maintains the stack of recently flipped triangles. */ 00690 00691 struct flipstacker *lastflip; 00692 00693 /* Other variables. */ 00694 00695 REAL xmin, xmax, ymin, ymax; /* x and y bounds. */ 00696 REAL xminextreme; /* Nonexistent x value used as a flag in sweepline. */ 00697 int invertices; /* Number of input vertices. */ 00698 int inelements; /* Number of input triangles. */ 00699 int insegments; /* Number of input segments. */ 00700 int holes; /* Number of input holes. */ 00701 int regions; /* Number of input regions. */ 00702 int undeads; /* Number of input vertices that don't appear in the mesh. */ 00703 long edges; /* Number of output edges. */ 00704 int mesh_dim; /* Dimension (ought to be 2). */ 00705 int nextras; /* Number of attributes per vertex. */ 00706 int eextras; /* Number of attributes per triangle. */ 00707 long hullsize; /* Number of edges in convex hull. */ 00708 int steinerleft; /* Number of Steiner points not yet used. */ 00709 int vertexmarkindex; /* Index to find boundary marker of a vertex. */ 00710 int vertex2triindex; /* Index to find a triangle adjacent to a vertex. */ 00711 int highorderindex; /* Index to find extra nodes for high-order elements. */ 00712 int elemattribindex; /* Index to find attributes of a triangle. */ 00713 int areaboundindex; /* Index to find area bound of a triangle. */ 00714 int checksegments; /* Are there segments in the triangulation yet? */ 00715 int checkquality; /* Has quality triangulation begun yet? */ 00716 int readnodefile; /* Has a .node file been read? */ 00717 long samples; /* Number of random samples for point location. */ 00718 00719 long incirclecount; /* Number of incircle tests performed. */ 00720 long counterclockcount; /* Number of counterclockwise tests performed. */ 00721 long orient3dcount; /* Number of 3D orientation tests performed. */ 00722 long hyperbolacount; /* Number of right-of-hyperbola tests performed. */ 00723 long circumcentercount; /* Number of circumcenter calculations performed. */ 00724 long circletopcount; /* Number of circle top calculations performed. */ 00725 00726 /* Triangular bounding box vertices. */ 00727 00728 vertex infvertex1, infvertex2, infvertex3; 00729 00730 /* Pointer to the `triangle' that occupies all of "outer space." */ 00731 00732 triangle *dummytri; 00733 triangle *dummytribase; /* Keep base address so we can free() it later. */ 00734 00735 /* Pointer to the omnipresent subsegment. Referenced by any triangle or */ 00736 /* subsegment that isn't really connected to a subsegment at that */ 00737 /* location. */ 00738 00739 subseg *dummysub; 00740 subseg *dummysubbase; /* Keep base address so we can free() it later. */ 00741 00742 /* Pointer to a recently visited triangle. Improves point location if */ 00743 /* proximate vertices are inserted sequentially. */ 00744 00745 struct otri recenttri; 00746 00747 }; /* End of `struct mesh'. */ 00748 00749 00750 /* Data structure for command line switches and file names. This structure */ 00751 /* is used (instead of global variables) to allow reentrancy. */ 00752 00753 struct behavior { 00754 00755 /* Switches for the triangulator. */ 00756 /* poly: -p switch. refine: -r switch. */ 00757 /* quality: -q switch. */ 00758 /* minangle: minimum angle bound, specified after -q switch. */ 00759 /* goodangle: cosine squared of minangle. */ 00760 /* offconstant: constant used to place off-center Steiner points. */ 00761 /* vararea: -a switch without number. */ 00762 /* fixedarea: -a switch with number. */ 00763 /* maxarea: maximum area bound, specified after -a switch. */ 00764 /* usertest: -u switch. */ 00765 /* regionattrib: -A switch. convex: -c switch. */ 00766 /* weighted: 1 for -w switch, 2 for -W switch. jettison: -j switch */ 00767 /* firstnumber: inverse of -z switch. All items are numbered starting */ 00768 /* from `firstnumber'. */ 00769 /* edgesout: -e switch. voronoi: -v switch. */ 00770 /* neighbors: -n switch. geomview: -g switch. */ 00771 /* nobound: -B switch. nopolywritten: -P switch. */ 00772 /* nonodewritten: -N switch. noelewritten: -E switch. */ 00773 /* noiterationnum: -I switch. noholes: -O switch. */ 00774 /* noexact: -X switch. */ 00775 /* order: element order, specified after -o switch. */ 00776 /* nobisect: count of how often -Y switch is selected. */ 00777 /* steiner: maximum number of Steiner points, specified after -S switch. */ 00778 /* incremental: -i switch. sweepline: -F switch. */ 00779 /* dwyer: inverse of -l switch. */ 00780 /* splitseg: -s switch. */ 00781 /* conformdel: -D switch. docheck: -C switch. */ 00782 /* quiet: -Q switch. verbose: count of how often -V switch is selected. */ 00783 /* usesegments: -p, -r, -q, or -c switch; determines whether segments are */ 00784 /* used at all. */ 00785 /* */ 00786 /* Read the instructions to find out the meaning of these switches. */ 00787 00788 int poly, refine, quality, vararea, fixedarea, usertest; 00789 int regionattrib, convex, weighted, jettison; 00790 int firstnumber; 00791 int edgesout, voronoi, neighbors, geomview; 00792 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum; 00793 int noholes, noexact, conformdel; 00794 int incremental, sweepline, dwyer; 00795 int splitseg; 00796 int docheck; 00797 int quiet, verbose; 00798 int usesegments; 00799 int order; 00800 int nobisect; 00801 int steiner; 00802 REAL minangle, goodangle, offconstant; 00803 REAL maxarea; 00804 00805 /* Variables for file names. */ 00806 00807 #ifndef TRILIBRARY 00808 char innodefilename[FILENAMESIZE]; 00809 char inelefilename[FILENAMESIZE]; 00810 char inpolyfilename[FILENAMESIZE]; 00811 char areafilename[FILENAMESIZE]; 00812 char outnodefilename[FILENAMESIZE]; 00813 char outelefilename[FILENAMESIZE]; 00814 char outpolyfilename[FILENAMESIZE]; 00815 char edgefilename[FILENAMESIZE]; 00816 char vnodefilename[FILENAMESIZE]; 00817 char vedgefilename[FILENAMESIZE]; 00818 char neighborfilename[FILENAMESIZE]; 00819 char offfilename[FILENAMESIZE]; 00820 #endif /* not TRILIBRARY */ 00821 00822 }; /* End of `struct behavior'. */ 00823 00824 00825 /*****************************************************************************/ 00826 /* */ 00827 /* Mesh manipulation primitives. Each triangle contains three pointers to */ 00828 /* other triangles, with orientations. Each pointer points not to the */ 00829 /* first byte of a triangle, but to one of the first three bytes of a */ 00830 /* triangle. It is necessary to extract both the triangle itself and the */ 00831 /* orientation. To save memory, I keep both pieces of information in one */ 00832 /* pointer. To make this possible, I assume that all triangles are aligned */ 00833 /* to four-byte boundaries. The decode() routine below decodes a pointer, */ 00834 /* extracting an orientation (in the range 0 to 2) and a pointer to the */ 00835 /* beginning of a triangle. The encode() routine compresses a pointer to a */ 00836 /* triangle and an orientation into a single pointer. My assumptions that */ 00837 /* triangles are four-byte-aligned and that the `unsigned long' type is */ 00838 /* long enough to hold a pointer are two of the few kludges in this program.*/ 00839 /* */ 00840 /* Subsegments are manipulated similarly. A pointer to a subsegment */ 00841 /* carries both an address and an orientation in the range 0 to 1. */ 00842 /* */ 00843 /* The other primitives take an oriented triangle or oriented subsegment, */ 00844 /* and return an oriented triangle or oriented subsegment or vertex; or */ 00845 /* they change the connections in the data structure. */ 00846 /* */ 00847 /* Below, triangles and subsegments are denoted by their vertices. The */ 00848 /* triangle abc has origin (org) a, destination (dest) b, and apex (apex) */ 00849 /* c. These vertices occur in counterclockwise order about the triangle. */ 00850 /* The handle abc may simultaneously denote vertex a, edge ab, and triangle */ 00851 /* abc. */ 00852 /* */ 00853 /* Similarly, the subsegment ab has origin (sorg) a and destination (sdest) */ 00854 /* b. If ab is thought to be directed upward (with b directly above a), */ 00855 /* then the handle ab is thought to grasp the right side of ab, and may */ 00856 /* simultaneously denote vertex a and edge ab. */ 00857 /* */ 00858 /* An asterisk (*) denotes a vertex whose identity is unknown. */ 00859 /* */ 00860 /* Given this notation, a partial list of mesh manipulation primitives */ 00861 /* follows. */ 00862 /* */ 00863 /* */ 00864 /* For triangles: */ 00865 /* */ 00866 /* sym: Find the abutting triangle; same edge. */ 00867 /* sym(abc) -> ba* */ 00868 /* */ 00869 /* lnext: Find the next edge (counterclockwise) of a triangle. */ 00870 /* lnext(abc) -> bca */ 00871 /* */ 00872 /* lprev: Find the previous edge (clockwise) of a triangle. */ 00873 /* lprev(abc) -> cab */ 00874 /* */ 00875 /* onext: Find the next edge counterclockwise with the same origin. */ 00876 /* onext(abc) -> ac* */ 00877 /* */ 00878 /* oprev: Find the next edge clockwise with the same origin. */ 00879 /* oprev(abc) -> a*b */ 00880 /* */ 00881 /* dnext: Find the next edge counterclockwise with the same destination. */ 00882 /* dnext(abc) -> *ba */ 00883 /* */ 00884 /* dprev: Find the next edge clockwise with the same destination. */ 00885 /* dprev(abc) -> cb* */ 00886 /* */ 00887 /* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */ 00888 /* rnext(abc) -> *a* */ 00889 /* */ 00890 /* rprev: Find the previous edge (clockwise) of the adjacent triangle. */ 00891 /* rprev(abc) -> b** */ 00892 /* */ 00893 /* org: Origin dest: Destination apex: Apex */ 00894 /* org(abc) -> a dest(abc) -> b apex(abc) -> c */ 00895 /* */ 00896 /* bond: Bond two triangles together at the resepective handles. */ 00897 /* bond(abc, bad) */ 00898 /* */ 00899 /* */ 00900 /* For subsegments: */ 00901 /* */ 00902 /* ssym: Reverse the orientation of a subsegment. */ 00903 /* ssym(ab) -> ba */ 00904 /* */ 00905 /* spivot: Find adjoining subsegment with the same origin. */ 00906 /* spivot(ab) -> a* */ 00907 /* */ 00908 /* snext: Find next subsegment in sequence. */ 00909 /* snext(ab) -> b* */ 00910 /* */ 00911 /* sorg: Origin sdest: Destination */ 00912 /* sorg(ab) -> a sdest(ab) -> b */ 00913 /* */ 00914 /* sbond: Bond two subsegments together at the respective origins. */ 00915 /* sbond(ab, ac) */ 00916 /* */ 00917 /* */ 00918 /* For interacting tetrahedra and subfacets: */ 00919 /* */ 00920 /* tspivot: Find a subsegment abutting a triangle. */ 00921 /* tspivot(abc) -> ba */ 00922 /* */ 00923 /* stpivot: Find a triangle abutting a subsegment. */ 00924 /* stpivot(ab) -> ba* */ 00925 /* */ 00926 /* tsbond: Bond a triangle to a subsegment. */ 00927 /* tsbond(abc, ba) */ 00928 /* */ 00929 /*****************************************************************************/ 00930 00931 /********* Mesh manipulation primitives begin here *********/ 00935 /* Fast lookup arrays to speed some of the mesh manipulation primitives. */ 00936 00937 int plus1mod3[3] = {1, 2, 0}; 00938 int minus1mod3[3] = {2, 0, 1}; 00939 00940 /********* Primitives for triangles *********/ 00941 /* */ 00942 /* */ 00943 00944 /* decode() converts a pointer to an oriented triangle. The orientation is */ 00945 /* extracted from the two least significant bits of the pointer. */ 00946 00947 #define decode(ptr, otri) \ 00948 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \ 00949 (otri).tri = (triangle *) \ 00950 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient) 00951 00952 /* encode() compresses an oriented triangle into a single pointer. It */ 00953 /* relies on the assumption that all triangles are aligned to four-byte */ 00954 /* boundaries, so the two least significant bits of (otri).tri are zero. */ 00955 00956 #define encode(otri) \ 00957 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient) 00958 00959 /* The following handle manipulation primitives are all described by Guibas */ 00960 /* and Stolfi. However, Guibas and Stolfi use an edge-based data */ 00961 /* structure, whereas I use a triangle-based data structure. */ 00962 00963 /* sym() finds the abutting triangle, on the same edge. Note that the edge */ 00964 /* direction is necessarily reversed, because the handle specified by an */ 00965 /* oriented triangle is directed counterclockwise around the triangle. */ 00966 00967 #define sym(otri1, otri2) \ 00968 ptr = (otri1).tri[(otri1).orient]; \ 00969 decode(ptr, otri2); 00970 00971 #define symself(otri) \ 00972 ptr = (otri).tri[(otri).orient]; \ 00973 decode(ptr, otri); 00974 00975 /* lnext() finds the next edge (counterclockwise) of a triangle. */ 00976 00977 #define lnext(otri1, otri2) \ 00978 (otri2).tri = (otri1).tri; \ 00979 (otri2).orient = plus1mod3[(otri1).orient] 00980 00981 #define lnextself(otri) \ 00982 (otri).orient = plus1mod3[(otri).orient] 00983 00984 /* lprev() finds the previous edge (clockwise) of a triangle. */ 00985 00986 #define lprev(otri1, otri2) \ 00987 (otri2).tri = (otri1).tri; \ 00988 (otri2).orient = minus1mod3[(otri1).orient] 00989 00990 #define lprevself(otri) \ 00991 (otri).orient = minus1mod3[(otri).orient] 00992 00993 /* onext() spins counterclockwise around a vertex; that is, it finds the */ 00994 /* next edge with the same origin in the counterclockwise direction. This */ 00995 /* edge is part of a different triangle. */ 00996 00997 #define onext(otri1, otri2) \ 00998 lprev(otri1, otri2); \ 00999 symself(otri2); 01000 01001 #define onextself(otri) \ 01002 lprevself(otri); \ 01003 symself(otri); 01004 01005 /* oprev() spins clockwise around a vertex; that is, it finds the next edge */ 01006 /* with the same origin in the clockwise direction. This edge is part of */ 01007 /* a different triangle. */ 01008 01009 #define oprev(otri1, otri2) \ 01010 sym(otri1, otri2); \ 01011 lnextself(otri2); 01012 01013 #define oprevself(otri) \ 01014 symself(otri); \ 01015 lnextself(otri); 01016 01017 /* dnext() spins counterclockwise around a vertex; that is, it finds the */ 01018 /* next edge with the same destination in the counterclockwise direction. */ 01019 /* This edge is part of a different triangle. */ 01020 01021 #define dnext(otri1, otri2) \ 01022 sym(otri1, otri2); \ 01023 lprevself(otri2); 01024 01025 #define dnextself(otri) \ 01026 symself(otri); \ 01027 lprevself(otri); 01028 01029 /* dprev() spins clockwise around a vertex; that is, it finds the next edge */ 01030 /* with the same destination in the clockwise direction. This edge is */ 01031 /* part of a different triangle. */ 01032 01033 #define dprev(otri1, otri2) \ 01034 lnext(otri1, otri2); \ 01035 symself(otri2); 01036 01037 #define dprevself(otri) \ 01038 lnextself(otri); \ 01039 symself(otri); 01040 01041 /* rnext() moves one edge counterclockwise about the adjacent triangle. */ 01042 /* (It's best understood by reading Guibas and Stolfi. It involves */ 01043 /* changing triangles twice.) */ 01044 01045 #define rnext(otri1, otri2) \ 01046 sym(otri1, otri2); \ 01047 lnextself(otri2); \ 01048 symself(otri2); 01049 01050 #define rnextself(otri) \ 01051 symself(otri); \ 01052 lnextself(otri); \ 01053 symself(otri); 01054 01055 /* rprev() moves one edge clockwise about the adjacent triangle. */ 01056 /* (It's best understood by reading Guibas and Stolfi. It involves */ 01057 /* changing triangles twice.) */ 01058 01059 #define rprev(otri1, otri2) \ 01060 sym(otri1, otri2); \ 01061 lprevself(otri2); \ 01062 symself(otri2); 01063 01064 #define rprevself(otri) \ 01065 symself(otri); \ 01066 lprevself(otri); \ 01067 symself(otri); 01068 01069 /* These primitives determine or set the origin, destination, or apex of a */ 01070 /* triangle. */ 01071 01072 #define org(otri, vertexptr) \ 01073 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3] 01074 01075 #define dest(otri, vertexptr) \ 01076 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3] 01077 01078 #define apex(otri, vertexptr) \ 01079 vertexptr = (vertex) (otri).tri[(otri).orient + 3] 01080 01081 #define setorg(otri, vertexptr) \ 01082 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr 01083 01084 #define setdest(otri, vertexptr) \ 01085 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr 01086 01087 #define setapex(otri, vertexptr) \ 01088 (otri).tri[(otri).orient + 3] = (triangle) vertexptr 01089 01090 /* Bond two triangles together. */ 01091 01092 #define bond(otri1, otri2) \ 01093 (otri1).tri[(otri1).orient] = encode(otri2); \ 01094 (otri2).tri[(otri2).orient] = encode(otri1) 01095 01096 /* Dissolve a bond (from one side). Note that the other triangle will still */ 01097 /* think it's connected to this triangle. Usually, however, the other */ 01098 /* triangle is being deleted entirely, or bonded to another triangle, so */ 01099 /* it doesn't matter. */ 01100 01101 #define dissolve(otri) \ 01102 (otri).tri[(otri).orient] = (triangle) m->dummytri 01103 01104 /* Copy an oriented triangle. */ 01105 01106 #define otricopy(otri1, otri2) \ 01107 (otri2).tri = (otri1).tri; \ 01108 (otri2).orient = (otri1).orient 01109 01110 /* Test for equality of oriented triangles. */ 01111 01112 #define otriequal(otri1, otri2) \ 01113 (((otri1).tri == (otri2).tri) && \ 01114 ((otri1).orient == (otri2).orient)) 01115 01116 /* Primitives to infect or cure a triangle with the virus. These rely on */ 01117 /* the assumption that all subsegments are aligned to four-byte boundaries.*/ 01118 01119 #define infect(otri) \ 01120 (otri).tri[6] = (triangle) \ 01121 ((unsigned long) (otri).tri[6] | (unsigned long) 2l) 01122 01123 #define uninfect(otri) \ 01124 (otri).tri[6] = (triangle) \ 01125 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l) 01126 01127 /* Test a triangle for viral infection. */ 01128 01129 #define infected(otri) \ 01130 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l) 01131 01132 /* Check or set a triangle's attributes. */ 01133 01134 #define elemattribute(otri, attnum) \ 01135 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] 01136 01137 #define setelemattribute(otri, attnum, value) \ 01138 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value 01139 01140 /* Check or set a triangle's maximum area bound. */ 01141 01142 #define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex] 01143 01144 #define setareabound(otri, value) \ 01145 ((REAL *) (otri).tri)[m->areaboundindex] = value 01146 01147 /* Check or set a triangle's deallocation. Its second pointer is set to */ 01148 /* NULL to indicate that it is not allocated. (Its first pointer is used */ 01149 /* for the stack of dead items.) Its fourth pointer (its first vertex) */ 01150 /* is set to NULL in case a `badtriang' structure points to it. */ 01151 01152 #define deadtri(tria) ((tria)[1] == (triangle) NULL) 01153 01154 #define killtri(tria) \ 01155 (tria)[1] = (triangle) NULL; \ 01156 (tria)[3] = (triangle) NULL 01157 01158 /********* Primitives for subsegments *********/ 01159 /* */ 01160 /* */ 01161 01162 /* sdecode() converts a pointer to an oriented subsegment. The orientation */ 01163 /* is extracted from the least significant bit of the pointer. The two */ 01164 /* least significant bits (one for orientation, one for viral infection) */ 01165 /* are masked out to produce the real pointer. */ 01166 01167 #define sdecode(sptr, osub) \ 01168 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \ 01169 (osub).ss = (subseg *) \ 01170 ((unsigned long) (sptr) & ~ (unsigned long) 3l) 01171 01172 /* sencode() compresses an oriented subsegment into a single pointer. It */ 01173 /* relies on the assumption that all subsegments are aligned to two-byte */ 01174 /* boundaries, so the least significant bit of (osub).ss is zero. */ 01175 01176 #define sencode(osub) \ 01177 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient) 01178 01179 /* ssym() toggles the orientation of a subsegment. */ 01180 01181 #define ssym(osub1, osub2) \ 01182 (osub2).ss = (osub1).ss; \ 01183 (osub2).ssorient = 1 - (osub1).ssorient 01184 01185 #define ssymself(osub) \ 01186 (osub).ssorient = 1 - (osub).ssorient 01187 01188 /* spivot() finds the other subsegment (from the same segment) that shares */ 01189 /* the same origin. */ 01190 01191 #define spivot(osub1, osub2) \ 01192 sptr = (osub1).ss[(osub1).ssorient]; \ 01193 sdecode(sptr, osub2) 01194 01195 #define spivotself(osub) \ 01196 sptr = (osub).ss[(osub).ssorient]; \ 01197 sdecode(sptr, osub) 01198 01199 /* snext() finds the next subsegment (from the same segment) in sequence; */ 01200 /* one whose origin is the input subsegment's destination. */ 01201 01202 #define snext(osub1, osub2) \ 01203 sptr = (osub1).ss[1 - (osub1).ssorient]; \ 01204 sdecode(sptr, osub2) 01205 01206 #define snextself(osub) \ 01207 sptr = (osub).ss[1 - (osub).ssorient]; \ 01208 sdecode(sptr, osub) 01209 01210 /* These primitives determine or set the origin or destination of a */ 01211 /* subsegment or the segment that includes it. */ 01212 01213 #define sorg(osub, vertexptr) \ 01214 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient] 01215 01216 #define sdest(osub, vertexptr) \ 01217 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient] 01218 01219 #define setsorg(osub, vertexptr) \ 01220 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr 01221 01222 #define setsdest(osub, vertexptr) \ 01223 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr 01224 01225 #define segorg(osub, vertexptr) \ 01226 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient] 01227 01228 #define segdest(osub, vertexptr) \ 01229 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient] 01230 01231 #define setsegorg(osub, vertexptr) \ 01232 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr 01233 01234 #define setsegdest(osub, vertexptr) \ 01235 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr 01236 01237 /* These primitives read or set a boundary marker. Boundary markers are */ 01238 /* used to hold user-defined tags for setting boundary conditions in */ 01239 /* finite element solvers. */ 01240 01241 #define mark(osub) (* (int *) ((osub).ss + 8)) 01242 01243 #define setmark(osub, value) \ 01244 * (int *) ((osub).ss + 8) = value 01245 01246 /* Bond two subsegments together. */ 01247 01248 #define sbond(osub1, osub2) \ 01249 (osub1).ss[(osub1).ssorient] = sencode(osub2); \ 01250 (osub2).ss[(osub2).ssorient] = sencode(osub1) 01251 01252 /* Dissolve a subsegment bond (from one side). Note that the other */ 01253 /* subsegment will still think it's connected to this subsegment. */ 01254 01255 #define sdissolve(osub) \ 01256 (osub).ss[(osub).ssorient] = (subseg) m->dummysub 01257 01258 /* Copy a subsegment. */ 01259 01260 #define subsegcopy(osub1, osub2) \ 01261 (osub2).ss = (osub1).ss; \ 01262 (osub2).ssorient = (osub1).ssorient 01263 01264 /* Test for equality of subsegments. */ 01265 01266 #define subsegequal(osub1, osub2) \ 01267 (((osub1).ss == (osub2).ss) && \ 01268 ((osub1).ssorient == (osub2).ssorient)) 01269 01270 /* Check or set a subsegment's deallocation. Its second pointer is set to */ 01271 /* NULL to indicate that it is not allocated. (Its first pointer is used */ 01272 /* for the stack of dead items.) Its third pointer (its first vertex) */ 01273 /* is set to NULL in case a `badsubseg' structure points to it. */ 01274 01275 #define deadsubseg(sub) ((sub)[1] == (subseg) NULL) 01276 01277 #define killsubseg(sub) \ 01278 (sub)[1] = (subseg) NULL; \ 01279 (sub)[2] = (subseg) NULL 01280 01281 /********* Primitives for interacting triangles and subsegments *********/ 01282 /* */ 01283 /* */ 01284 01285 /* tspivot() finds a subsegment abutting a triangle. */ 01286 01287 #define tspivot(otri, osub) \ 01288 sptr = (subseg) (otri).tri[6 + (otri).orient]; \ 01289 sdecode(sptr, osub) 01290 01291 /* stpivot() finds a triangle abutting a subsegment. It requires that the */ 01292 /* variable `ptr' of type `triangle' be defined. */ 01293 01294 #define stpivot(osub, otri) \ 01295 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \ 01296 decode(ptr, otri) 01297 01298 /* Bond a triangle to a subsegment. */ 01299 01300 #define tsbond(otri, osub) \ 01301 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \ 01302 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri) 01303 01304 /* Dissolve a bond (from the triangle side). */ 01305 01306 #define tsdissolve(otri) \ 01307 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub 01308 01309 /* Dissolve a bond (from the subsegment side). */ 01310 01311 #define stdissolve(osub) \ 01312 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri 01313 01314 /********* Primitives for vertices *********/ 01315 /* */ 01316 /* */ 01317 01318 #define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex] 01319 01320 #define setvertexmark(vx, value) \ 01321 ((int *) (vx))[m->vertexmarkindex] = value 01322 01323 #define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1] 01324 01325 #define setvertextype(vx, value) \ 01326 ((int *) (vx))[m->vertexmarkindex + 1] = value 01327 01328 #define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex] 01329 01330 #define setvertex2tri(vx, value) \ 01331 ((triangle *) (vx))[m->vertex2triindex] = value 01332 01335 /********* Mesh manipulation primitives end here *********/ 01336 01337 /********* User-defined triangle evaluation routine begins here *********/ 01341 /*****************************************************************************/ 01342 /* */ 01343 /* triunsuitable() Determine if a triangle is unsuitable, and thus must */ 01344 /* be further refined. */ 01345 /* */ 01346 /* You may write your own procedure that decides whether or not a selected */ 01347 /* triangle is too big (and needs to be refined). There are two ways to do */ 01348 /* this. */ 01349 /* */ 01350 /* (1) Modify the procedure `triunsuitable' below, then recompile */ 01351 /* Triangle. */ 01352 /* */ 01353 /* (2) Define the symbol EXTERNAL_TEST (either by adding the definition */ 01354 /* to this file, or by using the appropriate compiler switch). This way, */ 01355 /* you can compile triangle.c separately from your test. Write your own */ 01356 /* `triunsuitable' procedure in a separate C file (using the same prototype */ 01357 /* as below). Compile it and link the object code with triangle.o. */ 01358 /* */ 01359 /* This procedure returns 1 if the triangle is too large and should be */ 01360 /* refined; 0 otherwise. */ 01361 /* */ 01362 /*****************************************************************************/ 01363 01364 #ifdef EXTERNAL_TEST 01365 01366 int triunsuitable(); 01367 01368 #else /* not EXTERNAL_TEST */ 01369 01370 #ifdef ANSI_DECLARATORS 01371 int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area) 01372 #else /* not ANSI_DECLARATORS */ 01373 int triunsuitable(triorg, tridest, triapex, area) 01374 vertex triorg; /* The triangle's origin vertex. */ 01375 vertex tridest; /* The triangle's destination vertex. */ 01376 vertex triapex; /* The triangle's apex vertex. */ 01377 REAL area; /* The area of the triangle. */ 01378 #endif /* not ANSI_DECLARATORS */ 01379 01380 { 01381 REAL dxoa, dxda, dxod; 01382 REAL dyoa, dyda, dyod; 01383 REAL oalen, dalen, odlen; 01384 REAL maxlen; 01385 01386 dxoa = triorg[0] - triapex[0]; 01387 dyoa = triorg[1] - triapex[1]; 01388 dxda = tridest[0] - triapex[0]; 01389 dyda = tridest[1] - triapex[1]; 01390 dxod = triorg[0] - tridest[0]; 01391 dyod = triorg[1] - tridest[1]; 01392 /* Find the squares of the lengths of the triangle's three edges. */ 01393 oalen = dxoa * dxoa + dyoa * dyoa; 01394 dalen = dxda * dxda + dyda * dyda; 01395 odlen = dxod * dxod + dyod * dyod; 01396 /* Find the square of the length of the longest edge. */ 01397 maxlen = (dalen > oalen) ? dalen : oalen; 01398 maxlen = (odlen > maxlen) ? odlen : maxlen; 01399 01400 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) { 01401 return 1; 01402 } else { 01403 return 0; 01404 } 01405 } 01406 01407 #endif /* not EXTERNAL_TEST */ 01408 01411 /********* User-defined triangle evaluation routine ends here *********/ 01412 01413 /********* Memory allocation and program exit wrappers begin here *********/ 01417 #ifdef ANSI_DECLARATORS 01418 void triexit(int status) 01419 #else /* not ANSI_DECLARATORS */ 01420 void triexit(status) 01421 int status; 01422 #endif /* not ANSI_DECLARATORS */ 01423 01424 { 01425 exit(status); 01426 } 01427 01428 #ifdef ANSI_DECLARATORS 01429 VOID *trimalloc(int size) 01430 #else /* not ANSI_DECLARATORS */ 01431 VOID *trimalloc(size) 01432 int size; 01433 #endif /* not ANSI_DECLARATORS */ 01434 01435 { 01436 VOID *memptr; 01437 01438 memptr = (VOID *) malloc((unsigned int) size); 01439 if (memptr == (VOID *) NULL) { 01440 printf("Error: Out of memory.\n"); 01441 triexit(1); 01442 } 01443 return(memptr); 01444 } 01445 01446 #ifdef ANSI_DECLARATORS 01447 void trifree(VOID *memptr) 01448 #else /* not ANSI_DECLARATORS */ 01449 void trifree(memptr) 01450 VOID *memptr; 01451 #endif /* not ANSI_DECLARATORS */ 01452 01453 { 01454 free(memptr); 01455 } 01456 01459 /********* Memory allocation and program exit wrappers end here *********/ 01460 01461 /********* User interaction routines begin here *********/ 01465 /*****************************************************************************/ 01466 /* */ 01467 /* syntax() Print list of command line switches. */ 01468 /* */ 01469 /*****************************************************************************/ 01470 01471 #ifndef TRILIBRARY 01472 01473 void syntax() 01474 { 01475 #ifdef CDT_ONLY 01476 #ifdef REDUCED 01477 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n"); 01478 #else /* not REDUCED */ 01479 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n"); 01480 #endif /* not REDUCED */ 01481 #else /* not CDT_ONLY */ 01482 #ifdef REDUCED 01483 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n"); 01484 #else /* not REDUCED */ 01485 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n"); 01486 #endif /* not REDUCED */ 01487 #endif /* not CDT_ONLY */ 01488 01489 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n"); 01490 #ifndef CDT_ONLY 01491 printf(" -r Refines a previously generated mesh.\n"); 01492 printf( 01493 " -q Quality mesh generation. A minimum angle may be specified.\n"); 01494 printf(" -a Applies a maximum triangle area constraint.\n"); 01495 printf(" -u Applies a user-defined triangle constraint.\n"); 01496 #endif /* not CDT_ONLY */ 01497 printf( 01498 " -A Applies attributes to identify triangles in certain regions.\n"); 01499 printf(" -c Encloses the convex hull with segments.\n"); 01500 #ifndef CDT_ONLY 01501 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n"); 01502 #endif /* not CDT_ONLY */ 01503 /* 01504 printf(" -w Weighted Delaunay triangulation.\n"); 01505 printf(" -W Regular triangulation (lower hull of a height field).\n"); 01506 */ 01507 printf(" -j Jettison unused vertices from output .node file.\n"); 01508 printf(" -e Generates an edge list.\n"); 01509 printf(" -v Generates a Voronoi diagram.\n"); 01510 printf(" -n Generates a list of triangle neighbors.\n"); 01511 printf(" -g Generates an .off file for Geomview.\n"); 01512 printf(" -B Suppresses output of boundary information.\n"); 01513 printf(" -P Suppresses output of .poly file.\n"); 01514 printf(" -N Suppresses output of .node file.\n"); 01515 printf(" -E Suppresses output of .ele file.\n"); 01516 printf(" -I Suppresses mesh iteration numbers.\n"); 01517 printf(" -O Ignores holes in .poly file.\n"); 01518 printf(" -X Suppresses use of exact arithmetic.\n"); 01519 printf(" -z Numbers all items starting from zero (rather than one).\n"); 01520 printf(" -o2 Generates second-order subparametric elements.\n"); 01521 #ifndef CDT_ONLY 01522 printf(" -Y Suppresses boundary segment splitting.\n"); 01523 printf(" -S Specifies maximum number of added Steiner points.\n"); 01524 #endif /* not CDT_ONLY */ 01525 #ifndef REDUCED 01526 printf(" -i Uses incremental method, rather than divide-and-conquer.\n"); 01527 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n"); 01528 #endif /* not REDUCED */ 01529 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n"); 01530 #ifndef REDUCED 01531 #ifndef CDT_ONLY 01532 printf( 01533 " -s Force segments into mesh by splitting (instead of using CDT).\n"); 01534 #endif /* not CDT_ONLY */ 01535 printf(" -C Check consistency of final mesh.\n"); 01536 #endif /* not REDUCED */ 01537 printf(" -Q Quiet: No terminal output except errors.\n"); 01538 printf(" -V Verbose: Detailed information on what I'm doing.\n"); 01539 printf(" -h Help: Detailed instructions for Triangle.\n"); 01540 triexit(0); 01541 } 01542 01543 #endif /* not TRILIBRARY */ 01544 01545 /*****************************************************************************/ 01546 /* */ 01547 /* info() Print out complete instructions. */ 01548 /* */ 01549 /*****************************************************************************/ 01550 01551 #ifndef TRILIBRARY 01552 01553 void info() 01554 { 01555 printf("Triangle\n"); 01556 printf( 01557 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n"); 01558 printf("Version 1.6\n\n"); 01559 printf( 01560 "Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n"); 01561 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n"); 01562 printf("Bugs/comments to jrs@cs.berkeley.edu\n"); 01563 printf( 01564 "Created as part of the Quake project (tools for earthquake simulation).\n"); 01565 printf( 01566 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n"); 01567 printf("There is no warranty whatsoever. Use at your own risk.\n"); 01568 #ifdef SINGLE 01569 printf("This executable is compiled for single precision arithmetic.\n\n\n"); 01570 #else /* not SINGLE */ 01571 printf("This executable is compiled for double precision arithmetic.\n\n\n"); 01572 #endif /* not SINGLE */ 01573 printf( 01574 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n"); 01575 printf( 01576 "triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n"); 01577 printf( 01578 "high-quality triangular meshes. The latter can be generated with no small\n" 01579 ); 01580 printf( 01581 "or large angles, and are thus suitable for finite element analysis. If no\n" 01582 ); 01583 printf( 01584 "command line switch is specified, your .node input file is read, and the\n"); 01585 printf( 01586 "Delaunay triangulation is returned in .node and .ele output files. The\n"); 01587 printf("command syntax is:\n\n"); 01588 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n"); 01589 printf( 01590 "Underscores indicate that numbers may optionally follow certain switches.\n"); 01591 printf( 01592 "Do not leave any space between a switch and its numeric parameter.\n"); 01593 printf( 01594 "input_file must be a file with extension .node, or extension .poly if the\n"); 01595 printf( 01596 "-p switch is used. If -r is used, you must supply .node and .ele files,\n"); 01597 printf( 01598 "and possibly a .poly file and an .area file as well. The formats of these\n" 01599 ); 01600 printf("files are described below.\n\n"); 01601 printf("Command Line Switches:\n\n"); 01602 printf( 01603 " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n" 01604 ); 01605 printf( 01606 " vertices, segments, holes, regional attributes, and regional area\n"); 01607 printf( 01608 " constraints. Generates a constrained Delaunay triangulation (CDT)\n" 01609 ); 01610 printf( 01611 " fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n"); 01612 printf( 01613 " constrained Delaunay triangulation (CCDT). If you want a truly\n"); 01614 printf( 01615 " Delaunay (not just constrained Delaunay) triangulation, use -D as\n"); 01616 printf( 01617 " well. When -p is not used, Triangle reads a .node file by default.\n" 01618 ); 01619 printf( 01620 " -r Refines a previously generated mesh. The mesh is read from a .node\n" 01621 ); 01622 printf( 01623 " file and an .ele file. If -p is also used, a .poly file is read\n"); 01624 printf( 01625 " and used to constrain segments in the mesh. If -a is also used\n"); 01626 printf( 01627 " (with no number following), an .area file is read and used to\n"); 01628 printf( 01629 " impose area constraints on the mesh. Further details on refinement\n" 01630 ); 01631 printf(" appear below.\n"); 01632 printf( 01633 " -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n"); 01634 printf( 01635 " Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n" 01636 ); 01637 printf( 01638 " ensure that all angles are between 20 and 140 degrees. An\n"); 01639 printf( 01640 " alternative bound on the minimum angle, replacing 20 degrees, may\n"); 01641 printf( 01642 " be specified after the `q'. The specified angle may include a\n"); 01643 printf( 01644 " decimal point, but not exponential notation. Note that a bound of\n" 01645 ); 01646 printf( 01647 " theta degrees on the smallest angle also implies a bound of\n"); 01648 printf( 01649 " (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n" 01650 ); 01651 printf( 01652 " degrees or smaller, Triangle is mathematically guaranteed to\n"); 01653 printf( 01654 " terminate (assuming infinite precision arithmetic--Triangle may\n"); 01655 printf( 01656 " fail to terminate if you run out of precision). In practice,\n"); 01657 printf( 01658 " Triangle often succeeds for minimum angles up to 34 degrees. For\n"); 01659 printf( 01660 " some meshes, however, you might need to reduce the minimum angle to\n" 01661 ); 01662 printf( 01663 " avoid problems associated with insufficient floating-point\n"); 01664 printf(" precision.\n"); 01665 printf( 01666 " -a Imposes a maximum triangle area. If a number follows the `a', no\n"); 01667 printf( 01668 " triangle is generated whose area is larger than that number. If no\n" 01669 ); 01670 printf( 01671 " number is specified, an .area file (if -r is used) or .poly file\n"); 01672 printf( 01673 " (if -r is not used) specifies a set of maximum area constraints.\n"); 01674 printf( 01675 " An .area file contains a separate area constraint for each\n"); 01676 printf( 01677 " triangle, and is useful for refining a finite element mesh based on\n" 01678 ); 01679 printf( 01680 " a posteriori error estimates. A .poly file can optionally contain\n" 01681 ); 01682 printf( 01683 " an area constraint for each segment-bounded region, thereby\n"); 01684 printf( 01685 " controlling triangle densities in a first triangulation of a PSLG.\n" 01686 ); 01687 printf( 01688 " You can impose both a fixed area constraint and a varying area\n"); 01689 printf( 01690 " constraint by invoking the -a switch twice, once with and once\n"); 01691 printf( 01692 " without a number following. Each area specified may include a\n"); 01693 printf(" decimal point.\n"); 01694 printf( 01695 " -u Imposes a user-defined constraint on triangle size. There are two\n" 01696 ); 01697 printf( 01698 " ways to use this feature. One is to edit the triunsuitable()\n"); 01699 printf( 01700 " procedure in triangle.c to encode any constraint you like, then\n"); 01701 printf( 01702 " recompile Triangle. The other is to compile triangle.c with the\n"); 01703 printf( 01704 " EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n"); 01705 printf( 01706 " link Triangle with a separate object file that implements\n"); 01707 printf( 01708 " triunsuitable(). In either case, the -u switch causes the user-\n"); 01709 printf(" defined test to be applied to every triangle.\n"); 01710 printf( 01711 " -A Assigns an additional floating-point attribute to each triangle\n"); 01712 printf( 01713 " that identifies what segment-bounded region each triangle belongs\n"); 01714 printf( 01715 " to. Attributes are assigned to regions by the .poly file. If a\n"); 01716 printf( 01717 " region is not explicitly marked by the .poly file, triangles in\n"); 01718 printf( 01719 " that region are assigned an attribute of zero. The -A switch has\n"); 01720 printf( 01721 " an effect only when the -p switch is used and the -r switch is not.\n" 01722 ); 01723 printf( 01724 " -c Creates segments on the convex hull of the triangulation. If you\n"); 01725 printf( 01726 " are triangulating a vertex set, this switch causes a .poly file to\n" 01727 ); 01728 printf( 01729 " be written, containing all edges of the convex hull. If you are\n"); 01730 printf( 01731 " triangulating a PSLG, this switch specifies that the whole convex\n"); 01732 printf( 01733 " hull of the PSLG should be triangulated, regardless of what\n"); 01734 printf( 01735 " segments the PSLG has. If you do not use this switch when\n"); 01736 printf( 01737 " triangulating a PSLG, Triangle assumes that you have identified the\n" 01738 ); 01739 printf( 01740 " region to be triangulated by surrounding it with segments of the\n"); 01741 printf( 01742 " input PSLG. Beware: if you are not careful, this switch can cause\n" 01743 ); 01744 printf( 01745 " the introduction of an extremely thin angle between a PSLG segment\n" 01746 ); 01747 printf( 01748 " and a convex hull segment, which can cause overrefinement (and\n"); 01749 printf( 01750 " possibly failure if Triangle runs out of precision). If you are\n"); 01751 printf( 01752 " refining a mesh, the -c switch works differently: it causes a\n"); 01753 printf( 01754 " .poly file to be written containing the boundary edges of the mesh\n" 01755 ); 01756 printf(" (useful if no .poly file was read).\n"); 01757 printf( 01758 " -D Conforming Delaunay triangulation: use this switch if you want to\n" 01759 ); 01760 printf( 01761 " ensure that all the triangles in the mesh are Delaunay, and not\n"); 01762 printf( 01763 " merely constrained Delaunay; or if you want to ensure that all the\n" 01764 ); 01765 printf( 01766 " Voronoi vertices lie within the triangulation. (Some finite volume\n" 01767 ); 01768 printf( 01769 " methods have this requirement.) This switch invokes Ruppert's\n"); 01770 printf( 01771 " original algorithm, which splits every subsegment whose diametral\n"); 01772 printf( 01773 " circle is encroached. It usually increases the number of vertices\n" 01774 ); 01775 printf(" and triangles.\n"); 01776 printf( 01777 " -j Jettisons vertices that are not part of the final triangulation\n"); 01778 printf( 01779 " from the output .node file. By default, Triangle copies all\n"); 01780 printf( 01781 " vertices in the input .node file to the output .node file, in the\n"); 01782 printf( 01783 " same order, so their indices do not change. The -j switch prevents\n" 01784 ); 01785 printf( 01786 " duplicated input vertices, or vertices `eaten' by holes, from\n"); 01787 printf( 01788 " appearing in the output .node file. Thus, if two input vertices\n"); 01789 printf( 01790 " have exactly the same coordinates, only the first appears in the\n"); 01791 printf( 01792 " output. If any vertices are jettisoned, the vertex numbering in\n"); 01793 printf( 01794 " the output .node file differs from that of the input .node file.\n"); 01795 printf( 01796 " -e Outputs (to an .edge file) a list of edges of the triangulation.\n"); 01797 printf( 01798 " -v Outputs the Voronoi diagram associated with the triangulation.\n"); 01799 printf( 01800 " Does not attempt to detect degeneracies, so some Voronoi vertices\n"); 01801 printf( 01802 " may be duplicated. See the discussion of Voronoi diagrams below.\n"); 01803 printf( 01804 " -n Outputs (to a .neigh file) a list of triangles neighboring each\n"); 01805 printf(" triangle.\n"); 01806 printf( 01807 " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n" 01808 ); 01809 printf(" viewing with the Geometry Center's Geomview package.\n"); 01810 printf( 01811 " -B No boundary markers in the output .node, .poly, and .edge output\n"); 01812 printf( 01813 " files. See the detailed discussion of boundary markers below.\n"); 01814 printf( 01815 " -P No output .poly file. Saves disk space, but you lose the ability\n"); 01816 printf( 01817 " to maintain constraining segments on later refinements of the mesh.\n" 01818 ); 01819 printf(" -N No output .node file.\n"); 01820 printf(" -E No output .ele file.\n"); 01821 printf( 01822 " -I No iteration numbers. Suppresses the output of .node and .poly\n"); 01823 printf( 01824 " files, so your input files won't be overwritten. (If your input is\n" 01825 ); 01826 printf( 01827 " a .poly file only, a .node file is written.) Cannot be used with\n"); 01828 printf( 01829 " the -r switch, because that would overwrite your input .ele file.\n"); 01830 printf( 01831 " Shouldn't be used with the -q, -a, -u, or -s switch if you are\n"); 01832 printf( 01833 " using a .node file for input, because no .node file is written, so\n" 01834 ); 01835 printf(" there is no record of any added Steiner points.\n"); 01836 printf(" -O No holes. Ignores the holes in the .poly file.\n"); 01837 printf( 01838 " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n" 01839 ); 01840 printf( 01841 " arithmetic for certain tests if it thinks the inexact tests are not\n" 01842 ); 01843 printf( 01844 " accurate enough. Exact arithmetic ensures the robustness of the\n"); 01845 printf( 01846 " triangulation algorithms, despite floating-point roundoff error.\n"); 01847 printf( 01848 " Disabling exact arithmetic with the -X switch causes a small\n"); 01849 printf( 01850 " improvement in speed and creates the possibility that Triangle will\n" 01851 ); 01852 printf(" fail to produce a valid mesh. Not recommended.\n"); 01853 printf( 01854 " -z Numbers all items starting from zero (rather than one). Note that\n" 01855 ); 01856 printf( 01857 " this switch is normally overridden by the value used to number the\n" 01858 ); 01859 printf( 01860 " first vertex of the input .node or .poly file. However, this\n"); 01861 printf( 01862 " switch is useful when calling Triangle from another program.\n"); 01863 printf( 01864 " -o2 Generates second-order subparametric elements with six nodes each.\n" 01865 ); 01866 printf( 01867 " -Y No new vertices on the boundary. This switch is useful when the\n"); 01868 printf( 01869 " mesh boundary must be preserved so that it conforms to some\n"); 01870 printf( 01871 " adjacent mesh. Be forewarned that you will probably sacrifice much\n" 01872 ); 01873 printf( 01874 " of the quality of the mesh; Triangle will try, but the resulting\n"); 01875 printf( 01876 " mesh may contain poorly shaped triangles. Works well if all the\n"); 01877 printf( 01878 " boundary vertices are closely spaced. Specify this switch twice\n"); 01879 printf( 01880 " (`-YY') to prevent all segment splitting, including internal\n"); 01881 printf(" boundaries.\n"); 01882 printf( 01883 " -S Specifies the maximum number of Steiner points (vertices that are\n"); 01884 printf( 01885 " not in the input, but are added to meet the constraints on minimum\n" 01886 ); 01887 printf( 01888 " angle and maximum area). The default is to allow an unlimited\n"); 01889 printf( 01890 " number. If you specify this switch with no number after it,\n"); 01891 printf( 01892 " the limit is set to zero. Triangle always adds vertices at segment\n" 01893 ); 01894 printf( 01895 " intersections, even if it needs to use more vertices than the limit\n" 01896 ); 01897 printf( 01898 " you set. When Triangle inserts segments by splitting (-s), it\n"); 01899 printf( 01900 " always adds enough vertices to ensure that all the segments of the\n" 01901 ); 01902 printf(" PLSG are recovered, ignoring the limit if necessary.\n"); 01903 printf( 01904 " -i Uses an incremental rather than a divide-and-conquer algorithm to\n"); 01905 printf( 01906 " construct a Delaunay triangulation. Try it if the divide-and-\n"); 01907 printf(" conquer algorithm fails.\n"); 01908 printf( 01909 " -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n"); 01910 printf( 01911 " triangulation. Warning: does not use exact arithmetic for all\n"); 01912 printf(" calculations. An exact result is not guaranteed.\n"); 01913 printf( 01914 " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n"); 01915 printf( 01916 " default, Triangle alternates between vertical and horizontal cuts,\n" 01917 ); 01918 printf( 01919 " which usually improve the speed except with vertex sets that are\n"); 01920 printf( 01921 " small or short and wide. This switch is primarily of theoretical\n"); 01922 printf(" interest.\n"); 01923 printf( 01924 " -s Specifies that segments should be forced into the triangulation by\n" 01925 ); 01926 printf( 01927 " recursively splitting them at their midpoints, rather than by\n"); 01928 printf( 01929 " generating a constrained Delaunay triangulation. Segment splitting\n" 01930 ); 01931 printf( 01932 " is true to Ruppert's original algorithm, but can create needlessly\n" 01933 ); 01934 printf( 01935 " small triangles. This switch is primarily of theoretical interest.\n" 01936 ); 01937 printf( 01938 " -C Check the consistency of the final mesh. Uses exact arithmetic for\n" 01939 ); 01940 printf( 01941 " checking, even if the -X switch is used. Useful if you suspect\n"); 01942 printf(" Triangle is buggy.\n"); 01943 printf( 01944 " -Q Quiet: Suppresses all explanation of what Triangle is doing,\n"); 01945 printf(" unless an error occurs.\n"); 01946 printf( 01947 " -V Verbose: Gives detailed information about what Triangle is doing.\n" 01948 ); 01949 printf( 01950 " Add more `V's for increasing amount of detail. `-V' is most\n"); 01951 printf( 01952 " useful; itgives information on algorithmic progress and much more\n"); 01953 printf( 01954 " detailed statistics. `-VV' gives vertex-by-vertex details, and\n"); 01955 printf( 01956 " prints so much that Triangle runs much more slowly. `-VVVV' gives\n" 01957 ); 01958 printf(" information only a debugger could love.\n"); 01959 printf(" -h Help: Displays these instructions.\n"); 01960 printf("\n"); 01961 printf("Definitions:\n"); 01962 printf("\n"); 01963 printf( 01964 " A Delaunay triangulation of a vertex set is a triangulation whose\n"); 01965 printf( 01966 " vertices are the vertex set, that covers the convex hull of the vertex\n"); 01967 printf( 01968 " set. A Delaunay triangulation has the property that no vertex lies\n"); 01969 printf( 01970 " inside the circumscribing circle (circle that passes through all three\n"); 01971 printf(" vertices) of any triangle in the triangulation.\n\n"); 01972 printf( 01973 " A Voronoi diagram of a vertex set is a subdivision of the plane into\n"); 01974 printf( 01975 " polygonal cells (some of which may be unbounded, meaning infinitely\n"); 01976 printf( 01977 " large), where each cell is the set of points in the plane that are closer\n" 01978 ); 01979 printf( 01980 " to some input vertex than to any other input vertex. The Voronoi diagram\n" 01981 ); 01982 printf(" is a geometric dual of the Delaunay triangulation.\n\n"); 01983 printf( 01984 " A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n"); 01985 printf( 01986 " Segments are simply edges, whose endpoints are all vertices in the PSLG.\n" 01987 ); 01988 printf( 01989 " Segments may intersect each other only at their endpoints. The file\n"); 01990 printf(" format for PSLGs (.poly files) is described below.\n\n"); 01991 printf( 01992 " A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n"); 01993 printf( 01994 " Delaunay triangulation, but each PSLG segment is present as a single edge\n" 01995 ); 01996 printf( 01997 " of the CDT. (A constrained Delaunay triangulation is not truly a\n"); 01998 printf( 01999 " Delaunay triangulation, because some of its triangles might not be\n"); 02000 printf( 02001 " Delaunay.) By definition, a CDT does not have any vertices other than\n"); 02002 printf( 02003 " those specified in the input PSLG. Depending on context, a CDT might\n"); 02004 printf( 02005 " cover the convex hull of the PSLG, or it might cover only a segment-\n"); 02006 printf(" bounded region (e.g. a polygon).\n\n"); 02007 printf( 02008 " A conforming Delaunay triangulation of a PSLG is a triangulation in which\n" 02009 ); 02010 printf( 02011 " each triangle is truly Delaunay, and each PSLG segment is represented by\n" 02012 ); 02013 printf( 02014 " a linear contiguous sequence of edges of the triangulation. New vertices\n" 02015 ); 02016 printf( 02017 " (not part of the PSLG) may appear, and each input segment may have been\n"); 02018 printf( 02019 " subdivided into shorter edges (subsegments) by these additional vertices.\n" 02020 ); 02021 printf( 02022 " The new vertices are frequently necessary to maintain the Delaunay\n"); 02023 printf(" property while ensuring that every segment is represented.\n\n"); 02024 printf( 02025 " A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n"); 02026 printf( 02027 " triangulation of a PSLG whose triangles are constrained Delaunay. New\n"); 02028 printf(" vertices may appear, and input segments may be subdivided into\n"); 02029 printf( 02030 " subsegments, but not to guarantee that segments are respected; rather, to\n" 02031 ); 02032 printf( 02033 " improve the quality of the triangles. The high-quality meshes produced\n"); 02034 printf( 02035 " by the -q switch are usually CCDTs, but can be made conforming Delaunay\n"); 02036 printf(" with the -D switch.\n\n"); 02037 printf("File Formats:\n\n"); 02038 printf( 02039 " All files may contain comments prefixed by the character '#'. Vertices,\n" 02040 ); 02041 printf( 02042 " triangles, edges, holes, and maximum area constraints must be numbered\n"); 02043 printf( 02044 " consecutively, starting from either 1 or 0. Whichever you choose, all\n"); 02045 printf( 02046 " input files must be consistent; if the vertices are numbered from 1, so\n"); 02047 printf( 02048 " must be all other objects. Triangle automatically detects your choice\n"); 02049 printf( 02050 " while reading the .node (or .poly) file. (When calling Triangle from\n"); 02051 printf( 02052 " another program, use the -z switch if you wish to number objects from\n"); 02053 printf(" zero.) Examples of these file formats are given below.\n\n"); 02054 printf(" .node files:\n"); 02055 printf( 02056 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n" 02057 ); 02058 printf( 02059 " <# of boundary markers (0 or 1)>\n" 02060 ); 02061 printf( 02062 " Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n"); 02063 printf("\n"); 02064 printf( 02065 " The attributes, which are typically floating-point values of physical\n"); 02066 printf( 02067 " quantities (such as mass or conductivity) associated with the nodes of\n" 02068 ); 02069 printf( 02070 " a finite element mesh, are copied unchanged to the output mesh. If -q,\n" 02071 ); 02072 printf( 02073 " -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n" 02074 ); 02075 printf(" has attributes assigned to it by linear interpolation.\n\n"); 02076 printf( 02077 " If the fourth entry of the first line is `1', the last column of the\n"); 02078 printf( 02079 " remainder of the file is assumed to contain boundary markers. Boundary\n" 02080 ); 02081 printf( 02082 " markers are used to identify boundary vertices and vertices resting on\n" 02083 ); 02084 printf( 02085 " PSLG segments; a complete description appears in a section below. The\n" 02086 ); 02087 printf( 02088 " .node file produced by Triangle contains boundary markers in the last\n"); 02089 printf(" column unless they are suppressed by the -B switch.\n\n"); 02090 printf(" .ele files:\n"); 02091 printf( 02092 " First line: <# of triangles> <nodes per triangle> <# of attributes>\n"); 02093 printf( 02094 " Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n"); 02095 printf("\n"); 02096 printf( 02097 " Nodes are indices into the corresponding .node file. The first three\n"); 02098 printf( 02099 " nodes are the corner vertices, and are listed in counterclockwise order\n" 02100 ); 02101 printf( 02102 " around each triangle. (The remaining nodes, if any, depend on the type\n" 02103 ); 02104 printf(" of finite element used.)\n\n"); 02105 printf( 02106 " The attributes are just like those of .node files. Because there is no\n" 02107 ); 02108 printf( 02109 " simple mapping from input to output triangles, Triangle attempts to\n"); 02110 printf( 02111 " interpolate attributes, and may cause a lot of diffusion of attributes\n" 02112 ); 02113 printf( 02114 " among nearby triangles as the triangulation is refined. Attributes do\n" 02115 ); 02116 printf(" not diffuse across segments, so attributes used to identify\n"); 02117 printf(" segment-bounded regions remain intact.\n\n"); 02118 printf( 02119 " In .ele files produced by Triangle, each triangular element has three\n"); 02120 printf( 02121 " nodes (vertices) unless the -o2 switch is used, in which case\n"); 02122 printf( 02123 " subparametric quadratic elements with six nodes each are generated.\n"); 02124 printf( 02125 " The first three nodes are the corners in counterclockwise order, and\n"); 02126 printf( 02127 " the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n"); 02128 printf( 02129 " opposite the first, second, and third vertices, respectively.\n"); 02130 printf("\n"); 02131 printf(" .poly files:\n"); 02132 printf( 02133 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n" 02134 ); 02135 printf( 02136 " <# of boundary markers (0 or 1)>\n" 02137 ); 02138 printf( 02139 " Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n"); 02140 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n"); 02141 printf( 02142 " Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n"); 02143 printf(" One line: <# of holes>\n"); 02144 printf(" Following lines: <hole #> <x> <y>\n"); 02145 printf( 02146 " Optional line: <# of regional attributes and/or area constraints>\n"); 02147 printf( 02148 " Optional following lines: <region #> <x> <y> <attribute> <max area>\n"); 02149 printf("\n"); 02150 printf( 02151 " A .poly file represents a PSLG, as well as some additional information.\n" 02152 ); 02153 printf( 02154 " The first section lists all the vertices, and is identical to the\n"); 02155 printf( 02156 " format of .node files. <# of vertices> may be set to zero to indicate\n" 02157 ); 02158 printf( 02159 " that the vertices are listed in a separate .node file; .poly files\n"); 02160 printf( 02161 " produced by Triangle always have this format. A vertex set represented\n" 02162 ); 02163 printf( 02164 " this way has the advantage that it may easily be triangulated with or\n"); 02165 printf( 02166 " without segments (depending on whether the -p switch is invoked).\n"); 02167 printf("\n"); 02168 printf( 02169 " The second section lists the segments. Segments are edges whose\n"); 02170 printf( 02171 " presence in the triangulation is enforced. (Depending on the choice of\n" 02172 ); 02173 printf( 02174 " switches, segment might be subdivided into smaller edges). Each\n"); 02175 printf( 02176 " segment is specified by listing the indices of its two endpoints. This\n" 02177 ); 02178 printf( 02179 " means that you must include its endpoints in the vertex list. Each\n"); 02180 printf(" segment, like each point, may have a boundary marker.\n\n"); 02181 printf( 02182 " If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n" 02183 ); 02184 printf( 02185 " Delaunay triangulation (CDT), in which each segment appears as a single\n" 02186 ); 02187 printf( 02188 " edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n" 02189 ); 02190 printf( 02191 " produces a conforming constrained Delaunay triangulation (CCDT), in\n"); 02192 printf( 02193 " which segments may be subdivided into smaller edges. If -D is\n"); 02194 printf( 02195 " selected, Triangle produces a conforming Delaunay triangulation, so\n"); 02196 printf( 02197 " that every triangle is Delaunay, and not just constrained Delaunay.\n"); 02198 printf("\n"); 02199 printf( 02200 " The third section lists holes (and concavities, if -c is selected) in\n"); 02201 printf( 02202 " the triangulation. Holes are specified by identifying a point inside\n"); 02203 printf( 02204 " each hole. After the triangulation is formed, Triangle creates holes\n"); 02205 printf( 02206 " by eating triangles, spreading out from each hole point until its\n"); 02207 printf( 02208 " progress is blocked by segments in the PSLG. You must be careful to\n"); 02209 printf( 02210 " enclose each hole in segments, or your whole triangulation might be\n"); 02211 printf( 02212 " eaten away. If the two triangles abutting a segment are eaten, the\n"); 02213 printf( 02214 " segment itself is also eaten. Do not place a hole directly on a\n"); 02215 printf(" segment; if you do, Triangle chooses one side of the segment\n"); 02216 printf(" arbitrarily.\n\n"); 02217 printf( 02218 " The optional fourth section lists regional attributes (to be assigned\n"); 02219 printf( 02220 " to all triangles in a region) and regional constraints on the maximum\n"); 02221 printf( 02222 " triangle area. Triangle reads this section only if the -A switch is\n"); 02223 printf( 02224 " used or the -a switch is used without a number following it, and the -r\n" 02225 ); 02226 printf( 02227 " switch is not used. Regional attributes and area constraints are\n"); 02228 printf( 02229 " propagated in the same manner as holes: you specify a point for each\n"); 02230 printf( 02231 " attribute and/or constraint, and the attribute and/or constraint\n"); 02232 printf( 02233 " affects the whole region (bounded by segments) containing the point.\n"); 02234 printf( 02235 " If two values are written on a line after the x and y coordinate, the\n"); 02236 printf( 02237 " first such value is assumed to be a regional attribute (but is only\n"); 02238 printf( 02239 " applied if the -A switch is selected), and the second value is assumed\n" 02240 ); 02241 printf( 02242 " to be a regional area constraint (but is only applied if the -a switch\n" 02243 ); 02244 printf( 02245 " is selected). You may specify just one value after the coordinates,\n"); 02246 printf( 02247 " which can serve as both an attribute and an area constraint, depending\n" 02248 ); 02249 printf( 02250 " on the choice of switches. If you are using the -A and -a switches\n"); 02251 printf( 02252 " simultaneously and wish to assign an attribute to some region without\n"); 02253 printf(" imposing an area constraint, use a negative maximum area.\n\n"); 02254 printf( 02255 " When a triangulation is created from a .poly file, you must either\n"); 02256 printf( 02257 " enclose the entire region to be triangulated in PSLG segments, or\n"); 02258 printf( 02259 " use the -c switch, which automatically creates extra segments that\n"); 02260 printf( 02261 " enclose the convex hull of the PSLG. If you do not use the -c switch,\n" 02262 ); 02263 printf( 02264 " Triangle eats all triangles that are not enclosed by segments; if you\n"); 02265 printf( 02266 " are not careful, your whole triangulation may be eaten away. If you do\n" 02267 ); 02268 printf( 02269 " use the -c switch, you can still produce concavities by the appropriate\n" 02270 ); 02271 printf( 02272 " placement of holes just inside the boundary of the convex hull.\n"); 02273 printf("\n"); 02274 printf( 02275 " An ideal PSLG has no intersecting segments, nor any vertices that lie\n"); 02276 printf( 02277 " upon segments (except, of course, the endpoints of each segment). You\n" 02278 ); 02279 printf( 02280 " aren't required to make your .poly files ideal, but you should be aware\n" 02281 ); 02282 printf( 02283 " of what can go wrong. Segment intersections are relatively safe--\n"); 02284 printf( 02285 " Triangle calculates the intersection points for you and adds them to\n"); 02286 printf( 02287 " the triangulation--as long as your machine's floating-point precision\n"); 02288 printf( 02289 " doesn't become a problem. You are tempting the fates if you have three\n" 02290 ); 02291 printf( 02292 " segments that cross at the same location, and expect Triangle to figure\n" 02293 ); 02294 printf( 02295 " out where the intersection point is. Thanks to floating-point roundoff\n" 02296 ); 02297 printf( 02298 " error, Triangle will probably decide that the three segments intersect\n" 02299 ); 02300 printf( 02301 " at three different points, and you will find a minuscule triangle in\n"); 02302 printf( 02303 " your output--unless Triangle tries to refine the tiny triangle, uses\n"); 02304 printf( 02305 " up the last bit of machine precision, and fails to terminate at all.\n"); 02306 printf( 02307 " You're better off putting the intersection point in the input files,\n"); 02308 printf( 02309 " and manually breaking up each segment into two. Similarly, if you\n"); 02310 printf( 02311 " place a vertex at the middle of a segment, and hope that Triangle will\n" 02312 ); 02313 printf( 02314 " break up the segment at that vertex, you might get lucky. On the other\n" 02315 ); 02316 printf( 02317 " hand, Triangle might decide that the vertex doesn't lie precisely on\n"); 02318 printf( 02319 " the segment, and you'll have a needle-sharp triangle in your output--or\n" 02320 ); 02321 printf(" a lot of tiny triangles if you're generating a quality mesh.\n"); 02322 printf("\n"); 02323 printf( 02324 " When Triangle reads a .poly file, it also writes a .poly file, which\n"); 02325 printf( 02326 " includes all the subsegments--the edges that are parts of input\n"); 02327 printf( 02328 " segments. If the -c switch is used, the output .poly file also\n"); 02329 printf( 02330 " includes all of the edges on the convex hull. Hence, the output .poly\n" 02331 ); 02332 printf( 02333 " file is useful for finding edges associated with input segments and for\n" 02334 ); 02335 printf( 02336 " setting boundary conditions in finite element simulations. Moreover,\n"); 02337 printf( 02338 " you will need the output .poly file if you plan to refine the output\n"); 02339 printf( 02340 " mesh, and don't want segments to be missing in later triangulations.\n"); 02341 printf("\n"); 02342 printf(" .area files:\n"); 02343 printf(" First line: <# of triangles>\n"); 02344 printf(" Following lines: <triangle #> <maximum area>\n"); 02345 printf("\n"); 02346 printf( 02347 " An .area file associates with each triangle a maximum area that is used\n" 02348 ); 02349 printf( 02350 " for mesh refinement. As with other file formats, every triangle must\n"); 02351 printf( 02352 " be represented, and the triangles must be numbered consecutively. A\n"); 02353 printf( 02354 " triangle may be left unconstrained by assigning it a negative maximum\n"); 02355 printf(" area.\n\n"); 02356 printf(" .edge files:\n"); 02357 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n"); 02358 printf( 02359 " Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n"); 02360 printf("\n"); 02361 printf( 02362 " Endpoints are indices into the corresponding .node file. Triangle can\n" 02363 ); 02364 printf( 02365 " produce .edge files (use the -e switch), but cannot read them. The\n"); 02366 printf( 02367 " optional column of boundary markers is suppressed by the -B switch.\n"); 02368 printf("\n"); 02369 printf( 02370 " In Voronoi diagrams, one also finds a special kind of edge that is an\n"); 02371 printf( 02372 " infinite ray with only one endpoint. For these edges, a different\n"); 02373 printf(" format is used:\n\n"); 02374 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n"); 02375 printf( 02376 " The `direction' is a floating-point vector that indicates the direction\n" 02377 ); 02378 printf(" of the infinite ray.\n\n"); 02379 printf(" .neigh files:\n"); 02380 printf( 02381 " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n" 02382 ); 02383 printf( 02384 " Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n"); 02385 printf("\n"); 02386 printf( 02387 " Neighbors are indices into the corresponding .ele file. An index of -1\n" 02388 ); 02389 printf( 02390 " indicates no neighbor (because the triangle is on an exterior\n"); 02391 printf( 02392 " boundary). The first neighbor of triangle i is opposite the first\n"); 02393 printf(" corner of triangle i, and so on.\n\n"); 02394 printf( 02395 " Triangle can produce .neigh files (use the -n switch), but cannot read\n" 02396 ); 02397 printf(" them.\n\n"); 02398 printf("Boundary Markers:\n\n"); 02399 printf( 02400 " Boundary markers are tags used mainly to identify which output vertices\n"); 02401 printf( 02402 " and edges are associated with which PSLG segment, and to identify which\n"); 02403 printf( 02404 " vertices and edges occur on a boundary of the triangulation. A common\n"); 02405 printf( 02406 " use is to determine where boundary conditions should be applied to a\n"); 02407 printf( 02408 " finite element mesh. You can prevent boundary markers from being written\n" 02409 ); 02410 printf(" into files produced by Triangle by using the -B switch.\n\n"); 02411 printf( 02412 " The boundary marker associated with each segment in an output .poly file\n" 02413 ); 02414 printf(" and each edge in an output .edge file is chosen as follows:\n"); 02415 printf( 02416 " - If an output edge is part or all of a PSLG segment with a nonzero\n"); 02417 printf( 02418 " boundary marker, then the edge is assigned the same marker.\n"); 02419 printf( 02420 " - Otherwise, if the edge lies on a boundary of the triangulation\n"); 02421 printf( 02422 " (even the boundary of a hole), then the edge is assigned the marker\n"); 02423 printf(" one (1).\n"); 02424 printf(" - Otherwise, the edge is assigned the marker zero (0).\n"); 02425 printf( 02426 " The boundary marker associated with each vertex in an output .node file\n"); 02427 printf(" is chosen as follows:\n"); 02428 printf( 02429 " - If a vertex is assigned a nonzero boundary marker in the input file,\n" 02430 ); 02431 printf( 02432 " then it is assigned the same marker in the output .node file.\n"); 02433 printf( 02434 " - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n"); 02435 printf( 02436 " endpoint of the segment) with a nonzero boundary marker, then the\n"); 02437 printf( 02438 " vertex is assigned the same marker. If the vertex lies on several\n"); 02439 printf(" such segments, one of the markers is chosen arbitrarily.\n"); 02440 printf( 02441 " - Otherwise, if the vertex occurs on a boundary of the triangulation,\n"); 02442 printf(" then the vertex is assigned the marker one (1).\n"); 02443 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n"); 02444 printf("\n"); 02445 printf( 02446 " If you want Triangle to determine for you which vertices and edges are on\n" 02447 ); 02448 printf( 02449 " the boundary, assign them the boundary marker zero (or use no markers at\n" 02450 ); 02451 printf( 02452 " all) in your input files. In the output files, all boundary vertices,\n"); 02453 printf(" edges, and segments will be assigned the value one.\n\n"); 02454 printf("Triangulation Iteration Numbers:\n\n"); 02455 printf( 02456 " Because Triangle can read and refine its own triangulations, input\n"); 02457 printf( 02458 " and output files have iteration numbers. For instance, Triangle might\n"); 02459 printf( 02460 " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n"); 02461 printf( 02462 " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n"); 02463 printf(" mesh.4.poly. Files with no iteration number are treated as if\n"); 02464 printf( 02465 " their iteration number is zero; hence, Triangle might read the file\n"); 02466 printf( 02467 " points.node, triangulate it, and produce the files points.1.node and\n"); 02468 printf(" points.1.ele.\n\n"); 02469 printf( 02470 " Iteration numbers allow you to create a sequence of successively finer\n"); 02471 printf( 02472 " meshes suitable for multigrid methods. They also allow you to produce a\n" 02473 ); 02474 printf( 02475 " sequence of meshes using error estimate-driven mesh refinement.\n"); 02476 printf("\n"); 02477 printf( 02478 " If you're not using refinement or quality meshing, and you don't like\n"); 02479 printf( 02480 " iteration numbers, use the -I switch to disable them. This switch also\n"); 02481 printf( 02482 " disables output of .node and .poly files to prevent your input files from\n" 02483 ); 02484 printf( 02485 " being overwritten. (If the input is a .poly file that contains its own\n"); 02486 printf( 02487 " points, a .node file is written. This can be quite convenient for\n"); 02488 printf(" computing CDTs or quality meshes.)\n\n"); 02489 printf("Examples of How to Use Triangle:\n\n"); 02490 printf( 02491 " `triangle dots' reads vertices from dots.node, and writes their Delaunay\n" 02492 ); 02493 printf( 02494 " triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n"); 02495 printf( 02496 " to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n"); 02497 printf( 02498 " instead. (No additional .node file is needed, so none is written.)\n"); 02499 printf("\n"); 02500 printf( 02501 " `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n"); 02502 printf( 02503 " object.1.node, if the vertices are omitted from object.1.poly) and writes\n" 02504 ); 02505 printf( 02506 " its constrained Delaunay triangulation to object.2.node and object.2.ele.\n" 02507 ); 02508 printf( 02509 " The segments are copied to object.2.poly, and all edges are written to\n"); 02510 printf(" object.2.edge.\n\n"); 02511 printf( 02512 " `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n" 02513 ); 02514 printf( 02515 " object.node), generates a mesh whose angles are all between 31.5 and 117\n" 02516 ); 02517 printf( 02518 " degrees and whose triangles all have areas of 0.1 or less, and writes the\n" 02519 ); 02520 printf( 02521 " mesh to object.1.node and object.1.ele. Each segment may be broken up\n"); 02522 printf(" into multiple subsegments; these are written to object.1.poly.\n"); 02523 printf("\n"); 02524 printf( 02525 " Here is a sample file `box.poly' describing a square with a square hole:\n" 02526 ); 02527 printf("\n"); 02528 printf( 02529 " # A box with eight vertices in 2D, no attributes, one boundary marker.\n" 02530 ); 02531 printf(" 8 2 0 1\n"); 02532 printf(" # Outer box has these vertices:\n"); 02533 printf(" 1 0 0 0\n"); 02534 printf(" 2 0 3 0\n"); 02535 printf(" 3 3 0 0\n"); 02536 printf(" 4 3 3 33 # A special marker for this vertex.\n"); 02537 printf(" # Inner square has these vertices:\n"); 02538 printf(" 5 1 1 0\n"); 02539 printf(" 6 1 2 0\n"); 02540 printf(" 7 2 1 0\n"); 02541 printf(" 8 2 2 0\n"); 02542 printf(" # Five segments with boundary markers.\n"); 02543 printf(" 5 1\n"); 02544 printf(" 1 1 2 5 # Left side of outer box.\n"); 02545 printf(" # Square hole has these segments:\n"); 02546 printf(" 2 5 7 0\n"); 02547 printf(" 3 7 8 0\n"); 02548 printf(" 4 8 6 10\n"); 02549 printf(" 5 6 5 0\n"); 02550 printf(" # One hole in the middle of the inner square.\n"); 02551 printf(" 1\n"); 02552 printf(" 1 1.5 1.5\n"); 02553 printf("\n"); 02554 printf( 02555 " Note that some segments are missing from the outer square, so you must\n"); 02556 printf( 02557 " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n" 02558 ); 02559 printf( 02560 " file `box.1.node', with twelve vertices. The last four vertices were\n"); 02561 printf( 02562 " added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n"); 02563 printf( 02564 " from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n"); 02565 printf( 02566 " other vertices but 4 have been marked to indicate that they lie on a\n"); 02567 printf(" boundary.\n\n"); 02568 printf(" 12 2 0 1\n"); 02569 printf(" 1 0 0 5\n"); 02570 printf(" 2 0 3 5\n"); 02571 printf(" 3 3 0 1\n"); 02572 printf(" 4 3 3 33\n"); 02573 printf(" 5 1 1 1\n"); 02574 printf(" 6 1 2 10\n"); 02575 printf(" 7 2 1 1\n"); 02576 printf(" 8 2 2 10\n"); 02577 printf(" 9 0 1.5 5\n"); 02578 printf(" 10 1.5 0 1\n"); 02579 printf(" 11 3 1.5 1\n"); 02580 printf(" 12 1.5 3 1\n"); 02581 printf(" # Generated by triangle -pqc box.poly\n"); 02582 printf("\n"); 02583 printf(" Here is the output file `box.1.ele', with twelve triangles.\n"); 02584 printf("\n"); 02585 printf(" 12 3 0\n"); 02586 printf(" 1 5 6 9\n"); 02587 printf(" 2 10 3 7\n"); 02588 printf(" 3 6 8 12\n"); 02589 printf(" 4 9 1 5\n"); 02590 printf(" 5 6 2 9\n"); 02591 printf(" 6 7 3 11\n"); 02592 printf(" 7 11 4 8\n"); 02593 printf(" 8 7 5 10\n"); 02594 printf(" 9 12 2 6\n"); 02595 printf(" 10 8 7 11\n"); 02596 printf(" 11 5 1 10\n"); 02597 printf(" 12 8 4 12\n"); 02598 printf(" # Generated by triangle -pqc box.poly\n\n"); 02599 printf( 02600 " Here is the output file `box.1.poly'. Note that segments have been added\n" 02601 ); 02602 printf( 02603 " to represent the convex hull, and some segments have been subdivided by\n"); 02604 printf( 02605 " newly added vertices. Note also that <# of vertices> is set to zero to\n"); 02606 printf(" indicate that the vertices should be read from the .node file.\n"); 02607 printf("\n"); 02608 printf(" 0 2 0 1\n"); 02609 printf(" 12 1\n"); 02610 printf(" 1 1 9 5\n"); 02611 printf(" 2 5 7 1\n"); 02612 printf(" 3 8 7 1\n"); 02613 printf(" 4 6 8 10\n"); 02614 printf(" 5 5 6 1\n"); 02615 printf(" 6 3 10 1\n"); 02616 printf(" 7 4 11 1\n"); 02617 printf(" 8 2 12 1\n"); 02618 printf(" 9 9 2 5\n"); 02619 printf(" 10 10 1 1\n"); 02620 printf(" 11 11 3 1\n"); 02621 printf(" 12 12 4 1\n"); 02622 printf(" 1\n"); 02623 printf(" 1 1.5 1.5\n"); 02624 printf(" # Generated by triangle -pqc box.poly\n"); 02625 printf("\n"); 02626 printf("Refinement and Area Constraints:\n"); 02627 printf("\n"); 02628 printf( 02629 " The -r switch causes a mesh (.node and .ele files) to be read and\n"); 02630 printf( 02631 " refined. If the -p switch is also used, a .poly file is read and used to\n" 02632 ); 02633 printf( 02634 " specify edges that are constrained and cannot be eliminated (although\n"); 02635 printf( 02636 " they can be subdivided into smaller edges) by the refinement process.\n"); 02637 printf("\n"); 02638 printf( 02639 " When you refine a mesh, you generally want to impose tighter constraints.\n" 02640 ); 02641 printf( 02642 " One way to accomplish this is to use -q with a larger angle, or -a\n"); 02643 printf( 02644 " followed by a smaller area than you used to generate the mesh you are\n"); 02645 printf( 02646 " refining. Another way to do this is to create an .area file, which\n"); 02647 printf( 02648 " specifies a maximum area for each triangle, and use the -a switch\n"); 02649 printf( 02650 " (without a number following). Each triangle's area constraint is applied\n" 02651 ); 02652 printf( 02653 " to that triangle. Area constraints tend to diffuse as the mesh is\n"); 02654 printf( 02655 " refined, so if there are large variations in area constraint between\n"); 02656 printf( 02657 " adjacent triangles, you may not get the results you want. In that case,\n" 02658 ); 02659 printf( 02660 " consider instead using the -u switch and writing a C procedure that\n"); 02661 printf(" determines which triangles are too large.\n\n"); 02662 printf( 02663 " If you are refining a mesh composed of linear (three-node) elements, the\n" 02664 ); 02665 printf( 02666 " output mesh contains all the nodes present in the input mesh, in the same\n" 02667 ); 02668 printf( 02669 " order, with new nodes added at the end of the .node file. However, the\n"); 02670 printf( 02671 " refinement is not hierarchical: there is no guarantee that each output\n"); 02672 printf( 02673 " element is contained in a single input element. Often, an output element\n" 02674 ); 02675 printf( 02676 " can overlap two or three input elements, and some input edges are not\n"); 02677 printf( 02678 " present in the output mesh. Hence, a sequence of refined meshes forms a\n" 02679 ); 02680 printf( 02681 " hierarchy of nodes, but not a hierarchy of elements. If you refine a\n"); 02682 printf( 02683 " mesh of higher-order elements, the hierarchical property applies only to\n" 02684 ); 02685 printf( 02686 " the nodes at the corners of an element; the midpoint nodes on each edge\n"); 02687 printf(" are discarded before the mesh is refined.\n\n"); 02688 printf( 02689 " Maximum area constraints in .poly files operate differently from those in\n" 02690 ); 02691 printf( 02692 " .area files. A maximum area in a .poly file applies to the whole\n"); 02693 printf( 02694 " (segment-bounded) region in which a point falls, whereas a maximum area\n"); 02695 printf( 02696 " in an .area file applies to only one triangle. Area constraints in .poly\n" 02697 ); 02698 printf( 02699 " files are used only when a mesh is first generated, whereas area\n"); 02700 printf( 02701 " constraints in .area files are used only to refine an existing mesh, and\n" 02702 ); 02703 printf( 02704 " are typically based on a posteriori error estimates resulting from a\n"); 02705 printf(" finite element simulation on that mesh.\n\n"); 02706 printf( 02707 " `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n"); 02708 printf( 02709 " refines the triangulation to enforce a 25 degree minimum angle, and then\n" 02710 ); 02711 printf( 02712 " writes the refined triangulation to object.2.node and object.2.ele.\n"); 02713 printf("\n"); 02714 printf( 02715 " `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n" 02716 ); 02717 printf( 02718 " After reconstructing the mesh and its subsegments, Triangle refines the\n"); 02719 printf( 02720 " mesh so that no triangle has area greater than 6.2, and furthermore the\n"); 02721 printf( 02722 " triangles satisfy the maximum area constraints in z.3.area. No angle\n"); 02723 printf( 02724 " bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n" 02725 ); 02726 printf(" z.4.poly.\n\n"); 02727 printf( 02728 " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n"); 02729 printf( 02730 " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n"); 02731 printf(" suitable for multigrid.\n\n"); 02732 printf("Convex Hulls and Mesh Boundaries:\n\n"); 02733 printf( 02734 " If the input is a vertex set (not a PSLG), Triangle produces its convex\n"); 02735 printf( 02736 " hull as a by-product in the output .poly file if you use the -c switch.\n"); 02737 printf( 02738 " There are faster algorithms for finding a two-dimensional convex hull\n"); 02739 printf(" than triangulation, of course, but this one comes for free.\n\n"); 02740 printf( 02741 " If the input is an unconstrained mesh (you are using the -r switch but\n"); 02742 printf( 02743 " not the -p switch), Triangle produces a list of its boundary edges\n"); 02744 printf( 02745 " (including hole boundaries) as a by-product when you use the -c switch.\n"); 02746 printf( 02747 " If you also use the -p switch, the output .poly file contains all the\n"); 02748 printf(" segments from the input .poly file as well.\n\n"); 02749 printf("Voronoi Diagrams:\n\n"); 02750 printf( 02751 " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n"); 02752 printf( 02753 " .v.edge. For example, `triangle -v points' reads points.node, produces\n"); 02754 printf( 02755 " its Delaunay triangulation in points.1.node and points.1.ele, and\n"); 02756 printf( 02757 " produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n" 02758 ); 02759 printf( 02760 " .v.node file contains a list of all Voronoi vertices, and the .v.edge\n"); 02761 printf( 02762 " file contains a list of all Voronoi edges, some of which may be infinite\n" 02763 ); 02764 printf( 02765 " rays. (The choice of filenames makes it easy to run the set of Voronoi\n"); 02766 printf(" vertices through Triangle, if so desired.)\n\n"); 02767 printf( 02768 " This implementation does not use exact arithmetic to compute the Voronoi\n" 02769 ); 02770 printf( 02771 " vertices, and does not check whether neighboring vertices are identical.\n" 02772 ); 02773 printf( 02774 " Be forewarned that if the Delaunay triangulation is degenerate or\n"); 02775 printf( 02776 " near-degenerate, the Voronoi diagram may have duplicate vertices or\n"); 02777 printf(" crossing edges.\n\n"); 02778 printf( 02779 " The result is a valid Voronoi diagram only if Triangle's output is a true\n" 02780 ); 02781 printf( 02782 " Delaunay triangulation. The Voronoi output is usually meaningless (and\n"); 02783 printf( 02784 " may contain crossing edges and other pathology) if the output is a CDT or\n" 02785 ); 02786 printf( 02787 " CCDT, or if it has holes or concavities. If the triangulated domain is\n"); 02788 printf( 02789 " convex and has no holes, you can use -D switch to force Triangle to\n"); 02790 printf( 02791 " construct a conforming Delaunay triangulation instead of a CCDT, so the\n"); 02792 printf(" Voronoi diagram will be valid.\n\n"); 02793 printf("Mesh Topology:\n\n"); 02794 printf( 02795 " You may wish to know which triangles are adjacent to a certain Delaunay\n"); 02796 printf( 02797 " edge in an .edge file, which Voronoi cells are adjacent to a certain\n"); 02798 printf( 02799 " Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n"); 02800 printf( 02801 " each other. All of this information can be found by cross-referencing\n"); 02802 printf( 02803 " output files with the recollection that the Delaunay triangulation and\n"); 02804 printf(" the Voronoi diagram are planar duals.\n\n"); 02805 printf( 02806 " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n"); 02807 printf( 02808 " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n"); 02809 printf( 02810 " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n"); 02811 printf( 02812 " vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n"); 02813 printf(" of vertex k of the corresponding .node file.\n\n"); 02814 printf( 02815 " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n"); 02816 printf( 02817 " vertices of the corresponding Voronoi edge. If the endpoints of a\n"); 02818 printf( 02819 " Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n" 02820 ); 02821 printf( 02822 " and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n" 02823 ); 02824 printf( 02825 " respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n" 02826 ); 02827 printf( 02828 " at the endpoints of the corresponding Delaunay edge. If the endpoints of\n" 02829 ); 02830 printf( 02831 " a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n" 02832 ); 02833 printf( 02834 " adjoin the right and left sides of the corresponding Voronoi edge,\n"); 02835 printf( 02836 " respectively. To find which Voronoi cells are adjacent to each other,\n"); 02837 printf(" just read the list of Delaunay edges.\n\n"); 02838 printf( 02839 " Triangle does not write a list of the edges adjoining each Voronoi cell,\n" 02840 ); 02841 printf( 02842 " but you can reconstructed it straightforwardly. For instance, to find\n"); 02843 printf( 02844 " all the edges of Voronoi cell 1, search the output .edge file for every\n"); 02845 printf( 02846 " edge that has input vertex 1 as an endpoint. The corresponding dual\n"); 02847 printf( 02848 " edges in the output .v.edge file form the boundary of Voronoi cell 1.\n"); 02849 printf("\n"); 02850 printf( 02851 " For each Voronoi vertex, the .neigh file gives a list of the three\n"); 02852 printf( 02853 " Voronoi vertices attached to it. You might find this more convenient\n"); 02854 printf(" than the .v.edge file.\n\n"); 02855 printf("Quadratic Elements:\n\n"); 02856 printf( 02857 " Triangle generates meshes with subparametric quadratic elements if the\n"); 02858 printf( 02859 " -o2 switch is specified. Quadratic elements have six nodes per element,\n" 02860 ); 02861 printf( 02862 " rather than three. `Subparametric' means that the edges of the triangles\n" 02863 ); 02864 printf( 02865 " are always straight, so that subparametric quadratic elements are\n"); 02866 printf( 02867 " geometrically identical to linear elements, even though they can be used\n" 02868 ); 02869 printf( 02870 " with quadratic interpolating functions. The three extra nodes of an\n"); 02871 printf( 02872 " element fall at the midpoints of the three edges, with the fourth, fifth,\n" 02873 ); 02874 printf( 02875 " and sixth nodes appearing opposite the first, second, and third corners\n"); 02876 printf(" respectively.\n\n"); 02877 printf("Domains with Small Angles:\n\n"); 02878 printf( 02879 " If two input segments adjoin each other at a small angle, clearly the -q\n" 02880 ); 02881 printf( 02882 " switch cannot remove the small angle. Moreover, Triangle may have no\n"); 02883 printf( 02884 " choice but to generate additional triangles whose smallest angles are\n"); 02885 printf( 02886 " smaller than the specified bound. However, these triangles only appear\n"); 02887 printf( 02888 " between input segments separated by small angles. Moreover, if you\n"); 02889 printf( 02890 " request a minimum angle of theta degrees, Triangle will generally produce\n" 02891 ); 02892 printf( 02893 " no angle larger than 180 - 2 theta, even if it is forced to compromise on\n" 02894 ); 02895 printf(" the minimum angle.\n\n"); 02896 printf("Statistics:\n\n"); 02897 printf( 02898 " After generating a mesh, Triangle prints a count of entities in the\n"); 02899 printf( 02900 " output mesh, including the number of vertices, triangles, edges, exterior\n" 02901 ); 02902 printf( 02903 " boundary edges (i.e. subsegments on the boundary of the triangulation,\n"); 02904 printf( 02905 " including hole boundaries), interior boundary edges (i.e. subsegments of\n" 02906 ); 02907 printf( 02908 " input segments not on the boundary), and total subsegments. If you've\n"); 02909 printf( 02910 " forgotten the statistics for an existing mesh, run Triangle on that mesh\n" 02911 ); 02912 printf( 02913 " with the -rNEP switches to read the mesh and print the statistics without\n" 02914 ); 02915 printf( 02916 " writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n"); 02917 printf("\n"); 02918 printf( 02919 " The -V switch produces extended statistics, including a rough estimate\n"); 02920 printf( 02921 " of memory use, the number of calls to geometric predicates, and\n"); 02922 printf( 02923 " histograms of the angles and the aspect ratios of the triangles in the\n"); 02924 printf(" mesh.\n\n"); 02925 printf("Exact Arithmetic:\n\n"); 02926 printf( 02927 " Triangle uses adaptive exact arithmetic to perform what computational\n"); 02928 printf( 02929 " geometers call the `orientation' and `incircle' tests. If the floating-\n" 02930 ); 02931 printf( 02932 " point arithmetic of your machine conforms to the IEEE 754 standard (as\n"); 02933 printf( 02934 " most workstations do), and does not use extended precision internal\n"); 02935 printf( 02936 " floating-point registers, then your output is guaranteed to be an\n"); 02937 printf( 02938 " absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n" 02939 ); 02940 printf( 02941 " error notwithstanding. The word `adaptive' implies that these arithmetic\n" 02942 ); 02943 printf( 02944 " routines compute the result only to the precision necessary to guarantee\n" 02945 ); 02946 printf( 02947 " correctness, so they are usually nearly as fast as their approximate\n"); 02948 printf(" counterparts.\n\n"); 02949 printf( 02950 " May CPUs, including Intel x86 processors, have extended precision\n"); 02951 printf( 02952 " floating-point registers. These must be reconfigured so their precision\n" 02953 ); 02954 printf( 02955 " is reduced to memory precision. Triangle does this if it is compiled\n"); 02956 printf(" correctly. See the makefile for details.\n\n"); 02957 printf( 02958 " The exact tests can be disabled with the -X switch. On most inputs, this\n" 02959 ); 02960 printf( 02961 " switch reduces the computation time by about eight percent--it's not\n"); 02962 printf( 02963 " worth the risk. There are rare difficult inputs (having many collinear\n"); 02964 printf( 02965 " and cocircular vertices), however, for which the difference in speed\n"); 02966 printf( 02967 " could be a factor of two. Be forewarned that these are precisely the\n"); 02968 printf( 02969 " inputs most likely to cause errors if you use the -X switch. Hence, the\n" 02970 ); 02971 printf(" -X switch is not recommended.\n\n"); 02972 printf( 02973 " Unfortunately, the exact tests don't solve every numerical problem.\n"); 02974 printf( 02975 " Exact arithmetic is not used to compute the positions of new vertices,\n"); 02976 printf( 02977 " because the bit complexity of vertex coordinates would grow without\n"); 02978 printf( 02979 " bound. Hence, segment intersections aren't computed exactly; in very\n"); 02980 printf( 02981 " unusual cases, roundoff error in computing an intersection point might\n"); 02982 printf( 02983 " actually lead to an inverted triangle and an invalid triangulation.\n"); 02984 printf( 02985 " (This is one reason to specify your own intersection points in your .poly\n" 02986 ); 02987 printf( 02988 " files.) Similarly, exact arithmetic is not used to compute the vertices\n" 02989 ); 02990 printf(" of the Voronoi diagram.\n\n"); 02991 printf( 02992 " Another pair of problems not solved by the exact arithmetic routines is\n"); 02993 printf( 02994 " underflow and overflow. If Triangle is compiled for double precision\n"); 02995 printf( 02996 " arithmetic, I believe that Triangle's geometric predicates work correctly\n" 02997 ); 02998 printf( 02999 " if the exponent of every input coordinate falls in the range [-148, 201].\n" 03000 ); 03001 printf( 03002 " Underflow can silently prevent the orientation and incircle tests from\n"); 03003 printf( 03004 " being performed exactly, while overflow typically causes a floating\n"); 03005 printf(" exception.\n\n"); 03006 printf("Calling Triangle from Another Program:\n\n"); 03007 printf(" Read the file triangle.h for details.\n\n"); 03008 printf("Troubleshooting:\n\n"); 03009 printf(" Please read this section before mailing me bugs.\n\n"); 03010 printf(" `My output mesh has no triangles!'\n\n"); 03011 printf( 03012 " If you're using a PSLG, you've probably failed to specify a proper set\n" 03013 ); 03014 printf( 03015 " of bounding segments, or forgotten to use the -c switch. Or you may\n"); 03016 printf( 03017 " have placed a hole badly, thereby eating all your triangles. To test\n"); 03018 printf(" these possibilities, try again with the -c and -O switches.\n"); 03019 printf( 03020 " Alternatively, all your input vertices may be collinear, in which case\n" 03021 ); 03022 printf(" you can hardly expect to triangulate them.\n\n"); 03023 printf(" `Triangle doesn't terminate, or just crashes.'\n\n"); 03024 printf( 03025 " Bad things can happen when triangles get so small that the distance\n"); 03026 printf( 03027 " between their vertices isn't much larger than the precision of your\n"); 03028 printf( 03029 " machine's arithmetic. If you've compiled Triangle for single-precision\n" 03030 ); 03031 printf( 03032 " arithmetic, you might do better by recompiling it for double-precision.\n" 03033 ); 03034 printf( 03035 " Then again, you might just have to settle for more lenient constraints\n" 03036 ); 03037 printf( 03038 " on the minimum angle and the maximum area than you had planned.\n"); 03039 printf("\n"); 03040 printf( 03041 " You can minimize precision problems by ensuring that the origin lies\n"); 03042 printf( 03043 " inside your vertex set, or even inside the densest part of your\n"); 03044 printf( 03045 " mesh. If you're triangulating an object whose x-coordinates all fall\n"); 03046 printf( 03047 " between 6247133 and 6247134, you're not leaving much floating-point\n"); 03048 printf(" precision for Triangle to work with.\n\n"); 03049 printf( 03050 " Precision problems can occur covertly if the input PSLG contains two\n"); 03051 printf( 03052 " segments that meet (or intersect) at an extremely small angle, or if\n"); 03053 printf( 03054 " such an angle is introduced by the -c switch. If you don't realize\n"); 03055 printf( 03056 " that a tiny angle is being formed, you might never discover why\n"); 03057 printf( 03058 " Triangle is crashing. To check for this possibility, use the -S switch\n" 03059 ); 03060 printf( 03061 " (with an appropriate limit on the number of Steiner points, found by\n"); 03062 printf( 03063 " trial-and-error) to stop Triangle early, and view the output .poly file\n" 03064 ); 03065 printf( 03066 " with Show Me (described below). Look carefully for regions where dense\n" 03067 ); 03068 printf( 03069 " clusters of vertices are forming and for small angles between segments.\n" 03070 ); 03071 printf( 03072 " Zoom in closely, as such segments might look like a single segment from\n" 03073 ); 03074 printf(" a distance.\n\n"); 03075 printf( 03076 " If some of the input values are too large, Triangle may suffer a\n"); 03077 printf( 03078 " floating exception due to overflow when attempting to perform an\n"); 03079 printf( 03080 " orientation or incircle test. (Read the section on exact arithmetic\n"); 03081 printf( 03082 " above.) Again, I recommend compiling Triangle for double (rather\n"); 03083 printf(" than single) precision arithmetic.\n\n"); 03084 printf( 03085 " Unexpected problems can arise if you use quality meshing (-q, -a, or\n"); 03086 printf( 03087 " -u) with an input that is not segment-bounded--that is, if your input\n"); 03088 printf( 03089 " is a vertex set, or you're using the -c switch. If the convex hull of\n" 03090 ); 03091 printf( 03092 " your input vertices has collinear vertices on its boundary, an input\n"); 03093 printf( 03094 " vertex that you think lies on the convex hull might actually lie just\n"); 03095 printf( 03096 " inside the convex hull. If so, the vertex and the nearby convex hull\n"); 03097 printf( 03098 " edge form an extremely thin triangle. When Triangle tries to refine\n"); 03099 printf( 03100 " the mesh to enforce angle and area constraints, Triangle might generate\n" 03101 ); 03102 printf( 03103 " extremely tiny triangles, or it might fail because of insufficient\n"); 03104 printf(" floating-point precision.\n\n"); 03105 printf( 03106 " `The numbering of the output vertices doesn't match the input vertices.'\n" 03107 ); 03108 printf("\n"); 03109 printf( 03110 " You may have had duplicate input vertices, or you may have eaten some\n"); 03111 printf( 03112 " of your input vertices with a hole, or by placing them outside the area\n" 03113 ); 03114 printf( 03115 " enclosed by segments. In any case, you can solve the problem by not\n"); 03116 printf(" using the -j switch.\n\n"); 03117 printf( 03118 " `Triangle executes without incident, but when I look at the resulting\n"); 03119 printf( 03120 " mesh, it has overlapping triangles or other geometric inconsistencies.'\n"); 03121 printf("\n"); 03122 printf( 03123 " If you select the -X switch, Triangle occasionally makes mistakes due\n"); 03124 printf( 03125 " to floating-point roundoff error. Although these errors are rare,\n"); 03126 printf( 03127 " don't use the -X switch. If you still have problems, please report the\n" 03128 ); 03129 printf(" bug.\n\n"); 03130 printf( 03131 " `Triangle executes without incident, but when I look at the resulting\n"); 03132 printf(" Voronoi diagram, it has overlapping edges or other geometric\n"); 03133 printf(" inconsistencies.'\n"); 03134 printf("\n"); 03135 printf( 03136 " If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n" 03137 ); 03138 printf( 03139 " diagram if the domain you are triangulating is convex and free of\n"); 03140 printf( 03141 " holes, and you use the -D switch to construct a conforming Delaunay\n"); 03142 printf(" triangulation (instead of a CDT or CCDT).\n\n"); 03143 printf( 03144 " Strange things can happen if you've taken liberties with your PSLG. Do\n"); 03145 printf( 03146 " you have a vertex lying in the middle of a segment? Triangle sometimes\n"); 03147 printf( 03148 " copes poorly with that sort of thing. Do you want to lay out a collinear\n" 03149 ); 03150 printf( 03151 " row of evenly spaced, segment-connected vertices? Have you simply\n"); 03152 printf( 03153 " defined one long segment connecting the leftmost vertex to the rightmost\n" 03154 ); 03155 printf( 03156 " vertex, and a bunch of vertices lying along it? This method occasionally\n" 03157 ); 03158 printf( 03159 " works, especially with horizontal and vertical lines, but often it\n"); 03160 printf( 03161 " doesn't, and you'll have to connect each adjacent pair of vertices with a\n" 03162 ); 03163 printf(" separate segment. If you don't like it, tough.\n\n"); 03164 printf( 03165 " Furthermore, if you have segments that intersect other than at their\n"); 03166 printf( 03167 " endpoints, try not to let the intersections fall extremely close to PSLG\n" 03168 ); 03169 printf(" vertices or each other.\n\n"); 03170 printf( 03171 " If you have problems refining a triangulation not produced by Triangle:\n"); 03172 printf( 03173 " Are you sure the triangulation is geometrically valid? Is it formatted\n"); 03174 printf( 03175 " correctly for Triangle? Are the triangles all listed so the first three\n" 03176 ); 03177 printf( 03178 " vertices are their corners in counterclockwise order? Are all of the\n"); 03179 printf( 03180 " triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n" 03181 ); 03182 printf(" assumes that it starts with a CDT.\n\n"); 03183 printf("Show Me:\n\n"); 03184 printf( 03185 " Triangle comes with a separate program named `Show Me', whose primary\n"); 03186 printf( 03187 " purpose is to draw meshes on your screen or in PostScript. Its secondary\n" 03188 ); 03189 printf( 03190 " purpose is to check the validity of your input files, and do so more\n"); 03191 printf( 03192 " thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n"); 03193 printf( 03194 " you have the X Windows system. Sorry, Microsoft Windows users.\n"); 03195 printf("\n"); 03196 printf("Triangle on the Web:\n"); 03197 printf("\n"); 03198 printf(" To see an illustrated version of these instructions, check out\n"); 03199 printf("\n"); 03200 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n"); 03201 printf("\n"); 03202 printf("A Brief Plea:\n"); 03203 printf("\n"); 03204 printf( 03205 " If you use Triangle, and especially if you use it to accomplish real\n"); 03206 printf( 03207 " work, I would like very much to hear from you. A short letter or email\n"); 03208 printf( 03209 " (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n" 03210 ); 03211 printf( 03212 " to me. The more people I know are using this program, the more easily I\n" 03213 ); 03214 printf( 03215 " can justify spending time on improvements, which in turn will benefit\n"); 03216 printf( 03217 " you. Also, I can put you on a list to receive email whenever a new\n"); 03218 printf(" version of Triangle is available.\n\n"); 03219 printf( 03220 " If you use a mesh generated by Triangle in a publication, please include\n" 03221 ); 03222 printf( 03223 " an acknowledgment as well. And please spell Triangle with a capital `T'!\n" 03224 ); 03225 printf( 03226 " If you want to include a citation, use `Jonathan Richard Shewchuk,\n"); 03227 printf( 03228 " ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n"); 03229 printf( 03230 " Triangulator,'' in Applied Computational Geometry: Towards Geometric\n"); 03231 printf( 03232 " Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n"); 03233 printf( 03234 " Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n"); 03235 printf( 03236 " Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n" 03237 ); 03238 printf(" Geometry.)'\n\n"); 03239 printf("Research credit:\n\n"); 03240 printf( 03241 " Of course, I can take credit for only a fraction of the ideas that made\n"); 03242 printf( 03243 " this mesh generator possible. Triangle owes its existence to the efforts\n" 03244 ); 03245 printf( 03246 " of many fine computational geometers and other researchers, including\n"); 03247 printf( 03248 " Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n" 03249 ); 03250 printf( 03251 " Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n"); 03252 printf( 03253 " Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n"); 03254 printf( 03255 " Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n"); 03256 printf( 03257 " Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n" 03258 ); 03259 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n"); 03260 printf( 03261 " Walkington, and Binhai Zhu. See the comments at the beginning of the\n"); 03262 printf(" source code for references.\n\n"); 03263 triexit(0); 03264 } 03265 03266 #endif /* not TRILIBRARY */ 03267 03268 /*****************************************************************************/ 03269 /* */ 03270 /* internalerror() Ask the user to send me the defective product. Exit. */ 03271 /* */ 03272 /*****************************************************************************/ 03273 03274 void internalerror() 03275 { 03276 printf(" Please report this bug to jrs@cs.berkeley.edu\n"); 03277 printf(" Include the message above, your input data set, and the exact\n"); 03278 printf(" command line you used to run Triangle.\n"); 03279 triexit(1); 03280 } 03281 03282 /*****************************************************************************/ 03283 /* */ 03284 /* parsecommandline() Read the command line, identify switches, and set */ 03285 /* up options and file names. */ 03286 /* */ 03287 /*****************************************************************************/ 03288 03289 #ifdef ANSI_DECLARATORS 03290 void parsecommandline(int argc, char **argv, struct behavior *b) 03291 #else /* not ANSI_DECLARATORS */ 03292 void parsecommandline(argc, argv, b) 03293 int argc; 03294 char **argv; 03295 struct behavior *b; 03296 #endif /* not ANSI_DECLARATORS */ 03297 03298 { 03299 #ifdef TRILIBRARY 03300 #define STARTINDEX 0 03301 #else /* not TRILIBRARY */ 03302 #define STARTINDEX 1 03303 int increment; 03304 int meshnumber; 03305 #endif /* not TRILIBRARY */ 03306 int i, j, k; 03307 char workstring[FILENAMESIZE]; 03308 03309 b->poly = b->refine = b->quality = 0; 03310 b->vararea = b->fixedarea = b->usertest = 0; 03311 b->regionattrib = b->convex = b->weighted = b->jettison = 0; 03312 b->firstnumber = 1; 03313 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0; 03314 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0; 03315 b->noiterationnum = 0; 03316 b->noholes = b->noexact = 0; 03317 b->incremental = b->sweepline = 0; 03318 b->dwyer = 1; 03319 b->splitseg = 0; 03320 b->docheck = 0; 03321 b->nobisect = 0; 03322 b->conformdel = 0; 03323 b->steiner = -1; 03324 b->order = 1; 03325 b->minangle = 0.0; 03326 b->maxarea = -1.0; 03327 b->quiet = b->verbose = 0; 03328 #ifndef TRILIBRARY 03329 b->innodefilename[0] = '\0'; 03330 #endif /* not TRILIBRARY */ 03331 03332 for (i = STARTINDEX; i < argc; i++) { 03333 #ifndef TRILIBRARY 03334 if (argv[i][0] == '-') { 03335 #endif /* not TRILIBRARY */ 03336 for (j = STARTINDEX; argv[i][j] != '\0'; j++) { 03337 if (argv[i][j] == 'p') { 03338 b->poly = 1; 03339 } 03340 #ifndef CDT_ONLY 03341 if (argv[i][j] == 'r') { 03342 b->refine = 1; 03343 } 03344 if (argv[i][j] == 'q') { 03345 b->quality = 1; 03346 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || 03347 (argv[i][j + 1] == '.')) { 03348 k = 0; 03349 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || 03350 (argv[i][j + 1] == '.')) { 03351 j++; 03352 workstring[k] = argv[i][j]; 03353 k++; 03354 } 03355 workstring[k] = '\0'; 03356 b->minangle = (REAL) strtod(workstring, (char **) NULL); 03357 } else { 03358 b->minangle = 20.0; 03359 } 03360 } 03361 if (argv[i][j] == 'a') { 03362 b->quality = 1; 03363 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || 03364 (argv[i][j + 1] == '.')) { 03365 b->fixedarea = 1; 03366 k = 0; 03367 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) || 03368 (argv[i][j + 1] == '.')) { 03369 j++; 03370 workstring[k] = argv[i][j]; 03371 k++; 03372 } 03373 workstring[k] = '\0'; 03374 b->maxarea = (REAL) strtod(workstring, (char **) NULL); 03375 if (b->maxarea <= 0.0) { 03376 printf("Error: Maximum area must be greater than zero.\n"); 03377 triexit(1); 03378 } 03379 } else { 03380 b->vararea = 1; 03381 } 03382 } 03383 if (argv[i][j] == 'u') { 03384 b->quality = 1; 03385 b->usertest = 1; 03386 } 03387 #endif /* not CDT_ONLY */ 03388 if (argv[i][j] == 'A') { 03389 b->regionattrib = 1; 03390 } 03391 if (argv[i][j] == 'c') { 03392 b->convex = 1; 03393 } 03394 if (argv[i][j] == 'w') { 03395 b->weighted = 1; 03396 } 03397 if (argv[i][j] == 'W') { 03398 b->weighted = 2; 03399 } 03400 if (argv[i][j] == 'j') { 03401 b->jettison = 1; 03402 } 03403 if (argv[i][j] == 'z') { 03404 b->firstnumber = 0; 03405 } 03406 if (argv[i][j] == 'e') { 03407 b->edgesout = 1; 03408 } 03409 if (argv[i][j] == 'v') { 03410 b->voronoi = 1; 03411 } 03412 if (argv[i][j] == 'n') { 03413 b->neighbors = 1; 03414 } 03415 if (argv[i][j] == 'g') { 03416 b->geomview = 1; 03417 } 03418 if (argv[i][j] == 'B') { 03419 b->nobound = 1; 03420 } 03421 if (argv[i][j] == 'P') { 03422 b->nopolywritten = 1; 03423 } 03424 if (argv[i][j] == 'N') { 03425 b->nonodewritten = 1; 03426 } 03427 if (argv[i][j] == 'E') { 03428 b->noelewritten = 1; 03429 } 03430 #ifndef TRILIBRARY 03431 if (argv[i][j] == 'I') { 03432 b->noiterationnum = 1; 03433 } 03434 #endif /* not TRILIBRARY */ 03435 if (argv[i][j] == 'O') { 03436 b->noholes = 1; 03437 } 03438 if (argv[i][j] == 'X') { 03439 b->noexact = 1; 03440 } 03441 if (argv[i][j] == 'o') { 03442 if (argv[i][j + 1] == '2') { 03443 j++; 03444 b->order = 2; 03445 } 03446 } 03447 #ifndef CDT_ONLY 03448 if (argv[i][j] == 'Y') { 03449 b->nobisect++; 03450 } 03451 if (argv[i][j] == 'S') { 03452 b->steiner = 0; 03453 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) { 03454 j++; 03455 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0'); 03456 } 03457 } 03458 #endif /* not CDT_ONLY */ 03459 #ifndef REDUCED 03460 if (argv[i][j] == 'i') { 03461 b->incremental = 1; 03462 } 03463 if (argv[i][j] == 'F') { 03464 b->sweepline = 1; 03465 } 03466 #endif /* not REDUCED */ 03467 if (argv[i][j] == 'l') { 03468 b->dwyer = 0; 03469 } 03470 #ifndef REDUCED 03471 #ifndef CDT_ONLY 03472 if (argv[i][j] == 's') { 03473 b->splitseg = 1; 03474 } 03475 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) { 03476 b->quality = 1; 03477 b->conformdel = 1; 03478 } 03479 #endif /* not CDT_ONLY */ 03480 if (argv[i][j] == 'C') { 03481 b->docheck = 1; 03482 } 03483 #endif /* not REDUCED */ 03484 if (argv[i][j] == 'Q') { 03485 b->quiet = 1; 03486 } 03487 if (argv[i][j] == 'V') { 03488 b->verbose++; 03489 } 03490 #ifndef TRILIBRARY 03491 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') || 03492 (argv[i][j] == '?')) { 03493 info(); 03494 } 03495 #endif /* not TRILIBRARY */ 03496 } 03497 #ifndef TRILIBRARY 03498 } else { 03499 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1); 03500 b->innodefilename[FILENAMESIZE - 1] = '\0'; 03501 } 03502 #endif /* not TRILIBRARY */ 03503 } 03504 #ifndef TRILIBRARY 03505 if (b->innodefilename[0] == '\0') { 03506 syntax(); 03507 } 03508 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) { 03509 b->innodefilename[strlen(b->innodefilename) - 5] = '\0'; 03510 } 03511 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) { 03512 b->innodefilename[strlen(b->innodefilename) - 5] = '\0'; 03513 b->poly = 1; 03514 } 03515 #ifndef CDT_ONLY 03516 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) { 03517 b->innodefilename[strlen(b->innodefilename) - 4] = '\0'; 03518 b->refine = 1; 03519 } 03520 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) { 03521 b->innodefilename[strlen(b->innodefilename) - 5] = '\0'; 03522 b->refine = 1; 03523 b->quality = 1; 03524 b->vararea = 1; 03525 } 03526 #endif /* not CDT_ONLY */ 03527 #endif /* not TRILIBRARY */ 03528 b->usesegments = b->poly || b->refine || b->quality || b->convex; 03529 b->goodangle = cos(b->minangle * PI / 180.0); 03530 if (b->goodangle == 1.0) { 03531 b->offconstant = 0.0; 03532 } else { 03533 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle)); 03534 } 03535 b->goodangle *= b->goodangle; 03536 if (b->refine && b->noiterationnum) { 03537 printf( 03538 "Error: You cannot use the -I switch when refining a triangulation.\n"); 03539 triexit(1); 03540 } 03541 /* Be careful not to allocate space for element area constraints that */ 03542 /* will never be assigned any value (other than the default -1.0). */ 03543 if (!b->refine && !b->poly) { 03544 b->vararea = 0; 03545 } 03546 /* Be careful not to add an extra attribute to each element unless the */ 03547 /* input supports it (PSLG in, but not refining a preexisting mesh). */ 03548 if (b->refine || !b->poly) { 03549 b->regionattrib = 0; 03550 } 03551 /* Regular/weighted triangulations are incompatible with PSLGs */ 03552 /* and meshing. */ 03553 if (b->weighted && (b->poly || b->quality)) { 03554 b->weighted = 0; 03555 if (!b->quiet) { 03556 printf("Warning: weighted triangulations (-w, -W) are incompatible\n"); 03557 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n" 03558 ); 03559 } 03560 } 03561 if (b->jettison && b->nonodewritten && !b->quiet) { 03562 printf("Warning: -j and -N switches are somewhat incompatible.\n"); 03563 printf(" If any vertices are jettisoned, you will need the output\n"); 03564 printf(" .node file to reconstruct the new node indices."); 03565 } 03566 03567 #ifndef TRILIBRARY 03568 strcpy(b->inpolyfilename, b->innodefilename); 03569 strcpy(b->inelefilename, b->innodefilename); 03570 strcpy(b->areafilename, b->innodefilename); 03571 increment = 0; 03572 strcpy(workstring, b->innodefilename); 03573 j = 1; 03574 while (workstring[j] != '\0') { 03575 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) { 03576 increment = j + 1; 03577 } 03578 j++; 03579 } 03580 meshnumber = 0; 03581 if (increment > 0) { 03582 j = increment; 03583 do { 03584 if ((workstring[j] >= '0') && (workstring[j] <= '9')) { 03585 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0'); 03586 } else { 03587 increment = 0; 03588 } 03589 j++; 03590 } while (workstring[j] != '\0'); 03591 } 03592 if (b->noiterationnum) { 03593 strcpy(b->outnodefilename, b->innodefilename); 03594 strcpy(b->outelefilename, b->innodefilename); 03595 strcpy(b->edgefilename, b->innodefilename); 03596 strcpy(b->vnodefilename, b->innodefilename); 03597 strcpy(b->vedgefilename, b->innodefilename); 03598 strcpy(b->neighborfilename, b->innodefilename); 03599 strcpy(b->offfilename, b->innodefilename); 03600 strcat(b->outnodefilename, ".node"); 03601 strcat(b->outelefilename, ".ele"); 03602 strcat(b->edgefilename, ".edge"); 03603 strcat(b->vnodefilename, ".v.node"); 03604 strcat(b->vedgefilename, ".v.edge"); 03605 strcat(b->neighborfilename, ".neigh"); 03606 strcat(b->offfilename, ".off"); 03607 } else if (increment == 0) { 03608 strcpy(b->outnodefilename, b->innodefilename); 03609 strcpy(b->outpolyfilename, b->innodefilename); 03610 strcpy(b->outelefilename, b->innodefilename); 03611 strcpy(b->edgefilename, b->innodefilename); 03612 strcpy(b->vnodefilename, b->innodefilename); 03613 strcpy(b->vedgefilename, b->innodefilename); 03614 strcpy(b->neighborfilename, b->innodefilename); 03615 strcpy(b->offfilename, b->innodefilename); 03616 strcat(b->outnodefilename, ".1.node"); 03617 strcat(b->outpolyfilename, ".1.poly"); 03618 strcat(b->outelefilename, ".1.ele"); 03619 strcat(b->edgefilename, ".1.edge"); 03620 strcat(b->vnodefilename, ".1.v.node"); 03621 strcat(b->vedgefilename, ".1.v.edge"); 03622 strcat(b->neighborfilename, ".1.neigh"); 03623 strcat(b->offfilename, ".1.off"); 03624 } else { 03625 workstring[increment] = '%'; 03626 workstring[increment + 1] = 'd'; 03627 workstring[increment + 2] = '\0'; 03628 sprintf(b->outnodefilename, workstring, meshnumber + 1); 03629 strcpy(b->outpolyfilename, b->outnodefilename); 03630 strcpy(b->outelefilename, b->outnodefilename); 03631 strcpy(b->edgefilename, b->outnodefilename); 03632 strcpy(b->vnodefilename, b->outnodefilename); 03633 strcpy(b->vedgefilename, b->outnodefilename); 03634 strcpy(b->neighborfilename, b->outnodefilename); 03635 strcpy(b->offfilename, b->outnodefilename); 03636 strcat(b->outnodefilename, ".node"); 03637 strcat(b->outpolyfilename, ".poly"); 03638 strcat(b->outelefilename, ".ele"); 03639 strcat(b->edgefilename, ".edge"); 03640 strcat(b->vnodefilename, ".v.node"); 03641 strcat(b->vedgefilename, ".v.edge"); 03642 strcat(b->neighborfilename, ".neigh"); 03643 strcat(b->offfilename, ".off"); 03644 } 03645 strcat(b->innodefilename, ".node"); 03646 strcat(b->inpolyfilename, ".poly"); 03647 strcat(b->inelefilename, ".ele"); 03648 strcat(b->areafilename, ".area"); 03649 #endif /* not TRILIBRARY */ 03650 } 03651 03654 /********* User interaction routines begin here *********/ 03655 03656 /********* Debugging routines begin here *********/ 03660 /*****************************************************************************/ 03661 /* */ 03662 /* printtriangle() Print out the details of an oriented triangle. */ 03663 /* */ 03664 /* I originally wrote this procedure to simplify debugging; it can be */ 03665 /* called directly from the debugger, and presents information about an */ 03666 /* oriented triangle in digestible form. It's also used when the */ 03667 /* highest level of verbosity (`-VVV') is specified. */ 03668 /* */ 03669 /*****************************************************************************/ 03670 03671 #ifdef ANSI_DECLARATORS 03672 void printtriangle(struct mesh *m, struct behavior *b, struct otri *t) 03673 #else /* not ANSI_DECLARATORS */ 03674 void printtriangle(m, b, t) 03675 struct mesh *m; 03676 struct behavior *b; 03677 struct otri *t; 03678 #endif /* not ANSI_DECLARATORS */ 03679 03680 { 03681 struct otri printtri; 03682 struct osub printsh; 03683 vertex printvertex; 03684 03685 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri, 03686 t->orient); 03687 decode(t->tri[0], printtri); 03688 if (printtri.tri == m->dummytri) { 03689 printf(" [0] = Outer space\n"); 03690 } else { 03691 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri, 03692 printtri.orient); 03693 } 03694 decode(t->tri[1], printtri); 03695 if (printtri.tri == m->dummytri) { 03696 printf(" [1] = Outer space\n"); 03697 } else { 03698 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri, 03699 printtri.orient); 03700 } 03701 decode(t->tri[2], printtri); 03702 if (printtri.tri == m->dummytri) { 03703 printf(" [2] = Outer space\n"); 03704 } else { 03705 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri, 03706 printtri.orient); 03707 } 03708 03709 org(*t, printvertex); 03710 if (printvertex == (vertex) NULL) 03711 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3); 03712 else 03713 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n", 03714 (t->orient + 1) % 3 + 3, (unsigned long) printvertex, 03715 printvertex[0], printvertex[1]); 03716 dest(*t, printvertex); 03717 if (printvertex == (vertex) NULL) 03718 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3); 03719 else 03720 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n", 03721 (t->orient + 2) % 3 + 3, (unsigned long) printvertex, 03722 printvertex[0], printvertex[1]); 03723 apex(*t, printvertex); 03724 if (printvertex == (vertex) NULL) 03725 printf(" Apex [%d] = NULL\n", t->orient + 3); 03726 else 03727 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n", 03728 t->orient + 3, (unsigned long) printvertex, 03729 printvertex[0], printvertex[1]); 03730 03731 if (b->usesegments) { 03732 sdecode(t->tri[6], printsh); 03733 if (printsh.ss != m->dummysub) { 03734 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss, 03735 printsh.ssorient); 03736 } 03737 sdecode(t->tri[7], printsh); 03738 if (printsh.ss != m->dummysub) { 03739 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss, 03740 printsh.ssorient); 03741 } 03742 sdecode(t->tri[8], printsh); 03743 if (printsh.ss != m->dummysub) { 03744 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss, 03745 printsh.ssorient); 03746 } 03747 } 03748 03749 if (b->vararea) { 03750 printf(" Area constraint: %.4g\n", areabound(*t)); 03751 } 03752 } 03753 03754 /*****************************************************************************/ 03755 /* */ 03756 /* printsubseg() Print out the details of an oriented subsegment. */ 03757 /* */ 03758 /* I originally wrote this procedure to simplify debugging; it can be */ 03759 /* called directly from the debugger, and presents information about an */ 03760 /* oriented subsegment in digestible form. It's also used when the highest */ 03761 /* level of verbosity (`-VVV') is specified. */ 03762 /* */ 03763 /*****************************************************************************/ 03764 03765 #ifdef ANSI_DECLARATORS 03766 void printsubseg(struct mesh *m, struct behavior *b, struct osub *s) 03767 #else /* not ANSI_DECLARATORS */ 03768 void printsubseg(m, b, s) 03769 struct mesh *m; 03770 struct behavior *b; 03771 struct osub *s; 03772 #endif /* not ANSI_DECLARATORS */ 03773 03774 { 03775 struct osub printsh; 03776 struct otri printtri; 03777 vertex printvertex; 03778 03779 printf("subsegment x%lx with orientation %d and mark %d:\n", 03780 (unsigned long) s->ss, s->ssorient, mark(*s)); 03781 sdecode(s->ss[0], printsh); 03782 if (printsh.ss == m->dummysub) { 03783 printf(" [0] = No subsegment\n"); 03784 } else { 03785 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss, 03786 printsh.ssorient); 03787 } 03788 sdecode(s->ss[1], printsh); 03789 if (printsh.ss == m->dummysub) { 03790 printf(" [1] = No subsegment\n"); 03791 } else { 03792 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss, 03793 printsh.ssorient); 03794 } 03795 03796 sorg(*s, printvertex); 03797 if (printvertex == (vertex) NULL) 03798 printf(" Origin[%d] = NULL\n", 2 + s->ssorient); 03799 else 03800 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n", 03801 2 + s->ssorient, (unsigned long) printvertex, 03802 printvertex[0], printvertex[1]); 03803 sdest(*s, printvertex); 03804 if (printvertex == (vertex) NULL) 03805 printf(" Dest [%d] = NULL\n", 3 - s->ssorient); 03806 else 03807 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n", 03808 3 - s->ssorient, (unsigned long) printvertex, 03809 printvertex[0], printvertex[1]); 03810 03811 decode(s->ss[6], printtri); 03812 if (printtri.tri == m->dummytri) { 03813 printf(" [6] = Outer space\n"); 03814 } else { 03815 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri, 03816 printtri.orient); 03817 } 03818 decode(s->ss[7], printtri); 03819 if (printtri.tri == m->dummytri) { 03820 printf(" [7] = Outer space\n"); 03821 } else { 03822 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri, 03823 printtri.orient); 03824 } 03825 03826 segorg(*s, printvertex); 03827 if (printvertex == (vertex) NULL) 03828 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient); 03829 else 03830 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n", 03831 4 + s->ssorient, (unsigned long) printvertex, 03832 printvertex[0], printvertex[1]); 03833 segdest(*s, printvertex); 03834 if (printvertex == (vertex) NULL) 03835 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient); 03836 else 03837 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n", 03838 5 - s->ssorient, (unsigned long) printvertex, 03839 printvertex[0], printvertex[1]); 03840 } 03841 03844 /********* Debugging routines end here *********/ 03845 03846 /********* Memory management routines begin here *********/ 03850 /*****************************************************************************/ 03851 /* */ 03852 /* poolzero() Set all of a pool's fields to zero. */ 03853 /* */ 03854 /* This procedure should never be called on a pool that has any memory */ 03855 /* allocated to it, as that memory would leak. */ 03856 /* */ 03857 /*****************************************************************************/ 03858 03859 #ifdef ANSI_DECLARATORS 03860 void poolzero(struct memorypool* pool) 03861 #else /* not ANSI_DECLARATORS */ 03862 void poolzero(pool) 03863 struct memorypool* pool; 03864 #endif /* not ANSI_DECLARATORS */ 03865 03866 { 03867 pool->firstblock = (VOID **) NULL; 03868 pool->nowblock = (VOID **) NULL; 03869 pool->nextitem = (VOID *) NULL; 03870 pool->deaditemstack = (VOID *) NULL; 03871 pool->pathblock = (VOID **) NULL; 03872 pool->pathitem = (VOID *) NULL; 03873 pool->alignbytes = 0; 03874 pool->itembytes = 0; 03875 pool->itemsperblock = 0; 03876 pool->itemsfirstblock = 0; 03877 pool->items = 0; 03878 pool->maxitems = 0; 03879 pool->unallocateditems = 0; 03880 pool->pathitemsleft = 0; 03881 } 03882 03883 /*****************************************************************************/ 03884 /* */ 03885 /* poolrestart() Deallocate all items in a pool. */ 03886 /* */ 03887 /* The pool is returned to its starting state, except that no memory is */ 03888 /* freed to the operating system. Rather, the previously allocated blocks */ 03889 /* are ready to be reused. */ 03890 /* */ 03891 /*****************************************************************************/ 03892 03893 #ifdef ANSI_DECLARATORS 03894 void poolrestart(struct memorypool* pool) 03895 #else /* not ANSI_DECLARATORS */ 03896 void poolrestart(pool) 03897 struct memorypool* pool; 03898 #endif /* not ANSI_DECLARATORS */ 03899 03900 { 03901 unsigned long alignptr; 03902 03903 pool->items = 0; 03904 pool->maxitems = 0; 03905 03906 /* Set the currently active block. */ 03907 pool->nowblock = pool->firstblock; 03908 /* Find the first item in the pool. Increment by the size of (VOID *). */ 03909 alignptr = (unsigned long) (pool->nowblock + 1); 03910 /* Align the item on an `alignbytes'-byte boundary. */ 03911 pool->nextitem = (VOID *) 03912 (alignptr + (unsigned long) pool->alignbytes - 03913 (alignptr % (unsigned long) pool->alignbytes)); 03914 /* There are lots of unallocated items left in this block. */ 03915 pool->unallocateditems = pool->itemsfirstblock; 03916 /* The stack of deallocated items is empty. */ 03917 pool->deaditemstack = (VOID *) NULL; 03918 } 03919 03920 /*****************************************************************************/ 03921 /* */ 03922 /* poolinit() Initialize a pool of memory for allocation of items. */ 03923 /* */ 03924 /* This routine initializes the machinery for allocating items. A `pool' */ 03925 /* is created whose records have size at least `bytecount'. Items will be */ 03926 /* allocated in `itemcount'-item blocks. Each item is assumed to be a */ 03927 /* collection of words, and either pointers or floating-point values are */ 03928 /* assumed to be the "primary" word type. (The "primary" word type is used */ 03929 /* to determine alignment of items.) If `alignment' isn't zero, all items */ 03930 /* will be `alignment'-byte aligned in memory. `alignment' must be either */ 03931 /* a multiple or a factor of the primary word size; powers of two are safe. */ 03932 /* `alignment' is normally used to create a few unused bits at the bottom */ 03933 /* of each item's pointer, in which information may be stored. */ 03934 /* */ 03935 /* Don't change this routine unless you understand it. */ 03936 /* */ 03937 /*****************************************************************************/ 03938 03939 #ifdef ANSI_DECLARATORS 03940 void poolinit(struct memorypool* pool, int bytecount, int itemcount, 03941 int firstitemcount, unsigned alignment) 03942 #else /* not ANSI_DECLARATORS */ 03943 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment) 03944 struct memorypool* pool; 03945 int bytecount; 03946 int itemcount; 03947 int firstitemcount; 03948 unsigned alignment; 03949 #endif /* not ANSI_DECLARATORS */ 03950 03951 { 03952 /* Find the proper alignment, which must be at least as large as: */ 03953 /* - The parameter `alignment'. */ 03954 /* - sizeof(VOID *), so the stack of dead items can be maintained */ 03955 /* without unaligned accesses. */ 03956 if (alignment > sizeof(VOID *)) { 03957 pool->alignbytes = alignment; 03958 } else { 03959 pool->alignbytes = sizeof(VOID *); 03960 } 03961 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) * 03962 pool->alignbytes; 03963 pool->itemsperblock = itemcount; 03964 if (firstitemcount == 0) { 03965 pool->itemsfirstblock = itemcount; 03966 } else { 03967 pool->itemsfirstblock = firstitemcount; 03968 } 03969 03970 /* Allocate a block of items. Space for `itemsfirstblock' items and one */ 03971 /* pointer (to point to the next block) are allocated, as well as space */ 03972 /* to ensure alignment of the items. */ 03973 pool->firstblock = (VOID **) 03974 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) + 03975 pool->alignbytes); 03976 /* Set the next block pointer to NULL. */ 03977 *(pool->firstblock) = (VOID *) NULL; 03978 poolrestart(pool); 03979 } 03980 03981 /*****************************************************************************/ 03982 /* */ 03983 /* pooldeinit() Free to the operating system all memory taken by a pool. */ 03984 /* */ 03985 /*****************************************************************************/ 03986 03987 #ifdef ANSI_DECLARATORS 03988 void pooldeinit(struct memorypool* pool) 03989 #else /* not ANSI_DECLARATORS */ 03990 void pooldeinit(pool) 03991 struct memorypool* pool; 03992 #endif /* not ANSI_DECLARATORS */ 03993 03994 { 03995 while (pool->firstblock != (VOID **) NULL) { 03996 pool->nowblock = (VOID **) *(pool->firstblock); 03997 trifree((VOID *) pool->firstblock); 03998 pool->firstblock = pool->nowblock; 03999 } 04000 } 04001 04002 /*****************************************************************************/ 04003 /* */ 04004 /* poolalloc() Allocate space for an item. */ 04005 /* */ 04006 /*****************************************************************************/ 04007 04008 #ifdef ANSI_DECLARATORS 04009 VOID* poolalloc(struct memorypool* pool) 04010 #else /* not ANSI_DECLARATORS */ 04011 VOID* poolalloc(pool) 04012 struct memorypool* pool; 04013 #endif /* not ANSI_DECLARATORS */ 04014 04015 { 04016 VOID *newitem; 04017 VOID **newblock; 04018 unsigned long alignptr; 04019 04020 /* First check the linked list of dead items. If the list is not */ 04021 /* empty, allocate an item from the list rather than a fresh one. */ 04022 if (pool->deaditemstack != (VOID *) NULL) { 04023 newitem = pool->deaditemstack; /* Take first item in list. */ 04024 pool->deaditemstack = * (VOID **) pool->deaditemstack; 04025 } else { 04026 /* Check if there are any free items left in the current block. */ 04027 if (pool->unallocateditems == 0) { 04028 /* Check if another block must be allocated. */ 04029 if (*(pool->nowblock) == (VOID *) NULL) { 04030 /* Allocate a new block of items, pointed to by the previous block. */ 04031 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes + 04032 (int) sizeof(VOID *) + 04033 pool->alignbytes); 04034 *(pool->nowblock) = (VOID *) newblock; 04035 /* The next block pointer is NULL. */ 04036 *newblock = (VOID *) NULL; 04037 } 04038 04039 /* Move to the new block. */ 04040 pool->nowblock = (VOID **) *(pool->nowblock); 04041 /* Find the first item in the block. */ 04042 /* Increment by the size of (VOID *). */ 04043 alignptr = (unsigned long) (pool->nowblock + 1); 04044 /* Align the item on an `alignbytes'-byte boundary. */ 04045 pool->nextitem = (VOID *) 04046 (alignptr + (unsigned long) pool->alignbytes - 04047 (alignptr % (unsigned long) pool->alignbytes)); 04048 /* There are lots of unallocated items left in this block. */ 04049 pool->unallocateditems = pool->itemsperblock; 04050 } 04051 04052 /* Allocate a new item. */ 04053 newitem = pool->nextitem; 04054 /* Advance `nextitem' pointer to next free item in block. */ 04055 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes); 04056 pool->unallocateditems--; 04057 pool->maxitems++; 04058 } 04059 pool->items++; 04060 return newitem; 04061 } 04062 04063 /*****************************************************************************/ 04064 /* */ 04065 /* pooldealloc() Deallocate space for an item. */ 04066 /* */ 04067 /* The deallocated space is stored in a queue for later reuse. */ 04068 /* */ 04069 /*****************************************************************************/ 04070 04071 #ifdef ANSI_DECLARATORS 04072 void pooldealloc(struct memorypool* pool, VOID *dyingitem) 04073 #else /* not ANSI_DECLARATORS */ 04074 void pooldealloc(pool, dyingitem) 04075 struct memorypool* pool; 04076 VOID *dyingitem; 04077 #endif /* not ANSI_DECLARATORS */ 04078 04079 { 04080 /* Push freshly killed item onto stack. */ 04081 *((VOID **) dyingitem) = pool->deaditemstack; 04082 pool->deaditemstack = dyingitem; 04083 pool->items--; 04084 } 04085 04086 /*****************************************************************************/ 04087 /* */ 04088 /* traversalinit() Prepare to traverse the entire list of items. */ 04089 /* */ 04090 /* This routine is used in conjunction with traverse(). */ 04091 /* */ 04092 /*****************************************************************************/ 04093 04094 #ifdef ANSI_DECLARATORS 04095 void traversalinit(struct memorypool* pool) 04096 #else /* not ANSI_DECLARATORS */ 04097 void traversalinit(pool) 04098 struct memorypool* pool; 04099 #endif /* not ANSI_DECLARATORS */ 04100 04101 { 04102 unsigned long alignptr; 04103 04104 /* Begin the traversal in the first block. */ 04105 pool->pathblock = pool->firstblock; 04106 /* Find the first item in the block. Increment by the size of (VOID *). */ 04107 alignptr = (unsigned long) (pool->pathblock + 1); 04108 /* Align with item on an `alignbytes'-byte boundary. */ 04109 pool->pathitem = (VOID *) 04110 (alignptr + (unsigned long) pool->alignbytes - 04111 (alignptr % (unsigned long) pool->alignbytes)); 04112 /* Set the number of items left in the current block. */ 04113 pool->pathitemsleft = pool->itemsfirstblock; 04114 } 04115 04116 /*****************************************************************************/ 04117 /* */ 04118 /* traverse() Find the next item in the list. */ 04119 /* */ 04120 /* This routine is used in conjunction with traversalinit(). Be forewarned */ 04121 /* that this routine successively returns all items in the list, including */ 04122 /* deallocated ones on the deaditemqueue. It's up to you to figure out */ 04123 /* which ones are actually dead. Why? I don't want to allocate extra */ 04124 /* space just to demarcate dead items. It can usually be done more */ 04125 /* space-efficiently by a routine that knows something about the structure */ 04126 /* of the item. */ 04127 /* */ 04128 /*****************************************************************************/ 04129 04130 #ifdef ANSI_DECLARATORS 04131 VOID *traverse(struct memorypool* pool) 04132 #else /* not ANSI_DECLARATORS */ 04133 VOID *traverse(pool) 04134 struct memorypool* pool; 04135 #endif /* not ANSI_DECLARATORS */ 04136 04137 { 04138 VOID *newitem; 04139 unsigned long alignptr; 04140 04141 /* Stop upon exhausting the list of items. */ 04142 if (pool->pathitem == pool->nextitem) { 04143 return (VOID *) NULL; 04144 } 04145 04146 /* Check whether any untraversed items remain in the current block. */ 04147 if (pool->pathitemsleft == 0) { 04148 /* Find the next block. */ 04149 pool->pathblock = (VOID **) *(pool->pathblock); 04150 /* Find the first item in the block. Increment by the size of (VOID *). */ 04151 alignptr = (unsigned long) (pool->pathblock + 1); 04152 /* Align with item on an `alignbytes'-byte boundary. */ 04153 pool->pathitem = (VOID *) 04154 (alignptr + (unsigned long) pool->alignbytes - 04155 (alignptr % (unsigned long) pool->alignbytes)); 04156 /* Set the number of items left in the current block. */ 04157 pool->pathitemsleft = pool->itemsperblock; 04158 } 04159 04160 newitem = pool->pathitem; 04161 /* Find the next item in the block. */ 04162 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes); 04163 pool->pathitemsleft--; 04164 return newitem; 04165 } 04166 04167 /*****************************************************************************/ 04168 /* */ 04169 /* dummyinit() Initialize the triangle that fills "outer space" and the */ 04170 /* omnipresent subsegment. */ 04171 /* */ 04172 /* The triangle that fills "outer space," called `dummytri', is pointed to */ 04173 /* by every triangle and subsegment on a boundary (be it outer or inner) of */ 04174 /* the triangulation. Also, `dummytri' points to one of the triangles on */ 04175 /* the convex hull (until the holes and concavities are carved), making it */ 04176 /* possible to find a starting triangle for point location. */ 04177 /* */ 04178 /* The omnipresent subsegment, `dummysub', is pointed to by every triangle */ 04179 /* or subsegment that doesn't have a full complement of real subsegments */ 04180 /* to point to. */ 04181 /* */ 04182 /* `dummytri' and `dummysub' are generally required to fulfill only a few */ 04183 /* invariants: their vertices must remain NULL and `dummytri' must always */ 04184 /* be bonded (at offset zero) to some triangle on the convex hull of the */ 04185 /* mesh, via a boundary edge. Otherwise, the connections of `dummytri' and */ 04186 /* `dummysub' may change willy-nilly. This makes it possible to avoid */ 04187 /* writing a good deal of special-case code (in the edge flip, for example) */ 04188 /* for dealing with the boundary of the mesh, places where no subsegment is */ 04189 /* present, and so forth. Other entities are frequently bonded to */ 04190 /* `dummytri' and `dummysub' as if they were real mesh entities, with no */ 04191 /* harm done. */ 04192 /* */ 04193 /*****************************************************************************/ 04194 04195 #ifdef ANSI_DECLARATORS 04196 void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, 04197 int subsegbytes) 04198 #else /* not ANSI_DECLARATORS */ 04199 void dummyinit(m, b, trianglebytes, subsegbytes) 04200 struct mesh *m; 04201 struct behavior *b; 04202 int trianglebytes; 04203 int subsegbytes; 04204 #endif /* not ANSI_DECLARATORS */ 04205 04206 { 04207 unsigned long alignptr; 04208 04209 /* Set up `dummytri', the `triangle' that occupies "outer space." */ 04210 m->dummytribase = (triangle *) trimalloc(trianglebytes + 04211 m->triangles.alignbytes); 04212 /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */ 04213 alignptr = (unsigned long) m->dummytribase; 04214 m->dummytri = (triangle *) 04215 (alignptr + (unsigned long) m->triangles.alignbytes - 04216 (alignptr % (unsigned long) m->triangles.alignbytes)); 04217 /* Initialize the three adjoining triangles to be "outer space." These */ 04218 /* will eventually be changed by various bonding operations, but their */ 04219 /* values don't really matter, as long as they can legally be */ 04220 /* dereferenced. */ 04221 m->dummytri[0] = (triangle) m->dummytri; 04222 m->dummytri[1] = (triangle) m->dummytri; 04223 m->dummytri[2] = (triangle) m->dummytri; 04224 /* Three NULL vertices. */ 04225 m->dummytri[3] = (triangle) NULL; 04226 m->dummytri[4] = (triangle) NULL; 04227 m->dummytri[5] = (triangle) NULL; 04228 04229 if (b->usesegments) { 04230 /* Set up `dummysub', the omnipresent subsegment pointed to by any */ 04231 /* triangle side or subsegment end that isn't attached to a real */ 04232 /* subsegment. */ 04233 m->dummysubbase = (subseg *) trimalloc(subsegbytes + 04234 m->subsegs.alignbytes); 04235 /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */ 04236 alignptr = (unsigned long) m->dummysubbase; 04237 m->dummysub = (subseg *) 04238 (alignptr + (unsigned long) m->subsegs.alignbytes - 04239 (alignptr % (unsigned long) m->subsegs.alignbytes)); 04240 /* Initialize the two adjoining subsegments to be the omnipresent */ 04241 /* subsegment. These will eventually be changed by various bonding */ 04242 /* operations, but their values don't really matter, as long as they */ 04243 /* can legally be dereferenced. */ 04244 m->dummysub[0] = (subseg) m->dummysub; 04245 m->dummysub[1] = (subseg) m->dummysub; 04246 /* Four NULL vertices. */ 04247 m->dummysub[2] = (subseg) NULL; 04248 m->dummysub[3] = (subseg) NULL; 04249 m->dummysub[4] = (subseg) NULL; 04250 m->dummysub[5] = (subseg) NULL; 04251 /* Initialize the two adjoining triangles to be "outer space." */ 04252 m->dummysub[6] = (subseg) m->dummytri; 04253 m->dummysub[7] = (subseg) m->dummytri; 04254 /* Set the boundary marker to zero. */ 04255 * (int *) (m->dummysub + 8) = 0; 04256 04257 /* Initialize the three adjoining subsegments of `dummytri' to be */ 04258 /* the omnipresent subsegment. */ 04259 m->dummytri[6] = (triangle) m->dummysub; 04260 m->dummytri[7] = (triangle) m->dummysub; 04261 m->dummytri[8] = (triangle) m->dummysub; 04262 } 04263 } 04264 04265 /*****************************************************************************/ 04266 /* */ 04267 /* initializevertexpool() Calculate the size of the vertex data structure */ 04268 /* and initialize its memory pool. */ 04269 /* */ 04270 /* This routine also computes the `vertexmarkindex' and `vertex2triindex' */ 04271 /* indices used to find values within each vertex. */ 04272 /* */ 04273 /*****************************************************************************/ 04274 04275 #ifdef ANSI_DECLARATORS 04276 void initializevertexpool(struct mesh *m, struct behavior *b) 04277 #else /* not ANSI_DECLARATORS */ 04278 void initializevertexpool(m, b) 04279 struct mesh *m; 04280 struct behavior *b; 04281 #endif /* not ANSI_DECLARATORS */ 04282 04283 { 04284 int vertexsize; 04285 04286 /* The index within each vertex at which the boundary marker is found, */ 04287 /* followed by the vertex type. Ensure the vertex marker is aligned to */ 04288 /* a sizeof(int)-byte address. */ 04289 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) + 04290 sizeof(int) - 1) / 04291 sizeof(int); 04292 vertexsize = (m->vertexmarkindex + 2) * sizeof(int); 04293 if (b->poly) { 04294 /* The index within each vertex at which a triangle pointer is found. */ 04295 /* Ensure the pointer is aligned to a sizeof(triangle)-byte address. */ 04296 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) / 04297 sizeof(triangle); 04298 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle); 04299 } 04300 04301 /* Initialize the pool of vertices. */ 04302 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK, 04303 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK, 04304 sizeof(REAL)); 04305 } 04306 04307 /*****************************************************************************/ 04308 /* */ 04309 /* initializetrisubpools() Calculate the sizes of the triangle and */ 04310 /* subsegment data structures and initialize */ 04311 /* their memory pools. */ 04312 /* */ 04313 /* This routine also computes the `highorderindex', `elemattribindex', and */ 04314 /* `areaboundindex' indices used to find values within each triangle. */ 04315 /* */ 04316 /*****************************************************************************/ 04317 04318 #ifdef ANSI_DECLARATORS 04319 void initializetrisubpools(struct mesh *m, struct behavior *b) 04320 #else /* not ANSI_DECLARATORS */ 04321 void initializetrisubpools(m, b) 04322 struct mesh *m; 04323 struct behavior *b; 04324 #endif /* not ANSI_DECLARATORS */ 04325 04326 { 04327 unsigned trisize; 04328 04329 /* The index within each triangle at which the extra nodes (above three) */ 04330 /* associated with high order elements are found. There are three */ 04331 /* pointers to other triangles, three pointers to corners, and possibly */ 04332 /* three pointers to subsegments before the extra nodes. */ 04333 m->highorderindex = 6 + (b->usesegments * 3); 04334 /* The number of bytes occupied by a triangle. */ 04335 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) * 04336 sizeof(triangle); 04337 /* The index within each triangle at which its attributes are found, */ 04338 /* where the index is measured in REALs. */ 04339 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL); 04340 /* The index within each triangle at which the maximum area constraint */ 04341 /* is found, where the index is measured in REALs. Note that if the */ 04342 /* `regionattrib' flag is set, an additional attribute will be added. */ 04343 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib; 04344 /* If triangle attributes or an area bound are needed, increase the number */ 04345 /* of bytes occupied by a triangle. */ 04346 if (b->vararea) { 04347 trisize = (m->areaboundindex + 1) * sizeof(REAL); 04348 } else if (m->eextras + b->regionattrib > 0) { 04349 trisize = m->areaboundindex * sizeof(REAL); 04350 } 04351 /* If a Voronoi diagram or triangle neighbor graph is requested, make */ 04352 /* sure there's room to store an integer index in each triangle. This */ 04353 /* integer index can occupy the same space as the subsegment pointers */ 04354 /* or attributes or area constraint or extra nodes. */ 04355 if ((b->voronoi || b->neighbors) && 04356 (trisize < 6 * sizeof(triangle) + sizeof(int))) { 04357 trisize = 6 * sizeof(triangle) + sizeof(int); 04358 } 04359 04360 /* Having determined the memory size of a triangle, initialize the pool. */ 04361 poolinit(&m->triangles, trisize, TRIPERBLOCK, 04362 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) : 04363 TRIPERBLOCK, 4); 04364 04365 if (b->usesegments) { 04366 /* Initialize the pool of subsegments. Take into account all eight */ 04367 /* pointers and one boundary marker. */ 04368 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int), 04369 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4); 04370 04371 /* Initialize the "outer space" triangle and omnipresent subsegment. */ 04372 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes); 04373 } else { 04374 /* Initialize the "outer space" triangle. */ 04375 dummyinit(m, b, m->triangles.itembytes, 0); 04376 } 04377 } 04378 04379 /*****************************************************************************/ 04380 /* */ 04381 /* triangledealloc() Deallocate space for a triangle, marking it dead. */ 04382 /* */ 04383 /*****************************************************************************/ 04384 04385 #ifdef ANSI_DECLARATORS 04386 void triangledealloc(struct mesh *m, triangle *dyingtriangle) 04387 #else /* not ANSI_DECLARATORS */ 04388 void triangledealloc(m, dyingtriangle) 04389 struct mesh *m; 04390 triangle *dyingtriangle; 04391 #endif /* not ANSI_DECLARATORS */ 04392 04393 { 04394 /* Mark the triangle as dead. This makes it possible to detect dead */ 04395 /* triangles when traversing the list of all triangles. */ 04396 killtri(dyingtriangle); 04397 pooldealloc(&m->triangles, (VOID *) dyingtriangle); 04398 } 04399 04400 /*****************************************************************************/ 04401 /* */ 04402 /* triangletraverse() Traverse the triangles, skipping dead ones. */ 04403 /* */ 04404 /*****************************************************************************/ 04405 04406 #ifdef ANSI_DECLARATORS 04407 triangle *triangletraverse(struct mesh *m) 04408 #else /* not ANSI_DECLARATORS */ 04409 triangle *triangletraverse(m) 04410 struct mesh *m; 04411 #endif /* not ANSI_DECLARATORS */ 04412 04413 { 04414 triangle *newtriangle; 04415 04416 do { 04417 newtriangle = (triangle *) traverse(&m->triangles); 04418 if (newtriangle == (triangle *) NULL) { 04419 return (triangle *) NULL; 04420 } 04421 } while (deadtri(newtriangle)); /* Skip dead ones. */ 04422 return newtriangle; 04423 } 04424 04425 /*****************************************************************************/ 04426 /* */ 04427 /* subsegdealloc() Deallocate space for a subsegment, marking it dead. */ 04428 /* */ 04429 /*****************************************************************************/ 04430 04431 #ifdef ANSI_DECLARATORS 04432 void subsegdealloc(struct mesh *m, subseg *dyingsubseg) 04433 #else /* not ANSI_DECLARATORS */ 04434 void subsegdealloc(m, dyingsubseg) 04435 struct mesh *m; 04436 subseg *dyingsubseg; 04437 #endif /* not ANSI_DECLARATORS */ 04438 04439 { 04440 /* Mark the subsegment as dead. This makes it possible to detect dead */ 04441 /* subsegments when traversing the list of all subsegments. */ 04442 killsubseg(dyingsubseg); 04443 pooldealloc(&m->subsegs, (VOID *) dyingsubseg); 04444 } 04445 04446 /*****************************************************************************/ 04447 /* */ 04448 /* subsegtraverse() Traverse the subsegments, skipping dead ones. */ 04449 /* */ 04450 /*****************************************************************************/ 04451 04452 #ifdef ANSI_DECLARATORS 04453 subseg *subsegtraverse(struct mesh *m) 04454 #else /* not ANSI_DECLARATORS */ 04455 subseg *subsegtraverse(m) 04456 struct mesh *m; 04457 #endif /* not ANSI_DECLARATORS */ 04458 04459 { 04460 subseg *newsubseg; 04461 04462 do { 04463 newsubseg = (subseg *) traverse(&m->subsegs); 04464 if (newsubseg == (subseg *) NULL) { 04465 return (subseg *) NULL; 04466 } 04467 } while (deadsubseg(newsubseg)); /* Skip dead ones. */ 04468 return newsubseg; 04469 } 04470 04471 /*****************************************************************************/ 04472 /* */ 04473 /* vertexdealloc() Deallocate space for a vertex, marking it dead. */ 04474 /* */ 04475 /*****************************************************************************/ 04476 04477 #ifdef ANSI_DECLARATORS 04478 void vertexdealloc(struct mesh *m, vertex dyingvertex) 04479 #else /* not ANSI_DECLARATORS */ 04480 void vertexdealloc(m, dyingvertex) 04481 struct mesh *m; 04482 vertex dyingvertex; 04483 #endif /* not ANSI_DECLARATORS */ 04484 04485 { 04486 /* Mark the vertex as dead. This makes it possible to detect dead */ 04487 /* vertices when traversing the list of all vertices. */ 04488 setvertextype(dyingvertex, DEADVERTEX); 04489 pooldealloc(&m->vertices, (VOID *) dyingvertex); 04490 } 04491 04492 /*****************************************************************************/ 04493 /* */ 04494 /* vertextraverse() Traverse the vertices, skipping dead ones. */ 04495 /* */ 04496 /*****************************************************************************/ 04497 04498 #ifdef ANSI_DECLARATORS 04499 vertex vertextraverse(struct mesh *m) 04500 #else /* not ANSI_DECLARATORS */ 04501 vertex vertextraverse(m) 04502 struct mesh *m; 04503 #endif /* not ANSI_DECLARATORS */ 04504 04505 { 04506 vertex newvertex; 04507 04508 do { 04509 newvertex = (vertex) traverse(&m->vertices); 04510 if (newvertex == (vertex) NULL) { 04511 return (vertex) NULL; 04512 } 04513 } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */ 04514 return newvertex; 04515 } 04516 04517 /*****************************************************************************/ 04518 /* */ 04519 /* badsubsegdealloc() Deallocate space for a bad subsegment, marking it */ 04520 /* dead. */ 04521 /* */ 04522 /*****************************************************************************/ 04523 04524 #ifndef CDT_ONLY 04525 04526 #ifdef ANSI_DECLARATORS 04527 void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg) 04528 #else /* not ANSI_DECLARATORS */ 04529 void badsubsegdealloc(m, dyingseg) 04530 struct mesh *m; 04531 struct badsubseg *dyingseg; 04532 #endif /* not ANSI_DECLARATORS */ 04533 04534 { 04535 /* Set subsegment's origin to NULL. This makes it possible to detect dead */ 04536 /* badsubsegs when traversing the list of all badsubsegs . */ 04537 dyingseg->subsegorg = (vertex) NULL; 04538 pooldealloc(&m->badsubsegs, (VOID *) dyingseg); 04539 } 04540 04541 #endif /* not CDT_ONLY */ 04542 04543 /*****************************************************************************/ 04544 /* */ 04545 /* badsubsegtraverse() Traverse the bad subsegments, skipping dead ones. */ 04546 /* */ 04547 /*****************************************************************************/ 04548 04549 #ifndef CDT_ONLY 04550 04551 #ifdef ANSI_DECLARATORS 04552 struct badsubseg *badsubsegtraverse(struct mesh *m) 04553 #else /* not ANSI_DECLARATORS */ 04554 struct badsubseg *badsubsegtraverse(m) 04555 struct mesh *m; 04556 #endif /* not ANSI_DECLARATORS */ 04557 04558 { 04559 struct badsubseg *newseg; 04560 04561 do { 04562 newseg = (struct badsubseg *) traverse(&m->badsubsegs); 04563 if (newseg == (struct badsubseg *) NULL) { 04564 return (struct badsubseg *) NULL; 04565 } 04566 } while (newseg->subsegorg == (vertex) NULL); /* Skip dead ones. */ 04567 return newseg; 04568 } 04569 04570 #endif /* not CDT_ONLY */ 04571 04572 /*****************************************************************************/ 04573 /* */ 04574 /* getvertex() Get a specific vertex, by number, from the list. */ 04575 /* */ 04576 /* The first vertex is number 'firstnumber'. */ 04577 /* */ 04578 /* Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */ 04579 /* is large). I don't care to take the trouble to make it work in constant */ 04580 /* time. */ 04581 /* */ 04582 /*****************************************************************************/ 04583 04584 #ifdef ANSI_DECLARATORS 04585 vertex getvertex(struct mesh *m, struct behavior *b, int number) 04586 #else /* not ANSI_DECLARATORS */ 04587 vertex getvertex(m, b, number) 04588 struct mesh *m; 04589 struct behavior *b; 04590 int number; 04591 #endif /* not ANSI_DECLARATORS */ 04592 04593 { 04594 VOID **getblock; 04595 char *foundvertex; 04596 unsigned long alignptr; 04597 int current; 04598 04599 getblock = m->vertices.firstblock; 04600 current = b->firstnumber; 04601 04602 /* Find the right block. */ 04603 if (current + m->vertices.itemsfirstblock <= number) { 04604 getblock = (VOID **) *getblock; 04605 current += m->vertices.itemsfirstblock; 04606 while (current + m->vertices.itemsperblock <= number) { 04607 getblock = (VOID **) *getblock; 04608 current += m->vertices.itemsperblock; 04609 } 04610 } 04611 04612 /* Now find the right vertex. */ 04613 alignptr = (unsigned long) (getblock + 1); 04614 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes - 04615 (alignptr % (unsigned long) m->vertices.alignbytes)); 04616 return (vertex) (foundvertex + m->vertices.itembytes * (number - current)); 04617 } 04618 04619 /*****************************************************************************/ 04620 /* */ 04621 /* triangledeinit() Free all remaining allocated memory. */ 04622 /* */ 04623 /*****************************************************************************/ 04624 04625 #ifdef ANSI_DECLARATORS 04626 void triangledeinit(struct mesh *m, struct behavior *b) 04627 #else /* not ANSI_DECLARATORS */ 04628 void triangledeinit(m, b) 04629 struct mesh *m; 04630 struct behavior *b; 04631 #endif /* not ANSI_DECLARATORS */ 04632 04633 { 04634 pooldeinit(&m->triangles); 04635 trifree((VOID *) m->dummytribase); 04636 if (b->usesegments) { 04637 pooldeinit(&m->subsegs); 04638 trifree((VOID *) m->dummysubbase); 04639 } 04640 pooldeinit(&m->vertices); 04641 #ifndef CDT_ONLY 04642 if (b->quality) { 04643 pooldeinit(&m->badsubsegs); 04644 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) { 04645 pooldeinit(&m->badtriangles); 04646 pooldeinit(&m->flipstackers); 04647 } 04648 } 04649 #endif /* not CDT_ONLY */ 04650 } 04651 04654 /********* Memory management routines end here *********/ 04655 04656 /********* Constructors begin here *********/ 04660 /*****************************************************************************/ 04661 /* */ 04662 /* maketriangle() Create a new triangle with orientation zero. */ 04663 /* */ 04664 /*****************************************************************************/ 04665 04666 #ifdef ANSI_DECLARATORS 04667 void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri) 04668 #else /* not ANSI_DECLARATORS */ 04669 void maketriangle(m, b, newotri) 04670 struct mesh *m; 04671 struct behavior *b; 04672 struct otri *newotri; 04673 #endif /* not ANSI_DECLARATORS */ 04674 04675 { 04676 int i; 04677 04678 newotri->tri = (triangle *) poolalloc(&m->triangles); 04679 /* Initialize the three adjoining triangles to be "outer space". */ 04680 newotri->tri[0] = (triangle) m->dummytri; 04681 newotri->tri[1] = (triangle) m->dummytri; 04682 newotri->tri[2] = (triangle) m->dummytri; 04683 /* Three NULL vertices. */ 04684 newotri->tri[3] = (triangle) NULL; 04685 newotri->tri[4] = (triangle) NULL; 04686 newotri->tri[5] = (triangle) NULL; 04687 if (b->usesegments) { 04688 /* Initialize the three adjoining subsegments to be the omnipresent */ 04689 /* subsegment. */ 04690 newotri->tri[6] = (triangle) m->dummysub; 04691 newotri->tri[7] = (triangle) m->dummysub; 04692 newotri->tri[8] = (triangle) m->dummysub; 04693 } 04694 for (i = 0; i < m->eextras; i++) { 04695 setelemattribute(*newotri, i, 0.0); 04696 } 04697 if (b->vararea) { 04698 setareabound(*newotri, -1.0); 04699 } 04700 04701 newotri->orient = 0; 04702 } 04703 04704 /*****************************************************************************/ 04705 /* */ 04706 /* makesubseg() Create a new subsegment with orientation zero. */ 04707 /* */ 04708 /*****************************************************************************/ 04709 04710 #ifdef ANSI_DECLARATORS 04711 void makesubseg(struct mesh *m, struct osub *newsubseg) 04712 #else /* not ANSI_DECLARATORS */ 04713 void makesubseg(m, newsubseg) 04714 struct mesh *m; 04715 struct osub *newsubseg; 04716 #endif /* not ANSI_DECLARATORS */ 04717 04718 { 04719 newsubseg->ss = (subseg *) poolalloc(&m->subsegs); 04720 /* Initialize the two adjoining subsegments to be the omnipresent */ 04721 /* subsegment. */ 04722 newsubseg->ss[0] = (subseg) m->dummysub; 04723 newsubseg->ss[1] = (subseg) m->dummysub; 04724 /* Four NULL vertices. */ 04725 newsubseg->ss[2] = (subseg) NULL; 04726 newsubseg->ss[3] = (subseg) NULL; 04727 newsubseg->ss[4] = (subseg) NULL; 04728 newsubseg->ss[5] = (subseg) NULL; 04729 /* Initialize the two adjoining triangles to be "outer space." */ 04730 newsubseg->ss[6] = (subseg) m->dummytri; 04731 newsubseg->ss[7] = (subseg) m->dummytri; 04732 /* Set the boundary marker to zero. */ 04733 setmark(*newsubseg, 0); 04734 04735 newsubseg->ssorient = 0; 04736 } 04737 04740 /********* Constructors end here *********/ 04741 04742 /********* Geometric primitives begin here *********/ 04746 /* The adaptive exact arithmetic geometric predicates implemented herein are */ 04747 /* described in detail in my paper, "Adaptive Precision Floating-Point */ 04748 /* Arithmetic and Fast Robust Geometric Predicates." See the header for a */ 04749 /* full citation. */ 04750 04751 /* Which of the following two methods of finding the absolute values is */ 04752 /* fastest is compiler-dependent. A few compilers can inline and optimize */ 04753 /* the fabs() call; but most will incur the overhead of a function call, */ 04754 /* which is disastrously slow. A faster way on IEEE machines might be to */ 04755 /* mask the appropriate bit, but that's difficult to do in C without */ 04756 /* forcing the value to be stored to memory (rather than be kept in the */ 04757 /* register to which the optimizer assigned it). */ 04758 04759 #define Absolute(a) ((a) >= 0.0 ? (a) : -(a)) 04760 /* #define Absolute(a) fabs(a) */ 04761 04762 /* Many of the operations are broken up into two pieces, a main part that */ 04763 /* performs an approximate operation, and a "tail" that computes the */ 04764 /* roundoff error of that operation. */ 04765 /* */ 04766 /* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(), */ 04767 /* Split(), and Two_Product() are all implemented as described in the */ 04768 /* reference. Each of these macros requires certain variables to be */ 04769 /* defined in the calling routine. The variables `bvirt', `c', `abig', */ 04770 /* `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because */ 04771 /* they store the result of an operation that may incur roundoff error. */ 04772 /* The input parameter `x' (or the highest numbered `x_' parameter) must */ 04773 /* also be declared `INEXACT'. */ 04774 04775 #define Fast_Two_Sum_Tail(a, b, x, y) \ 04776 bvirt = x - a; \ 04777 y = b - bvirt 04778 04779 #define Fast_Two_Sum(a, b, x, y) \ 04780 x = (REAL) (a + b); \ 04781 Fast_Two_Sum_Tail(a, b, x, y) 04782 04783 #define Two_Sum_Tail(a, b, x, y) \ 04784 bvirt = (REAL) (x - a); \ 04785 avirt = x - bvirt; \ 04786 bround = b - bvirt; \ 04787 around = a - avirt; \ 04788 y = around + bround 04789 04790 #define Two_Sum(a, b, x, y) \ 04791 x = (REAL) (a + b); \ 04792 Two_Sum_Tail(a, b, x, y) 04793 04794 #define Two_Diff_Tail(a, b, x, y) \ 04795 bvirt = (REAL) (a - x); \ 04796 avirt = x + bvirt; \ 04797 bround = bvirt - b; \ 04798 around = a - avirt; \ 04799 y = around + bround 04800 04801 #define Two_Diff(a, b, x, y) \ 04802 x = (REAL) (a - b); \ 04803 Two_Diff_Tail(a, b, x, y) 04804 04805 #define Split(a, ahi, alo) \ 04806 c = (REAL) (splitter * a); \ 04807 abig = (REAL) (c - a); \ 04808 ahi = c - abig; \ 04809 alo = a - ahi 04810 04811 #define Two_Product_Tail(a, b, x, y) \ 04812 Split(a, ahi, alo); \ 04813 Split(b, bhi, blo); \ 04814 err1 = x - (ahi * bhi); \ 04815 err2 = err1 - (alo * bhi); \ 04816 err3 = err2 - (ahi * blo); \ 04817 y = (alo * blo) - err3 04818 04819 #define Two_Product(a, b, x, y) \ 04820 x = (REAL) (a * b); \ 04821 Two_Product_Tail(a, b, x, y) 04822 04823 /* Two_Product_Presplit() is Two_Product() where one of the inputs has */ 04824 /* already been split. Avoids redundant splitting. */ 04825 04826 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \ 04827 x = (REAL) (a * b); \ 04828 Split(a, ahi, alo); \ 04829 err1 = x - (ahi * bhi); \ 04830 err2 = err1 - (alo * bhi); \ 04831 err3 = err2 - (ahi * blo); \ 04832 y = (alo * blo) - err3 04833 04834 /* Square() can be done more quickly than Two_Product(). */ 04835 04836 #define Square_Tail(a, x, y) \ 04837 Split(a, ahi, alo); \ 04838 err1 = x - (ahi * ahi); \ 04839 err3 = err1 - ((ahi + ahi) * alo); \ 04840 y = (alo * alo) - err3 04841 04842 #define Square(a, x, y) \ 04843 x = (REAL) (a * a); \ 04844 Square_Tail(a, x, y) 04845 04846 /* Macros for summing expansions of various fixed lengths. These are all */ 04847 /* unrolled versions of Expansion_Sum(). */ 04848 04849 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \ 04850 Two_Sum(a0, b , _i, x0); \ 04851 Two_Sum(a1, _i, x2, x1) 04852 04853 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \ 04854 Two_Diff(a0, b , _i, x0); \ 04855 Two_Sum( a1, _i, x2, x1) 04856 04857 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \ 04858 Two_One_Sum(a1, a0, b0, _j, _0, x0); \ 04859 Two_One_Sum(_j, _0, b1, x3, x2, x1) 04860 04861 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \ 04862 Two_One_Diff(a1, a0, b0, _j, _0, x0); \ 04863 Two_One_Diff(_j, _0, b1, x3, x2, x1) 04864 04865 /* Macro for multiplying a two-component expansion by a single component. */ 04866 04867 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \ 04868 Split(b, bhi, blo); \ 04869 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \ 04870 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \ 04871 Two_Sum(_i, _0, _k, x1); \ 04872 Fast_Two_Sum(_j, _k, x3, x2) 04873 04874 /*****************************************************************************/ 04875 /* */ 04876 /* exactinit() Initialize the variables used for exact arithmetic. */ 04877 /* */ 04878 /* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */ 04879 /* floating-point arithmetic. `epsilon' bounds the relative roundoff */ 04880 /* error. It is used for floating-point error analysis. */ 04881 /* */ 04882 /* `splitter' is used to split floating-point numbers into two half- */ 04883 /* length significands for exact multiplication. */ 04884 /* */ 04885 /* I imagine that a highly optimizing compiler might be too smart for its */ 04886 /* own good, and somehow cause this routine to fail, if it pretends that */ 04887 /* floating-point arithmetic is too much like real arithmetic. */ 04888 /* */ 04889 /* Don't change this routine unless you fully understand it. */ 04890 /* */ 04891 /*****************************************************************************/ 04892 04893 void exactinit() 04894 { 04895 REAL half; 04896 REAL check, lastcheck; 04897 int every_other; 04898 #ifdef LINUX 04899 int cword; 04900 #endif /* LINUX */ 04901 04902 #ifdef CPU86 04903 #ifdef SINGLE 04904 _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */ 04905 #else /* not SINGLE */ 04906 _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */ 04907 #endif /* not SINGLE */ 04908 #endif /* CPU86 */ 04909 #ifdef LINUX 04910 #ifdef SINGLE 04911 /* cword = 4223; */ 04912 cword = 4210; /* set FPU control word for single precision */ 04913 #else /* not SINGLE */ 04914 /* cword = 4735; */ 04915 cword = 4722; /* set FPU control word for double precision */ 04916 #endif /* not SINGLE */ 04917 _FPU_SETCW(cword); 04918 #endif /* LINUX */ 04919 04920 every_other = 1; 04921 half = 0.5; 04922 epsilon = 1.0; 04923 splitter = 1.0; 04924 check = 1.0; 04925 /* Repeatedly divide `epsilon' by two until it is too small to add to */ 04926 /* one without causing roundoff. (Also check if the sum is equal to */ 04927 /* the previous sum, for machines that round up instead of using exact */ 04928 /* rounding. Not that these routines will work on such machines.) */ 04929 do { 04930 lastcheck = check; 04931 epsilon *= half; 04932 if (every_other) { 04933 splitter *= 2.0; 04934 } 04935 every_other = !every_other; 04936 check = 1.0 + epsilon; 04937 } while ((check != 1.0) && (check != lastcheck)); 04938 splitter += 1.0; 04939 /* Error bounds for orientation and incircle tests. */ 04940 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon; 04941 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon; 04942 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon; 04943 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon; 04944 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon; 04945 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon; 04946 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon; 04947 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon; 04948 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon; 04949 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon; 04950 } 04951 04952 /*****************************************************************************/ 04953 /* */ 04954 /* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */ 04955 /* components from the output expansion. */ 04956 /* */ 04957 /* Sets h = e + f. See my Robust Predicates paper for details. */ 04958 /* */ 04959 /* If round-to-even is used (as with IEEE 754), maintains the strongly */ 04960 /* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */ 04961 /* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */ 04962 /* properties. */ 04963 /* */ 04964 /*****************************************************************************/ 04965 04966 #ifdef ANSI_DECLARATORS 04967 int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h) 04968 #else /* not ANSI_DECLARATORS */ 04969 int fast_expansion_sum_zeroelim(elen, e, flen, f, h) /* h cannot be e or f. */ 04970 int elen; 04971 REAL *e; 04972 int flen; 04973 REAL *f; 04974 REAL *h; 04975 #endif /* not ANSI_DECLARATORS */ 04976 04977 { 04978 REAL Q; 04979 INEXACT REAL Qnew; 04980 INEXACT REAL hh; 04981 INEXACT REAL bvirt; 04982 REAL avirt, bround, around; 04983 int eindex, findex, hindex; 04984 REAL enow, fnow; 04985 04986 enow = e[0]; 04987 fnow = f[0]; 04988 eindex = findex = 0; 04989 if ((fnow > enow) == (fnow > -enow)) { 04990 Q = enow; 04991 enow = e[++eindex]; 04992 } else { 04993 Q = fnow; 04994 fnow = f[++findex]; 04995 } 04996 hindex = 0; 04997 if ((eindex < elen) && (findex < flen)) { 04998 if ((fnow > enow) == (fnow > -enow)) { 04999 Fast_Two_Sum(enow, Q, Qnew, hh); 05000 enow = e[++eindex]; 05001 } else { 05002 Fast_Two_Sum(fnow, Q, Qnew, hh); 05003 fnow = f[++findex]; 05004 } 05005 Q = Qnew; 05006 if (hh != 0.0) { 05007 h[hindex++] = hh; 05008 } 05009 while ((eindex < elen) && (findex < flen)) { 05010 if ((fnow > enow) == (fnow > -enow)) { 05011 Two_Sum(Q, enow, Qnew, hh); 05012 enow = e[++eindex]; 05013 } else { 05014 Two_Sum(Q, fnow, Qnew, hh); 05015 fnow = f[++findex]; 05016 } 05017 Q = Qnew; 05018 if (hh != 0.0) { 05019 h[hindex++] = hh; 05020 } 05021 } 05022 } 05023 while (eindex < elen) { 05024 Two_Sum(Q, enow, Qnew, hh); 05025 enow = e[++eindex]; 05026 Q = Qnew; 05027 if (hh != 0.0) { 05028 h[hindex++] = hh; 05029 } 05030 } 05031 while (findex < flen) { 05032 Two_Sum(Q, fnow, Qnew, hh); 05033 fnow = f[++findex]; 05034 Q = Qnew; 05035 if (hh != 0.0) { 05036 h[hindex++] = hh; 05037 } 05038 } 05039 if ((Q != 0.0) || (hindex == 0)) { 05040 h[hindex++] = Q; 05041 } 05042 return hindex; 05043 } 05044 05045 /*****************************************************************************/ 05046 /* */ 05047 /* scale_expansion_zeroelim() Multiply an expansion by a scalar, */ 05048 /* eliminating zero components from the */ 05049 /* output expansion. */ 05050 /* */ 05051 /* Sets h = be. See my Robust Predicates paper for details. */ 05052 /* */ 05053 /* Maintains the nonoverlapping property. If round-to-even is used (as */ 05054 /* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent */ 05055 /* properties as well. (That is, if e has one of these properties, so */ 05056 /* will h.) */ 05057 /* */ 05058 /*****************************************************************************/ 05059 05060 #ifdef ANSI_DECLARATORS 05061 int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h) 05062 #else /* not ANSI_DECLARATORS */ 05063 int scale_expansion_zeroelim(elen, e, b, h) /* e and h cannot be the same. */ 05064 int elen; 05065 REAL *e; 05066 REAL b; 05067 REAL *h; 05068 #endif /* not ANSI_DECLARATORS */ 05069 05070 { 05071 INEXACT REAL Q, sum; 05072 REAL hh; 05073 INEXACT REAL product1; 05074 REAL product0; 05075 int eindex, hindex; 05076 REAL enow; 05077 INEXACT REAL bvirt; 05078 REAL avirt, bround, around; 05079 INEXACT REAL c; 05080 INEXACT REAL abig; 05081 REAL ahi, alo, bhi, blo; 05082 REAL err1, err2, err3; 05083 05084 Split(b, bhi, blo); 05085 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh); 05086 hindex = 0; 05087 if (hh != 0) { 05088 h[hindex++] = hh; 05089 } 05090 for (eindex = 1; eindex < elen; eindex++) { 05091 enow = e[eindex]; 05092 Two_Product_Presplit(enow, b, bhi, blo, product1, product0); 05093 Two_Sum(Q, product0, sum, hh); 05094 if (hh != 0) { 05095 h[hindex++] = hh; 05096 } 05097 Fast_Two_Sum(product1, sum, Q, hh); 05098 if (hh != 0) { 05099 h[hindex++] = hh; 05100 } 05101 } 05102 if ((Q != 0.0) || (hindex == 0)) { 05103 h[hindex++] = Q; 05104 } 05105 return hindex; 05106 } 05107 05108 /*****************************************************************************/ 05109 /* */ 05110 /* estimate() Produce a one-word estimate of an expansion's value. */ 05111 /* */ 05112 /* See my Robust Predicates paper for details. */ 05113 /* */ 05114 /*****************************************************************************/ 05115 05116 #ifdef ANSI_DECLARATORS 05117 REAL estimate(int elen, REAL *e) 05118 #else /* not ANSI_DECLARATORS */ 05119 REAL estimate(elen, e) 05120 int elen; 05121 REAL *e; 05122 #endif /* not ANSI_DECLARATORS */ 05123 05124 { 05125 REAL Q; 05126 int eindex; 05127 05128 Q = e[0]; 05129 for (eindex = 1; eindex < elen; eindex++) { 05130 Q += e[eindex]; 05131 } 05132 return Q; 05133 } 05134 05135 /*****************************************************************************/ 05136 /* */ 05137 /* counterclockwise() Return a positive value if the points pa, pb, and */ 05138 /* pc occur in counterclockwise order; a negative */ 05139 /* value if they occur in clockwise order; and zero */ 05140 /* if they are collinear. The result is also a rough */ 05141 /* approximation of twice the signed area of the */ 05142 /* triangle defined by the three points. */ 05143 /* */ 05144 /* Uses exact arithmetic if necessary to ensure a correct answer. The */ 05145 /* result returned is the determinant of a matrix. This determinant is */ 05146 /* computed adaptively, in the sense that exact arithmetic is used only to */ 05147 /* the degree it is needed to ensure that the returned value has the */ 05148 /* correct sign. Hence, this function is usually quite fast, but will run */ 05149 /* more slowly when the input points are collinear or nearly so. */ 05150 /* */ 05151 /* See my Robust Predicates paper for details. */ 05152 /* */ 05153 /*****************************************************************************/ 05154 05155 #ifdef ANSI_DECLARATORS 05156 REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum) 05157 #else /* not ANSI_DECLARATORS */ 05158 REAL counterclockwiseadapt(pa, pb, pc, detsum) 05159 vertex pa; 05160 vertex pb; 05161 vertex pc; 05162 REAL detsum; 05163 #endif /* not ANSI_DECLARATORS */ 05164 05165 { 05166 INEXACT REAL acx, acy, bcx, bcy; 05167 REAL acxtail, acytail, bcxtail, bcytail; 05168 INEXACT REAL detleft, detright; 05169 REAL detlefttail, detrighttail; 05170 REAL det, errbound; 05171 REAL B[4], C1[8], C2[12], D[16]; 05172 INEXACT REAL B3; 05173 int C1length, C2length, Dlength; 05174 REAL u[4]; 05175 INEXACT REAL u3; 05176 INEXACT REAL s1, t1; 05177 REAL s0, t0; 05178 05179 INEXACT REAL bvirt; 05180 REAL avirt, bround, around; 05181 INEXACT REAL c; 05182 INEXACT REAL abig; 05183 REAL ahi, alo, bhi, blo; 05184 REAL err1, err2, err3; 05185 INEXACT REAL _i, _j; 05186 REAL _0; 05187 05188 acx = (REAL) (pa[0] - pc[0]); 05189 bcx = (REAL) (pb[0] - pc[0]); 05190 acy = (REAL) (pa[1] - pc[1]); 05191 bcy = (REAL) (pb[1] - pc[1]); 05192 05193 Two_Product(acx, bcy, detleft, detlefttail); 05194 Two_Product(acy, bcx, detright, detrighttail); 05195 05196 Two_Two_Diff(detleft, detlefttail, detright, detrighttail, 05197 B3, B[2], B[1], B[0]); 05198 B[3] = B3; 05199 05200 det = estimate(4, B); 05201 errbound = ccwerrboundB * detsum; 05202 if ((det >= errbound) || (-det >= errbound)) { 05203 return det; 05204 } 05205 05206 Two_Diff_Tail(pa[0], pc[0], acx, acxtail); 05207 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail); 05208 Two_Diff_Tail(pa[1], pc[1], acy, acytail); 05209 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail); 05210 05211 if ((acxtail == 0.0) && (acytail == 0.0) 05212 && (bcxtail == 0.0) && (bcytail == 0.0)) { 05213 return det; 05214 } 05215 05216 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det); 05217 det += (acx * bcytail + bcy * acxtail) 05218 - (acy * bcxtail + bcx * acytail); 05219 if ((det >= errbound) || (-det >= errbound)) { 05220 return det; 05221 } 05222 05223 Two_Product(acxtail, bcy, s1, s0); 05224 Two_Product(acytail, bcx, t1, t0); 05225 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); 05226 u[3] = u3; 05227 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1); 05228 05229 Two_Product(acx, bcytail, s1, s0); 05230 Two_Product(acy, bcxtail, t1, t0); 05231 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); 05232 u[3] = u3; 05233 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2); 05234 05235 Two_Product(acxtail, bcytail, s1, s0); 05236 Two_Product(acytail, bcxtail, t1, t0); 05237 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); 05238 u[3] = u3; 05239 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D); 05240 05241 return(D[Dlength - 1]); 05242 } 05243 05244 #ifdef ANSI_DECLARATORS 05245 REAL counterclockwise(struct mesh *m, struct behavior *b, 05246 vertex pa, vertex pb, vertex pc) 05247 #else /* not ANSI_DECLARATORS */ 05248 REAL counterclockwise(m, b, pa, pb, pc) 05249 struct mesh *m; 05250 struct behavior *b; 05251 vertex pa; 05252 vertex pb; 05253 vertex pc; 05254 #endif /* not ANSI_DECLARATORS */ 05255 05256 { 05257 REAL detleft, detright, det; 05258 REAL detsum, errbound; 05259 05260 m->counterclockcount++; 05261 05262 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]); 05263 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]); 05264 det = detleft - detright; 05265 05266 if (b->noexact) { 05267 return det; 05268 } 05269 05270 if (detleft > 0.0) { 05271 if (detright <= 0.0) { 05272 return det; 05273 } else { 05274 detsum = detleft + detright; 05275 } 05276 } else if (detleft < 0.0) { 05277 if (detright >= 0.0) { 05278 return det; 05279 } else { 05280 detsum = -detleft - detright; 05281 } 05282 } else { 05283 return det; 05284 } 05285 05286 errbound = ccwerrboundA * detsum; 05287 if ((det >= errbound) || (-det >= errbound)) { 05288 return det; 05289 } 05290 05291 return counterclockwiseadapt(pa, pb, pc, detsum); 05292 } 05293 05294 /*****************************************************************************/ 05295 /* */ 05296 /* incircle() Return a positive value if the point pd lies inside the */ 05297 /* circle passing through pa, pb, and pc; a negative value if */ 05298 /* it lies outside; and zero if the four points are cocircular.*/ 05299 /* The points pa, pb, and pc must be in counterclockwise */ 05300 /* order, or the sign of the result will be reversed. */ 05301 /* */ 05302 /* Uses exact arithmetic if necessary to ensure a correct answer. The */ 05303 /* result returned is the determinant of a matrix. This determinant is */ 05304 /* computed adaptively, in the sense that exact arithmetic is used only to */ 05305 /* the degree it is needed to ensure that the returned value has the */ 05306 /* correct sign. Hence, this function is usually quite fast, but will run */ 05307 /* more slowly when the input points are cocircular or nearly so. */ 05308 /* */ 05309 /* See my Robust Predicates paper for details. */ 05310 /* */ 05311 /*****************************************************************************/ 05312 05313 #ifdef ANSI_DECLARATORS 05314 REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent) 05315 #else /* not ANSI_DECLARATORS */ 05316 REAL incircleadapt(pa, pb, pc, pd, permanent) 05317 vertex pa; 05318 vertex pb; 05319 vertex pc; 05320 vertex pd; 05321 REAL permanent; 05322 #endif /* not ANSI_DECLARATORS */ 05323 05324 { 05325 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy; 05326 REAL det, errbound; 05327 05328 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; 05329 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; 05330 REAL bc[4], ca[4], ab[4]; 05331 INEXACT REAL bc3, ca3, ab3; 05332 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32]; 05333 int axbclen, axxbclen, aybclen, ayybclen, alen; 05334 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32]; 05335 int bxcalen, bxxcalen, bycalen, byycalen, blen; 05336 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32]; 05337 int cxablen, cxxablen, cyablen, cyyablen, clen; 05338 REAL abdet[64]; 05339 int ablen; 05340 REAL fin1[1152], fin2[1152]; 05341 REAL *finnow, *finother, *finswap; 05342 int finlength; 05343 05344 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail; 05345 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1; 05346 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0; 05347 REAL aa[4], bb[4], cc[4]; 05348 INEXACT REAL aa3, bb3, cc3; 05349 INEXACT REAL ti1, tj1; 05350 REAL ti0, tj0; 05351 REAL u[4], v[4]; 05352 INEXACT REAL u3, v3; 05353 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16]; 05354 REAL temp32a[32], temp32b[32], temp48[48], temp64[64]; 05355 int temp8len, temp16alen, temp16blen, temp16clen; 05356 int temp32alen, temp32blen, temp48len, temp64len; 05357 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8]; 05358 int axtbblen, axtcclen, aytbblen, aytcclen; 05359 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8]; 05360 int bxtaalen, bxtcclen, bytaalen, bytcclen; 05361 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8]; 05362 int cxtaalen, cxtbblen, cytaalen, cytbblen; 05363 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8]; 05364 int axtbclen=0, aytbclen=0, bxtcalen=0, bytcalen=0, cxtablen=0, cytablen=0; 05365 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16]; 05366 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen; 05367 REAL axtbctt[8], aytbctt[8], bxtcatt[8]; 05368 REAL bytcatt[8], cxtabtt[8], cytabtt[8]; 05369 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen; 05370 REAL abt[8], bct[8], cat[8]; 05371 int abtlen, bctlen, catlen; 05372 REAL abtt[4], bctt[4], catt[4]; 05373 int abttlen, bcttlen, cattlen; 05374 INEXACT REAL abtt3, bctt3, catt3; 05375 REAL negate; 05376 05377 INEXACT REAL bvirt; 05378 REAL avirt, bround, around; 05379 INEXACT REAL c; 05380 INEXACT REAL abig; 05381 REAL ahi, alo, bhi, blo; 05382 REAL err1, err2, err3; 05383 INEXACT REAL _i, _j; 05384 REAL _0; 05385 05386 adx = (REAL) (pa[0] - pd[0]); 05387 bdx = (REAL) (pb[0] - pd[0]); 05388 cdx = (REAL) (pc[0] - pd[0]); 05389 ady = (REAL) (pa[1] - pd[1]); 05390 bdy = (REAL) (pb[1] - pd[1]); 05391 cdy = (REAL) (pc[1] - pd[1]); 05392 05393 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); 05394 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); 05395 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]); 05396 bc[3] = bc3; 05397 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc); 05398 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc); 05399 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc); 05400 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc); 05401 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet); 05402 05403 Two_Product(cdx, ady, cdxady1, cdxady0); 05404 Two_Product(adx, cdy, adxcdy1, adxcdy0); 05405 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]); 05406 ca[3] = ca3; 05407 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca); 05408 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca); 05409 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca); 05410 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca); 05411 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet); 05412 05413 Two_Product(adx, bdy, adxbdy1, adxbdy0); 05414 Two_Product(bdx, ady, bdxady1, bdxady0); 05415 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]); 05416 ab[3] = ab3; 05417 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab); 05418 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab); 05419 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab); 05420 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab); 05421 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet); 05422 05423 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); 05424 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1); 05425 05426 det = estimate(finlength, fin1); 05427 errbound = iccerrboundB * permanent; 05428 if ((det >= errbound) || (-det >= errbound)) { 05429 return det; 05430 } 05431 05432 Two_Diff_Tail(pa[0], pd[0], adx, adxtail); 05433 Two_Diff_Tail(pa[1], pd[1], ady, adytail); 05434 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail); 05435 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail); 05436 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail); 05437 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail); 05438 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) 05439 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) { 05440 return det; 05441 } 05442 05443 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det); 05444 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) 05445 - (bdy * cdxtail + cdx * bdytail)) 05446 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) 05447 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) 05448 - (cdy * adxtail + adx * cdytail)) 05449 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) 05450 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) 05451 - (ady * bdxtail + bdx * adytail)) 05452 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx)); 05453 if ((det >= errbound) || (-det >= errbound)) { 05454 return det; 05455 } 05456 05457 finnow = fin1; 05458 finother = fin2; 05459 05460 if ((bdxtail != 0.0) || (bdytail != 0.0) 05461 || (cdxtail != 0.0) || (cdytail != 0.0)) { 05462 Square(adx, adxadx1, adxadx0); 05463 Square(ady, adyady1, adyady0); 05464 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]); 05465 aa[3] = aa3; 05466 } 05467 if ((cdxtail != 0.0) || (cdytail != 0.0) 05468 || (adxtail != 0.0) || (adytail != 0.0)) { 05469 Square(bdx, bdxbdx1, bdxbdx0); 05470 Square(bdy, bdybdy1, bdybdy0); 05471 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]); 05472 bb[3] = bb3; 05473 } 05474 if ((adxtail != 0.0) || (adytail != 0.0) 05475 || (bdxtail != 0.0) || (bdytail != 0.0)) { 05476 Square(cdx, cdxcdx1, cdxcdx0); 05477 Square(cdy, cdycdy1, cdycdy0); 05478 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]); 05479 cc[3] = cc3; 05480 } 05481 05482 if (adxtail != 0.0) { 05483 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc); 05484 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx, 05485 temp16a); 05486 05487 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc); 05488 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b); 05489 05490 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb); 05491 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c); 05492 05493 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05494 temp16blen, temp16b, temp32a); 05495 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, 05496 temp32alen, temp32a, temp48); 05497 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05498 temp48, finother); 05499 finswap = finnow; finnow = finother; finother = finswap; 05500 } 05501 if (adytail != 0.0) { 05502 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc); 05503 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady, 05504 temp16a); 05505 05506 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb); 05507 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b); 05508 05509 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc); 05510 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c); 05511 05512 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05513 temp16blen, temp16b, temp32a); 05514 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, 05515 temp32alen, temp32a, temp48); 05516 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05517 temp48, finother); 05518 finswap = finnow; finnow = finother; finother = finswap; 05519 } 05520 if (bdxtail != 0.0) { 05521 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca); 05522 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx, 05523 temp16a); 05524 05525 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa); 05526 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b); 05527 05528 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc); 05529 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c); 05530 05531 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05532 temp16blen, temp16b, temp32a); 05533 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, 05534 temp32alen, temp32a, temp48); 05535 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05536 temp48, finother); 05537 finswap = finnow; finnow = finother; finother = finswap; 05538 } 05539 if (bdytail != 0.0) { 05540 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca); 05541 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy, 05542 temp16a); 05543 05544 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc); 05545 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b); 05546 05547 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa); 05548 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c); 05549 05550 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05551 temp16blen, temp16b, temp32a); 05552 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, 05553 temp32alen, temp32a, temp48); 05554 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05555 temp48, finother); 05556 finswap = finnow; finnow = finother; finother = finswap; 05557 } 05558 if (cdxtail != 0.0) { 05559 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab); 05560 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx, 05561 temp16a); 05562 05563 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb); 05564 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b); 05565 05566 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa); 05567 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c); 05568 05569 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05570 temp16blen, temp16b, temp32a); 05571 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, 05572 temp32alen, temp32a, temp48); 05573 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05574 temp48, finother); 05575 finswap = finnow; finnow = finother; finother = finswap; 05576 } 05577 if (cdytail != 0.0) { 05578 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab); 05579 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy, 05580 temp16a); 05581 05582 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa); 05583 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b); 05584 05585 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb); 05586 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c); 05587 05588 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05589 temp16blen, temp16b, temp32a); 05590 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c, 05591 temp32alen, temp32a, temp48); 05592 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05593 temp48, finother); 05594 finswap = finnow; finnow = finother; finother = finswap; 05595 } 05596 05597 if ((adxtail != 0.0) || (adytail != 0.0)) { 05598 if ((bdxtail != 0.0) || (bdytail != 0.0) 05599 || (cdxtail != 0.0) || (cdytail != 0.0)) { 05600 Two_Product(bdxtail, cdy, ti1, ti0); 05601 Two_Product(bdx, cdytail, tj1, tj0); 05602 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); 05603 u[3] = u3; 05604 negate = -bdy; 05605 Two_Product(cdxtail, negate, ti1, ti0); 05606 negate = -bdytail; 05607 Two_Product(cdx, negate, tj1, tj0); 05608 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); 05609 v[3] = v3; 05610 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct); 05611 05612 Two_Product(bdxtail, cdytail, ti1, ti0); 05613 Two_Product(cdxtail, bdytail, tj1, tj0); 05614 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]); 05615 bctt[3] = bctt3; 05616 bcttlen = 4; 05617 } else { 05618 bct[0] = 0.0; 05619 bctlen = 1; 05620 bctt[0] = 0.0; 05621 bcttlen = 1; 05622 } 05623 05624 if (adxtail != 0.0) { 05625 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a); 05626 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct); 05627 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx, 05628 temp32a); 05629 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05630 temp32alen, temp32a, temp48); 05631 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05632 temp48, finother); 05633 finswap = finnow; finnow = finother; finother = finswap; 05634 if (bdytail != 0.0) { 05635 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8); 05636 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail, 05637 temp16a); 05638 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, 05639 temp16a, finother); 05640 finswap = finnow; finnow = finother; finother = finswap; 05641 } 05642 if (cdytail != 0.0) { 05643 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8); 05644 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail, 05645 temp16a); 05646 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, 05647 temp16a, finother); 05648 finswap = finnow; finnow = finother; finother = finswap; 05649 } 05650 05651 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail, 05652 temp32a); 05653 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt); 05654 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx, 05655 temp16a); 05656 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail, 05657 temp16b); 05658 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05659 temp16blen, temp16b, temp32b); 05660 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, 05661 temp32blen, temp32b, temp64); 05662 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, 05663 temp64, finother); 05664 finswap = finnow; finnow = finother; finother = finswap; 05665 } 05666 if (adytail != 0.0) { 05667 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a); 05668 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct); 05669 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady, 05670 temp32a); 05671 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05672 temp32alen, temp32a, temp48); 05673 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05674 temp48, finother); 05675 finswap = finnow; finnow = finother; finother = finswap; 05676 05677 05678 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail, 05679 temp32a); 05680 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt); 05681 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady, 05682 temp16a); 05683 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail, 05684 temp16b); 05685 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05686 temp16blen, temp16b, temp32b); 05687 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, 05688 temp32blen, temp32b, temp64); 05689 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, 05690 temp64, finother); 05691 finswap = finnow; finnow = finother; finother = finswap; 05692 } 05693 } 05694 if ((bdxtail != 0.0) || (bdytail != 0.0)) { 05695 if ((cdxtail != 0.0) || (cdytail != 0.0) 05696 || (adxtail != 0.0) || (adytail != 0.0)) { 05697 Two_Product(cdxtail, ady, ti1, ti0); 05698 Two_Product(cdx, adytail, tj1, tj0); 05699 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); 05700 u[3] = u3; 05701 negate = -cdy; 05702 Two_Product(adxtail, negate, ti1, ti0); 05703 negate = -cdytail; 05704 Two_Product(adx, negate, tj1, tj0); 05705 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); 05706 v[3] = v3; 05707 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat); 05708 05709 Two_Product(cdxtail, adytail, ti1, ti0); 05710 Two_Product(adxtail, cdytail, tj1, tj0); 05711 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]); 05712 catt[3] = catt3; 05713 cattlen = 4; 05714 } else { 05715 cat[0] = 0.0; 05716 catlen = 1; 05717 catt[0] = 0.0; 05718 cattlen = 1; 05719 } 05720 05721 if (bdxtail != 0.0) { 05722 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a); 05723 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat); 05724 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx, 05725 temp32a); 05726 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05727 temp32alen, temp32a, temp48); 05728 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05729 temp48, finother); 05730 finswap = finnow; finnow = finother; finother = finswap; 05731 if (cdytail != 0.0) { 05732 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8); 05733 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail, 05734 temp16a); 05735 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, 05736 temp16a, finother); 05737 finswap = finnow; finnow = finother; finother = finswap; 05738 } 05739 if (adytail != 0.0) { 05740 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8); 05741 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail, 05742 temp16a); 05743 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, 05744 temp16a, finother); 05745 finswap = finnow; finnow = finother; finother = finswap; 05746 } 05747 05748 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail, 05749 temp32a); 05750 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt); 05751 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx, 05752 temp16a); 05753 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail, 05754 temp16b); 05755 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05756 temp16blen, temp16b, temp32b); 05757 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, 05758 temp32blen, temp32b, temp64); 05759 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, 05760 temp64, finother); 05761 finswap = finnow; finnow = finother; finother = finswap; 05762 } 05763 if (bdytail != 0.0) { 05764 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a); 05765 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat); 05766 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy, 05767 temp32a); 05768 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05769 temp32alen, temp32a, temp48); 05770 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05771 temp48, finother); 05772 finswap = finnow; finnow = finother; finother = finswap; 05773 05774 05775 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail, 05776 temp32a); 05777 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt); 05778 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy, 05779 temp16a); 05780 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail, 05781 temp16b); 05782 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05783 temp16blen, temp16b, temp32b); 05784 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, 05785 temp32blen, temp32b, temp64); 05786 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, 05787 temp64, finother); 05788 finswap = finnow; finnow = finother; finother = finswap; 05789 } 05790 } 05791 if ((cdxtail != 0.0) || (cdytail != 0.0)) { 05792 if ((adxtail != 0.0) || (adytail != 0.0) 05793 || (bdxtail != 0.0) || (bdytail != 0.0)) { 05794 Two_Product(adxtail, bdy, ti1, ti0); 05795 Two_Product(adx, bdytail, tj1, tj0); 05796 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]); 05797 u[3] = u3; 05798 negate = -ady; 05799 Two_Product(bdxtail, negate, ti1, ti0); 05800 negate = -adytail; 05801 Two_Product(bdx, negate, tj1, tj0); 05802 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]); 05803 v[3] = v3; 05804 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt); 05805 05806 Two_Product(adxtail, bdytail, ti1, ti0); 05807 Two_Product(bdxtail, adytail, tj1, tj0); 05808 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]); 05809 abtt[3] = abtt3; 05810 abttlen = 4; 05811 } else { 05812 abt[0] = 0.0; 05813 abtlen = 1; 05814 abtt[0] = 0.0; 05815 abttlen = 1; 05816 } 05817 05818 if (cdxtail != 0.0) { 05819 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a); 05820 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt); 05821 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx, 05822 temp32a); 05823 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05824 temp32alen, temp32a, temp48); 05825 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05826 temp48, finother); 05827 finswap = finnow; finnow = finother; finother = finswap; 05828 if (adytail != 0.0) { 05829 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8); 05830 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail, 05831 temp16a); 05832 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, 05833 temp16a, finother); 05834 finswap = finnow; finnow = finother; finother = finswap; 05835 } 05836 if (bdytail != 0.0) { 05837 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8); 05838 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail, 05839 temp16a); 05840 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen, 05841 temp16a, finother); 05842 finswap = finnow; finnow = finother; finother = finswap; 05843 } 05844 05845 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail, 05846 temp32a); 05847 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt); 05848 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx, 05849 temp16a); 05850 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail, 05851 temp16b); 05852 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05853 temp16blen, temp16b, temp32b); 05854 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, 05855 temp32blen, temp32b, temp64); 05856 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, 05857 temp64, finother); 05858 finswap = finnow; finnow = finother; finother = finswap; 05859 } 05860 if (cdytail != 0.0) { 05861 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a); 05862 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt); 05863 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy, 05864 temp32a); 05865 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05866 temp32alen, temp32a, temp48); 05867 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len, 05868 temp48, finother); 05869 finswap = finnow; finnow = finother; finother = finswap; 05870 05871 05872 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail, 05873 temp32a); 05874 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt); 05875 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy, 05876 temp16a); 05877 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail, 05878 temp16b); 05879 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a, 05880 temp16blen, temp16b, temp32b); 05881 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a, 05882 temp32blen, temp32b, temp64); 05883 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len, 05884 temp64, finother); 05885 finswap = finnow; finnow = finother; finother = finswap; 05886 } 05887 } 05888 05889 return finnow[finlength - 1]; 05890 } 05891 05892 #ifdef ANSI_DECLARATORS 05893 REAL incircle(struct mesh *m, struct behavior *b, 05894 vertex pa, vertex pb, vertex pc, vertex pd) 05895 #else /* not ANSI_DECLARATORS */ 05896 REAL incircle(m, b, pa, pb, pc, pd) 05897 struct mesh *m; 05898 struct behavior *b; 05899 vertex pa; 05900 vertex pb; 05901 vertex pc; 05902 vertex pd; 05903 #endif /* not ANSI_DECLARATORS */ 05904 05905 { 05906 REAL adx, bdx, cdx, ady, bdy, cdy; 05907 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; 05908 REAL alift, blift, clift; 05909 REAL det; 05910 REAL permanent, errbound; 05911 05912 m->incirclecount++; 05913 05914 adx = pa[0] - pd[0]; 05915 bdx = pb[0] - pd[0]; 05916 cdx = pc[0] - pd[0]; 05917 ady = pa[1] - pd[1]; 05918 bdy = pb[1] - pd[1]; 05919 cdy = pc[1] - pd[1]; 05920 05921 bdxcdy = bdx * cdy; 05922 cdxbdy = cdx * bdy; 05923 alift = adx * adx + ady * ady; 05924 05925 cdxady = cdx * ady; 05926 adxcdy = adx * cdy; 05927 blift = bdx * bdx + bdy * bdy; 05928 05929 adxbdy = adx * bdy; 05930 bdxady = bdx * ady; 05931 clift = cdx * cdx + cdy * cdy; 05932 05933 det = alift * (bdxcdy - cdxbdy) 05934 + blift * (cdxady - adxcdy) 05935 + clift * (adxbdy - bdxady); 05936 05937 if (b->noexact) { 05938 return det; 05939 } 05940 05941 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift 05942 + (Absolute(cdxady) + Absolute(adxcdy)) * blift 05943 + (Absolute(adxbdy) + Absolute(bdxady)) * clift; 05944 errbound = iccerrboundA * permanent; 05945 if ((det > errbound) || (-det > errbound)) { 05946 return det; 05947 } 05948 05949 return incircleadapt(pa, pb, pc, pd, permanent); 05950 } 05951 05952 /*****************************************************************************/ 05953 /* */ 05954 /* orient3d() Return a positive value if the point pd lies below the */ 05955 /* plane passing through pa, pb, and pc; "below" is defined so */ 05956 /* that pa, pb, and pc appear in counterclockwise order when */ 05957 /* viewed from above the plane. Returns a negative value if */ 05958 /* pd lies above the plane. Returns zero if the points are */ 05959 /* coplanar. The result is also a rough approximation of six */ 05960 /* times the signed volume of the tetrahedron defined by the */ 05961 /* four points. */ 05962 /* */ 05963 /* Uses exact arithmetic if necessary to ensure a correct answer. The */ 05964 /* result returned is the determinant of a matrix. This determinant is */ 05965 /* computed adaptively, in the sense that exact arithmetic is used only to */ 05966 /* the degree it is needed to ensure that the returned value has the */ 05967 /* correct sign. Hence, this function is usually quite fast, but will run */ 05968 /* more slowly when the input points are coplanar or nearly so. */ 05969 /* */ 05970 /* See my Robust Predicates paper for details. */ 05971 /* */ 05972 /*****************************************************************************/ 05973 05974 #ifdef ANSI_DECLARATORS 05975 REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, 05976 REAL aheight, REAL bheight, REAL cheight, REAL dheight, 05977 REAL permanent) 05978 #else /* not ANSI_DECLARATORS */ 05979 REAL orient3dadapt(pa, pb, pc, pd, 05980 aheight, bheight, cheight, dheight, permanent) 05981 vertex pa; 05982 vertex pb; 05983 vertex pc; 05984 vertex pd; 05985 REAL aheight; 05986 REAL bheight; 05987 REAL cheight; 05988 REAL dheight; 05989 REAL permanent; 05990 #endif /* not ANSI_DECLARATORS */ 05991 05992 { 05993 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight; 05994 REAL det, errbound; 05995 05996 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1; 05997 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0; 05998 REAL bc[4], ca[4], ab[4]; 05999 INEXACT REAL bc3, ca3, ab3; 06000 REAL adet[8], bdet[8], cdet[8]; 06001 int alen, blen, clen; 06002 REAL abdet[16]; 06003 int ablen; 06004 REAL *finnow, *finother, *finswap; 06005 REAL fin1[192], fin2[192]; 06006 int finlength; 06007 06008 REAL adxtail, bdxtail, cdxtail; 06009 REAL adytail, bdytail, cdytail; 06010 REAL adheighttail, bdheighttail, cdheighttail; 06011 INEXACT REAL at_blarge, at_clarge; 06012 INEXACT REAL bt_clarge, bt_alarge; 06013 INEXACT REAL ct_alarge, ct_blarge; 06014 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4]; 06015 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen; 06016 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1; 06017 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1; 06018 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0; 06019 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0; 06020 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1; 06021 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1; 06022 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0; 06023 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0; 06024 REAL bct[8], cat[8], abt[8]; 06025 int bctlen, catlen, abtlen; 06026 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1; 06027 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1; 06028 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0; 06029 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0; 06030 REAL u[4], v[12], w[16]; 06031 INEXACT REAL u3; 06032 int vlength, wlength; 06033 REAL negate; 06034 06035 INEXACT REAL bvirt; 06036 REAL avirt, bround, around; 06037 INEXACT REAL c; 06038 INEXACT REAL abig; 06039 REAL ahi, alo, bhi, blo; 06040 REAL err1, err2, err3; 06041 INEXACT REAL _i, _j, _k; 06042 REAL _0; 06043 06044 adx = (REAL) (pa[0] - pd[0]); 06045 bdx = (REAL) (pb[0] - pd[0]); 06046 cdx = (REAL) (pc[0] - pd[0]); 06047 ady = (REAL) (pa[1] - pd[1]); 06048 bdy = (REAL) (pb[1] - pd[1]); 06049 cdy = (REAL) (pc[1] - pd[1]); 06050 adheight = (REAL) (aheight - dheight); 06051 bdheight = (REAL) (bheight - dheight); 06052 cdheight = (REAL) (cheight - dheight); 06053 06054 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); 06055 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); 06056 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]); 06057 bc[3] = bc3; 06058 alen = scale_expansion_zeroelim(4, bc, adheight, adet); 06059 06060 Two_Product(cdx, ady, cdxady1, cdxady0); 06061 Two_Product(adx, cdy, adxcdy1, adxcdy0); 06062 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]); 06063 ca[3] = ca3; 06064 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet); 06065 06066 Two_Product(adx, bdy, adxbdy1, adxbdy0); 06067 Two_Product(bdx, ady, bdxady1, bdxady0); 06068 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]); 06069 ab[3] = ab3; 06070 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet); 06071 06072 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet); 06073 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1); 06074 06075 det = estimate(finlength, fin1); 06076 errbound = o3derrboundB * permanent; 06077 if ((det >= errbound) || (-det >= errbound)) { 06078 return det; 06079 } 06080 06081 Two_Diff_Tail(pa[0], pd[0], adx, adxtail); 06082 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail); 06083 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail); 06084 Two_Diff_Tail(pa[1], pd[1], ady, adytail); 06085 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail); 06086 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail); 06087 Two_Diff_Tail(aheight, dheight, adheight, adheighttail); 06088 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail); 06089 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail); 06090 06091 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) && 06092 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) && 06093 (adheighttail == 0.0) && 06094 (bdheighttail == 0.0) && 06095 (cdheighttail == 0.0)) { 06096 return det; 06097 } 06098 06099 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det); 06100 det += (adheight * ((bdx * cdytail + cdy * bdxtail) - 06101 (bdy * cdxtail + cdx * bdytail)) + 06102 adheighttail * (bdx * cdy - bdy * cdx)) + 06103 (bdheight * ((cdx * adytail + ady * cdxtail) - 06104 (cdy * adxtail + adx * cdytail)) + 06105 bdheighttail * (cdx * ady - cdy * adx)) + 06106 (cdheight * ((adx * bdytail + bdy * adxtail) - 06107 (ady * bdxtail + bdx * adytail)) + 06108 cdheighttail * (adx * bdy - ady * bdx)); 06109 if ((det >= errbound) || (-det >= errbound)) { 06110 return det; 06111 } 06112 06113 finnow = fin1; 06114 finother = fin2; 06115 06116 if (adxtail == 0.0) { 06117 if (adytail == 0.0) { 06118 at_b[0] = 0.0; 06119 at_blen = 1; 06120 at_c[0] = 0.0; 06121 at_clen = 1; 06122 } else { 06123 negate = -adytail; 06124 Two_Product(negate, bdx, at_blarge, at_b[0]); 06125 at_b[1] = at_blarge; 06126 at_blen = 2; 06127 Two_Product(adytail, cdx, at_clarge, at_c[0]); 06128 at_c[1] = at_clarge; 06129 at_clen = 2; 06130 } 06131 } else { 06132 if (adytail == 0.0) { 06133 Two_Product(adxtail, bdy, at_blarge, at_b[0]); 06134 at_b[1] = at_blarge; 06135 at_blen = 2; 06136 negate = -adxtail; 06137 Two_Product(negate, cdy, at_clarge, at_c[0]); 06138 at_c[1] = at_clarge; 06139 at_clen = 2; 06140 } else { 06141 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0); 06142 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0); 06143 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0, 06144 at_blarge, at_b[2], at_b[1], at_b[0]); 06145 at_b[3] = at_blarge; 06146 at_blen = 4; 06147 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0); 06148 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0); 06149 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0, 06150 at_clarge, at_c[2], at_c[1], at_c[0]); 06151 at_c[3] = at_clarge; 06152 at_clen = 4; 06153 } 06154 } 06155 if (bdxtail == 0.0) { 06156 if (bdytail == 0.0) { 06157 bt_c[0] = 0.0; 06158 bt_clen = 1; 06159 bt_a[0] = 0.0; 06160 bt_alen = 1; 06161 } else { 06162 negate = -bdytail; 06163 Two_Product(negate, cdx, bt_clarge, bt_c[0]); 06164 bt_c[1] = bt_clarge; 06165 bt_clen = 2; 06166 Two_Product(bdytail, adx, bt_alarge, bt_a[0]); 06167 bt_a[1] = bt_alarge; 06168 bt_alen = 2; 06169 } 06170 } else { 06171 if (bdytail == 0.0) { 06172 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]); 06173 bt_c[1] = bt_clarge; 06174 bt_clen = 2; 06175 negate = -bdxtail; 06176 Two_Product(negate, ady, bt_alarge, bt_a[0]); 06177 bt_a[1] = bt_alarge; 06178 bt_alen = 2; 06179 } else { 06180 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0); 06181 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0); 06182 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0, 06183 bt_clarge, bt_c[2], bt_c[1], bt_c[0]); 06184 bt_c[3] = bt_clarge; 06185 bt_clen = 4; 06186 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0); 06187 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0); 06188 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0, 06189 bt_alarge, bt_a[2], bt_a[1], bt_a[0]); 06190 bt_a[3] = bt_alarge; 06191 bt_alen = 4; 06192 } 06193 } 06194 if (cdxtail == 0.0) { 06195 if (cdytail == 0.0) { 06196 ct_a[0] = 0.0; 06197 ct_alen = 1; 06198 ct_b[0] = 0.0; 06199 ct_blen = 1; 06200 } else { 06201 negate = -cdytail; 06202 Two_Product(negate, adx, ct_alarge, ct_a[0]); 06203 ct_a[1] = ct_alarge; 06204 ct_alen = 2; 06205 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]); 06206 ct_b[1] = ct_blarge; 06207 ct_blen = 2; 06208 } 06209 } else { 06210 if (cdytail == 0.0) { 06211 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]); 06212 ct_a[1] = ct_alarge; 06213 ct_alen = 2; 06214 negate = -cdxtail; 06215 Two_Product(negate, bdy, ct_blarge, ct_b[0]); 06216 ct_b[1] = ct_blarge; 06217 ct_blen = 2; 06218 } else { 06219 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0); 06220 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0); 06221 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0, 06222 ct_alarge, ct_a[2], ct_a[1], ct_a[0]); 06223 ct_a[3] = ct_alarge; 06224 ct_alen = 4; 06225 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0); 06226 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0); 06227 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0, 06228 ct_blarge, ct_b[2], ct_b[1], ct_b[0]); 06229 ct_b[3] = ct_blarge; 06230 ct_blen = 4; 06231 } 06232 } 06233 06234 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct); 06235 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w); 06236 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, 06237 finother); 06238 finswap = finnow; finnow = finother; finother = finswap; 06239 06240 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat); 06241 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w); 06242 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, 06243 finother); 06244 finswap = finnow; finnow = finother; finother = finswap; 06245 06246 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt); 06247 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w); 06248 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, 06249 finother); 06250 finswap = finnow; finnow = finother; finother = finswap; 06251 06252 if (adheighttail != 0.0) { 06253 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v); 06254 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, 06255 finother); 06256 finswap = finnow; finnow = finother; finother = finswap; 06257 } 06258 if (bdheighttail != 0.0) { 06259 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v); 06260 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, 06261 finother); 06262 finswap = finnow; finnow = finother; finother = finswap; 06263 } 06264 if (cdheighttail != 0.0) { 06265 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v); 06266 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v, 06267 finother); 06268 finswap = finnow; finnow = finother; finother = finswap; 06269 } 06270 06271 if (adxtail != 0.0) { 06272 if (bdytail != 0.0) { 06273 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0); 06274 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]); 06275 u[3] = u3; 06276 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06277 finother); 06278 finswap = finnow; finnow = finother; finother = finswap; 06279 if (cdheighttail != 0.0) { 06280 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail, 06281 u3, u[2], u[1], u[0]); 06282 u[3] = u3; 06283 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06284 finother); 06285 finswap = finnow; finnow = finother; finother = finswap; 06286 } 06287 } 06288 if (cdytail != 0.0) { 06289 negate = -adxtail; 06290 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0); 06291 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]); 06292 u[3] = u3; 06293 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06294 finother); 06295 finswap = finnow; finnow = finother; finother = finswap; 06296 if (bdheighttail != 0.0) { 06297 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail, 06298 u3, u[2], u[1], u[0]); 06299 u[3] = u3; 06300 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06301 finother); 06302 finswap = finnow; finnow = finother; finother = finswap; 06303 } 06304 } 06305 } 06306 if (bdxtail != 0.0) { 06307 if (cdytail != 0.0) { 06308 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0); 06309 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]); 06310 u[3] = u3; 06311 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06312 finother); 06313 finswap = finnow; finnow = finother; finother = finswap; 06314 if (adheighttail != 0.0) { 06315 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail, 06316 u3, u[2], u[1], u[0]); 06317 u[3] = u3; 06318 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06319 finother); 06320 finswap = finnow; finnow = finother; finother = finswap; 06321 } 06322 } 06323 if (adytail != 0.0) { 06324 negate = -bdxtail; 06325 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0); 06326 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]); 06327 u[3] = u3; 06328 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06329 finother); 06330 finswap = finnow; finnow = finother; finother = finswap; 06331 if (cdheighttail != 0.0) { 06332 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail, 06333 u3, u[2], u[1], u[0]); 06334 u[3] = u3; 06335 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06336 finother); 06337 finswap = finnow; finnow = finother; finother = finswap; 06338 } 06339 } 06340 } 06341 if (cdxtail != 0.0) { 06342 if (adytail != 0.0) { 06343 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0); 06344 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]); 06345 u[3] = u3; 06346 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06347 finother); 06348 finswap = finnow; finnow = finother; finother = finswap; 06349 if (bdheighttail != 0.0) { 06350 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail, 06351 u3, u[2], u[1], u[0]); 06352 u[3] = u3; 06353 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06354 finother); 06355 finswap = finnow; finnow = finother; finother = finswap; 06356 } 06357 } 06358 if (bdytail != 0.0) { 06359 negate = -cdxtail; 06360 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0); 06361 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]); 06362 u[3] = u3; 06363 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06364 finother); 06365 finswap = finnow; finnow = finother; finother = finswap; 06366 if (adheighttail != 0.0) { 06367 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail, 06368 u3, u[2], u[1], u[0]); 06369 u[3] = u3; 06370 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u, 06371 finother); 06372 finswap = finnow; finnow = finother; finother = finswap; 06373 } 06374 } 06375 } 06376 06377 if (adheighttail != 0.0) { 06378 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w); 06379 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, 06380 finother); 06381 finswap = finnow; finnow = finother; finother = finswap; 06382 } 06383 if (bdheighttail != 0.0) { 06384 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w); 06385 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, 06386 finother); 06387 finswap = finnow; finnow = finother; finother = finswap; 06388 } 06389 if (cdheighttail != 0.0) { 06390 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w); 06391 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w, 06392 finother); 06393 finswap = finnow; finnow = finother; finother = finswap; 06394 } 06395 06396 return finnow[finlength - 1]; 06397 } 06398 06399 #ifdef ANSI_DECLARATORS 06400 REAL orient3d(struct mesh *m, struct behavior *b, 06401 vertex pa, vertex pb, vertex pc, vertex pd, 06402 REAL aheight, REAL bheight, REAL cheight, REAL dheight) 06403 #else /* not ANSI_DECLARATORS */ 06404 REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight) 06405 struct mesh *m; 06406 struct behavior *b; 06407 vertex pa; 06408 vertex pb; 06409 vertex pc; 06410 vertex pd; 06411 REAL aheight; 06412 REAL bheight; 06413 REAL cheight; 06414 REAL dheight; 06415 #endif /* not ANSI_DECLARATORS */ 06416 06417 { 06418 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight; 06419 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady; 06420 REAL det; 06421 REAL permanent, errbound; 06422 06423 m->orient3dcount++; 06424 06425 adx = pa[0] - pd[0]; 06426 bdx = pb[0] - pd[0]; 06427 cdx = pc[0] - pd[0]; 06428 ady = pa[1] - pd[1]; 06429 bdy = pb[1] - pd[1]; 06430 cdy = pc[1] - pd[1]; 06431 adheight = aheight - dheight; 06432 bdheight = bheight - dheight; 06433 cdheight = cheight - dheight; 06434 06435 bdxcdy = bdx * cdy; 06436 cdxbdy = cdx * bdy; 06437 06438 cdxady = cdx * ady; 06439 adxcdy = adx * cdy; 06440 06441 adxbdy = adx * bdy; 06442 bdxady = bdx * ady; 06443 06444 det = adheight * (bdxcdy - cdxbdy) 06445 + bdheight * (cdxady - adxcdy) 06446 + cdheight * (adxbdy - bdxady); 06447 06448 if (b->noexact) { 06449 return det; 06450 } 06451 06452 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight) 06453 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight) 06454 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight); 06455 errbound = o3derrboundA * permanent; 06456 if ((det > errbound) || (-det > errbound)) { 06457 return det; 06458 } 06459 06460 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight, 06461 permanent); 06462 } 06463 06464 /*****************************************************************************/ 06465 /* */ 06466 /* nonregular() Return a positive value if the point pd is incompatible */ 06467 /* with the circle or plane passing through pa, pb, and pc */ 06468 /* (meaning that pd is inside the circle or below the */ 06469 /* plane); a negative value if it is compatible; and zero if */ 06470 /* the four points are cocircular/coplanar. The points pa, */ 06471 /* pb, and pc must be in counterclockwise order, or the sign */ 06472 /* of the result will be reversed. */ 06473 /* */ 06474 /* If the -w switch is used, the points are lifted onto the parabolic */ 06475 /* lifting map, then they are dropped according to their weights, then the */ 06476 /* 3D orientation test is applied. If the -W switch is used, the points' */ 06477 /* heights are already provided, so the 3D orientation test is applied */ 06478 /* directly. If neither switch is used, the incircle test is applied. */ 06479 /* */ 06480 /*****************************************************************************/ 06481 06482 #ifdef ANSI_DECLARATORS 06483 REAL nonregular(struct mesh *m, struct behavior *b, 06484 vertex pa, vertex pb, vertex pc, vertex pd) 06485 #else /* not ANSI_DECLARATORS */ 06486 REAL nonregular(m, b, pa, pb, pc, pd) 06487 struct mesh *m; 06488 struct behavior *b; 06489 vertex pa; 06490 vertex pb; 06491 vertex pc; 06492 vertex pd; 06493 #endif /* not ANSI_DECLARATORS */ 06494 06495 { 06496 if (b->weighted == 0) { 06497 return incircle(m, b, pa, pb, pc, pd); 06498 } else if (b->weighted == 1) { 06499 return orient3d(m, b, pa, pb, pc, pd, 06500 pa[0] * pa[0] + pa[1] * pa[1] - pa[2], 06501 pb[0] * pb[0] + pb[1] * pb[1] - pb[2], 06502 pc[0] * pc[0] + pc[1] * pc[1] - pc[2], 06503 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]); 06504 } else { 06505 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]); 06506 } 06507 } 06508 06509 /*****************************************************************************/ 06510 /* */ 06511 /* findcircumcenter() Find the circumcenter of a triangle. */ 06512 /* */ 06513 /* The result is returned both in terms of x-y coordinates and xi-eta */ 06514 /* (barycentric) coordinates. The xi-eta coordinate system is defined in */ 06515 /* terms of the triangle: the origin of the triangle is the origin of the */ 06516 /* coordinate system; the destination of the triangle is one unit along the */ 06517 /* xi axis; and the apex of the triangle is one unit along the eta axis. */ 06518 /* This procedure also returns the square of the length of the triangle's */ 06519 /* shortest edge. */ 06520 /* */ 06521 /*****************************************************************************/ 06522 06523 #ifdef ANSI_DECLARATORS 06524 void findcircumcenter(struct mesh *m, struct behavior *b, 06525 vertex torg, vertex tdest, vertex tapex, 06526 vertex circumcenter, REAL *xi, REAL *eta, int offcenter) 06527 #else /* not ANSI_DECLARATORS */ 06528 void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta, 06529 offcenter) 06530 struct mesh *m; 06531 struct behavior *b; 06532 vertex torg; 06533 vertex tdest; 06534 vertex tapex; 06535 vertex circumcenter; 06536 REAL *xi; 06537 REAL *eta; 06538 int offcenter; 06539 #endif /* not ANSI_DECLARATORS */ 06540 06541 { 06542 REAL xdo, ydo, xao, yao; 06543 REAL dodist, aodist, dadist; 06544 REAL denominator; 06545 REAL dx, dy, dxoff, dyoff; 06546 06547 m->circumcentercount++; 06548 06549 /* Compute the circumcenter of the triangle. */ 06550 xdo = tdest[0] - torg[0]; 06551 ydo = tdest[1] - torg[1]; 06552 xao = tapex[0] - torg[0]; 06553 yao = tapex[1] - torg[1]; 06554 dodist = xdo * xdo + ydo * ydo; 06555 aodist = xao * xao + yao * yao; 06556 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) + 06557 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]); 06558 if (b->noexact) { 06559 denominator = 0.5 / (xdo * yao - xao * ydo); 06560 } else { 06561 /* Use the counterclockwise() routine to ensure a positive (and */ 06562 /* reasonably accurate) result, avoiding any possibility of */ 06563 /* division by zero. */ 06564 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg); 06565 /* Don't count the above as an orientation test. */ 06566 m->counterclockcount--; 06567 } 06568 dx = (yao * dodist - ydo * aodist) * denominator; 06569 dy = (xdo * aodist - xao * dodist) * denominator; 06570 06571 /* Find the (squared) length of the triangle's shortest edge. This */ 06572 /* serves as a conservative estimate of the insertion radius of the */ 06573 /* circumcenter's parent. The estimate is used to ensure that */ 06574 /* the algorithm terminates even if very small angles appear in */ 06575 /* the input PSLG. */ 06576 if ((dodist < aodist) && (dodist < dadist)) { 06577 if (offcenter && (b->offconstant > 0.0)) { 06578 /* Find the position of the off-center, as described by Alper Ungor. */ 06579 dxoff = 0.5 * xdo - b->offconstant * ydo; 06580 dyoff = 0.5 * ydo + b->offconstant * xdo; 06581 /* If the off-center is closer to the origin than the */ 06582 /* circumcenter, use the off-center instead. */ 06583 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) { 06584 dx = dxoff; 06585 dy = dyoff; 06586 } 06587 } 06588 } else if (aodist < dadist) { 06589 if (offcenter && (b->offconstant > 0.0)) { 06590 dxoff = 0.5 * xao + b->offconstant * yao; 06591 dyoff = 0.5 * yao - b->offconstant * xao; 06592 /* If the off-center is closer to the origin than the */ 06593 /* circumcenter, use the off-center instead. */ 06594 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) { 06595 dx = dxoff; 06596 dy = dyoff; 06597 } 06598 } 06599 } else { 06600 if (offcenter && (b->offconstant > 0.0)) { 06601 dxoff = 0.5 * (tapex[0] - tdest[0]) - 06602 b->offconstant * (tapex[1] - tdest[1]); 06603 dyoff = 0.5 * (tapex[1] - tdest[1]) + 06604 b->offconstant * (tapex[0] - tdest[0]); 06605 /* If the off-center is closer to the destination than the */ 06606 /* circumcenter, use the off-center instead. */ 06607 if (dxoff * dxoff + dyoff * dyoff < 06608 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) { 06609 dx = xdo + dxoff; 06610 dy = ydo + dyoff; 06611 } 06612 } 06613 } 06614 06615 circumcenter[0] = torg[0] + dx; 06616 circumcenter[1] = torg[1] + dy; 06617 06618 /* To interpolate vertex attributes for the new vertex inserted at */ 06619 /* the circumcenter, define a coordinate system with a xi-axis, */ 06620 /* directed from the triangle's origin to its destination, and */ 06621 /* an eta-axis, directed from its origin to its apex. */ 06622 /* Calculate the xi and eta coordinates of the circumcenter. */ 06623 *xi = (yao * dx - xao * dy) * (2.0 * denominator); 06624 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator); 06625 } 06626 06629 /********* Geometric primitives end here *********/ 06630 06631 /*****************************************************************************/ 06632 /* */ 06633 /* triangleinit() Initialize some variables. */ 06634 /* */ 06635 /*****************************************************************************/ 06636 06637 #ifdef ANSI_DECLARATORS 06638 void triangleinit(struct mesh *m) 06639 #else /* not ANSI_DECLARATORS */ 06640 void triangleinit(m) 06641 struct mesh *m; 06642 #endif /* not ANSI_DECLARATORS */ 06643 06644 { 06645 poolzero(&m->vertices); 06646 poolzero(&m->triangles); 06647 poolzero(&m->subsegs); 06648 poolzero(&m->viri); 06649 poolzero(&m->badsubsegs); 06650 poolzero(&m->badtriangles); 06651 poolzero(&m->flipstackers); 06652 poolzero(&m->splaynodes); 06653 06654 m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */ 06655 m->undeads = 0; /* No eliminated input vertices yet. */ 06656 m->samples = 1; /* Point location should take at least one sample. */ 06657 m->checksegments = 0; /* There are no segments in the triangulation yet. */ 06658 m->checkquality = 0; /* The quality triangulation stage has not begun. */ 06659 m->incirclecount = m->counterclockcount = m->orient3dcount = 0; 06660 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0; 06661 randomseed = 1; 06662 06663 exactinit(); /* Initialize exact arithmetic constants. */ 06664 } 06665 06666 /*****************************************************************************/ 06667 /* */ 06668 /* randomnation() Generate a random number between 0 and `choices' - 1. */ 06669 /* */ 06670 /* This is a simple linear congruential random number generator. Hence, it */ 06671 /* is a bad random number generator, but good enough for most randomized */ 06672 /* geometric algorithms. */ 06673 /* */ 06674 /*****************************************************************************/ 06675 06676 #ifdef ANSI_DECLARATORS 06677 unsigned long randomnation(unsigned int choices) 06678 #else /* not ANSI_DECLARATORS */ 06679 unsigned long randomnation(choices) 06680 unsigned int choices; 06681 #endif /* not ANSI_DECLARATORS */ 06682 06683 { 06684 randomseed = (randomseed * 1366l + 150889l) % 714025l; 06685 return randomseed / (714025l / choices + 1); 06686 } 06687 06688 /********* Mesh quality testing routines begin here *********/ 06692 /*****************************************************************************/ 06693 /* */ 06694 /* checkmesh() Test the mesh for topological consistency. */ 06695 /* */ 06696 /*****************************************************************************/ 06697 06698 #ifndef REDUCED 06699 06700 #ifdef ANSI_DECLARATORS 06701 void checkmesh(struct mesh *m, struct behavior *b) 06702 #else /* not ANSI_DECLARATORS */ 06703 void checkmesh(m, b) 06704 struct mesh *m; 06705 struct behavior *b; 06706 #endif /* not ANSI_DECLARATORS */ 06707 06708 { 06709 struct otri triangleloop; 06710 struct otri oppotri, oppooppotri; 06711 vertex triorg, tridest, triapex; 06712 vertex oppoorg, oppodest; 06713 int horrors; 06714 int saveexact; 06715 triangle ptr; /* Temporary variable used by sym(). */ 06716 06717 /* Temporarily turn on exact arithmetic if it's off. */ 06718 saveexact = b->noexact; 06719 b->noexact = 0; 06720 if (!b->quiet) { 06721 printf(" Checking consistency of mesh...\n"); 06722 } 06723 horrors = 0; 06724 /* Run through the list of triangles, checking each one. */ 06725 traversalinit(&m->triangles); 06726 triangleloop.tri = triangletraverse(m); 06727 while (triangleloop.tri != (triangle *) NULL) { 06728 /* Check all three edges of the triangle. */ 06729 for (triangleloop.orient = 0; triangleloop.orient < 3; 06730 triangleloop.orient++) { 06731 org(triangleloop, triorg); 06732 dest(triangleloop, tridest); 06733 if (triangleloop.orient == 0) { /* Only test for inversion once. */ 06734 /* Test if the triangle is flat or inverted. */ 06735 apex(triangleloop, triapex); 06736 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) { 06737 printf(" !! !! Inverted "); 06738 printtriangle(m, b, &triangleloop); 06739 horrors++; 06740 } 06741 } 06742 /* Find the neighboring triangle on this edge. */ 06743 sym(triangleloop, oppotri); 06744 if (oppotri.tri != m->dummytri) { 06745 /* Check that the triangle's neighbor knows it's a neighbor. */ 06746 sym(oppotri, oppooppotri); 06747 if ((triangleloop.tri != oppooppotri.tri) 06748 || (triangleloop.orient != oppooppotri.orient)) { 06749 printf(" !! !! Asymmetric triangle-triangle bond:\n"); 06750 if (triangleloop.tri == oppooppotri.tri) { 06751 printf(" (Right triangle, wrong orientation)\n"); 06752 } 06753 printf(" First "); 06754 printtriangle(m, b, &triangleloop); 06755 printf(" Second (nonreciprocating) "); 06756 printtriangle(m, b, &oppotri); 06757 horrors++; 06758 } 06759 /* Check that both triangles agree on the identities */ 06760 /* of their shared vertices. */ 06761 org(oppotri, oppoorg); 06762 dest(oppotri, oppodest); 06763 if ((triorg != oppodest) || (tridest != oppoorg)) { 06764 printf(" !! !! Mismatched edge coordinates between two triangles:\n" 06765 ); 06766 printf(" First mismatched "); 06767 printtriangle(m, b, &triangleloop); 06768 printf(" Second mismatched "); 06769 printtriangle(m, b, &oppotri); 06770 horrors++; 06771 } 06772 } 06773 } 06774 triangleloop.tri = triangletraverse(m); 06775 } 06776 if (horrors == 0) { 06777 if (!b->quiet) { 06778 printf(" In my studied opinion, the mesh appears to be consistent.\n"); 06779 } 06780 } else if (horrors == 1) { 06781 printf(" !! !! !! !! Precisely one festering wound discovered.\n"); 06782 } else { 06783 printf(" !! !! !! !! %d abominations witnessed.\n", horrors); 06784 } 06785 /* Restore the status of exact arithmetic. */ 06786 b->noexact = saveexact; 06787 } 06788 06789 #endif /* not REDUCED */ 06790 06791 /*****************************************************************************/ 06792 /* */ 06793 /* checkdelaunay() Ensure that the mesh is (constrained) Delaunay. */ 06794 /* */ 06795 /*****************************************************************************/ 06796 06797 #ifndef REDUCED 06798 06799 #ifdef ANSI_DECLARATORS 06800 void checkdelaunay(struct mesh *m, struct behavior *b) 06801 #else /* not ANSI_DECLARATORS */ 06802 void checkdelaunay(m, b) 06803 struct mesh *m; 06804 struct behavior *b; 06805 #endif /* not ANSI_DECLARATORS */ 06806 06807 { 06808 struct otri triangleloop; 06809 struct otri oppotri; 06810 struct osub opposubseg; 06811 vertex triorg, tridest, triapex; 06812 vertex oppoapex; 06813 int shouldbedelaunay; 06814 int horrors; 06815 int saveexact; 06816 triangle ptr; /* Temporary variable used by sym(). */ 06817 subseg sptr; /* Temporary variable used by tspivot(). */ 06818 06819 /* Temporarily turn on exact arithmetic if it's off. */ 06820 saveexact = b->noexact; 06821 b->noexact = 0; 06822 if (!b->quiet) { 06823 printf(" Checking Delaunay property of mesh...\n"); 06824 } 06825 horrors = 0; 06826 /* Run through the list of triangles, checking each one. */ 06827 traversalinit(&m->triangles); 06828 triangleloop.tri = triangletraverse(m); 06829 while (triangleloop.tri != (triangle *) NULL) { 06830 /* Check all three edges of the triangle. */ 06831 for (triangleloop.orient = 0; triangleloop.orient < 3; 06832 triangleloop.orient++) { 06833 org(triangleloop, triorg); 06834 dest(triangleloop, tridest); 06835 apex(triangleloop, triapex); 06836 sym(triangleloop, oppotri); 06837 apex(oppotri, oppoapex); 06838 /* Only test that the edge is locally Delaunay if there is an */ 06839 /* adjoining triangle whose pointer is larger (to ensure that */ 06840 /* each pair isn't tested twice). */ 06841 shouldbedelaunay = (oppotri.tri != m->dummytri) && 06842 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) && 06843 (triorg != m->infvertex1) && (triorg != m->infvertex2) && 06844 (triorg != m->infvertex3) && 06845 (tridest != m->infvertex1) && (tridest != m->infvertex2) && 06846 (tridest != m->infvertex3) && 06847 (triapex != m->infvertex1) && (triapex != m->infvertex2) && 06848 (triapex != m->infvertex3) && 06849 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) && 06850 (oppoapex != m->infvertex3); 06851 if (m->checksegments && shouldbedelaunay) { 06852 /* If a subsegment separates the triangles, then the edge is */ 06853 /* constrained, so no local Delaunay test should be done. */ 06854 tspivot(triangleloop, opposubseg); 06855 if (opposubseg.ss != m->dummysub){ 06856 shouldbedelaunay = 0; 06857 } 06858 } 06859 if (shouldbedelaunay) { 06860 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) { 06861 if (!b->weighted) { 06862 printf(" !! !! Non-Delaunay pair of triangles:\n"); 06863 printf(" First non-Delaunay "); 06864 printtriangle(m, b, &triangleloop); 06865 printf(" Second non-Delaunay "); 06866 } else { 06867 printf(" !! !! Non-regular pair of triangles:\n"); 06868 printf(" First non-regular "); 06869 printtriangle(m, b, &triangleloop); 06870 printf(" Second non-regular "); 06871 } 06872 printtriangle(m, b, &oppotri); 06873 horrors++; 06874 } 06875 } 06876 } 06877 triangleloop.tri = triangletraverse(m); 06878 } 06879 if (horrors == 0) { 06880 if (!b->quiet) { 06881 printf( 06882 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n"); 06883 } 06884 } else if (horrors == 1) { 06885 printf( 06886 " !! !! !! !! Precisely one terrifying transgression identified.\n"); 06887 } else { 06888 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors); 06889 } 06890 /* Restore the status of exact arithmetic. */ 06891 b->noexact = saveexact; 06892 } 06893 06894 #endif /* not REDUCED */ 06895 06896 /*****************************************************************************/ 06897 /* */ 06898 /* enqueuebadtriang() Add a bad triangle data structure to the end of a */ 06899 /* queue. */ 06900 /* */ 06901 /* The queue is actually a set of 4096 queues. I use multiple queues to */ 06902 /* give priority to smaller angles. I originally implemented a heap, but */ 06903 /* the queues are faster by a larger margin than I'd suspected. */ 06904 /* */ 06905 /*****************************************************************************/ 06906 06907 #ifndef CDT_ONLY 06908 06909 #ifdef ANSI_DECLARATORS 06910 void enqueuebadtriang(struct mesh *m, struct behavior *b, 06911 struct badtriang *badtri) 06912 #else /* not ANSI_DECLARATORS */ 06913 void enqueuebadtriang(m, b, badtri) 06914 struct mesh *m; 06915 struct behavior *b; 06916 struct badtriang *badtri; 06917 #endif /* not ANSI_DECLARATORS */ 06918 06919 { 06920 REAL length, multiplier; 06921 int exponent, expincrement; 06922 int queuenumber; 06923 int posexponent; 06924 int i; 06925 06926 if (b->verbose > 2) { 06927 printf(" Queueing bad triangle:\n"); 06928 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 06929 badtri->triangorg[0], badtri->triangorg[1], 06930 badtri->triangdest[0], badtri->triangdest[1], 06931 badtri->triangapex[0], badtri->triangapex[1]); 06932 } 06933 06934 /* Determine the appropriate queue to put the bad triangle into. */ 06935 /* Recall that the key is the square of its shortest edge length. */ 06936 if (badtri->key >= 1.0) { 06937 length = badtri->key; 06938 posexponent = 1; 06939 } else { 06940 /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */ 06941 /* fact and use the reciprocal of `badtri->key', which is > 1.0. */ 06942 length = 1.0 / badtri->key; 06943 posexponent = 0; 06944 } 06945 /* `length' is approximately 2.0 to what exponent? The following code */ 06946 /* determines the answer in time logarithmic in the exponent. */ 06947 exponent = 0; 06948 while (length > 2.0) { 06949 /* Find an approximation by repeated squaring of two. */ 06950 expincrement = 1; 06951 multiplier = 0.5; 06952 while (length * multiplier * multiplier > 1.0) { 06953 expincrement *= 2; 06954 multiplier *= multiplier; 06955 } 06956 /* Reduce the value of `length', then iterate if necessary. */ 06957 exponent += expincrement; 06958 length *= multiplier; 06959 } 06960 /* `length' is approximately squareroot(2.0) to what exponent? */ 06961 exponent = 2 * exponent + (length > SQUAREROOTTWO); 06962 /* `exponent' is now in the range 0...2047 for IEEE double precision. */ 06963 /* Choose a queue in the range 0...4095. The shortest edges have the */ 06964 /* highest priority (queue 4095). */ 06965 if (posexponent) { 06966 queuenumber = 2047 - exponent; 06967 } else { 06968 queuenumber = 2048 + exponent; 06969 } 06970 06971 /* Are we inserting into an empty queue? */ 06972 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) { 06973 /* Yes, we are inserting into an empty queue. */ 06974 /* Will this become the highest-priority queue? */ 06975 if (queuenumber > m->firstnonemptyq) { 06976 /* Yes, this is the highest-priority queue. */ 06977 m->nextnonemptyq[queuenumber] = m->firstnonemptyq; 06978 m->firstnonemptyq = queuenumber; 06979 } else { 06980 /* No, this is not the highest-priority queue. */ 06981 /* Find the queue with next higher priority. */ 06982 i = queuenumber + 1; 06983 while (m->queuefront[i] == (struct badtriang *) NULL) { 06984 i++; 06985 } 06986 /* Mark the newly nonempty queue as following a higher-priority queue. */ 06987 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i]; 06988 m->nextnonemptyq[i] = queuenumber; 06989 } 06990 /* Put the bad triangle at the beginning of the (empty) queue. */ 06991 m->queuefront[queuenumber] = badtri; 06992 } else { 06993 /* Add the bad triangle to the end of an already nonempty queue. */ 06994 m->queuetail[queuenumber]->nexttriang = badtri; 06995 } 06996 /* Maintain a pointer to the last triangle of the queue. */ 06997 m->queuetail[queuenumber] = badtri; 06998 /* Newly enqueued bad triangle has no successor in the queue. */ 06999 badtri->nexttriang = (struct badtriang *) NULL; 07000 } 07001 07002 #endif /* not CDT_ONLY */ 07003 07004 /*****************************************************************************/ 07005 /* */ 07006 /* enqueuebadtri() Add a bad triangle to the end of a queue. */ 07007 /* */ 07008 /* Allocates a badtriang data structure for the triangle, then passes it to */ 07009 /* enqueuebadtriang(). */ 07010 /* */ 07011 /*****************************************************************************/ 07012 07013 #ifndef CDT_ONLY 07014 07015 #ifdef ANSI_DECLARATORS 07016 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri, 07017 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest) 07018 #else /* not ANSI_DECLARATORS */ 07019 void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest) 07020 struct mesh *m; 07021 struct behavior *b; 07022 struct otri *enqtri; 07023 REAL minedge; 07024 vertex enqapex; 07025 vertex enqorg; 07026 vertex enqdest; 07027 #endif /* not ANSI_DECLARATORS */ 07028 07029 { 07030 struct badtriang *newbad; 07031 07032 /* Allocate space for the bad triangle. */ 07033 newbad = (struct badtriang *) poolalloc(&m->badtriangles); 07034 newbad->poortri = encode(*enqtri); 07035 newbad->key = minedge; 07036 newbad->triangapex = enqapex; 07037 newbad->triangorg = enqorg; 07038 newbad->triangdest = enqdest; 07039 enqueuebadtriang(m, b, newbad); 07040 } 07041 07042 #endif /* not CDT_ONLY */ 07043 07044 /*****************************************************************************/ 07045 /* */ 07046 /* dequeuebadtriang() Remove a triangle from the front of the queue. */ 07047 /* */ 07048 /*****************************************************************************/ 07049 07050 #ifndef CDT_ONLY 07051 07052 #ifdef ANSI_DECLARATORS 07053 struct badtriang *dequeuebadtriang(struct mesh *m) 07054 #else /* not ANSI_DECLARATORS */ 07055 struct badtriang *dequeuebadtriang(m) 07056 struct mesh *m; 07057 #endif /* not ANSI_DECLARATORS */ 07058 07059 { 07060 struct badtriang *result; 07061 07062 /* If no queues are nonempty, return NULL. */ 07063 if (m->firstnonemptyq < 0) { 07064 return (struct badtriang *) NULL; 07065 } 07066 /* Find the first triangle of the highest-priority queue. */ 07067 result = m->queuefront[m->firstnonemptyq]; 07068 /* Remove the triangle from the queue. */ 07069 m->queuefront[m->firstnonemptyq] = result->nexttriang; 07070 /* If this queue is now empty, note the new highest-priority */ 07071 /* nonempty queue. */ 07072 if (result == m->queuetail[m->firstnonemptyq]) { 07073 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq]; 07074 } 07075 return result; 07076 } 07077 07078 #endif /* not CDT_ONLY */ 07079 07080 /*****************************************************************************/ 07081 /* */ 07082 /* checkseg4encroach() Check a subsegment to see if it is encroached; add */ 07083 /* it to the list if it is. */ 07084 /* */ 07085 /* A subsegment is encroached if there is a vertex in its diametral lens. */ 07086 /* For Ruppert's algorithm (-D switch), the "diametral lens" is the */ 07087 /* diametral circle. For Chew's algorithm (default), the diametral lens is */ 07088 /* just big enough to enclose two isosceles triangles whose bases are the */ 07089 /* subsegment. Each of the two isosceles triangles has two angles equal */ 07090 /* to `b->minangle'. */ 07091 /* */ 07092 /* Chew's algorithm does not require diametral lenses at all--but they save */ 07093 /* time. Any vertex inside a subsegment's diametral lens implies that the */ 07094 /* triangle adjoining the subsegment will be too skinny, so it's only a */ 07095 /* matter of time before the encroaching vertex is deleted by Chew's */ 07096 /* algorithm. It's faster to simply not insert the doomed vertex in the */ 07097 /* first place, which is why I use diametral lenses with Chew's algorithm. */ 07098 /* */ 07099 /* Returns a nonzero value if the subsegment is encroached. */ 07100 /* */ 07101 /*****************************************************************************/ 07102 07103 #ifndef CDT_ONLY 07104 07105 #ifdef ANSI_DECLARATORS 07106 int checkseg4encroach(struct mesh *m, struct behavior *b, 07107 struct osub *testsubseg) 07108 #else /* not ANSI_DECLARATORS */ 07109 int checkseg4encroach(m, b, testsubseg) 07110 struct mesh *m; 07111 struct behavior *b; 07112 struct osub *testsubseg; 07113 #endif /* not ANSI_DECLARATORS */ 07114 07115 { 07116 struct otri neighbortri; 07117 struct osub testsym; 07118 struct badsubseg *encroachedseg; 07119 REAL dotproduct; 07120 int encroached; 07121 int sides; 07122 vertex eorg, edest, eapex; 07123 triangle ptr; /* Temporary variable used by stpivot(). */ 07124 07125 encroached = 0; 07126 sides = 0; 07127 07128 sorg(*testsubseg, eorg); 07129 sdest(*testsubseg, edest); 07130 /* Check one neighbor of the subsegment. */ 07131 stpivot(*testsubseg, neighbortri); 07132 /* Does the neighbor exist, or is this a boundary edge? */ 07133 if (neighbortri.tri != m->dummytri) { 07134 sides++; 07135 /* Find a vertex opposite this subsegment. */ 07136 apex(neighbortri, eapex); 07137 /* Check whether the apex is in the diametral lens of the subsegment */ 07138 /* (the diametral circle if `conformdel' is set). A dot product */ 07139 /* of two sides of the triangle is used to check whether the angle */ 07140 /* at the apex is greater than (180 - 2 `minangle') degrees (for */ 07141 /* lenses; 90 degrees for diametral circles). */ 07142 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + 07143 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]); 07144 if (dotproduct < 0.0) { 07145 if (b->conformdel || 07146 (dotproduct * dotproduct >= 07147 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) * 07148 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) + 07149 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) * 07150 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) + 07151 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) { 07152 encroached = 1; 07153 } 07154 } 07155 } 07156 /* Check the other neighbor of the subsegment. */ 07157 ssym(*testsubseg, testsym); 07158 stpivot(testsym, neighbortri); 07159 /* Does the neighbor exist, or is this a boundary edge? */ 07160 if (neighbortri.tri != m->dummytri) { 07161 sides++; 07162 /* Find the other vertex opposite this subsegment. */ 07163 apex(neighbortri, eapex); 07164 /* Check whether the apex is in the diametral lens of the subsegment */ 07165 /* (or the diametral circle, if `conformdel' is set). */ 07166 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + 07167 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]); 07168 if (dotproduct < 0.0) { 07169 if (b->conformdel || 07170 (dotproduct * dotproduct >= 07171 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) * 07172 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) + 07173 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) * 07174 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) + 07175 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) { 07176 encroached += 2; 07177 } 07178 } 07179 } 07180 07181 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) { 07182 if (b->verbose > 2) { 07183 printf( 07184 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n", 07185 eorg[0], eorg[1], edest[0], edest[1]); 07186 } 07187 /* Add the subsegment to the list of encroached subsegments. */ 07188 /* Be sure to get the orientation right. */ 07189 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs); 07190 if (encroached == 1) { 07191 encroachedseg->encsubseg = sencode(*testsubseg); 07192 encroachedseg->subsegorg = eorg; 07193 encroachedseg->subsegdest = edest; 07194 } else { 07195 encroachedseg->encsubseg = sencode(testsym); 07196 encroachedseg->subsegorg = edest; 07197 encroachedseg->subsegdest = eorg; 07198 } 07199 } 07200 07201 return encroached; 07202 } 07203 07204 #endif /* not CDT_ONLY */ 07205 07206 /*****************************************************************************/ 07207 /* */ 07208 /* testtriangle() Test a triangle for quality and size. */ 07209 /* */ 07210 /* Tests a triangle to see if it satisfies the minimum angle condition and */ 07211 /* the maximum area condition. Triangles that aren't up to spec are added */ 07212 /* to the bad triangle queue. */ 07213 /* */ 07214 /*****************************************************************************/ 07215 07216 #ifndef CDT_ONLY 07217 07218 #ifdef ANSI_DECLARATORS 07219 void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri) 07220 #else /* not ANSI_DECLARATORS */ 07221 void testtriangle(m, b, testtri) 07222 struct mesh *m; 07223 struct behavior *b; 07224 struct otri *testtri; 07225 #endif /* not ANSI_DECLARATORS */ 07226 07227 { 07228 struct otri tri1, tri2; 07229 struct osub testsub; 07230 vertex torg, tdest, tapex; 07231 vertex base1, base2; 07232 vertex org1, dest1, org2, dest2; 07233 vertex joinvertex; 07234 REAL dxod, dyod, dxda, dyda, dxao, dyao; 07235 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2; 07236 REAL apexlen, orglen, destlen, minedge; 07237 REAL angle; 07238 REAL area; 07239 REAL dist1, dist2; 07240 subseg sptr; /* Temporary variable used by tspivot(). */ 07241 triangle ptr; /* Temporary variable used by oprev() and dnext(). */ 07242 07243 org(*testtri, torg); 07244 dest(*testtri, tdest); 07245 apex(*testtri, tapex); 07246 dxod = torg[0] - tdest[0]; 07247 dyod = torg[1] - tdest[1]; 07248 dxda = tdest[0] - tapex[0]; 07249 dyda = tdest[1] - tapex[1]; 07250 dxao = tapex[0] - torg[0]; 07251 dyao = tapex[1] - torg[1]; 07252 dxod2 = dxod * dxod; 07253 dyod2 = dyod * dyod; 07254 dxda2 = dxda * dxda; 07255 dyda2 = dyda * dyda; 07256 dxao2 = dxao * dxao; 07257 dyao2 = dyao * dyao; 07258 /* Find the lengths of the triangle's three edges. */ 07259 apexlen = dxod2 + dyod2; 07260 orglen = dxda2 + dyda2; 07261 destlen = dxao2 + dyao2; 07262 07263 if ((apexlen < orglen) && (apexlen < destlen)) { 07264 /* The edge opposite the apex is shortest. */ 07265 minedge = apexlen; 07266 /* Find the square of the cosine of the angle at the apex. */ 07267 angle = dxda * dxao + dyda * dyao; 07268 angle = angle * angle / (orglen * destlen); 07269 base1 = torg; 07270 base2 = tdest; 07271 otricopy(*testtri, tri1); 07272 } else if (orglen < destlen) { 07273 /* The edge opposite the origin is shortest. */ 07274 minedge = orglen; 07275 /* Find the square of the cosine of the angle at the origin. */ 07276 angle = dxod * dxao + dyod * dyao; 07277 angle = angle * angle / (apexlen * destlen); 07278 base1 = tdest; 07279 base2 = tapex; 07280 lnext(*testtri, tri1); 07281 } else { 07282 /* The edge opposite the destination is shortest. */ 07283 minedge = destlen; 07284 /* Find the square of the cosine of the angle at the destination. */ 07285 angle = dxod * dxda + dyod * dyda; 07286 angle = angle * angle / (apexlen * orglen); 07287 base1 = tapex; 07288 base2 = torg; 07289 lprev(*testtri, tri1); 07290 } 07291 07292 if (b->vararea || b->fixedarea || b->usertest) { 07293 /* Check whether the area is larger than permitted. */ 07294 area = 0.5 * (dxod * dyda - dyod * dxda); 07295 if (b->fixedarea && (area > b->maxarea)) { 07296 /* Add this triangle to the list of bad triangles. */ 07297 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); 07298 return; 07299 } 07300 07301 /* Nonpositive area constraints are treated as unconstrained. */ 07302 if ((b->vararea) && (area > areabound(*testtri)) && 07303 (areabound(*testtri) > 0.0)) { 07304 /* Add this triangle to the list of bad triangles. */ 07305 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); 07306 return; 07307 } 07308 07309 if (b->usertest) { 07310 /* Check whether the user thinks this triangle is too large. */ 07311 if (triunsuitable(torg, tdest, tapex, area)) { 07312 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); 07313 return; 07314 } 07315 } 07316 } 07317 07318 /* Check whether the angle is smaller than permitted. */ 07319 if (angle > b->goodangle) { 07320 /* Use the rules of Miller, Pav, and Walkington to decide that certain */ 07321 /* triangles should not be split, even if they have bad angles. */ 07322 /* A skinny triangle is not split if its shortest edge subtends a */ 07323 /* small input angle, and both endpoints of the edge lie on a */ 07324 /* concentric circular shell. For convenience, I make a small */ 07325 /* adjustment to that rule: I check if the endpoints of the edge */ 07326 /* both lie in segment interiors, equidistant from the apex where */ 07327 /* the two segments meet. */ 07328 /* First, check if both points lie in segment interiors. */ 07329 if ((vertextype(base1) == SEGMENTVERTEX) && 07330 (vertextype(base2) == SEGMENTVERTEX)) { 07331 /* Check if both points lie in a common segment. If they do, the */ 07332 /* skinny triangle is enqueued to be split as usual. */ 07333 tspivot(tri1, testsub); 07334 if (testsub.ss == m->dummysub) { 07335 /* No common segment. Find a subsegment that contains `torg'. */ 07336 otricopy(tri1, tri2); 07337 do { 07338 oprevself(tri1); 07339 tspivot(tri1, testsub); 07340 } while (testsub.ss == m->dummysub); 07341 /* Find the endpoints of the containing segment. */ 07342 segorg(testsub, org1); 07343 segdest(testsub, dest1); 07344 /* Find a subsegment that contains `tdest'. */ 07345 do { 07346 dnextself(tri2); 07347 tspivot(tri2, testsub); 07348 } while (testsub.ss == m->dummysub); 07349 /* Find the endpoints of the containing segment. */ 07350 segorg(testsub, org2); 07351 segdest(testsub, dest2); 07352 /* Check if the two containing segments have an endpoint in common. */ 07353 joinvertex = (vertex) NULL; 07354 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) { 07355 joinvertex = dest1; 07356 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) { 07357 joinvertex = org1; 07358 } 07359 if (joinvertex != (vertex) NULL) { 07360 /* Compute the distance from the common endpoint (of the two */ 07361 /* segments) to each of the endpoints of the shortest edge. */ 07362 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) + 07363 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1])); 07364 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) + 07365 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1])); 07366 /* If the two distances are equal, don't split the triangle. */ 07367 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) { 07368 /* Return now to avoid enqueueing the bad triangle. */ 07369 return; 07370 } 07371 } 07372 } 07373 } 07374 07375 /* Add this triangle to the list of bad triangles. */ 07376 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest); 07377 } 07378 } 07379 07380 #endif /* not CDT_ONLY */ 07381 07384 /********* Mesh quality testing routines end here *********/ 07385 07386 /********* Point location routines begin here *********/ 07390 /*****************************************************************************/ 07391 /* */ 07392 /* makevertexmap() Construct a mapping from vertices to triangles to */ 07393 /* improve the speed of point location for segment */ 07394 /* insertion. */ 07395 /* */ 07396 /* Traverses all the triangles, and provides each corner of each triangle */ 07397 /* with a pointer to that triangle. Of course, pointers will be */ 07398 /* overwritten by other pointers because (almost) each vertex is a corner */ 07399 /* of several triangles, but in the end every vertex will point to some */ 07400 /* triangle that contains it. */ 07401 /* */ 07402 /*****************************************************************************/ 07403 07404 #ifdef ANSI_DECLARATORS 07405 void makevertexmap(struct mesh *m, struct behavior *b) 07406 #else /* not ANSI_DECLARATORS */ 07407 void makevertexmap(m, b) 07408 struct mesh *m; 07409 struct behavior *b; 07410 #endif /* not ANSI_DECLARATORS */ 07411 07412 { 07413 struct otri triangleloop; 07414 vertex triorg; 07415 07416 if (b->verbose) { 07417 printf(" Constructing mapping from vertices to triangles.\n"); 07418 } 07419 traversalinit(&m->triangles); 07420 triangleloop.tri = triangletraverse(m); 07421 while (triangleloop.tri != (triangle *) NULL) { 07422 /* Check all three vertices of the triangle. */ 07423 for (triangleloop.orient = 0; triangleloop.orient < 3; 07424 triangleloop.orient++) { 07425 org(triangleloop, triorg); 07426 setvertex2tri(triorg, encode(triangleloop)); 07427 } 07428 triangleloop.tri = triangletraverse(m); 07429 } 07430 } 07431 07432 /*****************************************************************************/ 07433 /* */ 07434 /* preciselocate() Find a triangle or edge containing a given point. */ 07435 /* */ 07436 /* Begins its search from `searchtri'. It is important that `searchtri' */ 07437 /* be a handle with the property that `searchpoint' is strictly to the left */ 07438 /* of the edge denoted by `searchtri', or is collinear with that edge and */ 07439 /* does not intersect that edge. (In particular, `searchpoint' should not */ 07440 /* be the origin or destination of that edge.) */ 07441 /* */ 07442 /* These conditions are imposed because preciselocate() is normally used in */ 07443 /* one of two situations: */ 07444 /* */ 07445 /* (1) To try to find the location to insert a new point. Normally, we */ 07446 /* know an edge that the point is strictly to the left of. In the */ 07447 /* incremental Delaunay algorithm, that edge is a bounding box edge. */ 07448 /* In Ruppert's Delaunay refinement algorithm for quality meshing, */ 07449 /* that edge is the shortest edge of the triangle whose circumcenter */ 07450 /* is being inserted. */ 07451 /* */ 07452 /* (2) To try to find an existing point. In this case, any edge on the */ 07453 /* convex hull is a good starting edge. You must screen out the */ 07454 /* possibility that the vertex sought is an endpoint of the starting */ 07455 /* edge before you call preciselocate(). */ 07456 /* */ 07457 /* On completion, `searchtri' is a triangle that contains `searchpoint'. */ 07458 /* */ 07459 /* This implementation differs from that given by Guibas and Stolfi. It */ 07460 /* walks from triangle to triangle, crossing an edge only if `searchpoint' */ 07461 /* is on the other side of the line containing that edge. After entering */ 07462 /* a triangle, there are two edges by which one can leave that triangle. */ 07463 /* If both edges are valid (`searchpoint' is on the other side of both */ 07464 /* edges), one of the two is chosen by drawing a line perpendicular to */ 07465 /* the entry edge (whose endpoints are `forg' and `fdest') passing through */ 07466 /* `fapex'. Depending on which side of this perpendicular `searchpoint' */ 07467 /* falls on, an exit edge is chosen. */ 07468 /* */ 07469 /* This implementation is empirically faster than the Guibas and Stolfi */ 07470 /* point location routine (which I originally used), which tends to spiral */ 07471 /* in toward its target. */ 07472 /* */ 07473 /* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */ 07474 /* is a handle whose origin is the existing vertex. */ 07475 /* */ 07476 /* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */ 07477 /* handle whose primary edge is the edge on which the point lies. */ 07478 /* */ 07479 /* Returns INTRIANGLE if the point lies strictly within a triangle. */ 07480 /* `searchtri' is a handle on the triangle that contains the point. */ 07481 /* */ 07482 /* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */ 07483 /* handle whose primary edge the point is to the right of. This might */ 07484 /* occur when the circumcenter of a triangle falls just slightly outside */ 07485 /* the mesh due to floating-point roundoff error. It also occurs when */ 07486 /* seeking a hole or region point that a foolish user has placed outside */ 07487 /* the mesh. */ 07488 /* */ 07489 /* If `stopatsubsegment' is nonzero, the search will stop if it tries to */ 07490 /* walk through a subsegment, and will return OUTSIDE. */ 07491 /* */ 07492 /* WARNING: This routine is designed for convex triangulations, and will */ 07493 /* not generally work after the holes and concavities have been carved. */ 07494 /* However, it can still be used to find the circumcenter of a triangle, as */ 07495 /* long as the search is begun from the triangle in question. */ 07496 /* */ 07497 /*****************************************************************************/ 07498 07499 #ifdef ANSI_DECLARATORS 07500 enum locateresult preciselocate(struct mesh *m, struct behavior *b, 07501 vertex searchpoint, struct otri *searchtri, 07502 int stopatsubsegment) 07503 #else /* not ANSI_DECLARATORS */ 07504 enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment) 07505 struct mesh *m; 07506 struct behavior *b; 07507 vertex searchpoint; 07508 struct otri *searchtri; 07509 int stopatsubsegment; 07510 #endif /* not ANSI_DECLARATORS */ 07511 07512 { 07513 struct otri backtracktri; 07514 struct osub checkedge; 07515 vertex forg, fdest, fapex; 07516 REAL orgorient, destorient; 07517 int moveleft; 07518 triangle ptr; /* Temporary variable used by sym(). */ 07519 subseg sptr; /* Temporary variable used by tspivot(). */ 07520 07521 if (b->verbose > 2) { 07522 printf(" Searching for point (%.12g, %.12g).\n", 07523 searchpoint[0], searchpoint[1]); 07524 } 07525 /* Where are we? */ 07526 org(*searchtri, forg); 07527 dest(*searchtri, fdest); 07528 apex(*searchtri, fapex); 07529 while (1) { 07530 if (b->verbose > 2) { 07531 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 07532 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]); 07533 } 07534 /* Check whether the apex is the point we seek. */ 07535 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) { 07536 lprevself(*searchtri); 07537 return ONVERTEX; 07538 } 07539 /* Does the point lie on the other side of the line defined by the */ 07540 /* triangle edge opposite the triangle's destination? */ 07541 destorient = counterclockwise(m, b, forg, fapex, searchpoint); 07542 /* Does the point lie on the other side of the line defined by the */ 07543 /* triangle edge opposite the triangle's origin? */ 07544 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint); 07545 if (destorient > 0.0) { 07546 if (orgorient > 0.0) { 07547 /* Move left if the inner product of (fapex - searchpoint) and */ 07548 /* (fdest - forg) is positive. This is equivalent to drawing */ 07549 /* a line perpendicular to the line (forg, fdest) and passing */ 07550 /* through `fapex', and determining which side of this line */ 07551 /* `searchpoint' falls on. */ 07552 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) + 07553 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0; 07554 } else { 07555 moveleft = 1; 07556 } 07557 } else { 07558 if (orgorient > 0.0) { 07559 moveleft = 0; 07560 } else { 07561 /* The point we seek must be on the boundary of or inside this */ 07562 /* triangle. */ 07563 if (destorient == 0.0) { 07564 lprevself(*searchtri); 07565 return ONEDGE; 07566 } 07567 if (orgorient == 0.0) { 07568 lnextself(*searchtri); 07569 return ONEDGE; 07570 } 07571 return INTRIANGLE; 07572 } 07573 } 07574 07575 /* Move to another triangle. Leave a trace `backtracktri' in case */ 07576 /* floating-point roundoff or some such bogey causes us to walk */ 07577 /* off a boundary of the triangulation. */ 07578 if (moveleft) { 07579 lprev(*searchtri, backtracktri); 07580 fdest = fapex; 07581 } else { 07582 lnext(*searchtri, backtracktri); 07583 forg = fapex; 07584 } 07585 sym(backtracktri, *searchtri); 07586 07587 if (m->checksegments && stopatsubsegment) { 07588 /* Check for walking through a subsegment. */ 07589 tspivot(backtracktri, checkedge); 07590 if (checkedge.ss != m->dummysub) { 07591 /* Go back to the last triangle. */ 07592 otricopy(backtracktri, *searchtri); 07593 return OUTSIDE; 07594 } 07595 } 07596 /* Check for walking right out of the triangulation. */ 07597 if (searchtri->tri == m->dummytri) { 07598 /* Go back to the last triangle. */ 07599 otricopy(backtracktri, *searchtri); 07600 return OUTSIDE; 07601 } 07602 07603 apex(*searchtri, fapex); 07604 } 07605 } 07606 07607 /*****************************************************************************/ 07608 /* */ 07609 /* locate() Find a triangle or edge containing a given point. */ 07610 /* */ 07611 /* Searching begins from one of: the input `searchtri', a recently */ 07612 /* encountered triangle `recenttri', or from a triangle chosen from a */ 07613 /* random sample. The choice is made by determining which triangle's */ 07614 /* origin is closest to the point we are searching for. Normally, */ 07615 /* `searchtri' should be a handle on the convex hull of the triangulation. */ 07616 /* */ 07617 /* Details on the random sampling method can be found in the Mucke, Saias, */ 07618 /* and Zhu paper cited in the header of this code. */ 07619 /* */ 07620 /* On completion, `searchtri' is a triangle that contains `searchpoint'. */ 07621 /* */ 07622 /* Returns ONVERTEX if the point lies on an existing vertex. `searchtri' */ 07623 /* is a handle whose origin is the existing vertex. */ 07624 /* */ 07625 /* Returns ONEDGE if the point lies on a mesh edge. `searchtri' is a */ 07626 /* handle whose primary edge is the edge on which the point lies. */ 07627 /* */ 07628 /* Returns INTRIANGLE if the point lies strictly within a triangle. */ 07629 /* `searchtri' is a handle on the triangle that contains the point. */ 07630 /* */ 07631 /* Returns OUTSIDE if the point lies outside the mesh. `searchtri' is a */ 07632 /* handle whose primary edge the point is to the right of. This might */ 07633 /* occur when the circumcenter of a triangle falls just slightly outside */ 07634 /* the mesh due to floating-point roundoff error. It also occurs when */ 07635 /* seeking a hole or region point that a foolish user has placed outside */ 07636 /* the mesh. */ 07637 /* */ 07638 /* WARNING: This routine is designed for convex triangulations, and will */ 07639 /* not generally work after the holes and concavities have been carved. */ 07640 /* */ 07641 /*****************************************************************************/ 07642 07643 #ifdef ANSI_DECLARATORS 07644 enum locateresult locate(struct mesh *m, struct behavior *b, 07645 vertex searchpoint, struct otri *searchtri) 07646 #else /* not ANSI_DECLARATORS */ 07647 enum locateresult locate(m, b, searchpoint, searchtri) 07648 struct mesh *m; 07649 struct behavior *b; 07650 vertex searchpoint; 07651 struct otri *searchtri; 07652 #endif /* not ANSI_DECLARATORS */ 07653 07654 { 07655 VOID **sampleblock; 07656 char *firsttri; 07657 struct otri sampletri; 07658 vertex torg, tdest; 07659 unsigned long alignptr; 07660 REAL searchdist, dist; 07661 REAL ahead; 07662 long samplesperblock, totalsamplesleft, samplesleft; 07663 long population, totalpopulation; 07664 triangle ptr; /* Temporary variable used by sym(). */ 07665 07666 if (b->verbose > 2) { 07667 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n", 07668 searchpoint[0], searchpoint[1]); 07669 } 07670 /* Record the distance from the suggested starting triangle to the */ 07671 /* point we seek. */ 07672 org(*searchtri, torg); 07673 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) + 07674 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]); 07675 if (b->verbose > 2) { 07676 printf(" Boundary triangle has origin (%.12g, %.12g).\n", 07677 torg[0], torg[1]); 07678 } 07679 07680 /* If a recently encountered triangle has been recorded and has not been */ 07681 /* deallocated, test it as a good starting point. */ 07682 if (m->recenttri.tri != (triangle *) NULL) { 07683 if (!deadtri(m->recenttri.tri)) { 07684 org(m->recenttri, torg); 07685 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) { 07686 otricopy(m->recenttri, *searchtri); 07687 return ONVERTEX; 07688 } 07689 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) + 07690 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]); 07691 if (dist < searchdist) { 07692 otricopy(m->recenttri, *searchtri); 07693 searchdist = dist; 07694 if (b->verbose > 2) { 07695 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n", 07696 torg[0], torg[1]); 07697 } 07698 } 07699 } 07700 } 07701 07702 /* The number of random samples taken is proportional to the cube root of */ 07703 /* the number of triangles in the mesh. The next bit of code assumes */ 07704 /* that the number of triangles increases monotonically (or at least */ 07705 /* doesn't decrease enough to matter). */ 07706 while (SAMPLEFACTOR * m->samples * m->samples * m->samples < 07707 m->triangles.items) { 07708 m->samples++; 07709 } 07710 07711 /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */ 07712 /* from each block of triangles (except the first)--until we meet the */ 07713 /* sample quota. The ceiling means that blocks at the end might be */ 07714 /* neglected, but I don't care. */ 07715 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1; 07716 /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */ 07717 /* from the first block of triangles. */ 07718 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) / 07719 m->triangles.maxitems + 1; 07720 totalsamplesleft = m->samples; 07721 population = m->triangles.itemsfirstblock; 07722 totalpopulation = m->triangles.maxitems; 07723 sampleblock = m->triangles.firstblock; 07724 sampletri.orient = 0; 07725 while (totalsamplesleft > 0) { 07726 /* If we're in the last block, `population' needs to be corrected. */ 07727 if (population > totalpopulation) { 07728 population = totalpopulation; 07729 } 07730 /* Find a pointer to the first triangle in the block. */ 07731 alignptr = (unsigned long) (sampleblock + 1); 07732 firsttri = (char *) (alignptr + 07733 (unsigned long) m->triangles.alignbytes - 07734 (alignptr % 07735 (unsigned long) m->triangles.alignbytes)); 07736 07737 /* Choose `samplesleft' randomly sampled triangles in this block. */ 07738 do { 07739 sampletri.tri = (triangle *) (firsttri + 07740 (randomnation((unsigned int) population) * 07741 m->triangles.itembytes)); 07742 if (!deadtri(sampletri.tri)) { 07743 org(sampletri, torg); 07744 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) + 07745 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]); 07746 if (dist < searchdist) { 07747 otricopy(sampletri, *searchtri); 07748 searchdist = dist; 07749 if (b->verbose > 2) { 07750 printf(" Choosing triangle with origin (%.12g, %.12g).\n", 07751 torg[0], torg[1]); 07752 } 07753 } 07754 } 07755 07756 samplesleft--; 07757 totalsamplesleft--; 07758 } while ((samplesleft > 0) && (totalsamplesleft > 0)); 07759 07760 if (totalsamplesleft > 0) { 07761 sampleblock = (VOID **) *sampleblock; 07762 samplesleft = samplesperblock; 07763 totalpopulation -= population; 07764 population = TRIPERBLOCK; 07765 } 07766 } 07767 07768 /* Where are we? */ 07769 org(*searchtri, torg); 07770 dest(*searchtri, tdest); 07771 /* Check the starting triangle's vertices. */ 07772 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) { 07773 return ONVERTEX; 07774 } 07775 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) { 07776 lnextself(*searchtri); 07777 return ONVERTEX; 07778 } 07779 /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */ 07780 ahead = counterclockwise(m, b, torg, tdest, searchpoint); 07781 if (ahead < 0.0) { 07782 /* Turn around so that `searchpoint' is to the left of the */ 07783 /* edge specified by `searchtri'. */ 07784 symself(*searchtri); 07785 } else if (ahead == 0.0) { 07786 /* Check if `searchpoint' is between `torg' and `tdest'. */ 07787 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) && 07788 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) { 07789 return ONEDGE; 07790 } 07791 } 07792 return preciselocate(m, b, searchpoint, searchtri, 0); 07793 } 07794 07797 /********* Point location routines end here *********/ 07798 07799 /********* Mesh transformation routines begin here *********/ 07803 /*****************************************************************************/ 07804 /* */ 07805 /* insertsubseg() Create a new subsegment and insert it between two */ 07806 /* triangles. */ 07807 /* */ 07808 /* The new subsegment is inserted at the edge described by the handle */ 07809 /* `tri'. Its vertices are properly initialized. The marker `subsegmark' */ 07810 /* is applied to the subsegment and, if appropriate, its vertices. */ 07811 /* */ 07812 /*****************************************************************************/ 07813 07814 #ifdef ANSI_DECLARATORS 07815 void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, 07816 int subsegmark) 07817 #else /* not ANSI_DECLARATORS */ 07818 void insertsubseg(m, b, tri, subsegmark) 07819 struct mesh *m; 07820 struct behavior *b; 07821 struct otri *tri; /* Edge at which to insert the new subsegment. */ 07822 int subsegmark; /* Marker for the new subsegment. */ 07823 #endif /* not ANSI_DECLARATORS */ 07824 07825 { 07826 struct otri oppotri; 07827 struct osub newsubseg; 07828 vertex triorg, tridest; 07829 triangle ptr; /* Temporary variable used by sym(). */ 07830 subseg sptr; /* Temporary variable used by tspivot(). */ 07831 07832 org(*tri, triorg); 07833 dest(*tri, tridest); 07834 /* Mark vertices if possible. */ 07835 if (vertexmark(triorg) == 0) { 07836 setvertexmark(triorg, subsegmark); 07837 } 07838 if (vertexmark(tridest) == 0) { 07839 setvertexmark(tridest, subsegmark); 07840 } 07841 /* Check if there's already a subsegment here. */ 07842 tspivot(*tri, newsubseg); 07843 if (newsubseg.ss == m->dummysub) { 07844 /* Make new subsegment and initialize its vertices. */ 07845 makesubseg(m, &newsubseg); 07846 setsorg(newsubseg, tridest); 07847 setsdest(newsubseg, triorg); 07848 setsegorg(newsubseg, tridest); 07849 setsegdest(newsubseg, triorg); 07850 /* Bond new subsegment to the two triangles it is sandwiched between. */ 07851 /* Note that the facing triangle `oppotri' might be equal to */ 07852 /* `dummytri' (outer space), but the new subsegment is bonded to it */ 07853 /* all the same. */ 07854 tsbond(*tri, newsubseg); 07855 sym(*tri, oppotri); 07856 ssymself(newsubseg); 07857 tsbond(oppotri, newsubseg); 07858 setmark(newsubseg, subsegmark); 07859 if (b->verbose > 2) { 07860 printf(" Inserting new "); 07861 printsubseg(m, b, &newsubseg); 07862 } 07863 } else { 07864 if (mark(newsubseg) == 0) { 07865 setmark(newsubseg, subsegmark); 07866 } 07867 } 07868 } 07869 07870 /*****************************************************************************/ 07871 /* */ 07872 /* Terminology */ 07873 /* */ 07874 /* A "local transformation" replaces a small set of triangles with another */ 07875 /* set of triangles. This may or may not involve inserting or deleting a */ 07876 /* vertex. */ 07877 /* */ 07878 /* The term "casing" is used to describe the set of triangles that are */ 07879 /* attached to the triangles being transformed, but are not transformed */ 07880 /* themselves. Think of the casing as a fixed hollow structure inside */ 07881 /* which all the action happens. A "casing" is only defined relative to */ 07882 /* a single transformation; each occurrence of a transformation will */ 07883 /* involve a different casing. */ 07884 /* */ 07885 /*****************************************************************************/ 07886 07887 /*****************************************************************************/ 07888 /* */ 07889 /* flip() Transform two triangles to two different triangles by flipping */ 07890 /* an edge counterclockwise within a quadrilateral. */ 07891 /* */ 07892 /* Imagine the original triangles, abc and bad, oriented so that the */ 07893 /* shared edge ab lies in a horizontal plane, with the vertex b on the left */ 07894 /* and the vertex a on the right. The vertex c lies below the edge, and */ 07895 /* the vertex d lies above the edge. The `flipedge' handle holds the edge */ 07896 /* ab of triangle abc, and is directed left, from vertex a to vertex b. */ 07897 /* */ 07898 /* The triangles abc and bad are deleted and replaced by the triangles cdb */ 07899 /* and dca. The triangles that represent abc and bad are NOT deallocated; */ 07900 /* they are reused for dca and cdb, respectively. Hence, any handles that */ 07901 /* may have held the original triangles are still valid, although not */ 07902 /* directed as they were before. */ 07903 /* */ 07904 /* Upon completion of this routine, the `flipedge' handle holds the edge */ 07905 /* dc of triangle dca, and is directed down, from vertex d to vertex c. */ 07906 /* (Hence, the two triangles have rotated counterclockwise.) */ 07907 /* */ 07908 /* WARNING: This transformation is geometrically valid only if the */ 07909 /* quadrilateral adbc is convex. Furthermore, this transformation is */ 07910 /* valid only if there is not a subsegment between the triangles abc and */ 07911 /* bad. This routine does not check either of these preconditions, and */ 07912 /* it is the responsibility of the calling routine to ensure that they are */ 07913 /* met. If they are not, the streets shall be filled with wailing and */ 07914 /* gnashing of teeth. */ 07915 /* */ 07916 /*****************************************************************************/ 07917 07918 #ifdef ANSI_DECLARATORS 07919 void flip(struct mesh *m, struct behavior *b, struct otri *flipedge) 07920 #else /* not ANSI_DECLARATORS */ 07921 void flip(m, b, flipedge) 07922 struct mesh *m; 07923 struct behavior *b; 07924 struct otri *flipedge; /* Handle for the triangle abc. */ 07925 #endif /* not ANSI_DECLARATORS */ 07926 07927 { 07928 struct otri botleft, botright; 07929 struct otri topleft, topright; 07930 struct otri top; 07931 struct otri botlcasing, botrcasing; 07932 struct otri toplcasing, toprcasing; 07933 struct osub botlsubseg, botrsubseg; 07934 struct osub toplsubseg, toprsubseg; 07935 vertex leftvertex, rightvertex, botvertex; 07936 vertex farvertex; 07937 triangle ptr; /* Temporary variable used by sym(). */ 07938 subseg sptr; /* Temporary variable used by tspivot(). */ 07939 07940 /* Identify the vertices of the quadrilateral. */ 07941 org(*flipedge, rightvertex); 07942 dest(*flipedge, leftvertex); 07943 apex(*flipedge, botvertex); 07944 sym(*flipedge, top); 07945 #ifdef SELF_CHECK 07946 if (top.tri == m->dummytri) { 07947 printf("Internal error in flip(): Attempt to flip on boundary.\n"); 07948 lnextself(*flipedge); 07949 return; 07950 } 07951 if (m->checksegments) { 07952 tspivot(*flipedge, toplsubseg); 07953 if (toplsubseg.ss != m->dummysub) { 07954 printf("Internal error in flip(): Attempt to flip a segment.\n"); 07955 lnextself(*flipedge); 07956 return; 07957 } 07958 } 07959 #endif /* SELF_CHECK */ 07960 apex(top, farvertex); 07961 07962 /* Identify the casing of the quadrilateral. */ 07963 lprev(top, topleft); 07964 sym(topleft, toplcasing); 07965 lnext(top, topright); 07966 sym(topright, toprcasing); 07967 lnext(*flipedge, botleft); 07968 sym(botleft, botlcasing); 07969 lprev(*flipedge, botright); 07970 sym(botright, botrcasing); 07971 /* Rotate the quadrilateral one-quarter turn counterclockwise. */ 07972 bond(topleft, botlcasing); 07973 bond(botleft, botrcasing); 07974 bond(botright, toprcasing); 07975 bond(topright, toplcasing); 07976 07977 if (m->checksegments) { 07978 /* Check for subsegments and rebond them to the quadrilateral. */ 07979 tspivot(topleft, toplsubseg); 07980 tspivot(botleft, botlsubseg); 07981 tspivot(botright, botrsubseg); 07982 tspivot(topright, toprsubseg); 07983 if (toplsubseg.ss == m->dummysub) { 07984 tsdissolve(topright); 07985 } else { 07986 tsbond(topright, toplsubseg); 07987 } 07988 if (botlsubseg.ss == m->dummysub) { 07989 tsdissolve(topleft); 07990 } else { 07991 tsbond(topleft, botlsubseg); 07992 } 07993 if (botrsubseg.ss == m->dummysub) { 07994 tsdissolve(botleft); 07995 } else { 07996 tsbond(botleft, botrsubseg); 07997 } 07998 if (toprsubseg.ss == m->dummysub) { 07999 tsdissolve(botright); 08000 } else { 08001 tsbond(botright, toprsubseg); 08002 } 08003 } 08004 08005 /* New vertex assignments for the rotated quadrilateral. */ 08006 setorg(*flipedge, farvertex); 08007 setdest(*flipedge, botvertex); 08008 setapex(*flipedge, rightvertex); 08009 setorg(top, botvertex); 08010 setdest(top, farvertex); 08011 setapex(top, leftvertex); 08012 if (b->verbose > 2) { 08013 printf(" Edge flip results in left "); 08014 printtriangle(m, b, &top); 08015 printf(" and right "); 08016 printtriangle(m, b, flipedge); 08017 } 08018 } 08019 08020 /*****************************************************************************/ 08021 /* */ 08022 /* unflip() Transform two triangles to two different triangles by */ 08023 /* flipping an edge clockwise within a quadrilateral. Reverses */ 08024 /* the flip() operation so that the data structures representing */ 08025 /* the triangles are back where they were before the flip(). */ 08026 /* */ 08027 /* Imagine the original triangles, abc and bad, oriented so that the */ 08028 /* shared edge ab lies in a horizontal plane, with the vertex b on the left */ 08029 /* and the vertex a on the right. The vertex c lies below the edge, and */ 08030 /* the vertex d lies above the edge. The `flipedge' handle holds the edge */ 08031 /* ab of triangle abc, and is directed left, from vertex a to vertex b. */ 08032 /* */ 08033 /* The triangles abc and bad are deleted and replaced by the triangles cdb */ 08034 /* and dca. The triangles that represent abc and bad are NOT deallocated; */ 08035 /* they are reused for cdb and dca, respectively. Hence, any handles that */ 08036 /* may have held the original triangles are still valid, although not */ 08037 /* directed as they were before. */ 08038 /* */ 08039 /* Upon completion of this routine, the `flipedge' handle holds the edge */ 08040 /* cd of triangle cdb, and is directed up, from vertex c to vertex d. */ 08041 /* (Hence, the two triangles have rotated clockwise.) */ 08042 /* */ 08043 /* WARNING: This transformation is geometrically valid only if the */ 08044 /* quadrilateral adbc is convex. Furthermore, this transformation is */ 08045 /* valid only if there is not a subsegment between the triangles abc and */ 08046 /* bad. This routine does not check either of these preconditions, and */ 08047 /* it is the responsibility of the calling routine to ensure that they are */ 08048 /* met. If they are not, the streets shall be filled with wailing and */ 08049 /* gnashing of teeth. */ 08050 /* */ 08051 /*****************************************************************************/ 08052 08053 #ifdef ANSI_DECLARATORS 08054 void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge) 08055 #else /* not ANSI_DECLARATORS */ 08056 void unflip(m, b, flipedge) 08057 struct mesh *m; 08058 struct behavior *b; 08059 struct otri *flipedge; /* Handle for the triangle abc. */ 08060 #endif /* not ANSI_DECLARATORS */ 08061 08062 { 08063 struct otri botleft, botright; 08064 struct otri topleft, topright; 08065 struct otri top; 08066 struct otri botlcasing, botrcasing; 08067 struct otri toplcasing, toprcasing; 08068 struct osub botlsubseg, botrsubseg; 08069 struct osub toplsubseg, toprsubseg; 08070 vertex leftvertex, rightvertex, botvertex; 08071 vertex farvertex; 08072 triangle ptr; /* Temporary variable used by sym(). */ 08073 subseg sptr; /* Temporary variable used by tspivot(). */ 08074 08075 /* Identify the vertices of the quadrilateral. */ 08076 org(*flipedge, rightvertex); 08077 dest(*flipedge, leftvertex); 08078 apex(*flipedge, botvertex); 08079 sym(*flipedge, top); 08080 #ifdef SELF_CHECK 08081 if (top.tri == m->dummytri) { 08082 printf("Internal error in unflip(): Attempt to flip on boundary.\n"); 08083 lnextself(*flipedge); 08084 return; 08085 } 08086 if (m->checksegments) { 08087 tspivot(*flipedge, toplsubseg); 08088 if (toplsubseg.ss != m->dummysub) { 08089 printf("Internal error in unflip(): Attempt to flip a subsegment.\n"); 08090 lnextself(*flipedge); 08091 return; 08092 } 08093 } 08094 #endif /* SELF_CHECK */ 08095 apex(top, farvertex); 08096 08097 /* Identify the casing of the quadrilateral. */ 08098 lprev(top, topleft); 08099 sym(topleft, toplcasing); 08100 lnext(top, topright); 08101 sym(topright, toprcasing); 08102 lnext(*flipedge, botleft); 08103 sym(botleft, botlcasing); 08104 lprev(*flipedge, botright); 08105 sym(botright, botrcasing); 08106 /* Rotate the quadrilateral one-quarter turn clockwise. */ 08107 bond(topleft, toprcasing); 08108 bond(botleft, toplcasing); 08109 bond(botright, botlcasing); 08110 bond(topright, botrcasing); 08111 08112 if (m->checksegments) { 08113 /* Check for subsegments and rebond them to the quadrilateral. */ 08114 tspivot(topleft, toplsubseg); 08115 tspivot(botleft, botlsubseg); 08116 tspivot(botright, botrsubseg); 08117 tspivot(topright, toprsubseg); 08118 if (toplsubseg.ss == m->dummysub) { 08119 tsdissolve(botleft); 08120 } else { 08121 tsbond(botleft, toplsubseg); 08122 } 08123 if (botlsubseg.ss == m->dummysub) { 08124 tsdissolve(botright); 08125 } else { 08126 tsbond(botright, botlsubseg); 08127 } 08128 if (botrsubseg.ss == m->dummysub) { 08129 tsdissolve(topright); 08130 } else { 08131 tsbond(topright, botrsubseg); 08132 } 08133 if (toprsubseg.ss == m->dummysub) { 08134 tsdissolve(topleft); 08135 } else { 08136 tsbond(topleft, toprsubseg); 08137 } 08138 } 08139 08140 /* New vertex assignments for the rotated quadrilateral. */ 08141 setorg(*flipedge, botvertex); 08142 setdest(*flipedge, farvertex); 08143 setapex(*flipedge, leftvertex); 08144 setorg(top, farvertex); 08145 setdest(top, botvertex); 08146 setapex(top, rightvertex); 08147 if (b->verbose > 2) { 08148 printf(" Edge unflip results in left "); 08149 printtriangle(m, b, flipedge); 08150 printf(" and right "); 08151 printtriangle(m, b, &top); 08152 } 08153 } 08154 08155 /*****************************************************************************/ 08156 /* */ 08157 /* insertvertex() Insert a vertex into a Delaunay triangulation, */ 08158 /* performing flips as necessary to maintain the Delaunay */ 08159 /* property. */ 08160 /* */ 08161 /* The point `insertvertex' is located. If `searchtri.tri' is not NULL, */ 08162 /* the search for the containing triangle begins from `searchtri'. If */ 08163 /* `searchtri.tri' is NULL, a full point location procedure is called. */ 08164 /* If `insertvertex' is found inside a triangle, the triangle is split into */ 08165 /* three; if `insertvertex' lies on an edge, the edge is split in two, */ 08166 /* thereby splitting the two adjacent triangles into four. Edge flips are */ 08167 /* used to restore the Delaunay property. If `insertvertex' lies on an */ 08168 /* existing vertex, no action is taken, and the value DUPLICATEVERTEX is */ 08169 /* returned. On return, `searchtri' is set to a handle whose origin is the */ 08170 /* existing vertex. */ 08171 /* */ 08172 /* Normally, the parameter `splitseg' is set to NULL, implying that no */ 08173 /* subsegment should be split. In this case, if `insertvertex' is found to */ 08174 /* lie on a segment, no action is taken, and the value VIOLATINGVERTEX is */ 08175 /* returned. On return, `searchtri' is set to a handle whose primary edge */ 08176 /* is the violated subsegment. */ 08177 /* */ 08178 /* If the calling routine wishes to split a subsegment by inserting a */ 08179 /* vertex in it, the parameter `splitseg' should be that subsegment. In */ 08180 /* this case, `searchtri' MUST be the triangle handle reached by pivoting */ 08181 /* from that subsegment; no point location is done. */ 08182 /* */ 08183 /* `segmentflaws' and `triflaws' are flags that indicate whether or not */ 08184 /* there should be checks for the creation of encroached subsegments or bad */ 08185 /* quality triangles. If a newly inserted vertex encroaches upon */ 08186 /* subsegments, these subsegments are added to the list of subsegments to */ 08187 /* be split if `segmentflaws' is set. If bad triangles are created, these */ 08188 /* are added to the queue if `triflaws' is set. */ 08189 /* */ 08190 /* If a duplicate vertex or violated segment does not prevent the vertex */ 08191 /* from being inserted, the return value will be ENCROACHINGVERTEX if the */ 08192 /* vertex encroaches upon a subsegment (and checking is enabled), or */ 08193 /* SUCCESSFULVERTEX otherwise. In either case, `searchtri' is set to a */ 08194 /* handle whose origin is the newly inserted vertex. */ 08195 /* */ 08196 /* insertvertex() does not use flip() for reasons of speed; some */ 08197 /* information can be reused from edge flip to edge flip, like the */ 08198 /* locations of subsegments. */ 08199 /* */ 08200 /*****************************************************************************/ 08201 08202 #ifdef ANSI_DECLARATORS 08203 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, 08204 vertex newvertex, struct otri *searchtri, 08205 struct osub *splitseg, 08206 int segmentflaws, int triflaws) 08207 #else /* not ANSI_DECLARATORS */ 08208 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg, 08209 segmentflaws, triflaws) 08210 struct mesh *m; 08211 struct behavior *b; 08212 vertex newvertex; 08213 struct otri *searchtri; 08214 struct osub *splitseg; 08215 int segmentflaws; 08216 int triflaws; 08217 #endif /* not ANSI_DECLARATORS */ 08218 08219 { 08220 struct otri horiz; 08221 struct otri top; 08222 struct otri botleft, botright; 08223 struct otri topleft, topright; 08224 struct otri newbotleft, newbotright; 08225 struct otri newtopright; 08226 struct otri botlcasing, botrcasing; 08227 struct otri toplcasing={NULL, 0}, toprcasing={NULL, 0}; 08228 struct otri testtri; 08229 struct osub botlsubseg, botrsubseg; 08230 struct osub toplsubseg, toprsubseg; 08231 struct osub brokensubseg; 08232 struct osub checksubseg; 08233 struct osub rightsubseg; 08234 struct osub newsubseg; 08235 struct badsubseg *encroached; 08236 struct flipstacker *newflip; 08237 vertex first; 08238 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex; 08239 vertex segmentorg, segmentdest; 08240 REAL attrib; 08241 REAL area; 08242 enum insertvertexresult success; 08243 enum locateresult intersect; 08244 int doflip; 08245 int mirrorflag; 08246 int enq; 08247 int i; 08248 triangle ptr; /* Temporary variable used by sym(). */ 08249 subseg sptr; /* Temporary variable used by spivot() and tspivot(). */ 08250 08251 if (b->verbose > 1) { 08252 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]); 08253 } 08254 08255 if (splitseg == (struct osub *) NULL) { 08256 /* Find the location of the vertex to be inserted. Check if a good */ 08257 /* starting triangle has already been provided by the caller. */ 08258 if (searchtri->tri == m->dummytri) { 08259 /* Find a boundary triangle. */ 08260 horiz.tri = m->dummytri; 08261 horiz.orient = 0; 08262 symself(horiz); 08263 /* Search for a triangle containing `newvertex'. */ 08264 intersect = locate(m, b, newvertex, &horiz); 08265 } else { 08266 /* Start searching from the triangle provided by the caller. */ 08267 otricopy(*searchtri, horiz); 08268 intersect = preciselocate(m, b, newvertex, &horiz, 1); 08269 } 08270 } else { 08271 /* The calling routine provides the subsegment in which */ 08272 /* the vertex is inserted. */ 08273 otricopy(*searchtri, horiz); 08274 intersect = ONEDGE; 08275 } 08276 08277 if (intersect == ONVERTEX) { 08278 /* There's already a vertex there. Return in `searchtri' a triangle */ 08279 /* whose origin is the existing vertex. */ 08280 otricopy(horiz, *searchtri); 08281 otricopy(horiz, m->recenttri); 08282 return DUPLICATEVERTEX; 08283 } 08284 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) { 08285 /* The vertex falls on an edge or boundary. */ 08286 if (m->checksegments && (splitseg == (struct osub *) NULL)) { 08287 /* Check whether the vertex falls on a subsegment. */ 08288 tspivot(horiz, brokensubseg); 08289 if (brokensubseg.ss != m->dummysub) { 08290 /* The vertex falls on a subsegment, and hence will not be inserted. */ 08291 if (segmentflaws) { 08292 enq = b->nobisect != 2; 08293 if (enq && (b->nobisect == 1)) { 08294 /* This subsegment may be split only if it is an */ 08295 /* internal boundary. */ 08296 sym(horiz, testtri); 08297 enq = testtri.tri != m->dummytri; 08298 } 08299 if (enq) { 08300 /* Add the subsegment to the list of encroached subsegments. */ 08301 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs); 08302 encroached->encsubseg = sencode(brokensubseg); 08303 sorg(brokensubseg, encroached->subsegorg); 08304 sdest(brokensubseg, encroached->subsegdest); 08305 if (b->verbose > 2) { 08306 printf( 08307 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n", 08308 encroached->subsegorg[0], encroached->subsegorg[1], 08309 encroached->subsegdest[0], encroached->subsegdest[1]); 08310 } 08311 } 08312 } 08313 /* Return a handle whose primary edge contains the vertex, */ 08314 /* which has not been inserted. */ 08315 otricopy(horiz, *searchtri); 08316 otricopy(horiz, m->recenttri); 08317 return VIOLATINGVERTEX; 08318 } 08319 } 08320 08321 /* Insert the vertex on an edge, dividing one triangle into two (if */ 08322 /* the edge lies on a boundary) or two triangles into four. */ 08323 lprev(horiz, botright); 08324 sym(botright, botrcasing); 08325 sym(horiz, topright); 08326 /* Is there a second triangle? (Or does this edge lie on a boundary?) */ 08327 mirrorflag = topright.tri != m->dummytri; 08328 if (mirrorflag) { 08329 lnextself(topright); 08330 sym(topright, toprcasing); 08331 maketriangle(m, b, &newtopright); 08332 } else { 08333 /* Splitting a boundary edge increases the number of boundary edges. */ 08334 m->hullsize++; 08335 } 08336 maketriangle(m, b, &newbotright); 08337 08338 /* Set the vertices of changed and new triangles. */ 08339 org(horiz, rightvertex); 08340 dest(horiz, leftvertex); 08341 apex(horiz, botvertex); 08342 setorg(newbotright, botvertex); 08343 setdest(newbotright, rightvertex); 08344 setapex(newbotright, newvertex); 08345 setorg(horiz, newvertex); 08346 for (i = 0; i < m->eextras; i++) { 08347 /* Set the element attributes of a new triangle. */ 08348 setelemattribute(newbotright, i, elemattribute(botright, i)); 08349 } 08350 if (b->vararea) { 08351 /* Set the area constraint of a new triangle. */ 08352 setareabound(newbotright, areabound(botright)); 08353 } 08354 if (mirrorflag) { 08355 dest(topright, topvertex); 08356 setorg(newtopright, rightvertex); 08357 setdest(newtopright, topvertex); 08358 setapex(newtopright, newvertex); 08359 setorg(topright, newvertex); 08360 for (i = 0; i < m->eextras; i++) { 08361 /* Set the element attributes of another new triangle. */ 08362 setelemattribute(newtopright, i, elemattribute(topright, i)); 08363 } 08364 if (b->vararea) { 08365 /* Set the area constraint of another new triangle. */ 08366 setareabound(newtopright, areabound(topright)); 08367 } 08368 } 08369 08370 /* There may be subsegments that need to be bonded */ 08371 /* to the new triangle(s). */ 08372 if (m->checksegments) { 08373 tspivot(botright, botrsubseg); 08374 if (botrsubseg.ss != m->dummysub) { 08375 tsdissolve(botright); 08376 tsbond(newbotright, botrsubseg); 08377 } 08378 if (mirrorflag) { 08379 tspivot(topright, toprsubseg); 08380 if (toprsubseg.ss != m->dummysub) { 08381 tsdissolve(topright); 08382 tsbond(newtopright, toprsubseg); 08383 } 08384 } 08385 } 08386 08387 /* Bond the new triangle(s) to the surrounding triangles. */ 08388 bond(newbotright, botrcasing); 08389 lprevself(newbotright); 08390 bond(newbotright, botright); 08391 lprevself(newbotright); 08392 if (mirrorflag) { 08393 bond(newtopright, toprcasing); 08394 lnextself(newtopright); 08395 bond(newtopright, topright); 08396 lnextself(newtopright); 08397 bond(newtopright, newbotright); 08398 } 08399 08400 if (splitseg != (struct osub *) NULL) { 08401 /* Split the subsegment into two. */ 08402 setsdest(*splitseg, newvertex); 08403 segorg(*splitseg, segmentorg); 08404 segdest(*splitseg, segmentdest); 08405 ssymself(*splitseg); 08406 spivot(*splitseg, rightsubseg); 08407 insertsubseg(m, b, &newbotright, mark(*splitseg)); 08408 tspivot(newbotright, newsubseg); 08409 setsegorg(newsubseg, segmentorg); 08410 setsegdest(newsubseg, segmentdest); 08411 sbond(*splitseg, newsubseg); 08412 ssymself(newsubseg); 08413 sbond(newsubseg, rightsubseg); 08414 ssymself(*splitseg); 08415 /* Transfer the subsegment's boundary marker to the vertex */ 08416 /* if required. */ 08417 if (vertexmark(newvertex) == 0) { 08418 setvertexmark(newvertex, mark(*splitseg)); 08419 } 08420 } 08421 08422 if (m->checkquality) { 08423 poolrestart(&m->flipstackers); 08424 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers); 08425 m->lastflip->flippedtri = encode(horiz); 08426 m->lastflip->prevflip = (struct flipstacker *) &insertvertex; 08427 } 08428 08429 #ifdef SELF_CHECK 08430 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) { 08431 printf("Internal error in insertvertex():\n"); 08432 printf( 08433 " Clockwise triangle prior to edge vertex insertion (bottom).\n"); 08434 } 08435 if (mirrorflag) { 08436 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) { 08437 printf("Internal error in insertvertex():\n"); 08438 printf(" Clockwise triangle prior to edge vertex insertion (top).\n"); 08439 } 08440 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) { 08441 printf("Internal error in insertvertex():\n"); 08442 printf( 08443 " Clockwise triangle after edge vertex insertion (top right).\n"); 08444 } 08445 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) { 08446 printf("Internal error in insertvertex():\n"); 08447 printf( 08448 " Clockwise triangle after edge vertex insertion (top left).\n"); 08449 } 08450 } 08451 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) { 08452 printf("Internal error in insertvertex():\n"); 08453 printf( 08454 " Clockwise triangle after edge vertex insertion (bottom left).\n"); 08455 } 08456 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) { 08457 printf("Internal error in insertvertex():\n"); 08458 printf( 08459 " Clockwise triangle after edge vertex insertion (bottom right).\n"); 08460 } 08461 #endif /* SELF_CHECK */ 08462 if (b->verbose > 2) { 08463 printf(" Updating bottom left "); 08464 printtriangle(m, b, &botright); 08465 if (mirrorflag) { 08466 printf(" Updating top left "); 08467 printtriangle(m, b, &topright); 08468 printf(" Creating top right "); 08469 printtriangle(m, b, &newtopright); 08470 } 08471 printf(" Creating bottom right "); 08472 printtriangle(m, b, &newbotright); 08473 } 08474 08475 /* Position `horiz' on the first edge to check for */ 08476 /* the Delaunay property. */ 08477 lnextself(horiz); 08478 } else { 08479 /* Insert the vertex in a triangle, splitting it into three. */ 08480 lnext(horiz, botleft); 08481 lprev(horiz, botright); 08482 sym(botleft, botlcasing); 08483 sym(botright, botrcasing); 08484 maketriangle(m, b, &newbotleft); 08485 maketriangle(m, b, &newbotright); 08486 08487 /* Set the vertices of changed and new triangles. */ 08488 org(horiz, rightvertex); 08489 dest(horiz, leftvertex); 08490 apex(horiz, botvertex); 08491 setorg(newbotleft, leftvertex); 08492 setdest(newbotleft, botvertex); 08493 setapex(newbotleft, newvertex); 08494 setorg(newbotright, botvertex); 08495 setdest(newbotright, rightvertex); 08496 setapex(newbotright, newvertex); 08497 setapex(horiz, newvertex); 08498 for (i = 0; i < m->eextras; i++) { 08499 /* Set the element attributes of the new triangles. */ 08500 attrib = elemattribute(horiz, i); 08501 setelemattribute(newbotleft, i, attrib); 08502 setelemattribute(newbotright, i, attrib); 08503 } 08504 if (b->vararea) { 08505 /* Set the area constraint of the new triangles. */ 08506 area = areabound(horiz); 08507 setareabound(newbotleft, area); 08508 setareabound(newbotright, area); 08509 } 08510 08511 /* There may be subsegments that need to be bonded */ 08512 /* to the new triangles. */ 08513 if (m->checksegments) { 08514 tspivot(botleft, botlsubseg); 08515 if (botlsubseg.ss != m->dummysub) { 08516 tsdissolve(botleft); 08517 tsbond(newbotleft, botlsubseg); 08518 } 08519 tspivot(botright, botrsubseg); 08520 if (botrsubseg.ss != m->dummysub) { 08521 tsdissolve(botright); 08522 tsbond(newbotright, botrsubseg); 08523 } 08524 } 08525 08526 /* Bond the new triangles to the surrounding triangles. */ 08527 bond(newbotleft, botlcasing); 08528 bond(newbotright, botrcasing); 08529 lnextself(newbotleft); 08530 lprevself(newbotright); 08531 bond(newbotleft, newbotright); 08532 lnextself(newbotleft); 08533 bond(botleft, newbotleft); 08534 lprevself(newbotright); 08535 bond(botright, newbotright); 08536 08537 if (m->checkquality) { 08538 poolrestart(&m->flipstackers); 08539 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers); 08540 m->lastflip->flippedtri = encode(horiz); 08541 m->lastflip->prevflip = (struct flipstacker *) NULL; 08542 } 08543 08544 #ifdef SELF_CHECK 08545 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) { 08546 printf("Internal error in insertvertex():\n"); 08547 printf(" Clockwise triangle prior to vertex insertion.\n"); 08548 } 08549 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) { 08550 printf("Internal error in insertvertex():\n"); 08551 printf(" Clockwise triangle after vertex insertion (top).\n"); 08552 } 08553 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) { 08554 printf("Internal error in insertvertex():\n"); 08555 printf(" Clockwise triangle after vertex insertion (left).\n"); 08556 } 08557 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) { 08558 printf("Internal error in insertvertex():\n"); 08559 printf(" Clockwise triangle after vertex insertion (right).\n"); 08560 } 08561 #endif /* SELF_CHECK */ 08562 if (b->verbose > 2) { 08563 printf(" Updating top "); 08564 printtriangle(m, b, &horiz); 08565 printf(" Creating left "); 08566 printtriangle(m, b, &newbotleft); 08567 printf(" Creating right "); 08568 printtriangle(m, b, &newbotright); 08569 } 08570 } 08571 08572 /* The insertion is successful by default, unless an encroached */ 08573 /* subsegment is found. */ 08574 success = SUCCESSFULVERTEX; 08575 /* Circle around the newly inserted vertex, checking each edge opposite */ 08576 /* it for the Delaunay property. Non-Delaunay edges are flipped. */ 08577 /* `horiz' is always the edge being checked. `first' marks where to */ 08578 /* stop circling. */ 08579 org(horiz, first); 08580 rightvertex = first; 08581 dest(horiz, leftvertex); 08582 /* Circle until finished. */ 08583 while (1) { 08584 /* By default, the edge will be flipped. */ 08585 doflip = 1; 08586 08587 if (m->checksegments) { 08588 /* Check for a subsegment, which cannot be flipped. */ 08589 tspivot(horiz, checksubseg); 08590 if (checksubseg.ss != m->dummysub) { 08591 /* The edge is a subsegment and cannot be flipped. */ 08592 doflip = 0; 08593 #ifndef CDT_ONLY 08594 if (segmentflaws) { 08595 /* Does the new vertex encroach upon this subsegment? */ 08596 if (checkseg4encroach(m, b, &checksubseg)) { 08597 success = ENCROACHINGVERTEX; 08598 } 08599 } 08600 #endif /* not CDT_ONLY */ 08601 } 08602 } 08603 08604 if (doflip) { 08605 /* Check if the edge is a boundary edge. */ 08606 sym(horiz, top); 08607 if (top.tri == m->dummytri) { 08608 /* The edge is a boundary edge and cannot be flipped. */ 08609 doflip = 0; 08610 } else { 08611 /* Find the vertex on the other side of the edge. */ 08612 apex(top, farvertex); 08613 /* In the incremental Delaunay triangulation algorithm, any of */ 08614 /* `leftvertex', `rightvertex', and `farvertex' could be vertices */ 08615 /* of the triangular bounding box. These vertices must be */ 08616 /* treated as if they are infinitely distant, even though their */ 08617 /* "coordinates" are not. */ 08618 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) || 08619 (leftvertex == m->infvertex3)) { 08620 /* `leftvertex' is infinitely distant. Check the convexity of */ 08621 /* the boundary of the triangulation. 'farvertex' might be */ 08622 /* infinite as well, but trust me, this same condition should */ 08623 /* be applied. */ 08624 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex) 08625 > 0.0; 08626 } else if ((rightvertex == m->infvertex1) || 08627 (rightvertex == m->infvertex2) || 08628 (rightvertex == m->infvertex3)) { 08629 /* `rightvertex' is infinitely distant. Check the convexity of */ 08630 /* the boundary of the triangulation. 'farvertex' might be */ 08631 /* infinite as well, but trust me, this same condition should */ 08632 /* be applied. */ 08633 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex) 08634 > 0.0; 08635 } else if ((farvertex == m->infvertex1) || 08636 (farvertex == m->infvertex2) || 08637 (farvertex == m->infvertex3)) { 08638 /* `farvertex' is infinitely distant and cannot be inside */ 08639 /* the circumcircle of the triangle `horiz'. */ 08640 doflip = 0; 08641 } else { 08642 /* Test whether the edge is locally Delaunay. */ 08643 doflip = incircle(m, b, leftvertex, newvertex, rightvertex, 08644 farvertex) > 0.0; 08645 } 08646 if (doflip) { 08647 /* We made it! Flip the edge `horiz' by rotating its containing */ 08648 /* quadrilateral (the two triangles adjacent to `horiz'). */ 08649 /* Identify the casing of the quadrilateral. */ 08650 lprev(top, topleft); 08651 sym(topleft, toplcasing); 08652 lnext(top, topright); 08653 sym(topright, toprcasing); 08654 lnext(horiz, botleft); 08655 sym(botleft, botlcasing); 08656 lprev(horiz, botright); 08657 sym(botright, botrcasing); 08658 /* Rotate the quadrilateral one-quarter turn counterclockwise. */ 08659 bond(topleft, botlcasing); 08660 bond(botleft, botrcasing); 08661 bond(botright, toprcasing); 08662 bond(topright, toplcasing); 08663 if (m->checksegments) { 08664 /* Check for subsegments and rebond them to the quadrilateral. */ 08665 tspivot(topleft, toplsubseg); 08666 tspivot(botleft, botlsubseg); 08667 tspivot(botright, botrsubseg); 08668 tspivot(topright, toprsubseg); 08669 if (toplsubseg.ss == m->dummysub) { 08670 tsdissolve(topright); 08671 } else { 08672 tsbond(topright, toplsubseg); 08673 } 08674 if (botlsubseg.ss == m->dummysub) { 08675 tsdissolve(topleft); 08676 } else { 08677 tsbond(topleft, botlsubseg); 08678 } 08679 if (botrsubseg.ss == m->dummysub) { 08680 tsdissolve(botleft); 08681 } else { 08682 tsbond(botleft, botrsubseg); 08683 } 08684 if (toprsubseg.ss == m->dummysub) { 08685 tsdissolve(botright); 08686 } else { 08687 tsbond(botright, toprsubseg); 08688 } 08689 } 08690 /* New vertex assignments for the rotated quadrilateral. */ 08691 setorg(horiz, farvertex); 08692 setdest(horiz, newvertex); 08693 setapex(horiz, rightvertex); 08694 setorg(top, newvertex); 08695 setdest(top, farvertex); 08696 setapex(top, leftvertex); 08697 for (i = 0; i < m->eextras; i++) { 08698 /* Take the average of the two triangles' attributes. */ 08699 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i)); 08700 setelemattribute(top, i, attrib); 08701 setelemattribute(horiz, i, attrib); 08702 } 08703 if (b->vararea) { 08704 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) { 08705 area = -1.0; 08706 } else { 08707 /* Take the average of the two triangles' area constraints. */ 08708 /* This prevents small area constraints from migrating a */ 08709 /* long, long way from their original location due to flips. */ 08710 area = 0.5 * (areabound(top) + areabound(horiz)); 08711 } 08712 setareabound(top, area); 08713 setareabound(horiz, area); 08714 } 08715 08716 if (m->checkquality) { 08717 newflip = (struct flipstacker *) poolalloc(&m->flipstackers); 08718 newflip->flippedtri = encode(horiz); 08719 newflip->prevflip = m->lastflip; 08720 m->lastflip = newflip; 08721 } 08722 08723 #ifdef SELF_CHECK 08724 if (newvertex != (vertex) NULL) { 08725 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) < 08726 0.0) { 08727 printf("Internal error in insertvertex():\n"); 08728 printf(" Clockwise triangle prior to edge flip (bottom).\n"); 08729 } 08730 /* The following test has been removed because constrainededge() */ 08731 /* sometimes generates inverted triangles that insertvertex() */ 08732 /* removes. */ 08733 /* 08734 if (counterclockwise(m, b, rightvertex, farvertex, leftvertex) < 08735 0.0) { 08736 printf("Internal error in insertvertex():\n"); 08737 printf(" Clockwise triangle prior to edge flip (top).\n"); 08738 } 08739 */ 08740 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) < 08741 0.0) { 08742 printf("Internal error in insertvertex():\n"); 08743 printf(" Clockwise triangle after edge flip (left).\n"); 08744 } 08745 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) < 08746 0.0) { 08747 printf("Internal error in insertvertex():\n"); 08748 printf(" Clockwise triangle after edge flip (right).\n"); 08749 } 08750 } 08751 #endif /* SELF_CHECK */ 08752 if (b->verbose > 2) { 08753 printf(" Edge flip results in left "); 08754 lnextself(topleft); 08755 printtriangle(m, b, &topleft); 08756 printf(" and right "); 08757 printtriangle(m, b, &horiz); 08758 } 08759 /* On the next iterations, consider the two edges that were */ 08760 /* exposed (this is, are now visible to the newly inserted */ 08761 /* vertex) by the edge flip. */ 08762 lprevself(horiz); 08763 leftvertex = farvertex; 08764 } 08765 } 08766 } 08767 if (!doflip) { 08768 /* The handle `horiz' is accepted as locally Delaunay. */ 08769 #ifndef CDT_ONLY 08770 if (triflaws) { 08771 /* Check the triangle `horiz' for quality. */ 08772 testtriangle(m, b, &horiz); 08773 } 08774 #endif /* not CDT_ONLY */ 08775 /* Look for the next edge around the newly inserted vertex. */ 08776 lnextself(horiz); 08777 sym(horiz, testtri); 08778 /* Check for finishing a complete revolution about the new vertex, or */ 08779 /* falling outside of the triangulation. The latter will happen */ 08780 /* when a vertex is inserted at a boundary. */ 08781 if ((leftvertex == first) || (testtri.tri == m->dummytri)) { 08782 /* We're done. Return a triangle whose origin is the new vertex. */ 08783 lnext(horiz, *searchtri); 08784 lnext(horiz, m->recenttri); 08785 return success; 08786 } 08787 /* Finish finding the next edge around the newly inserted vertex. */ 08788 lnext(testtri, horiz); 08789 rightvertex = leftvertex; 08790 dest(horiz, leftvertex); 08791 } 08792 } 08793 } 08794 08795 /*****************************************************************************/ 08796 /* */ 08797 /* triangulatepolygon() Find the Delaunay triangulation of a polygon that */ 08798 /* has a certain "nice" shape. This includes the */ 08799 /* polygons that result from deletion of a vertex or */ 08800 /* insertion of a segment. */ 08801 /* */ 08802 /* This is a conceptually difficult routine. The starting assumption is */ 08803 /* that we have a polygon with n sides. n - 1 of these sides are currently */ 08804 /* represented as edges in the mesh. One side, called the "base", need not */ 08805 /* be. */ 08806 /* */ 08807 /* Inside the polygon is a structure I call a "fan", consisting of n - 1 */ 08808 /* triangles that share a common origin. For each of these triangles, the */ 08809 /* edge opposite the origin is one of the sides of the polygon. The */ 08810 /* primary edge of each triangle is the edge directed from the origin to */ 08811 /* the destination; note that this is not the same edge that is a side of */ 08812 /* the polygon. `firstedge' is the primary edge of the first triangle. */ 08813 /* From there, the triangles follow in counterclockwise order about the */ 08814 /* polygon, until `lastedge', the primary edge of the last triangle. */ 08815 /* `firstedge' and `lastedge' are probably connected to other triangles */ 08816 /* beyond the extremes of the fan, but their identity is not important, as */ 08817 /* long as the fan remains connected to them. */ 08818 /* */ 08819 /* Imagine the polygon oriented so that its base is at the bottom. This */ 08820 /* puts `firstedge' on the far right, and `lastedge' on the far left. */ 08821 /* The right vertex of the base is the destination of `firstedge', and the */ 08822 /* left vertex of the base is the apex of `lastedge'. */ 08823 /* */ 08824 /* The challenge now is to find the right sequence of edge flips to */ 08825 /* transform the fan into a Delaunay triangulation of the polygon. Each */ 08826 /* edge flip effectively removes one triangle from the fan, committing it */ 08827 /* to the polygon. The resulting polygon has one fewer edge. If `doflip' */ 08828 /* is set, the final flip will be performed, resulting in a fan of one */ 08829 /* (useless?) triangle. If `doflip' is not set, the final flip is not */ 08830 /* performed, resulting in a fan of two triangles, and an unfinished */ 08831 /* triangular polygon that is not yet filled out with a single triangle. */ 08832 /* On completion of the routine, `lastedge' is the last remaining triangle, */ 08833 /* or the leftmost of the last two. */ 08834 /* */ 08835 /* Although the flips are performed in the order described above, the */ 08836 /* decisions about what flips to perform are made in precisely the reverse */ 08837 /* order. The recursive triangulatepolygon() procedure makes a decision, */ 08838 /* uses up to two recursive calls to triangulate the "subproblems" */ 08839 /* (polygons with fewer edges), and then performs an edge flip. */ 08840 /* */ 08841 /* The "decision" it makes is which vertex of the polygon should be */ 08842 /* connected to the base. This decision is made by testing every possible */ 08843 /* vertex. Once the best vertex is found, the two edges that connect this */ 08844 /* vertex to the base become the bases for two smaller polygons. These */ 08845 /* are triangulated recursively. Unfortunately, this approach can take */ 08846 /* O(n^2) time not only in the worst case, but in many common cases. It's */ 08847 /* rarely a big deal for vertex deletion, where n is rarely larger than */ 08848 /* ten, but it could be a big deal for segment insertion, especially if */ 08849 /* there's a lot of long segments that each cut many triangles. I ought to */ 08850 /* code a faster algorithm some day. */ 08851 /* */ 08852 /* The `edgecount' parameter is the number of sides of the polygon, */ 08853 /* including its base. `triflaws' is a flag that determines whether the */ 08854 /* new triangles should be tested for quality, and enqueued if they are */ 08855 /* bad. */ 08856 /* */ 08857 /*****************************************************************************/ 08858 08859 #ifdef ANSI_DECLARATORS 08860 void triangulatepolygon(struct mesh *m, struct behavior *b, 08861 struct otri *firstedge, struct otri *lastedge, 08862 int edgecount, int doflip, int triflaws) 08863 #else /* not ANSI_DECLARATORS */ 08864 void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws) 08865 struct mesh *m; 08866 struct behavior *b; 08867 struct otri *firstedge; 08868 struct otri *lastedge; 08869 int edgecount; 08870 int doflip; 08871 int triflaws; 08872 #endif /* not ANSI_DECLARATORS */ 08873 08874 { 08875 struct otri testtri; 08876 struct otri besttri; 08877 struct otri tempedge; 08878 vertex leftbasevertex, rightbasevertex; 08879 vertex testvertex; 08880 vertex bestvertex; 08881 int bestnumber; 08882 int i; 08883 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ 08884 08885 /* Identify the base vertices. */ 08886 apex(*lastedge, leftbasevertex); 08887 dest(*firstedge, rightbasevertex); 08888 if (b->verbose > 2) { 08889 printf(" Triangulating interior polygon at edge\n"); 08890 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0], 08891 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]); 08892 } 08893 /* Find the best vertex to connect the base to. */ 08894 onext(*firstedge, besttri); 08895 dest(besttri, bestvertex); 08896 otricopy(besttri, testtri); 08897 bestnumber = 1; 08898 for (i = 2; i <= edgecount - 2; i++) { 08899 onextself(testtri); 08900 dest(testtri, testvertex); 08901 /* Is this a better vertex? */ 08902 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex, 08903 testvertex) > 0.0) { 08904 otricopy(testtri, besttri); 08905 bestvertex = testvertex; 08906 bestnumber = i; 08907 } 08908 } 08909 if (b->verbose > 2) { 08910 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0], 08911 bestvertex[1]); 08912 } 08913 if (bestnumber > 1) { 08914 /* Recursively triangulate the smaller polygon on the right. */ 08915 oprev(besttri, tempedge); 08916 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1, 08917 triflaws); 08918 } 08919 if (bestnumber < edgecount - 2) { 08920 /* Recursively triangulate the smaller polygon on the left. */ 08921 sym(besttri, tempedge); 08922 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1, 08923 triflaws); 08924 /* Find `besttri' again; it may have been lost to edge flips. */ 08925 sym(tempedge, besttri); 08926 } 08927 if (doflip) { 08928 /* Do one final edge flip. */ 08929 flip(m, b, &besttri); 08930 #ifndef CDT_ONLY 08931 if (triflaws) { 08932 /* Check the quality of the newly committed triangle. */ 08933 sym(besttri, testtri); 08934 testtriangle(m, b, &testtri); 08935 } 08936 #endif /* not CDT_ONLY */ 08937 } 08938 /* Return the base triangle. */ 08939 otricopy(besttri, *lastedge); 08940 } 08941 08942 /*****************************************************************************/ 08943 /* */ 08944 /* deletevertex() Delete a vertex from a Delaunay triangulation, ensuring */ 08945 /* that the triangulation remains Delaunay. */ 08946 /* */ 08947 /* The origin of `deltri' is deleted. The union of the triangles adjacent */ 08948 /* to this vertex is a polygon, for which the Delaunay triangulation is */ 08949 /* found. Two triangles are removed from the mesh. */ 08950 /* */ 08951 /* Only interior vertices that do not lie on segments or boundaries may be */ 08952 /* deleted. */ 08953 /* */ 08954 /*****************************************************************************/ 08955 08956 #ifndef CDT_ONLY 08957 08958 #ifdef ANSI_DECLARATORS 08959 void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri) 08960 #else /* not ANSI_DECLARATORS */ 08961 void deletevertex(m, b, deltri) 08962 struct mesh *m; 08963 struct behavior *b; 08964 struct otri *deltri; 08965 #endif /* not ANSI_DECLARATORS */ 08966 08967 { 08968 struct otri countingtri; 08969 struct otri firstedge, lastedge; 08970 struct otri deltriright; 08971 struct otri lefttri, righttri; 08972 struct otri leftcasing, rightcasing; 08973 struct osub leftsubseg, rightsubseg; 08974 vertex delvertex; 08975 vertex neworg; 08976 int edgecount; 08977 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ 08978 subseg sptr; /* Temporary variable used by tspivot(). */ 08979 08980 org(*deltri, delvertex); 08981 if (b->verbose > 1) { 08982 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]); 08983 } 08984 vertexdealloc(m, delvertex); 08985 08986 /* Count the degree of the vertex being deleted. */ 08987 onext(*deltri, countingtri); 08988 edgecount = 1; 08989 while (!otriequal(*deltri, countingtri)) { 08990 #ifdef SELF_CHECK 08991 if (countingtri.tri == m->dummytri) { 08992 printf("Internal error in deletevertex():\n"); 08993 printf(" Attempt to delete boundary vertex.\n"); 08994 internalerror(); 08995 } 08996 #endif /* SELF_CHECK */ 08997 edgecount++; 08998 onextself(countingtri); 08999 } 09000 09001 #ifdef SELF_CHECK 09002 if (edgecount < 3) { 09003 printf("Internal error in deletevertex():\n Vertex has degree %d.\n", 09004 edgecount); 09005 internalerror(); 09006 } 09007 #endif /* SELF_CHECK */ 09008 if (edgecount > 3) { 09009 /* Triangulate the polygon defined by the union of all triangles */ 09010 /* adjacent to the vertex being deleted. Check the quality of */ 09011 /* the resulting triangles. */ 09012 onext(*deltri, firstedge); 09013 oprev(*deltri, lastedge); 09014 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0, 09015 !b->nobisect); 09016 } 09017 /* Splice out two triangles. */ 09018 lprev(*deltri, deltriright); 09019 dnext(*deltri, lefttri); 09020 sym(lefttri, leftcasing); 09021 oprev(deltriright, righttri); 09022 sym(righttri, rightcasing); 09023 bond(*deltri, leftcasing); 09024 bond(deltriright, rightcasing); 09025 tspivot(lefttri, leftsubseg); 09026 if (leftsubseg.ss != m->dummysub) { 09027 tsbond(*deltri, leftsubseg); 09028 } 09029 tspivot(righttri, rightsubseg); 09030 if (rightsubseg.ss != m->dummysub) { 09031 tsbond(deltriright, rightsubseg); 09032 } 09033 09034 /* Set the new origin of `deltri' and check its quality. */ 09035 org(lefttri, neworg); 09036 setorg(*deltri, neworg); 09037 if (!b->nobisect) { 09038 testtriangle(m, b, deltri); 09039 } 09040 09041 /* Delete the two spliced-out triangles. */ 09042 triangledealloc(m, lefttri.tri); 09043 triangledealloc(m, righttri.tri); 09044 } 09045 09046 #endif /* not CDT_ONLY */ 09047 09048 /*****************************************************************************/ 09049 /* */ 09050 /* undovertex() Undo the most recent vertex insertion. */ 09051 /* */ 09052 /* Walks through the list of transformations (flips and a vertex insertion) */ 09053 /* in the reverse of the order in which they were done, and undoes them. */ 09054 /* The inserted vertex is removed from the triangulation and deallocated. */ 09055 /* Two triangles (possibly just one) are also deallocated. */ 09056 /* */ 09057 /*****************************************************************************/ 09058 09059 #ifndef CDT_ONLY 09060 09061 #ifdef ANSI_DECLARATORS 09062 void undovertex(struct mesh *m, struct behavior *b) 09063 #else /* not ANSI_DECLARATORS */ 09064 void undovertex(m, b) 09065 struct mesh *m; 09066 struct behavior *b; 09067 #endif /* not ANSI_DECLARATORS */ 09068 09069 { 09070 struct otri fliptri; 09071 struct otri botleft, botright, topright; 09072 struct otri botlcasing, botrcasing, toprcasing; 09073 struct otri gluetri; 09074 struct osub botlsubseg, botrsubseg, toprsubseg; 09075 vertex botvertex, rightvertex; 09076 triangle ptr; /* Temporary variable used by sym(). */ 09077 subseg sptr; /* Temporary variable used by tspivot(). */ 09078 09079 /* Walk through the list of transformations (flips and a vertex insertion) */ 09080 /* in the reverse of the order in which they were done, and undo them. */ 09081 while (m->lastflip != (struct flipstacker *) NULL) { 09082 /* Find a triangle involved in the last unreversed transformation. */ 09083 decode(m->lastflip->flippedtri, fliptri); 09084 09085 /* We are reversing one of three transformations: a trisection of one */ 09086 /* triangle into three (by inserting a vertex in the triangle), a */ 09087 /* bisection of two triangles into four (by inserting a vertex in an */ 09088 /* edge), or an edge flip. */ 09089 if (m->lastflip->prevflip == (struct flipstacker *) NULL) { 09090 /* Restore a triangle that was split into three triangles, */ 09091 /* so it is again one triangle. */ 09092 dprev(fliptri, botleft); 09093 lnextself(botleft); 09094 onext(fliptri, botright); 09095 lprevself(botright); 09096 sym(botleft, botlcasing); 09097 sym(botright, botrcasing); 09098 dest(botleft, botvertex); 09099 09100 setapex(fliptri, botvertex); 09101 lnextself(fliptri); 09102 bond(fliptri, botlcasing); 09103 tspivot(botleft, botlsubseg); 09104 tsbond(fliptri, botlsubseg); 09105 lnextself(fliptri); 09106 bond(fliptri, botrcasing); 09107 tspivot(botright, botrsubseg); 09108 tsbond(fliptri, botrsubseg); 09109 09110 /* Delete the two spliced-out triangles. */ 09111 triangledealloc(m, botleft.tri); 09112 triangledealloc(m, botright.tri); 09113 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) { 09114 /* Restore two triangles that were split into four triangles, */ 09115 /* so they are again two triangles. */ 09116 lprev(fliptri, gluetri); 09117 sym(gluetri, botright); 09118 lnextself(botright); 09119 sym(botright, botrcasing); 09120 dest(botright, rightvertex); 09121 09122 setorg(fliptri, rightvertex); 09123 bond(gluetri, botrcasing); 09124 tspivot(botright, botrsubseg); 09125 tsbond(gluetri, botrsubseg); 09126 09127 /* Delete the spliced-out triangle. */ 09128 triangledealloc(m, botright.tri); 09129 09130 sym(fliptri, gluetri); 09131 if (gluetri.tri != m->dummytri) { 09132 lnextself(gluetri); 09133 dnext(gluetri, topright); 09134 sym(topright, toprcasing); 09135 09136 setorg(gluetri, rightvertex); 09137 bond(gluetri, toprcasing); 09138 tspivot(topright, toprsubseg); 09139 tsbond(gluetri, toprsubseg); 09140 09141 /* Delete the spliced-out triangle. */ 09142 triangledealloc(m, topright.tri); 09143 } 09144 09145 /* This is the end of the list, sneakily encoded. */ 09146 m->lastflip->prevflip = (struct flipstacker *) NULL; 09147 } else { 09148 /* Undo an edge flip. */ 09149 unflip(m, b, &fliptri); 09150 } 09151 09152 /* Go on and process the next transformation. */ 09153 m->lastflip = m->lastflip->prevflip; 09154 } 09155 } 09156 09157 #endif /* not CDT_ONLY */ 09158 09161 /********* Mesh transformation routines end here *********/ 09162 09163 /********* Divide-and-conquer Delaunay triangulation begins here *********/ 09167 /*****************************************************************************/ 09168 /* */ 09169 /* The divide-and-conquer bounding box */ 09170 /* */ 09171 /* I originally implemented the divide-and-conquer and incremental Delaunay */ 09172 /* triangulations using the edge-based data structure presented by Guibas */ 09173 /* and Stolfi. Switching to a triangle-based data structure doubled the */ 09174 /* speed. However, I had to think of a few extra tricks to maintain the */ 09175 /* elegance of the original algorithms. */ 09176 /* */ 09177 /* The "bounding box" used by my variant of the divide-and-conquer */ 09178 /* algorithm uses one triangle for each edge of the convex hull of the */ 09179 /* triangulation. These bounding triangles all share a common apical */ 09180 /* vertex, which is represented by NULL and which represents nothing. */ 09181 /* The bounding triangles are linked in a circular fan about this NULL */ 09182 /* vertex, and the edges on the convex hull of the triangulation appear */ 09183 /* opposite the NULL vertex. You might find it easiest to imagine that */ 09184 /* the NULL vertex is a point in 3D space behind the center of the */ 09185 /* triangulation, and that the bounding triangles form a sort of cone. */ 09186 /* */ 09187 /* This bounding box makes it easy to represent degenerate cases. For */ 09188 /* instance, the triangulation of two vertices is a single edge. This edge */ 09189 /* is represented by two bounding box triangles, one on each "side" of the */ 09190 /* edge. These triangles are also linked together in a fan about the NULL */ 09191 /* vertex. */ 09192 /* */ 09193 /* The bounding box also makes it easy to traverse the convex hull, as the */ 09194 /* divide-and-conquer algorithm needs to do. */ 09195 /* */ 09196 /*****************************************************************************/ 09197 09198 /*****************************************************************************/ 09199 /* */ 09200 /* vertexsort() Sort an array of vertices by x-coordinate, using the */ 09201 /* y-coordinate as a secondary key. */ 09202 /* */ 09203 /* Uses quicksort. Randomized O(n log n) time. No, I did not make any of */ 09204 /* the usual quicksort mistakes. */ 09205 /* */ 09206 /*****************************************************************************/ 09207 09208 #ifdef ANSI_DECLARATORS 09209 void vertexsort(vertex *sortarray, int arraysize) 09210 #else /* not ANSI_DECLARATORS */ 09211 void vertexsort(sortarray, arraysize) 09212 vertex *sortarray; 09213 int arraysize; 09214 #endif /* not ANSI_DECLARATORS */ 09215 09216 { 09217 int left, right; 09218 int pivot; 09219 REAL pivotx, pivoty; 09220 vertex temp; 09221 09222 if (arraysize == 2) { 09223 /* Recursive base case. */ 09224 if ((sortarray[0][0] > sortarray[1][0]) || 09225 ((sortarray[0][0] == sortarray[1][0]) && 09226 (sortarray[0][1] > sortarray[1][1]))) { 09227 temp = sortarray[1]; 09228 sortarray[1] = sortarray[0]; 09229 sortarray[0] = temp; 09230 } 09231 return; 09232 } 09233 /* Choose a random pivot to split the array. */ 09234 pivot = (int) randomnation((unsigned int) arraysize); 09235 pivotx = sortarray[pivot][0]; 09236 pivoty = sortarray[pivot][1]; 09237 /* Split the array. */ 09238 left = -1; 09239 right = arraysize; 09240 while (left < right) { 09241 /* Search for a vertex whose x-coordinate is too large for the left. */ 09242 do { 09243 left++; 09244 } while ((left <= right) && ((sortarray[left][0] < pivotx) || 09245 ((sortarray[left][0] == pivotx) && 09246 (sortarray[left][1] < pivoty)))); 09247 /* Search for a vertex whose x-coordinate is too small for the right. */ 09248 do { 09249 right--; 09250 } while ((left <= right) && ((sortarray[right][0] > pivotx) || 09251 ((sortarray[right][0] == pivotx) && 09252 (sortarray[right][1] > pivoty)))); 09253 if (left < right) { 09254 /* Swap the left and right vertices. */ 09255 temp = sortarray[left]; 09256 sortarray[left] = sortarray[right]; 09257 sortarray[right] = temp; 09258 } 09259 } 09260 if (left > 1) { 09261 /* Recursively sort the left subset. */ 09262 vertexsort(sortarray, left); 09263 } 09264 if (right < arraysize - 2) { 09265 /* Recursively sort the right subset. */ 09266 vertexsort(&sortarray[right + 1], arraysize - right - 1); 09267 } 09268 } 09269 09270 /*****************************************************************************/ 09271 /* */ 09272 /* vertexmedian() An order statistic algorithm, almost. Shuffles an */ 09273 /* array of vertices so that the first `median' vertices */ 09274 /* occur lexicographically before the remaining vertices. */ 09275 /* */ 09276 /* Uses the x-coordinate as the primary key if axis == 0; the y-coordinate */ 09277 /* if axis == 1. Very similar to the vertexsort() procedure, but runs in */ 09278 /* randomized linear time. */ 09279 /* */ 09280 /*****************************************************************************/ 09281 09282 #ifdef ANSI_DECLARATORS 09283 void vertexmedian(vertex *sortarray, int arraysize, int median, int axis) 09284 #else /* not ANSI_DECLARATORS */ 09285 void vertexmedian(sortarray, arraysize, median, axis) 09286 vertex *sortarray; 09287 int arraysize; 09288 int median; 09289 int axis; 09290 #endif /* not ANSI_DECLARATORS */ 09291 09292 { 09293 int left, right; 09294 int pivot; 09295 REAL pivot1, pivot2; 09296 vertex temp; 09297 09298 if (arraysize == 2) { 09299 /* Recursive base case. */ 09300 if ((sortarray[0][axis] > sortarray[1][axis]) || 09301 ((sortarray[0][axis] == sortarray[1][axis]) && 09302 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) { 09303 temp = sortarray[1]; 09304 sortarray[1] = sortarray[0]; 09305 sortarray[0] = temp; 09306 } 09307 return; 09308 } 09309 /* Choose a random pivot to split the array. */ 09310 pivot = (int) randomnation((unsigned int) arraysize); 09311 pivot1 = sortarray[pivot][axis]; 09312 pivot2 = sortarray[pivot][1 - axis]; 09313 /* Split the array. */ 09314 left = -1; 09315 right = arraysize; 09316 while (left < right) { 09317 /* Search for a vertex whose x-coordinate is too large for the left. */ 09318 do { 09319 left++; 09320 } while ((left <= right) && ((sortarray[left][axis] < pivot1) || 09321 ((sortarray[left][axis] == pivot1) && 09322 (sortarray[left][1 - axis] < pivot2)))); 09323 /* Search for a vertex whose x-coordinate is too small for the right. */ 09324 do { 09325 right--; 09326 } while ((left <= right) && ((sortarray[right][axis] > pivot1) || 09327 ((sortarray[right][axis] == pivot1) && 09328 (sortarray[right][1 - axis] > pivot2)))); 09329 if (left < right) { 09330 /* Swap the left and right vertices. */ 09331 temp = sortarray[left]; 09332 sortarray[left] = sortarray[right]; 09333 sortarray[right] = temp; 09334 } 09335 } 09336 /* Unlike in vertexsort(), at most one of the following */ 09337 /* conditionals is true. */ 09338 if (left > median) { 09339 /* Recursively shuffle the left subset. */ 09340 vertexmedian(sortarray, left, median, axis); 09341 } 09342 if (right < median - 1) { 09343 /* Recursively shuffle the right subset. */ 09344 vertexmedian(&sortarray[right + 1], arraysize - right - 1, 09345 median - right - 1, axis); 09346 } 09347 } 09348 09349 /*****************************************************************************/ 09350 /* */ 09351 /* alternateaxes() Sorts the vertices as appropriate for the divide-and- */ 09352 /* conquer algorithm with alternating cuts. */ 09353 /* */ 09354 /* Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1. */ 09355 /* For the base case, subsets containing only two or three vertices are */ 09356 /* always sorted by x-coordinate. */ 09357 /* */ 09358 /*****************************************************************************/ 09359 09360 #ifdef ANSI_DECLARATORS 09361 void alternateaxes(vertex *sortarray, int arraysize, int axis) 09362 #else /* not ANSI_DECLARATORS */ 09363 void alternateaxes(sortarray, arraysize, axis) 09364 vertex *sortarray; 09365 int arraysize; 09366 int axis; 09367 #endif /* not ANSI_DECLARATORS */ 09368 09369 { 09370 int divider; 09371 09372 divider = arraysize >> 1; 09373 if (arraysize <= 3) { 09374 /* Recursive base case: subsets of two or three vertices will be */ 09375 /* handled specially, and should always be sorted by x-coordinate. */ 09376 axis = 0; 09377 } 09378 /* Partition with a horizontal or vertical cut. */ 09379 vertexmedian(sortarray, arraysize, divider, axis); 09380 /* Recursively partition the subsets with a cross cut. */ 09381 if (arraysize - divider >= 2) { 09382 if (divider >= 2) { 09383 alternateaxes(sortarray, divider, 1 - axis); 09384 } 09385 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis); 09386 } 09387 } 09388 09389 /*****************************************************************************/ 09390 /* */ 09391 /* mergehulls() Merge two adjacent Delaunay triangulations into a */ 09392 /* single Delaunay triangulation. */ 09393 /* */ 09394 /* This is similar to the algorithm given by Guibas and Stolfi, but uses */ 09395 /* a triangle-based, rather than edge-based, data structure. */ 09396 /* */ 09397 /* The algorithm walks up the gap between the two triangulations, knitting */ 09398 /* them together. As they are merged, some of their bounding triangles */ 09399 /* are converted into real triangles of the triangulation. The procedure */ 09400 /* pulls each hull's bounding triangles apart, then knits them together */ 09401 /* like the teeth of two gears. The Delaunay property determines, at each */ 09402 /* step, whether the next "tooth" is a bounding triangle of the left hull */ 09403 /* or the right. When a bounding triangle becomes real, its apex is */ 09404 /* changed from NULL to a real vertex. */ 09405 /* */ 09406 /* Only two new triangles need to be allocated. These become new bounding */ 09407 /* triangles at the top and bottom of the seam. They are used to connect */ 09408 /* the remaining bounding triangles (those that have not been converted */ 09409 /* into real triangles) into a single fan. */ 09410 /* */ 09411 /* On entry, `farleft' and `innerleft' are bounding triangles of the left */ 09412 /* triangulation. The origin of `farleft' is the leftmost vertex, and */ 09413 /* the destination of `innerleft' is the rightmost vertex of the */ 09414 /* triangulation. Similarly, `innerright' and `farright' are bounding */ 09415 /* triangles of the right triangulation. The origin of `innerright' and */ 09416 /* destination of `farright' are the leftmost and rightmost vertices. */ 09417 /* */ 09418 /* On completion, the origin of `farleft' is the leftmost vertex of the */ 09419 /* merged triangulation, and the destination of `farright' is the rightmost */ 09420 /* vertex. */ 09421 /* */ 09422 /*****************************************************************************/ 09423 09424 #ifdef ANSI_DECLARATORS 09425 void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, 09426 struct otri *innerleft, struct otri *innerright, 09427 struct otri *farright, int axis) 09428 #else /* not ANSI_DECLARATORS */ 09429 void mergehulls(m, b, farleft, innerleft, innerright, farright, axis) 09430 struct mesh *m; 09431 struct behavior *b; 09432 struct otri *farleft; 09433 struct otri *innerleft; 09434 struct otri *innerright; 09435 struct otri *farright; 09436 int axis; 09437 #endif /* not ANSI_DECLARATORS */ 09438 09439 { 09440 struct otri leftcand, rightcand; 09441 struct otri baseedge; 09442 struct otri nextedge; 09443 struct otri sidecasing, topcasing, outercasing; 09444 struct otri checkedge; 09445 vertex innerleftdest; 09446 vertex innerrightorg; 09447 vertex innerleftapex, innerrightapex; 09448 vertex farleftpt, farrightpt; 09449 vertex farleftapex, farrightapex; 09450 vertex lowerleft, lowerright; 09451 vertex upperleft, upperright; 09452 vertex nextapex; 09453 vertex checkvertex; 09454 int changemade; 09455 int badedge; 09456 int leftfinished, rightfinished; 09457 triangle ptr; /* Temporary variable used by sym(). */ 09458 09459 dest(*innerleft, innerleftdest); 09460 apex(*innerleft, innerleftapex); 09461 org(*innerright, innerrightorg); 09462 apex(*innerright, innerrightapex); 09463 /* Special treatment for horizontal cuts. */ 09464 if (b->dwyer && (axis == 1)) { 09465 org(*farleft, farleftpt); 09466 apex(*farleft, farleftapex); 09467 dest(*farright, farrightpt); 09468 apex(*farright, farrightapex); 09469 /* The pointers to the extremal vertices are shifted to point to the */ 09470 /* topmost and bottommost vertex of each hull, rather than the */ 09471 /* leftmost and rightmost vertices. */ 09472 while (farleftapex[1] < farleftpt[1]) { 09473 lnextself(*farleft); 09474 symself(*farleft); 09475 farleftpt = farleftapex; 09476 apex(*farleft, farleftapex); 09477 } 09478 sym(*innerleft, checkedge); 09479 apex(checkedge, checkvertex); 09480 while (checkvertex[1] > innerleftdest[1]) { 09481 lnext(checkedge, *innerleft); 09482 innerleftapex = innerleftdest; 09483 innerleftdest = checkvertex; 09484 sym(*innerleft, checkedge); 09485 apex(checkedge, checkvertex); 09486 } 09487 while (innerrightapex[1] < innerrightorg[1]) { 09488 lnextself(*innerright); 09489 symself(*innerright); 09490 innerrightorg = innerrightapex; 09491 apex(*innerright, innerrightapex); 09492 } 09493 sym(*farright, checkedge); 09494 apex(checkedge, checkvertex); 09495 while (checkvertex[1] > farrightpt[1]) { 09496 lnext(checkedge, *farright); 09497 farrightapex = farrightpt; 09498 farrightpt = checkvertex; 09499 sym(*farright, checkedge); 09500 apex(checkedge, checkvertex); 09501 } 09502 } 09503 /* Find a line tangent to and below both hulls. */ 09504 do { 09505 changemade = 0; 09506 /* Make innerleftdest the "bottommost" vertex of the left hull. */ 09507 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) > 09508 0.0) { 09509 lprevself(*innerleft); 09510 symself(*innerleft); 09511 innerleftdest = innerleftapex; 09512 apex(*innerleft, innerleftapex); 09513 changemade = 1; 09514 } 09515 /* Make innerrightorg the "bottommost" vertex of the right hull. */ 09516 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) > 09517 0.0) { 09518 lnextself(*innerright); 09519 symself(*innerright); 09520 innerrightorg = innerrightapex; 09521 apex(*innerright, innerrightapex); 09522 changemade = 1; 09523 } 09524 } while (changemade); 09525 /* Find the two candidates to be the next "gear tooth." */ 09526 sym(*innerleft, leftcand); 09527 sym(*innerright, rightcand); 09528 /* Create the bottom new bounding triangle. */ 09529 maketriangle(m, b, &baseedge); 09530 /* Connect it to the bounding boxes of the left and right triangulations. */ 09531 bond(baseedge, *innerleft); 09532 lnextself(baseedge); 09533 bond(baseedge, *innerright); 09534 lnextself(baseedge); 09535 setorg(baseedge, innerrightorg); 09536 setdest(baseedge, innerleftdest); 09537 /* Apex is intentionally left NULL. */ 09538 if (b->verbose > 2) { 09539 printf(" Creating base bounding "); 09540 printtriangle(m, b, &baseedge); 09541 } 09542 /* Fix the extreme triangles if necessary. */ 09543 org(*farleft, farleftpt); 09544 if (innerleftdest == farleftpt) { 09545 lnext(baseedge, *farleft); 09546 } 09547 dest(*farright, farrightpt); 09548 if (innerrightorg == farrightpt) { 09549 lprev(baseedge, *farright); 09550 } 09551 /* The vertices of the current knitting edge. */ 09552 lowerleft = innerleftdest; 09553 lowerright = innerrightorg; 09554 /* The candidate vertices for knitting. */ 09555 apex(leftcand, upperleft); 09556 apex(rightcand, upperright); 09557 /* Walk up the gap between the two triangulations, knitting them together. */ 09558 while (1) { 09559 /* Have we reached the top? (This isn't quite the right question, */ 09560 /* because even though the left triangulation might seem finished now, */ 09561 /* moving up on the right triangulation might reveal a new vertex of */ 09562 /* the left triangulation. And vice-versa.) */ 09563 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <= 09564 0.0; 09565 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright) 09566 <= 0.0; 09567 if (leftfinished && rightfinished) { 09568 /* Create the top new bounding triangle. */ 09569 maketriangle(m, b, &nextedge); 09570 setorg(nextedge, lowerleft); 09571 setdest(nextedge, lowerright); 09572 /* Apex is intentionally left NULL. */ 09573 /* Connect it to the bounding boxes of the two triangulations. */ 09574 bond(nextedge, baseedge); 09575 lnextself(nextedge); 09576 bond(nextedge, rightcand); 09577 lnextself(nextedge); 09578 bond(nextedge, leftcand); 09579 if (b->verbose > 2) { 09580 printf(" Creating top bounding "); 09581 printtriangle(m, b, &nextedge); 09582 } 09583 /* Special treatment for horizontal cuts. */ 09584 if (b->dwyer && (axis == 1)) { 09585 org(*farleft, farleftpt); 09586 apex(*farleft, farleftapex); 09587 dest(*farright, farrightpt); 09588 apex(*farright, farrightapex); 09589 sym(*farleft, checkedge); 09590 apex(checkedge, checkvertex); 09591 /* The pointers to the extremal vertices are restored to the */ 09592 /* leftmost and rightmost vertices (rather than topmost and */ 09593 /* bottommost). */ 09594 while (checkvertex[0] < farleftpt[0]) { 09595 lprev(checkedge, *farleft); 09596 farleftapex = farleftpt; 09597 farleftpt = checkvertex; 09598 sym(*farleft, checkedge); 09599 apex(checkedge, checkvertex); 09600 } 09601 while (farrightapex[0] > farrightpt[0]) { 09602 lprevself(*farright); 09603 symself(*farright); 09604 farrightpt = farrightapex; 09605 apex(*farright, farrightapex); 09606 } 09607 } 09608 return; 09609 } 09610 /* Consider eliminating edges from the left triangulation. */ 09611 if (!leftfinished) { 09612 /* What vertex would be exposed if an edge were deleted? */ 09613 lprev(leftcand, nextedge); 09614 symself(nextedge); 09615 apex(nextedge, nextapex); 09616 /* If nextapex is NULL, then no vertex would be exposed; the */ 09617 /* triangulation would have been eaten right through. */ 09618 if (nextapex != (vertex) NULL) { 09619 /* Check whether the edge is Delaunay. */ 09620 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) > 09621 0.0; 09622 while (badedge) { 09623 /* Eliminate the edge with an edge flip. As a result, the */ 09624 /* left triangulation will have one more boundary triangle. */ 09625 lnextself(nextedge); 09626 sym(nextedge, topcasing); 09627 lnextself(nextedge); 09628 sym(nextedge, sidecasing); 09629 bond(nextedge, topcasing); 09630 bond(leftcand, sidecasing); 09631 lnextself(leftcand); 09632 sym(leftcand, outercasing); 09633 lprevself(nextedge); 09634 bond(nextedge, outercasing); 09635 /* Correct the vertices to reflect the edge flip. */ 09636 setorg(leftcand, lowerleft); 09637 setdest(leftcand, NULL); 09638 setapex(leftcand, nextapex); 09639 setorg(nextedge, NULL); 09640 setdest(nextedge, upperleft); 09641 setapex(nextedge, nextapex); 09642 /* Consider the newly exposed vertex. */ 09643 upperleft = nextapex; 09644 /* What vertex would be exposed if another edge were deleted? */ 09645 otricopy(sidecasing, nextedge); 09646 apex(nextedge, nextapex); 09647 if (nextapex != (vertex) NULL) { 09648 /* Check whether the edge is Delaunay. */ 09649 badedge = incircle(m, b, lowerleft, lowerright, upperleft, 09650 nextapex) > 0.0; 09651 } else { 09652 /* Avoid eating right through the triangulation. */ 09653 badedge = 0; 09654 } 09655 } 09656 } 09657 } 09658 /* Consider eliminating edges from the right triangulation. */ 09659 if (!rightfinished) { 09660 /* What vertex would be exposed if an edge were deleted? */ 09661 lnext(rightcand, nextedge); 09662 symself(nextedge); 09663 apex(nextedge, nextapex); 09664 /* If nextapex is NULL, then no vertex would be exposed; the */ 09665 /* triangulation would have been eaten right through. */ 09666 if (nextapex != (vertex) NULL) { 09667 /* Check whether the edge is Delaunay. */ 09668 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) > 09669 0.0; 09670 while (badedge) { 09671 /* Eliminate the edge with an edge flip. As a result, the */ 09672 /* right triangulation will have one more boundary triangle. */ 09673 lprevself(nextedge); 09674 sym(nextedge, topcasing); 09675 lprevself(nextedge); 09676 sym(nextedge, sidecasing); 09677 bond(nextedge, topcasing); 09678 bond(rightcand, sidecasing); 09679 lprevself(rightcand); 09680 sym(rightcand, outercasing); 09681 lnextself(nextedge); 09682 bond(nextedge, outercasing); 09683 /* Correct the vertices to reflect the edge flip. */ 09684 setorg(rightcand, NULL); 09685 setdest(rightcand, lowerright); 09686 setapex(rightcand, nextapex); 09687 setorg(nextedge, upperright); 09688 setdest(nextedge, NULL); 09689 setapex(nextedge, nextapex); 09690 /* Consider the newly exposed vertex. */ 09691 upperright = nextapex; 09692 /* What vertex would be exposed if another edge were deleted? */ 09693 otricopy(sidecasing, nextedge); 09694 apex(nextedge, nextapex); 09695 if (nextapex != (vertex) NULL) { 09696 /* Check whether the edge is Delaunay. */ 09697 badedge = incircle(m, b, lowerleft, lowerright, upperright, 09698 nextapex) > 0.0; 09699 } else { 09700 /* Avoid eating right through the triangulation. */ 09701 badedge = 0; 09702 } 09703 } 09704 } 09705 } 09706 if (leftfinished || (!rightfinished && 09707 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) > 09708 0.0))) { 09709 /* Knit the triangulations, adding an edge from `lowerleft' */ 09710 /* to `upperright'. */ 09711 bond(baseedge, rightcand); 09712 lprev(rightcand, baseedge); 09713 setdest(baseedge, lowerleft); 09714 lowerright = upperright; 09715 sym(baseedge, rightcand); 09716 apex(rightcand, upperright); 09717 } else { 09718 /* Knit the triangulations, adding an edge from `upperleft' */ 09719 /* to `lowerright'. */ 09720 bond(baseedge, leftcand); 09721 lnext(leftcand, baseedge); 09722 setorg(baseedge, lowerright); 09723 lowerleft = upperleft; 09724 sym(baseedge, leftcand); 09725 apex(leftcand, upperleft); 09726 } 09727 if (b->verbose > 2) { 09728 printf(" Connecting "); 09729 printtriangle(m, b, &baseedge); 09730 } 09731 } 09732 } 09733 09734 /*****************************************************************************/ 09735 /* */ 09736 /* divconqrecurse() Recursively form a Delaunay triangulation by the */ 09737 /* divide-and-conquer method. */ 09738 /* */ 09739 /* Recursively breaks down the problem into smaller pieces, which are */ 09740 /* knitted together by mergehulls(). The base cases (problems of two or */ 09741 /* three vertices) are handled specially here. */ 09742 /* */ 09743 /* On completion, `farleft' and `farright' are bounding triangles such that */ 09744 /* the origin of `farleft' is the leftmost vertex (breaking ties by */ 09745 /* choosing the highest leftmost vertex), and the destination of */ 09746 /* `farright' is the rightmost vertex (breaking ties by choosing the */ 09747 /* lowest rightmost vertex). */ 09748 /* */ 09749 /*****************************************************************************/ 09750 09751 #ifdef ANSI_DECLARATORS 09752 void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, 09753 int vertices, int axis, 09754 struct otri *farleft, struct otri *farright) 09755 #else /* not ANSI_DECLARATORS */ 09756 void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright) 09757 struct mesh *m; 09758 struct behavior *b; 09759 vertex *sortarray; 09760 int vertices; 09761 int axis; 09762 struct otri *farleft; 09763 struct otri *farright; 09764 #endif /* not ANSI_DECLARATORS */ 09765 09766 { 09767 struct otri midtri, tri1, tri2, tri3; 09768 struct otri innerleft, innerright; 09769 REAL area; 09770 int divider; 09771 09772 if (b->verbose > 2) { 09773 printf(" Triangulating %d vertices.\n", vertices); 09774 } 09775 if (vertices == 2) { 09776 /* The triangulation of two vertices is an edge. An edge is */ 09777 /* represented by two bounding triangles. */ 09778 maketriangle(m, b, farleft); 09779 setorg(*farleft, sortarray[0]); 09780 setdest(*farleft, sortarray[1]); 09781 /* The apex is intentionally left NULL. */ 09782 maketriangle(m, b, farright); 09783 setorg(*farright, sortarray[1]); 09784 setdest(*farright, sortarray[0]); 09785 /* The apex is intentionally left NULL. */ 09786 bond(*farleft, *farright); 09787 lprevself(*farleft); 09788 lnextself(*farright); 09789 bond(*farleft, *farright); 09790 lprevself(*farleft); 09791 lnextself(*farright); 09792 bond(*farleft, *farright); 09793 if (b->verbose > 2) { 09794 printf(" Creating "); 09795 printtriangle(m, b, farleft); 09796 printf(" Creating "); 09797 printtriangle(m, b, farright); 09798 } 09799 /* Ensure that the origin of `farleft' is sortarray[0]. */ 09800 lprev(*farright, *farleft); 09801 return; 09802 } else if (vertices == 3) { 09803 /* The triangulation of three vertices is either a triangle (with */ 09804 /* three bounding triangles) or two edges (with four bounding */ 09805 /* triangles). In either case, four triangles are created. */ 09806 maketriangle(m, b, &midtri); 09807 maketriangle(m, b, &tri1); 09808 maketriangle(m, b, &tri2); 09809 maketriangle(m, b, &tri3); 09810 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]); 09811 if (area == 0.0) { 09812 /* Three collinear vertices; the triangulation is two edges. */ 09813 setorg(midtri, sortarray[0]); 09814 setdest(midtri, sortarray[1]); 09815 setorg(tri1, sortarray[1]); 09816 setdest(tri1, sortarray[0]); 09817 setorg(tri2, sortarray[2]); 09818 setdest(tri2, sortarray[1]); 09819 setorg(tri3, sortarray[1]); 09820 setdest(tri3, sortarray[2]); 09821 /* All apices are intentionally left NULL. */ 09822 bond(midtri, tri1); 09823 bond(tri2, tri3); 09824 lnextself(midtri); 09825 lprevself(tri1); 09826 lnextself(tri2); 09827 lprevself(tri3); 09828 bond(midtri, tri3); 09829 bond(tri1, tri2); 09830 lnextself(midtri); 09831 lprevself(tri1); 09832 lnextself(tri2); 09833 lprevself(tri3); 09834 bond(midtri, tri1); 09835 bond(tri2, tri3); 09836 /* Ensure that the origin of `farleft' is sortarray[0]. */ 09837 otricopy(tri1, *farleft); 09838 /* Ensure that the destination of `farright' is sortarray[2]. */ 09839 otricopy(tri2, *farright); 09840 } else { 09841 /* The three vertices are not collinear; the triangulation is one */ 09842 /* triangle, namely `midtri'. */ 09843 setorg(midtri, sortarray[0]); 09844 setdest(tri1, sortarray[0]); 09845 setorg(tri3, sortarray[0]); 09846 /* Apices of tri1, tri2, and tri3 are left NULL. */ 09847 if (area > 0.0) { 09848 /* The vertices are in counterclockwise order. */ 09849 setdest(midtri, sortarray[1]); 09850 setorg(tri1, sortarray[1]); 09851 setdest(tri2, sortarray[1]); 09852 setapex(midtri, sortarray[2]); 09853 setorg(tri2, sortarray[2]); 09854 setdest(tri3, sortarray[2]); 09855 } else { 09856 /* The vertices are in clockwise order. */ 09857 setdest(midtri, sortarray[2]); 09858 setorg(tri1, sortarray[2]); 09859 setdest(tri2, sortarray[2]); 09860 setapex(midtri, sortarray[1]); 09861 setorg(tri2, sortarray[1]); 09862 setdest(tri3, sortarray[1]); 09863 } 09864 /* The topology does not depend on how the vertices are ordered. */ 09865 bond(midtri, tri1); 09866 lnextself(midtri); 09867 bond(midtri, tri2); 09868 lnextself(midtri); 09869 bond(midtri, tri3); 09870 lprevself(tri1); 09871 lnextself(tri2); 09872 bond(tri1, tri2); 09873 lprevself(tri1); 09874 lprevself(tri3); 09875 bond(tri1, tri3); 09876 lnextself(tri2); 09877 lprevself(tri3); 09878 bond(tri2, tri3); 09879 /* Ensure that the origin of `farleft' is sortarray[0]. */ 09880 otricopy(tri1, *farleft); 09881 /* Ensure that the destination of `farright' is sortarray[2]. */ 09882 if (area > 0.0) { 09883 otricopy(tri2, *farright); 09884 } else { 09885 lnext(*farleft, *farright); 09886 } 09887 } 09888 if (b->verbose > 2) { 09889 printf(" Creating "); 09890 printtriangle(m, b, &midtri); 09891 printf(" Creating "); 09892 printtriangle(m, b, &tri1); 09893 printf(" Creating "); 09894 printtriangle(m, b, &tri2); 09895 printf(" Creating "); 09896 printtriangle(m, b, &tri3); 09897 } 09898 return; 09899 } else { 09900 /* Split the vertices in half. */ 09901 divider = vertices >> 1; 09902 /* Recursively triangulate each half. */ 09903 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft); 09904 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis, 09905 &innerright, farright); 09906 if (b->verbose > 1) { 09907 printf(" Joining triangulations with %d and %d vertices.\n", divider, 09908 vertices - divider); 09909 } 09910 /* Merge the two triangulations into one. */ 09911 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis); 09912 } 09913 } 09914 09915 #ifdef ANSI_DECLARATORS 09916 long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost) 09917 #else /* not ANSI_DECLARATORS */ 09918 long removeghosts(m, b, startghost) 09919 struct mesh *m; 09920 struct behavior *b; 09921 struct otri *startghost; 09922 #endif /* not ANSI_DECLARATORS */ 09923 09924 { 09925 struct otri searchedge; 09926 struct otri dissolveedge; 09927 struct otri deadtriangle; 09928 vertex markorg; 09929 long hullsize; 09930 triangle ptr; /* Temporary variable used by sym(). */ 09931 09932 if (b->verbose) { 09933 printf(" Removing ghost triangles.\n"); 09934 } 09935 /* Find an edge on the convex hull to start point location from. */ 09936 lprev(*startghost, searchedge); 09937 symself(searchedge); 09938 m->dummytri[0] = encode(searchedge); 09939 /* Remove the bounding box and count the convex hull edges. */ 09940 otricopy(*startghost, dissolveedge); 09941 hullsize = 0; 09942 do { 09943 hullsize++; 09944 lnext(dissolveedge, deadtriangle); 09945 lprevself(dissolveedge); 09946 symself(dissolveedge); 09947 /* If no PSLG is involved, set the boundary markers of all the vertices */ 09948 /* on the convex hull. If a PSLG is used, this step is done later. */ 09949 if (!b->poly) { 09950 /* Watch out for the case where all the input vertices are collinear. */ 09951 if (dissolveedge.tri != m->dummytri) { 09952 org(dissolveedge, markorg); 09953 if (vertexmark(markorg) == 0) { 09954 setvertexmark(markorg, 1); 09955 } 09956 } 09957 } 09958 /* Remove a bounding triangle from a convex hull triangle. */ 09959 dissolve(dissolveedge); 09960 /* Find the next bounding triangle. */ 09961 sym(deadtriangle, dissolveedge); 09962 /* Delete the bounding triangle. */ 09963 triangledealloc(m, deadtriangle.tri); 09964 } while (!otriequal(dissolveedge, *startghost)); 09965 return hullsize; 09966 } 09967 09968 /*****************************************************************************/ 09969 /* */ 09970 /* divconqdelaunay() Form a Delaunay triangulation by the divide-and- */ 09971 /* conquer method. */ 09972 /* */ 09973 /* Sorts the vertices, calls a recursive procedure to triangulate them, and */ 09974 /* removes the bounding box, setting boundary markers as appropriate. */ 09975 /* */ 09976 /*****************************************************************************/ 09977 09978 #ifdef ANSI_DECLARATORS 09979 long divconqdelaunay(struct mesh *m, struct behavior *b) 09980 #else /* not ANSI_DECLARATORS */ 09981 long divconqdelaunay(m, b) 09982 struct mesh *m; 09983 struct behavior *b; 09984 #endif /* not ANSI_DECLARATORS */ 09985 09986 { 09987 vertex *sortarray; 09988 struct otri hullleft, hullright; 09989 int divider; 09990 int i, j; 09991 09992 if (b->verbose) { 09993 printf(" Sorting vertices.\n"); 09994 } 09995 09996 /* Allocate an array of pointers to vertices for sorting. */ 09997 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex)); 09998 traversalinit(&m->vertices); 09999 for (i = 0; i < m->invertices; i++) { 10000 sortarray[i] = vertextraverse(m); 10001 } 10002 /* Sort the vertices. */ 10003 vertexsort(sortarray, m->invertices); 10004 /* Discard duplicate vertices, which can really mess up the algorithm. */ 10005 i = 0; 10006 for (j = 1; j < m->invertices; j++) { 10007 if ((sortarray[i][0] == sortarray[j][0]) 10008 && (sortarray[i][1] == sortarray[j][1])) { 10009 if (!b->quiet) { 10010 printf( 10011 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", 10012 sortarray[j][0], sortarray[j][1]); 10013 } 10014 setvertextype(sortarray[j], UNDEADVERTEX); 10015 m->undeads++; 10016 } else { 10017 i++; 10018 sortarray[i] = sortarray[j]; 10019 } 10020 } 10021 i++; 10022 if (b->dwyer) { 10023 /* Re-sort the array of vertices to accommodate alternating cuts. */ 10024 divider = i >> 1; 10025 if (i - divider >= 2) { 10026 if (divider >= 2) { 10027 alternateaxes(sortarray, divider, 1); 10028 } 10029 alternateaxes(&sortarray[divider], i - divider, 1); 10030 } 10031 } 10032 10033 if (b->verbose) { 10034 printf(" Forming triangulation.\n"); 10035 } 10036 10037 /* Form the Delaunay triangulation. */ 10038 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright); 10039 trifree((VOID *) sortarray); 10040 10041 return removeghosts(m, b, &hullleft); 10042 } 10043 10046 /********* Divide-and-conquer Delaunay triangulation ends here *********/ 10047 10048 /********* Incremental Delaunay triangulation begins here *********/ 10052 /*****************************************************************************/ 10053 /* */ 10054 /* boundingbox() Form an "infinite" bounding triangle to insert vertices */ 10055 /* into. */ 10056 /* */ 10057 /* The vertices at "infinity" are assigned finite coordinates, which are */ 10058 /* used by the point location routines, but (mostly) ignored by the */ 10059 /* Delaunay edge flip routines. */ 10060 /* */ 10061 /*****************************************************************************/ 10062 10063 #ifndef REDUCED 10064 10065 #ifdef ANSI_DECLARATORS 10066 void boundingbox(struct mesh *m, struct behavior *b) 10067 #else /* not ANSI_DECLARATORS */ 10068 void boundingbox(m, b) 10069 struct mesh *m; 10070 struct behavior *b; 10071 #endif /* not ANSI_DECLARATORS */ 10072 10073 { 10074 struct otri inftri; /* Handle for the triangular bounding box. */ 10075 REAL width; 10076 10077 if (b->verbose) { 10078 printf(" Creating triangular bounding box.\n"); 10079 } 10080 /* Find the width (or height, whichever is larger) of the triangulation. */ 10081 width = m->xmax - m->xmin; 10082 if (m->ymax - m->ymin > width) { 10083 width = m->ymax - m->ymin; 10084 } 10085 if (width == 0.0) { 10086 width = 1.0; 10087 } 10088 /* Create the vertices of the bounding box. */ 10089 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes); 10090 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes); 10091 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes); 10092 m->infvertex1[0] = m->xmin - 50.0 * width; 10093 m->infvertex1[1] = m->ymin - 40.0 * width; 10094 m->infvertex2[0] = m->xmax + 50.0 * width; 10095 m->infvertex2[1] = m->ymin - 40.0 * width; 10096 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax); 10097 m->infvertex3[1] = m->ymax + 60.0 * width; 10098 10099 /* Create the bounding box. */ 10100 maketriangle(m, b, &inftri); 10101 setorg(inftri, m->infvertex1); 10102 setdest(inftri, m->infvertex2); 10103 setapex(inftri, m->infvertex3); 10104 /* Link dummytri to the bounding box so we can always find an */ 10105 /* edge to begin searching (point location) from. */ 10106 m->dummytri[0] = (triangle) inftri.tri; 10107 if (b->verbose > 2) { 10108 printf(" Creating "); 10109 printtriangle(m, b, &inftri); 10110 } 10111 } 10112 10113 #endif /* not REDUCED */ 10114 10115 /*****************************************************************************/ 10116 /* */ 10117 /* removebox() Remove the "infinite" bounding triangle, setting boundary */ 10118 /* markers as appropriate. */ 10119 /* */ 10120 /* The triangular bounding box has three boundary triangles (one for each */ 10121 /* side of the bounding box), and a bunch of triangles fanning out from */ 10122 /* the three bounding box vertices (one triangle for each edge of the */ 10123 /* convex hull of the inner mesh). This routine removes these triangles. */ 10124 /* */ 10125 /* Returns the number of edges on the convex hull of the triangulation. */ 10126 /* */ 10127 /*****************************************************************************/ 10128 10129 #ifndef REDUCED 10130 10131 #ifdef ANSI_DECLARATORS 10132 long removebox(struct mesh *m, struct behavior *b) 10133 #else /* not ANSI_DECLARATORS */ 10134 long removebox(m, b) 10135 struct mesh *m; 10136 struct behavior *b; 10137 #endif /* not ANSI_DECLARATORS */ 10138 10139 { 10140 struct otri deadtriangle; 10141 struct otri searchedge; 10142 struct otri checkedge; 10143 struct otri nextedge, finaledge, dissolveedge; 10144 vertex markorg; 10145 long hullsize; 10146 triangle ptr; /* Temporary variable used by sym(). */ 10147 10148 if (b->verbose) { 10149 printf(" Removing triangular bounding box.\n"); 10150 } 10151 /* Find a boundary triangle. */ 10152 nextedge.tri = m->dummytri; 10153 nextedge.orient = 0; 10154 symself(nextedge); 10155 /* Mark a place to stop. */ 10156 lprev(nextedge, finaledge); 10157 lnextself(nextedge); 10158 symself(nextedge); 10159 /* Find a triangle (on the boundary of the vertex set) that isn't */ 10160 /* a bounding box triangle. */ 10161 lprev(nextedge, searchedge); 10162 symself(searchedge); 10163 /* Check whether nextedge is another boundary triangle */ 10164 /* adjacent to the first one. */ 10165 lnext(nextedge, checkedge); 10166 symself(checkedge); 10167 if (checkedge.tri == m->dummytri) { 10168 /* Go on to the next triangle. There are only three boundary */ 10169 /* triangles, and this next triangle cannot be the third one, */ 10170 /* so it's safe to stop here. */ 10171 lprevself(searchedge); 10172 symself(searchedge); 10173 } 10174 /* Find a new boundary edge to search from, as the current search */ 10175 /* edge lies on a bounding box triangle and will be deleted. */ 10176 m->dummytri[0] = encode(searchedge); 10177 hullsize = -2l; 10178 while (!otriequal(nextedge, finaledge)) { 10179 hullsize++; 10180 lprev(nextedge, dissolveedge); 10181 symself(dissolveedge); 10182 /* If not using a PSLG, the vertices should be marked now. */ 10183 /* (If using a PSLG, markhull() will do the job.) */ 10184 if (!b->poly) { 10185 /* Be careful! One must check for the case where all the input */ 10186 /* vertices are collinear, and thus all the triangles are part of */ 10187 /* the bounding box. Otherwise, the setvertexmark() call below */ 10188 /* will cause a bad pointer reference. */ 10189 if (dissolveedge.tri != m->dummytri) { 10190 org(dissolveedge, markorg); 10191 if (vertexmark(markorg) == 0) { 10192 setvertexmark(markorg, 1); 10193 } 10194 } 10195 } 10196 /* Disconnect the bounding box triangle from the mesh triangle. */ 10197 dissolve(dissolveedge); 10198 lnext(nextedge, deadtriangle); 10199 sym(deadtriangle, nextedge); 10200 /* Get rid of the bounding box triangle. */ 10201 triangledealloc(m, deadtriangle.tri); 10202 /* Do we need to turn the corner? */ 10203 if (nextedge.tri == m->dummytri) { 10204 /* Turn the corner. */ 10205 otricopy(dissolveedge, nextedge); 10206 } 10207 } 10208 triangledealloc(m, finaledge.tri); 10209 10210 trifree((VOID *) m->infvertex1); /* Deallocate the bounding box vertices. */ 10211 trifree((VOID *) m->infvertex2); 10212 trifree((VOID *) m->infvertex3); 10213 10214 return hullsize; 10215 } 10216 10217 #endif /* not REDUCED */ 10218 10219 /*****************************************************************************/ 10220 /* */ 10221 /* incrementaldelaunay() Form a Delaunay triangulation by incrementally */ 10222 /* inserting vertices. */ 10223 /* */ 10224 /* Returns the number of edges on the convex hull of the triangulation. */ 10225 /* */ 10226 /*****************************************************************************/ 10227 10228 #ifndef REDUCED 10229 10230 #ifdef ANSI_DECLARATORS 10231 long incrementaldelaunay(struct mesh *m, struct behavior *b) 10232 #else /* not ANSI_DECLARATORS */ 10233 long incrementaldelaunay(m, b) 10234 struct mesh *m; 10235 struct behavior *b; 10236 #endif /* not ANSI_DECLARATORS */ 10237 10238 { 10239 struct otri starttri; 10240 vertex vertexloop; 10241 10242 /* Create a triangular bounding box. */ 10243 boundingbox(m, b); 10244 if (b->verbose) { 10245 printf(" Incrementally inserting vertices.\n"); 10246 } 10247 traversalinit(&m->vertices); 10248 vertexloop = vertextraverse(m); 10249 while (vertexloop != (vertex) NULL) { 10250 starttri.tri = m->dummytri; 10251 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0) 10252 == DUPLICATEVERTEX) { 10253 if (!b->quiet) { 10254 printf( 10255 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", 10256 vertexloop[0], vertexloop[1]); 10257 } 10258 setvertextype(vertexloop, UNDEADVERTEX); 10259 m->undeads++; 10260 } 10261 vertexloop = vertextraverse(m); 10262 } 10263 /* Remove the bounding box. */ 10264 return removebox(m, b); 10265 } 10266 10267 #endif /* not REDUCED */ 10268 10271 /********* Incremental Delaunay triangulation ends here *********/ 10272 10273 /********* Sweepline Delaunay triangulation begins here *********/ 10277 #ifndef REDUCED 10278 10279 #ifdef ANSI_DECLARATORS 10280 void eventheapinsert(struct event **heap, int heapsize, struct event *newevent) 10281 #else /* not ANSI_DECLARATORS */ 10282 void eventheapinsert(heap, heapsize, newevent) 10283 struct event **heap; 10284 int heapsize; 10285 struct event *newevent; 10286 #endif /* not ANSI_DECLARATORS */ 10287 10288 { 10289 REAL eventx, eventy; 10290 int eventnum; 10291 int parent; 10292 int notdone; 10293 10294 eventx = newevent->xkey; 10295 eventy = newevent->ykey; 10296 eventnum = heapsize; 10297 notdone = eventnum > 0; 10298 while (notdone) { 10299 parent = (eventnum - 1) >> 1; 10300 if ((heap[parent]->ykey < eventy) || 10301 ((heap[parent]->ykey == eventy) 10302 && (heap[parent]->xkey <= eventx))) { 10303 notdone = 0; 10304 } else { 10305 heap[eventnum] = heap[parent]; 10306 heap[eventnum]->heapposition = eventnum; 10307 10308 eventnum = parent; 10309 notdone = eventnum > 0; 10310 } 10311 } 10312 heap[eventnum] = newevent; 10313 newevent->heapposition = eventnum; 10314 } 10315 10316 #endif /* not REDUCED */ 10317 10318 #ifndef REDUCED 10319 10320 #ifdef ANSI_DECLARATORS 10321 void eventheapify(struct event **heap, int heapsize, int eventnum) 10322 #else /* not ANSI_DECLARATORS */ 10323 void eventheapify(heap, heapsize, eventnum) 10324 struct event **heap; 10325 int heapsize; 10326 int eventnum; 10327 #endif /* not ANSI_DECLARATORS */ 10328 10329 { 10330 struct event *thisevent; 10331 REAL eventx, eventy; 10332 int leftchild, rightchild; 10333 int smallest; 10334 int notdone; 10335 10336 thisevent = heap[eventnum]; 10337 eventx = thisevent->xkey; 10338 eventy = thisevent->ykey; 10339 leftchild = 2 * eventnum + 1; 10340 notdone = leftchild < heapsize; 10341 while (notdone) { 10342 if ((heap[leftchild]->ykey < eventy) || 10343 ((heap[leftchild]->ykey == eventy) 10344 && (heap[leftchild]->xkey < eventx))) { 10345 smallest = leftchild; 10346 } else { 10347 smallest = eventnum; 10348 } 10349 rightchild = leftchild + 1; 10350 if (rightchild < heapsize) { 10351 if ((heap[rightchild]->ykey < heap[smallest]->ykey) || 10352 ((heap[rightchild]->ykey == heap[smallest]->ykey) 10353 && (heap[rightchild]->xkey < heap[smallest]->xkey))) { 10354 smallest = rightchild; 10355 } 10356 } 10357 if (smallest == eventnum) { 10358 notdone = 0; 10359 } else { 10360 heap[eventnum] = heap[smallest]; 10361 heap[eventnum]->heapposition = eventnum; 10362 heap[smallest] = thisevent; 10363 thisevent->heapposition = smallest; 10364 10365 eventnum = smallest; 10366 leftchild = 2 * eventnum + 1; 10367 notdone = leftchild < heapsize; 10368 } 10369 } 10370 } 10371 10372 #endif /* not REDUCED */ 10373 10374 #ifndef REDUCED 10375 10376 #ifdef ANSI_DECLARATORS 10377 void eventheapdelete(struct event **heap, int heapsize, int eventnum) 10378 #else /* not ANSI_DECLARATORS */ 10379 void eventheapdelete(heap, heapsize, eventnum) 10380 struct event **heap; 10381 int heapsize; 10382 int eventnum; 10383 #endif /* not ANSI_DECLARATORS */ 10384 10385 { 10386 struct event *moveevent; 10387 REAL eventx, eventy; 10388 int parent; 10389 int notdone; 10390 10391 moveevent = heap[heapsize - 1]; 10392 if (eventnum > 0) { 10393 eventx = moveevent->xkey; 10394 eventy = moveevent->ykey; 10395 do { 10396 parent = (eventnum - 1) >> 1; 10397 if ((heap[parent]->ykey < eventy) || 10398 ((heap[parent]->ykey == eventy) 10399 && (heap[parent]->xkey <= eventx))) { 10400 notdone = 0; 10401 } else { 10402 heap[eventnum] = heap[parent]; 10403 heap[eventnum]->heapposition = eventnum; 10404 10405 eventnum = parent; 10406 notdone = eventnum > 0; 10407 } 10408 } while (notdone); 10409 } 10410 heap[eventnum] = moveevent; 10411 moveevent->heapposition = eventnum; 10412 eventheapify(heap, heapsize - 1, eventnum); 10413 } 10414 10415 #endif /* not REDUCED */ 10416 10417 #ifndef REDUCED 10418 10419 #ifdef ANSI_DECLARATORS 10420 void createeventheap(struct mesh *m, struct event ***eventheap, 10421 struct event **events, struct event **freeevents) 10422 #else /* not ANSI_DECLARATORS */ 10423 void createeventheap(m, eventheap, events, freeevents) 10424 struct mesh *m; 10425 struct event ***eventheap; 10426 struct event **events; 10427 struct event **freeevents; 10428 #endif /* not ANSI_DECLARATORS */ 10429 10430 { 10431 vertex thisvertex; 10432 int maxevents; 10433 int i; 10434 10435 maxevents = (3 * m->invertices) / 2; 10436 *eventheap = (struct event **) trimalloc(maxevents * 10437 (int) sizeof(struct event *)); 10438 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event)); 10439 traversalinit(&m->vertices); 10440 for (i = 0; i < m->invertices; i++) { 10441 thisvertex = vertextraverse(m); 10442 (*events)[i].eventptr = (VOID *) thisvertex; 10443 (*events)[i].xkey = thisvertex[0]; 10444 (*events)[i].ykey = thisvertex[1]; 10445 eventheapinsert(*eventheap, i, *events + i); 10446 } 10447 *freeevents = (struct event *) NULL; 10448 for (i = maxevents - 1; i >= m->invertices; i--) { 10449 (*events)[i].eventptr = (VOID *) *freeevents; 10450 *freeevents = *events + i; 10451 } 10452 } 10453 10454 #endif /* not REDUCED */ 10455 10456 #ifndef REDUCED 10457 10458 #ifdef ANSI_DECLARATORS 10459 int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite) 10460 #else /* not ANSI_DECLARATORS */ 10461 int rightofhyperbola(m, fronttri, newsite) 10462 struct mesh *m; 10463 struct otri *fronttri; 10464 vertex newsite; 10465 #endif /* not ANSI_DECLARATORS */ 10466 10467 { 10468 vertex leftvertex, rightvertex; 10469 REAL dxa, dya, dxb, dyb; 10470 10471 m->hyperbolacount++; 10472 10473 dest(*fronttri, leftvertex); 10474 apex(*fronttri, rightvertex); 10475 if ((leftvertex[1] < rightvertex[1]) || 10476 ((leftvertex[1] == rightvertex[1]) && 10477 (leftvertex[0] < rightvertex[0]))) { 10478 if (newsite[0] >= rightvertex[0]) { 10479 return 1; 10480 } 10481 } else { 10482 if (newsite[0] <= leftvertex[0]) { 10483 return 0; 10484 } 10485 } 10486 dxa = leftvertex[0] - newsite[0]; 10487 dya = leftvertex[1] - newsite[1]; 10488 dxb = rightvertex[0] - newsite[0]; 10489 dyb = rightvertex[1] - newsite[1]; 10490 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya); 10491 } 10492 10493 #endif /* not REDUCED */ 10494 10495 #ifndef REDUCED 10496 10497 #ifdef ANSI_DECLARATORS 10498 REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc) 10499 #else /* not ANSI_DECLARATORS */ 10500 REAL circletop(m, pa, pb, pc, ccwabc) 10501 struct mesh *m; 10502 vertex pa; 10503 vertex pb; 10504 vertex pc; 10505 REAL ccwabc; 10506 #endif /* not ANSI_DECLARATORS */ 10507 10508 { 10509 REAL xac, yac, xbc, ybc, xab, yab; 10510 REAL aclen2, bclen2, ablen2; 10511 10512 m->circletopcount++; 10513 10514 xac = pa[0] - pc[0]; 10515 yac = pa[1] - pc[1]; 10516 xbc = pb[0] - pc[0]; 10517 ybc = pb[1] - pc[1]; 10518 xab = pa[0] - pb[0]; 10519 yab = pa[1] - pb[1]; 10520 aclen2 = xac * xac + yac * yac; 10521 bclen2 = xbc * xbc + ybc * ybc; 10522 ablen2 = xab * xab + yab * yab; 10523 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2)) 10524 / (2.0 * ccwabc); 10525 } 10526 10527 #endif /* not REDUCED */ 10528 10529 #ifndef REDUCED 10530 10531 #ifdef ANSI_DECLARATORS 10532 void check4deadevent(struct otri *checktri, struct event **freeevents, 10533 struct event **eventheap, int *heapsize) 10534 #else /* not ANSI_DECLARATORS */ 10535 void check4deadevent(checktri, freeevents, eventheap, heapsize) 10536 struct otri *checktri; 10537 struct event **freeevents; 10538 struct event **eventheap; 10539 int *heapsize; 10540 #endif /* not ANSI_DECLARATORS */ 10541 10542 { 10543 struct event *deadevent; 10544 vertex eventvertex; 10545 int eventnum; 10546 10547 org(*checktri, eventvertex); 10548 if (eventvertex != (vertex) NULL) { 10549 deadevent = (struct event *) eventvertex; 10550 eventnum = deadevent->heapposition; 10551 deadevent->eventptr = (VOID *) *freeevents; 10552 *freeevents = deadevent; 10553 eventheapdelete(eventheap, *heapsize, eventnum); 10554 (*heapsize)--; 10555 setorg(*checktri, NULL); 10556 } 10557 } 10558 10559 #endif /* not REDUCED */ 10560 10561 #ifndef REDUCED 10562 10563 #ifdef ANSI_DECLARATORS 10564 struct splaynode *splay(struct mesh *m, struct splaynode *splaytree, 10565 vertex searchpoint, struct otri *searchtri) 10566 #else /* not ANSI_DECLARATORS */ 10567 struct splaynode *splay(m, splaytree, searchpoint, searchtri) 10568 struct mesh *m; 10569 struct splaynode *splaytree; 10570 vertex searchpoint; 10571 struct otri *searchtri; 10572 #endif /* not ANSI_DECLARATORS */ 10573 10574 { 10575 struct splaynode *child, *grandchild; 10576 struct splaynode *lefttree, *righttree; 10577 struct splaynode *leftright; 10578 vertex checkvertex; 10579 int rightofroot, rightofchild; 10580 10581 if (splaytree == (struct splaynode *) NULL) { 10582 return (struct splaynode *) NULL; 10583 } 10584 dest(splaytree->keyedge, checkvertex); 10585 if (checkvertex == splaytree->keydest) { 10586 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint); 10587 if (rightofroot) { 10588 otricopy(splaytree->keyedge, *searchtri); 10589 child = splaytree->rchild; 10590 } else { 10591 child = splaytree->lchild; 10592 } 10593 if (child == (struct splaynode *) NULL) { 10594 return splaytree; 10595 } 10596 dest(child->keyedge, checkvertex); 10597 if (checkvertex != child->keydest) { 10598 child = splay(m, child, searchpoint, searchtri); 10599 if (child == (struct splaynode *) NULL) { 10600 if (rightofroot) { 10601 splaytree->rchild = (struct splaynode *) NULL; 10602 } else { 10603 splaytree->lchild = (struct splaynode *) NULL; 10604 } 10605 return splaytree; 10606 } 10607 } 10608 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint); 10609 if (rightofchild) { 10610 otricopy(child->keyedge, *searchtri); 10611 grandchild = splay(m, child->rchild, searchpoint, searchtri); 10612 child->rchild = grandchild; 10613 } else { 10614 grandchild = splay(m, child->lchild, searchpoint, searchtri); 10615 child->lchild = grandchild; 10616 } 10617 if (grandchild == (struct splaynode *) NULL) { 10618 if (rightofroot) { 10619 splaytree->rchild = child->lchild; 10620 child->lchild = splaytree; 10621 } else { 10622 splaytree->lchild = child->rchild; 10623 child->rchild = splaytree; 10624 } 10625 return child; 10626 } 10627 if (rightofchild) { 10628 if (rightofroot) { 10629 splaytree->rchild = child->lchild; 10630 child->lchild = splaytree; 10631 } else { 10632 splaytree->lchild = grandchild->rchild; 10633 grandchild->rchild = splaytree; 10634 } 10635 child->rchild = grandchild->lchild; 10636 grandchild->lchild = child; 10637 } else { 10638 if (rightofroot) { 10639 splaytree->rchild = grandchild->lchild; 10640 grandchild->lchild = splaytree; 10641 } else { 10642 splaytree->lchild = child->rchild; 10643 child->rchild = splaytree; 10644 } 10645 child->lchild = grandchild->rchild; 10646 grandchild->rchild = child; 10647 } 10648 return grandchild; 10649 } else { 10650 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri); 10651 righttree = splay(m, splaytree->rchild, searchpoint, searchtri); 10652 10653 pooldealloc(&m->splaynodes, (VOID *) splaytree); 10654 if (lefttree == (struct splaynode *) NULL) { 10655 return righttree; 10656 } else if (righttree == (struct splaynode *) NULL) { 10657 return lefttree; 10658 } else if (lefttree->rchild == (struct splaynode *) NULL) { 10659 lefttree->rchild = righttree->lchild; 10660 righttree->lchild = lefttree; 10661 return righttree; 10662 } else if (righttree->lchild == (struct splaynode *) NULL) { 10663 righttree->lchild = lefttree->rchild; 10664 lefttree->rchild = righttree; 10665 return lefttree; 10666 } else { 10667 /* printf("Holy Toledo!!!\n"); */ 10668 leftright = lefttree->rchild; 10669 while (leftright->rchild != (struct splaynode *) NULL) { 10670 leftright = leftright->rchild; 10671 } 10672 leftright->rchild = righttree; 10673 return lefttree; 10674 } 10675 } 10676 } 10677 10678 #endif /* not REDUCED */ 10679 10680 #ifndef REDUCED 10681 10682 #ifdef ANSI_DECLARATORS 10683 struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot, 10684 struct otri *newkey, vertex searchpoint) 10685 #else /* not ANSI_DECLARATORS */ 10686 struct splaynode *splayinsert(m, splayroot, newkey, searchpoint) 10687 struct mesh *m; 10688 struct splaynode *splayroot; 10689 struct otri *newkey; 10690 vertex searchpoint; 10691 #endif /* not ANSI_DECLARATORS */ 10692 10693 { 10694 struct splaynode *newsplaynode; 10695 10696 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes); 10697 otricopy(*newkey, newsplaynode->keyedge); 10698 dest(*newkey, newsplaynode->keydest); 10699 if (splayroot == (struct splaynode *) NULL) { 10700 newsplaynode->lchild = (struct splaynode *) NULL; 10701 newsplaynode->rchild = (struct splaynode *) NULL; 10702 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) { 10703 newsplaynode->lchild = splayroot; 10704 newsplaynode->rchild = splayroot->rchild; 10705 splayroot->rchild = (struct splaynode *) NULL; 10706 } else { 10707 newsplaynode->lchild = splayroot->lchild; 10708 newsplaynode->rchild = splayroot; 10709 splayroot->lchild = (struct splaynode *) NULL; 10710 } 10711 return newsplaynode; 10712 } 10713 10714 #endif /* not REDUCED */ 10715 10716 #ifndef REDUCED 10717 10718 #ifdef ANSI_DECLARATORS 10719 struct splaynode *circletopinsert(struct mesh *m, struct behavior *b, 10720 struct splaynode *splayroot, 10721 struct otri *newkey, 10722 vertex pa, vertex pb, vertex pc, REAL topy) 10723 #else /* not ANSI_DECLARATORS */ 10724 struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy) 10725 struct mesh *m; 10726 struct behavior *b; 10727 struct splaynode *splayroot; 10728 struct otri *newkey; 10729 vertex pa; 10730 vertex pb; 10731 vertex pc; 10732 REAL topy; 10733 #endif /* not ANSI_DECLARATORS */ 10734 10735 { 10736 REAL ccwabc; 10737 REAL xac, yac, xbc, ybc; 10738 REAL aclen2, bclen2; 10739 REAL searchpoint[2]; 10740 struct otri dummytri; 10741 10742 ccwabc = counterclockwise(m, b, pa, pb, pc); 10743 xac = pa[0] - pc[0]; 10744 yac = pa[1] - pc[1]; 10745 xbc = pb[0] - pc[0]; 10746 ybc = pb[1] - pc[1]; 10747 aclen2 = xac * xac + yac * yac; 10748 bclen2 = xbc * xbc + ybc * ybc; 10749 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc); 10750 searchpoint[1] = topy; 10751 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri), 10752 newkey, (vertex) searchpoint); 10753 } 10754 10755 #endif /* not REDUCED */ 10756 10757 #ifndef REDUCED 10758 10759 #ifdef ANSI_DECLARATORS 10760 struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot, 10761 struct otri *bottommost, vertex searchvertex, 10762 struct otri *searchtri, int *farright) 10763 #else /* not ANSI_DECLARATORS */ 10764 struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex, 10765 searchtri, farright) 10766 struct mesh *m; 10767 struct splaynode *splayroot; 10768 struct otri *bottommost; 10769 vertex searchvertex; 10770 struct otri *searchtri; 10771 int *farright; 10772 #endif /* not ANSI_DECLARATORS */ 10773 10774 { 10775 int farrightflag; 10776 triangle ptr; /* Temporary variable used by onext(). */ 10777 10778 otricopy(*bottommost, *searchtri); 10779 splayroot = splay(m, splayroot, searchvertex, searchtri); 10780 10781 farrightflag = 0; 10782 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) { 10783 onextself(*searchtri); 10784 farrightflag = otriequal(*searchtri, *bottommost); 10785 } 10786 *farright = farrightflag; 10787 return splayroot; 10788 } 10789 10790 #endif /* not REDUCED */ 10791 10792 #ifndef REDUCED 10793 10794 #ifdef ANSI_DECLARATORS 10795 long sweeplinedelaunay(struct mesh *m, struct behavior *b) 10796 #else /* not ANSI_DECLARATORS */ 10797 long sweeplinedelaunay(m, b) 10798 struct mesh *m; 10799 struct behavior *b; 10800 #endif /* not ANSI_DECLARATORS */ 10801 10802 { 10803 struct event **eventheap; 10804 struct event *events; 10805 struct event *freeevents; 10806 struct event *nextevent; 10807 struct event *newevent; 10808 struct splaynode *splayroot; 10809 struct otri bottommost; 10810 struct otri searchtri; 10811 struct otri fliptri; 10812 struct otri lefttri, righttri, farlefttri, farrighttri; 10813 struct otri inserttri; 10814 vertex firstvertex, secondvertex; 10815 vertex nextvertex, lastvertex; 10816 vertex connectvertex; 10817 vertex leftvertex, midvertex, rightvertex; 10818 REAL lefttest, righttest; 10819 int heapsize; 10820 int check4events, farrightflag; 10821 triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */ 10822 10823 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK, 10824 SPLAYNODEPERBLOCK, 0); 10825 splayroot = (struct splaynode *) NULL; 10826 10827 if (b->verbose) { 10828 printf(" Placing vertices in event heap.\n"); 10829 } 10830 createeventheap(m, &eventheap, &events, &freeevents); 10831 heapsize = m->invertices; 10832 10833 if (b->verbose) { 10834 printf(" Forming triangulation.\n"); 10835 } 10836 maketriangle(m, b, &lefttri); 10837 maketriangle(m, b, &righttri); 10838 bond(lefttri, righttri); 10839 lnextself(lefttri); 10840 lprevself(righttri); 10841 bond(lefttri, righttri); 10842 lnextself(lefttri); 10843 lprevself(righttri); 10844 bond(lefttri, righttri); 10845 firstvertex = (vertex) eventheap[0]->eventptr; 10846 eventheap[0]->eventptr = (VOID *) freeevents; 10847 freeevents = eventheap[0]; 10848 eventheapdelete(eventheap, heapsize, 0); 10849 heapsize--; 10850 do { 10851 if (heapsize == 0) { 10852 printf("Error: Input vertices are all identical.\n"); 10853 triexit(1); 10854 } 10855 secondvertex = (vertex) eventheap[0]->eventptr; 10856 eventheap[0]->eventptr = (VOID *) freeevents; 10857 freeevents = eventheap[0]; 10858 eventheapdelete(eventheap, heapsize, 0); 10859 heapsize--; 10860 if ((firstvertex[0] == secondvertex[0]) && 10861 (firstvertex[1] == secondvertex[1])) { 10862 if (!b->quiet) { 10863 printf( 10864 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", 10865 secondvertex[0], secondvertex[1]); 10866 } 10867 setvertextype(secondvertex, UNDEADVERTEX); 10868 m->undeads++; 10869 } 10870 } while ((firstvertex[0] == secondvertex[0]) && 10871 (firstvertex[1] == secondvertex[1])); 10872 setorg(lefttri, firstvertex); 10873 setdest(lefttri, secondvertex); 10874 setorg(righttri, secondvertex); 10875 setdest(righttri, firstvertex); 10876 lprev(lefttri, bottommost); 10877 lastvertex = secondvertex; 10878 while (heapsize > 0) { 10879 nextevent = eventheap[0]; 10880 eventheapdelete(eventheap, heapsize, 0); 10881 heapsize--; 10882 check4events = 1; 10883 if (nextevent->xkey < m->xmin) { 10884 decode(nextevent->eventptr, fliptri); 10885 oprev(fliptri, farlefttri); 10886 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize); 10887 onext(fliptri, farrighttri); 10888 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize); 10889 10890 if (otriequal(farlefttri, bottommost)) { 10891 lprev(fliptri, bottommost); 10892 } 10893 flip(m, b, &fliptri); 10894 setapex(fliptri, NULL); 10895 lprev(fliptri, lefttri); 10896 lnext(fliptri, righttri); 10897 sym(lefttri, farlefttri); 10898 10899 if (randomnation(SAMPLERATE) == 0) { 10900 symself(fliptri); 10901 dest(fliptri, leftvertex); 10902 apex(fliptri, midvertex); 10903 org(fliptri, rightvertex); 10904 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex, 10905 midvertex, rightvertex, nextevent->ykey); 10906 } 10907 } else { 10908 nextvertex = (vertex) nextevent->eventptr; 10909 if ((nextvertex[0] == lastvertex[0]) && 10910 (nextvertex[1] == lastvertex[1])) { 10911 if (!b->quiet) { 10912 printf( 10913 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n", 10914 nextvertex[0], nextvertex[1]); 10915 } 10916 setvertextype(nextvertex, UNDEADVERTEX); 10917 m->undeads++; 10918 check4events = 0; 10919 } else { 10920 lastvertex = nextvertex; 10921 10922 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex, 10923 &searchtri, &farrightflag); 10924 /* 10925 otricopy(bottommost, searchtri); 10926 farrightflag = 0; 10927 while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) { 10928 onextself(searchtri); 10929 farrightflag = otriequal(searchtri, bottommost); 10930 } 10931 */ 10932 10933 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize); 10934 10935 otricopy(searchtri, farrighttri); 10936 sym(searchtri, farlefttri); 10937 maketriangle(m, b, &lefttri); 10938 maketriangle(m, b, &righttri); 10939 dest(farrighttri, connectvertex); 10940 setorg(lefttri, connectvertex); 10941 setdest(lefttri, nextvertex); 10942 setorg(righttri, nextvertex); 10943 setdest(righttri, connectvertex); 10944 bond(lefttri, righttri); 10945 lnextself(lefttri); 10946 lprevself(righttri); 10947 bond(lefttri, righttri); 10948 lnextself(lefttri); 10949 lprevself(righttri); 10950 bond(lefttri, farlefttri); 10951 bond(righttri, farrighttri); 10952 if (!farrightflag && otriequal(farrighttri, bottommost)) { 10953 otricopy(lefttri, bottommost); 10954 } 10955 10956 if (randomnation(SAMPLERATE) == 0) { 10957 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex); 10958 } else if (randomnation(SAMPLERATE) == 0) { 10959 lnext(righttri, inserttri); 10960 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex); 10961 } 10962 } 10963 } 10964 nextevent->eventptr = (VOID *) freeevents; 10965 freeevents = nextevent; 10966 10967 if (check4events) { 10968 apex(farlefttri, leftvertex); 10969 dest(lefttri, midvertex); 10970 apex(lefttri, rightvertex); 10971 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex); 10972 if (lefttest > 0.0) { 10973 newevent = freeevents; 10974 freeevents = (struct event *) freeevents->eventptr; 10975 newevent->xkey = m->xminextreme; 10976 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex, 10977 lefttest); 10978 newevent->eventptr = (VOID *) encode(lefttri); 10979 eventheapinsert(eventheap, heapsize, newevent); 10980 heapsize++; 10981 setorg(lefttri, newevent); 10982 } 10983 apex(righttri, leftvertex); 10984 org(righttri, midvertex); 10985 apex(farrighttri, rightvertex); 10986 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex); 10987 if (righttest > 0.0) { 10988 newevent = freeevents; 10989 freeevents = (struct event *) freeevents->eventptr; 10990 newevent->xkey = m->xminextreme; 10991 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex, 10992 righttest); 10993 newevent->eventptr = (VOID *) encode(farrighttri); 10994 eventheapinsert(eventheap, heapsize, newevent); 10995 heapsize++; 10996 setorg(farrighttri, newevent); 10997 } 10998 } 10999 } 11000 11001 pooldeinit(&m->splaynodes); 11002 lprevself(bottommost); 11003 return removeghosts(m, b, &bottommost); 11004 } 11005 11006 #endif /* not REDUCED */ 11007 11010 /********* Sweepline Delaunay triangulation ends here *********/ 11011 11012 /********* General mesh construction routines begin here *********/ 11016 /*****************************************************************************/ 11017 /* */ 11018 /* delaunay() Form a Delaunay triangulation. */ 11019 /* */ 11020 /*****************************************************************************/ 11021 11022 #ifdef ANSI_DECLARATORS 11023 long delaunay(struct mesh *m, struct behavior *b) 11024 #else /* not ANSI_DECLARATORS */ 11025 long delaunay(m, b) 11026 struct mesh *m; 11027 struct behavior *b; 11028 #endif /* not ANSI_DECLARATORS */ 11029 11030 { 11031 long hulledges; 11032 11033 m->eextras = 0; 11034 initializetrisubpools(m, b); 11035 11036 #ifdef REDUCED 11037 if (!b->quiet) { 11038 printf( 11039 "Constructing Delaunay triangulation by divide-and-conquer method.\n"); 11040 } 11041 hulledges = divconqdelaunay(m, b); 11042 #else /* not REDUCED */ 11043 if (!b->quiet) { 11044 printf("Constructing Delaunay triangulation "); 11045 if (b->incremental) { 11046 printf("by incremental method.\n"); 11047 } else if (b->sweepline) { 11048 printf("by sweepline method.\n"); 11049 } else { 11050 printf("by divide-and-conquer method.\n"); 11051 } 11052 } 11053 if (b->incremental) { 11054 hulledges = incrementaldelaunay(m, b); 11055 } else if (b->sweepline) { 11056 hulledges = sweeplinedelaunay(m, b); 11057 } else { 11058 hulledges = divconqdelaunay(m, b); 11059 } 11060 #endif /* not REDUCED */ 11061 11062 if (m->triangles.items == 0) { 11063 /* The input vertices were all collinear, so there are no triangles. */ 11064 return 0l; 11065 } else { 11066 return hulledges; 11067 } 11068 } 11069 11070 /*****************************************************************************/ 11071 /* */ 11072 /* reconstruct() Reconstruct a triangulation from its .ele (and possibly */ 11073 /* .poly) file. Used when the -r switch is used. */ 11074 /* */ 11075 /* Reads an .ele file and reconstructs the original mesh. If the -p switch */ 11076 /* is used, this procedure will also read a .poly file and reconstruct the */ 11077 /* subsegments of the original mesh. If the -a switch is used, this */ 11078 /* procedure will also read an .area file and set a maximum area constraint */ 11079 /* on each triangle. */ 11080 /* */ 11081 /* Vertices that are not corners of triangles, such as nodes on edges of */ 11082 /* subparametric elements, are discarded. */ 11083 /* */ 11084 /* This routine finds the adjacencies between triangles (and subsegments) */ 11085 /* by forming one stack of triangles for each vertex. Each triangle is on */ 11086 /* three different stacks simultaneously. Each triangle's subsegment */ 11087 /* pointers are used to link the items in each stack. This memory-saving */ 11088 /* feature makes the code harder to read. The most important thing to keep */ 11089 /* in mind is that each triangle is removed from a stack precisely when */ 11090 /* the corresponding pointer is adjusted to refer to a subsegment rather */ 11091 /* than the next triangle of the stack. */ 11092 /* */ 11093 /*****************************************************************************/ 11094 11095 #ifndef CDT_ONLY 11096 11097 #ifdef TRILIBRARY 11098 11099 #ifdef ANSI_DECLARATORS 11100 int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist, 11101 REAL *triangleattriblist, REAL *trianglearealist, 11102 int elements, int corners, int attribs, 11103 int *segmentlist,int *segmentmarkerlist, int numberofsegments) 11104 #else /* not ANSI_DECLARATORS */ 11105 int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist, 11106 elements, corners, attribs, segmentlist, segmentmarkerlist, 11107 numberofsegments) 11108 struct mesh *m; 11109 struct behavior *b; 11110 int *trianglelist; 11111 REAL *triangleattriblist; 11112 REAL *trianglearealist; 11113 int elements; 11114 int corners; 11115 int attribs; 11116 int *segmentlist; 11117 int *segmentmarkerlist; 11118 int numberofsegments; 11119 #endif /* not ANSI_DECLARATORS */ 11120 11121 #else /* not TRILIBRARY */ 11122 11123 #ifdef ANSI_DECLARATORS 11124 long reconstruct(struct mesh *m, struct behavior *b, char *elefilename, 11125 char *areafilename, char* polyfilename, FILE* polyfile) 11126 #else /* not ANSI_DECLARATORS */ 11127 long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile) 11128 struct mesh *m; 11129 struct behavior *b; 11130 char *elefilename; 11131 char *areafilename; 11132 char* polyfilename; 11133 FILE* polyfile; 11134 #endif /* not ANSI_DECLARATORS */ 11135 11136 #endif /* not TRILIBRARY */ 11137 11138 { 11139 #ifdef TRILIBRARY 11140 int vertexindex; 11141 int attribindex; 11142 #else /* not TRILIBRARY */ 11143 FILE *elefile; 11144 FILE *areafile; 11145 char inputline[INPUTLINESIZE]; 11146 char *stringptr; 11147 int areaelements; 11148 #endif /* not TRILIBRARY */ 11149 struct otri triangleloop; 11150 struct otri triangleleft; 11151 struct otri checktri; 11152 struct otri checkleft; 11153 struct otri checkneighbor; 11154 struct osub subsegloop; 11155 triangle *vertexarray; 11156 triangle* prevlink; 11157 triangle nexttri; 11158 vertex tdest, tapex; 11159 vertex checkdest, checkapex; 11160 vertex shorg; 11161 vertex killvertex; 11162 vertex segmentorg, segmentdest; 11163 REAL area; 11164 int corner[3]; 11165 int end[2]; 11166 int killvertexindex; 11167 int incorners; 11168 int segmentmarkers; 11169 int boundmarker; 11170 int aroundvertex; 11171 long hullsize; 11172 int notfound; 11173 long elementnumber, segmentnumber; 11174 int i, j; 11175 triangle ptr; /* Temporary variable used by sym(). */ 11176 11177 #ifdef TRILIBRARY 11178 m->inelements = elements; 11179 incorners = corners; 11180 if (incorners < 3) { 11181 printf("Error: Triangles must have at least 3 vertices.\n"); 11182 triexit(1); 11183 } 11184 m->eextras = attribs; 11185 #else /* not TRILIBRARY */ 11186 /* Read the triangles from an .ele file. */ 11187 if (!b->quiet) { 11188 printf("Opening %s.\n", elefilename); 11189 } 11190 elefile = fopen(elefilename, "r"); 11191 if (elefile == (FILE *) NULL) { 11192 printf(" Error: Cannot access file %s.\n", elefilename); 11193 triexit(1); 11194 } 11195 /* Read number of triangles, number of vertices per triangle, and */ 11196 /* number of triangle attributes from .ele file. */ 11197 stringptr = readline(inputline, elefile, elefilename); 11198 m->inelements = (int) strtol(stringptr, &stringptr, 0); 11199 stringptr = findfield(stringptr); 11200 if (*stringptr == '\0') { 11201 incorners = 3; 11202 } else { 11203 incorners = (int) strtol(stringptr, &stringptr, 0); 11204 if (incorners < 3) { 11205 printf("Error: Triangles in %s must have at least 3 vertices.\n", 11206 elefilename); 11207 triexit(1); 11208 } 11209 } 11210 stringptr = findfield(stringptr); 11211 if (*stringptr == '\0') { 11212 m->eextras = 0; 11213 } else { 11214 m->eextras = (int) strtol(stringptr, &stringptr, 0); 11215 } 11216 #endif /* not TRILIBRARY */ 11217 11218 initializetrisubpools(m, b); 11219 11220 /* Create the triangles. */ 11221 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) { 11222 maketriangle(m, b, &triangleloop); 11223 /* Mark the triangle as living. */ 11224 triangleloop.tri[3] = (triangle) triangleloop.tri; 11225 } 11226 11227 segmentmarkers = 0; 11228 if (b->poly) { 11229 #ifdef TRILIBRARY 11230 m->insegments = numberofsegments; 11231 segmentmarkers = segmentmarkerlist != (int *) NULL; 11232 #else /* not TRILIBRARY */ 11233 /* Read number of segments and number of segment */ 11234 /* boundary markers from .poly file. */ 11235 stringptr = readline(inputline, polyfile, b->inpolyfilename); 11236 m->insegments = (int) strtol(stringptr, &stringptr, 0); 11237 stringptr = findfield(stringptr); 11238 if (*stringptr != '\0') { 11239 segmentmarkers = (int) strtol(stringptr, &stringptr, 0); 11240 } 11241 #endif /* not TRILIBRARY */ 11242 11243 /* Create the subsegments. */ 11244 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) { 11245 makesubseg(m, &subsegloop); 11246 /* Mark the subsegment as living. */ 11247 subsegloop.ss[2] = (subseg) subsegloop.ss; 11248 } 11249 } 11250 11251 #ifdef TRILIBRARY 11252 vertexindex = 0; 11253 attribindex = 0; 11254 #else /* not TRILIBRARY */ 11255 if (b->vararea) { 11256 /* Open an .area file, check for consistency with the .ele file. */ 11257 if (!b->quiet) { 11258 printf("Opening %s.\n", areafilename); 11259 } 11260 areafile = fopen(areafilename, "r"); 11261 if (areafile == (FILE *) NULL) { 11262 printf(" Error: Cannot access file %s.\n", areafilename); 11263 triexit(1); 11264 } 11265 stringptr = readline(inputline, areafile, areafilename); 11266 areaelements = (int) strtol(stringptr, &stringptr, 0); 11267 if (areaelements != m->inelements) { 11268 printf("Error: %s and %s disagree on number of triangles.\n", 11269 elefilename, areafilename); 11270 triexit(1); 11271 } 11272 } 11273 #endif /* not TRILIBRARY */ 11274 11275 if (!b->quiet) { 11276 printf("Reconstructing mesh.\n"); 11277 } 11278 /* Allocate a temporary array that maps each vertex to some adjacent */ 11279 /* triangle. I took care to allocate all the permanent memory for */ 11280 /* triangles and subsegments first. */ 11281 vertexarray = (triangle *) trimalloc(m->vertices.items * 11282 (int) sizeof(triangle)); 11283 /* Each vertex is initially unrepresented. */ 11284 for (i = 0; i < m->vertices.items; i++) { 11285 vertexarray[i] = (triangle) m->dummytri; 11286 } 11287 11288 if (b->verbose) { 11289 printf(" Assembling triangles.\n"); 11290 } 11291 /* Read the triangles from the .ele file, and link */ 11292 /* together those that share an edge. */ 11293 traversalinit(&m->triangles); 11294 triangleloop.tri = triangletraverse(m); 11295 elementnumber = b->firstnumber; 11296 while (triangleloop.tri != (triangle *) NULL) { 11297 #ifdef TRILIBRARY 11298 /* Copy the triangle's three corners. */ 11299 for (j = 0; j < 3; j++) { 11300 corner[j] = trianglelist[vertexindex++]; 11301 if ((corner[j] < b->firstnumber) || 11302 (corner[j] >= b->firstnumber + m->invertices)) { 11303 printf("Error: Triangle %ld has an invalid vertex index.\n", 11304 elementnumber); 11305 triexit(1); 11306 } 11307 } 11308 #else /* not TRILIBRARY */ 11309 /* Read triangle number and the triangle's three corners. */ 11310 stringptr = readline(inputline, elefile, elefilename); 11311 for (j = 0; j < 3; j++) { 11312 stringptr = findfield(stringptr); 11313 if (*stringptr == '\0') { 11314 printf("Error: Triangle %ld is missing vertex %d in %s.\n", 11315 elementnumber, j + 1, elefilename); 11316 triexit(1); 11317 } else { 11318 corner[j] = (int) strtol(stringptr, &stringptr, 0); 11319 if ((corner[j] < b->firstnumber) || 11320 (corner[j] >= b->firstnumber + m->invertices)) { 11321 printf("Error: Triangle %ld has an invalid vertex index.\n", 11322 elementnumber); 11323 triexit(1); 11324 } 11325 } 11326 } 11327 #endif /* not TRILIBRARY */ 11328 11329 /* Find out about (and throw away) extra nodes. */ 11330 for (j = 3; j < incorners; j++) { 11331 #ifdef TRILIBRARY 11332 killvertexindex = trianglelist[vertexindex++]; 11333 #else /* not TRILIBRARY */ 11334 stringptr = findfield(stringptr); 11335 if (*stringptr != '\0') { 11336 killvertexindex = (int) strtol(stringptr, &stringptr, 0); 11337 #endif /* not TRILIBRARY */ 11338 if ((killvertexindex >= b->firstnumber) && 11339 (killvertexindex < b->firstnumber + m->invertices)) { 11340 /* Delete the non-corner vertex if it's not already deleted. */ 11341 killvertex = getvertex(m, b, killvertexindex); 11342 if (vertextype(killvertex) != DEADVERTEX) { 11343 vertexdealloc(m, killvertex); 11344 } 11345 } 11346 #ifndef TRILIBRARY 11347 } 11348 #endif /* not TRILIBRARY */ 11349 } 11350 11351 /* Read the triangle's attributes. */ 11352 for (j = 0; j < m->eextras; j++) { 11353 #ifdef TRILIBRARY 11354 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]); 11355 #else /* not TRILIBRARY */ 11356 stringptr = findfield(stringptr); 11357 if (*stringptr == '\0') { 11358 setelemattribute(triangleloop, j, 0); 11359 } else { 11360 setelemattribute(triangleloop, j, 11361 (REAL) strtod(stringptr, &stringptr)); 11362 } 11363 #endif /* not TRILIBRARY */ 11364 } 11365 11366 if (b->vararea) { 11367 #ifdef TRILIBRARY 11368 area = trianglearealist[elementnumber - b->firstnumber]; 11369 #else /* not TRILIBRARY */ 11370 /* Read an area constraint from the .area file. */ 11371 stringptr = readline(inputline, areafile, areafilename); 11372 stringptr = findfield(stringptr); 11373 if (*stringptr == '\0') { 11374 area = -1.0; /* No constraint on this triangle. */ 11375 } else { 11376 area = (REAL) strtod(stringptr, &stringptr); 11377 } 11378 #endif /* not TRILIBRARY */ 11379 setareabound(triangleloop, area); 11380 } 11381 11382 /* Set the triangle's vertices. */ 11383 triangleloop.orient = 0; 11384 setorg(triangleloop, getvertex(m, b, corner[0])); 11385 setdest(triangleloop, getvertex(m, b, corner[1])); 11386 setapex(triangleloop, getvertex(m, b, corner[2])); 11387 /* Try linking the triangle to others that share these vertices. */ 11388 for (triangleloop.orient = 0; triangleloop.orient < 3; 11389 triangleloop.orient++) { 11390 /* Take the number for the origin of triangleloop. */ 11391 aroundvertex = corner[triangleloop.orient]; 11392 /* Look for other triangles having this vertex. */ 11393 nexttri = vertexarray[aroundvertex - b->firstnumber]; 11394 /* Link the current triangle to the next one in the stack. */ 11395 triangleloop.tri[6 + triangleloop.orient] = nexttri; 11396 /* Push the current triangle onto the stack. */ 11397 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop); 11398 decode(nexttri, checktri); 11399 if (checktri.tri != m->dummytri) { 11400 dest(triangleloop, tdest); 11401 apex(triangleloop, tapex); 11402 /* Look for other triangles that share an edge. */ 11403 do { 11404 dest(checktri, checkdest); 11405 apex(checktri, checkapex); 11406 if (tapex == checkdest) { 11407 /* The two triangles share an edge; bond them together. */ 11408 lprev(triangleloop, triangleleft); 11409 bond(triangleleft, checktri); 11410 } 11411 if (tdest == checkapex) { 11412 /* The two triangles share an edge; bond them together. */ 11413 lprev(checktri, checkleft); 11414 bond(triangleloop, checkleft); 11415 } 11416 /* Find the next triangle in the stack. */ 11417 nexttri = checktri.tri[6 + checktri.orient]; 11418 decode(nexttri, checktri); 11419 } while (checktri.tri != m->dummytri); 11420 } 11421 } 11422 triangleloop.tri = triangletraverse(m); 11423 elementnumber++; 11424 } 11425 11426 #ifdef TRILIBRARY 11427 vertexindex = 0; 11428 #else /* not TRILIBRARY */ 11429 fclose(elefile); 11430 if (b->vararea) { 11431 fclose(areafile); 11432 } 11433 #endif /* not TRILIBRARY */ 11434 11435 hullsize = 0; /* Prepare to count the boundary edges. */ 11436 if (b->poly) { 11437 if (b->verbose) { 11438 printf(" Marking segments in triangulation.\n"); 11439 } 11440 /* Read the segments from the .poly file, and link them */ 11441 /* to their neighboring triangles. */ 11442 boundmarker = 0; 11443 traversalinit(&m->subsegs); 11444 subsegloop.ss = subsegtraverse(m); 11445 segmentnumber = b->firstnumber; 11446 while (subsegloop.ss != (subseg *) NULL) { 11447 #ifdef TRILIBRARY 11448 end[0] = segmentlist[vertexindex++]; 11449 end[1] = segmentlist[vertexindex++]; 11450 if (segmentmarkers) { 11451 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber]; 11452 } 11453 #else /* not TRILIBRARY */ 11454 /* Read the endpoints of each segment, and possibly a boundary marker. */ 11455 stringptr = readline(inputline, polyfile, b->inpolyfilename); 11456 /* Skip the first (segment number) field. */ 11457 stringptr = findfield(stringptr); 11458 if (*stringptr == '\0') { 11459 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber, 11460 polyfilename); 11461 triexit(1); 11462 } else { 11463 end[0] = (int) strtol(stringptr, &stringptr, 0); 11464 } 11465 stringptr = findfield(stringptr); 11466 if (*stringptr == '\0') { 11467 printf("Error: Segment %ld is missing its second endpoint in %s.\n", 11468 segmentnumber, polyfilename); 11469 triexit(1); 11470 } else { 11471 end[1] = (int) strtol(stringptr, &stringptr, 0); 11472 } 11473 if (segmentmarkers) { 11474 stringptr = findfield(stringptr); 11475 if (*stringptr == '\0') { 11476 boundmarker = 0; 11477 } else { 11478 boundmarker = (int) strtol(stringptr, &stringptr, 0); 11479 } 11480 } 11481 #endif /* not TRILIBRARY */ 11482 for (j = 0; j < 2; j++) { 11483 if ((end[j] < b->firstnumber) || 11484 (end[j] >= b->firstnumber + m->invertices)) { 11485 printf("Error: Segment %ld has an invalid vertex index.\n", 11486 segmentnumber); 11487 triexit(1); 11488 } 11489 } 11490 11491 /* set the subsegment's vertices. */ 11492 subsegloop.ssorient = 0; 11493 segmentorg = getvertex(m, b, end[0]); 11494 segmentdest = getvertex(m, b, end[1]); 11495 setsorg(subsegloop, segmentorg); 11496 setsdest(subsegloop, segmentdest); 11497 setsegorg(subsegloop, segmentorg); 11498 setsegdest(subsegloop, segmentdest); 11499 setmark(subsegloop, boundmarker); 11500 /* Try linking the subsegment to triangles that share these vertices. */ 11501 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2; 11502 subsegloop.ssorient++) { 11503 /* Take the number for the destination of subsegloop. */ 11504 aroundvertex = end[1 - subsegloop.ssorient]; 11505 /* Look for triangles having this vertex. */ 11506 prevlink = &vertexarray[aroundvertex - b->firstnumber]; 11507 nexttri = vertexarray[aroundvertex - b->firstnumber]; 11508 decode(nexttri, checktri); 11509 sorg(subsegloop, shorg); 11510 notfound = 1; 11511 /* Look for triangles having this edge. Note that I'm only */ 11512 /* comparing each triangle's destination with the subsegment; */ 11513 /* each triangle's apex is handled through a different vertex. */ 11514 /* Because each triangle appears on three vertices' lists, each */ 11515 /* occurrence of a triangle on a list can (and does) represent */ 11516 /* an edge. In this way, most edges are represented twice, and */ 11517 /* every triangle-subsegment bond is represented once. */ 11518 while (notfound && (checktri.tri != m->dummytri)) { 11519 dest(checktri, checkdest); 11520 if (shorg == checkdest) { 11521 /* We have a match. Remove this triangle from the list. */ 11522 * prevlink = checktri.tri[6 + checktri.orient]; 11523 /* Bond the subsegment to the triangle. */ 11524 tsbond(checktri, subsegloop); 11525 /* Check if this is a boundary edge. */ 11526 sym(checktri, checkneighbor); 11527 if (checkneighbor.tri == m->dummytri) { 11528 /* The next line doesn't insert a subsegment (because there's */ 11529 /* already one there), but it sets the boundary markers of */ 11530 /* the existing subsegment and its vertices. */ 11531 insertsubseg(m, b, &checktri, 1); 11532 hullsize++; 11533 } 11534 notfound = 0; 11535 } 11536 /* Find the next triangle in the stack. */ 11537 prevlink = &checktri.tri[6 + checktri.orient]; 11538 nexttri = checktri.tri[6 + checktri.orient]; 11539 decode(nexttri, checktri); 11540 } 11541 } 11542 subsegloop.ss = subsegtraverse(m); 11543 segmentnumber++; 11544 } 11545 } 11546 11547 /* Mark the remaining edges as not being attached to any subsegment. */ 11548 /* Also, count the (yet uncounted) boundary edges. */ 11549 for (i = 0; i < m->vertices.items; i++) { 11550 /* Search the stack of triangles adjacent to a vertex. */ 11551 nexttri = vertexarray[i]; 11552 decode(nexttri, checktri); 11553 while (checktri.tri != m->dummytri) { 11554 /* Find the next triangle in the stack before this */ 11555 /* information gets overwritten. */ 11556 nexttri = checktri.tri[6 + checktri.orient]; 11557 /* No adjacent subsegment. (This overwrites the stack info.) */ 11558 tsdissolve(checktri); 11559 sym(checktri, checkneighbor); 11560 if (checkneighbor.tri == m->dummytri) { 11561 insertsubseg(m, b, &checktri, 1); 11562 hullsize++; 11563 } 11564 decode(nexttri, checktri); 11565 } 11566 } 11567 11568 trifree((VOID *) vertexarray); 11569 return hullsize; 11570 } 11571 11572 #endif /* not CDT_ONLY */ 11573 11576 /********* General mesh construction routines end here *********/ 11577 11578 /********* Segment insertion begins here *********/ 11582 /*****************************************************************************/ 11583 /* */ 11584 /* finddirection() Find the first triangle on the path from one point */ 11585 /* to another. */ 11586 /* */ 11587 /* Finds the triangle that intersects a line segment drawn from the */ 11588 /* origin of `searchtri' to the point `searchpoint', and returns the result */ 11589 /* in `searchtri'. The origin of `searchtri' does not change, even though */ 11590 /* the triangle returned may differ from the one passed in. This routine */ 11591 /* is used to find the direction to move in to get from one point to */ 11592 /* another. */ 11593 /* */ 11594 /* The return value notes whether the destination or apex of the found */ 11595 /* triangle is collinear with the two points in question. */ 11596 /* */ 11597 /*****************************************************************************/ 11598 11599 #ifdef ANSI_DECLARATORS 11600 enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, 11601 struct otri *searchtri, 11602 vertex searchpoint) 11603 #else /* not ANSI_DECLARATORS */ 11604 enum finddirectionresult finddirection(m, b, searchtri, searchpoint) 11605 struct mesh *m; 11606 struct behavior *b; 11607 struct otri *searchtri; 11608 vertex searchpoint; 11609 #endif /* not ANSI_DECLARATORS */ 11610 11611 { 11612 struct otri checktri; 11613 vertex startvertex; 11614 vertex leftvertex, rightvertex; 11615 REAL leftccw, rightccw; 11616 int leftflag, rightflag; 11617 triangle ptr; /* Temporary variable used by onext() and oprev(). */ 11618 11619 org(*searchtri, startvertex); 11620 dest(*searchtri, rightvertex); 11621 apex(*searchtri, leftvertex); 11622 /* Is `searchpoint' to the left? */ 11623 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex); 11624 leftflag = leftccw > 0.0; 11625 /* Is `searchpoint' to the right? */ 11626 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex); 11627 rightflag = rightccw > 0.0; 11628 if (leftflag && rightflag) { 11629 /* `searchtri' faces directly away from `searchpoint'. We could go left */ 11630 /* or right. Ask whether it's a triangle or a boundary on the left. */ 11631 onext(*searchtri, checktri); 11632 if (checktri.tri == m->dummytri) { 11633 leftflag = 0; 11634 } else { 11635 rightflag = 0; 11636 } 11637 } 11638 while (leftflag) { 11639 /* Turn left until satisfied. */ 11640 onextself(*searchtri); 11641 if (searchtri->tri == m->dummytri) { 11642 printf("Internal error in finddirection(): Unable to find a\n"); 11643 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0], 11644 startvertex[1]); 11645 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]); 11646 internalerror(); 11647 } 11648 apex(*searchtri, leftvertex); 11649 rightccw = leftccw; 11650 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex); 11651 leftflag = leftccw > 0.0; 11652 } 11653 while (rightflag) { 11654 /* Turn right until satisfied. */ 11655 oprevself(*searchtri); 11656 if (searchtri->tri == m->dummytri) { 11657 printf("Internal error in finddirection(): Unable to find a\n"); 11658 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0], 11659 startvertex[1]); 11660 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]); 11661 internalerror(); 11662 } 11663 dest(*searchtri, rightvertex); 11664 leftccw = rightccw; 11665 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex); 11666 rightflag = rightccw > 0.0; 11667 } 11668 if (leftccw == 0.0) { 11669 return LEFTCOLLINEAR; 11670 } else if (rightccw == 0.0) { 11671 return RIGHTCOLLINEAR; 11672 } else { 11673 return WITHIN; 11674 } 11675 } 11676 11677 /*****************************************************************************/ 11678 /* */ 11679 /* segmentintersection() Find the intersection of an existing segment */ 11680 /* and a segment that is being inserted. Insert */ 11681 /* a vertex at the intersection, splitting an */ 11682 /* existing subsegment. */ 11683 /* */ 11684 /* The segment being inserted connects the apex of splittri to endpoint2. */ 11685 /* splitsubseg is the subsegment being split, and MUST adjoin splittri. */ 11686 /* Hence, endpoints of the subsegment being split are the origin and */ 11687 /* destination of splittri. */ 11688 /* */ 11689 /* On completion, splittri is a handle having the newly inserted */ 11690 /* intersection point as its origin, and endpoint1 as its destination. */ 11691 /* */ 11692 /*****************************************************************************/ 11693 11694 #ifdef ANSI_DECLARATORS 11695 void segmentintersection(struct mesh *m, struct behavior *b, 11696 struct otri *splittri, struct osub *splitsubseg, 11697 vertex endpoint2) 11698 #else /* not ANSI_DECLARATORS */ 11699 void segmentintersection(m, b, splittri, splitsubseg, endpoint2) 11700 struct mesh *m; 11701 struct behavior *b; 11702 struct otri *splittri; 11703 struct osub *splitsubseg; 11704 vertex endpoint2; 11705 #endif /* not ANSI_DECLARATORS */ 11706 11707 { 11708 struct osub opposubseg; 11709 vertex endpoint1; 11710 vertex torg, tdest; 11711 vertex leftvertex, rightvertex; 11712 vertex newvertex; 11713 enum insertvertexresult success; 11714 //enum finddirectionresult collinear; // commented out to get gcc4.6 working 11715 REAL ex, ey; 11716 REAL tx, ty; 11717 REAL etx, ety; 11718 REAL split, denom; 11719 int i; 11720 triangle ptr; /* Temporary variable used by onext(). */ 11721 subseg sptr; /* Temporary variable used by snext(). */ 11722 11723 /* Find the other three segment endpoints. */ 11724 apex(*splittri, endpoint1); 11725 org(*splittri, torg); 11726 dest(*splittri, tdest); 11727 /* Segment intersection formulae; see the Antonio reference. */ 11728 tx = tdest[0] - torg[0]; 11729 ty = tdest[1] - torg[1]; 11730 ex = endpoint2[0] - endpoint1[0]; 11731 ey = endpoint2[1] - endpoint1[1]; 11732 etx = torg[0] - endpoint2[0]; 11733 ety = torg[1] - endpoint2[1]; 11734 denom = ty * ex - tx * ey; 11735 if (denom == 0.0) { 11736 printf("Internal error in segmentintersection():"); 11737 printf(" Attempt to find intersection of parallel segments.\n"); 11738 internalerror(); 11739 } 11740 split = (ey * etx - ex * ety) / denom; 11741 /* Create the new vertex. */ 11742 newvertex = (vertex) poolalloc(&m->vertices); 11743 /* Interpolate its coordinate and attributes. */ 11744 for (i = 0; i < 2 + m->nextras; i++) { 11745 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]); 11746 } 11747 setvertexmark(newvertex, mark(*splitsubseg)); 11748 setvertextype(newvertex, INPUTVERTEX); 11749 if (b->verbose > 1) { 11750 printf( 11751 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", 11752 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]); 11753 } 11754 /* Insert the intersection vertex. This should always succeed. */ 11755 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0); 11756 if (success != SUCCESSFULVERTEX) { 11757 printf("Internal error in segmentintersection():\n"); 11758 printf(" Failure to split a segment.\n"); 11759 internalerror(); 11760 } 11761 /* Record a triangle whose origin is the new vertex. */ 11762 setvertex2tri(newvertex, encode(*splittri)); 11763 if (m->steinerleft > 0) { 11764 m->steinerleft--; 11765 } 11766 11767 /* Divide the segment into two, and correct the segment endpoints. */ 11768 ssymself(*splitsubseg); 11769 spivot(*splitsubseg, opposubseg); 11770 sdissolve(*splitsubseg); 11771 sdissolve(opposubseg); 11772 do { 11773 setsegorg(*splitsubseg, newvertex); 11774 snextself(*splitsubseg); 11775 } while (splitsubseg->ss != m->dummysub); 11776 do { 11777 setsegorg(opposubseg, newvertex); 11778 snextself(opposubseg); 11779 } while (opposubseg.ss != m->dummysub); 11780 11781 /* Inserting the vertex may have caused edge flips. We wish to rediscover */ 11782 /* the edge connecting endpoint1 to the new intersection vertex. */ 11783 finddirection(m, b, splittri, endpoint1); // "collinear =" commented out to get gcc4.6 working 11784 dest(*splittri, rightvertex); 11785 apex(*splittri, leftvertex); 11786 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) { 11787 onextself(*splittri); 11788 } else if ((rightvertex[0] != endpoint1[0]) || 11789 (rightvertex[1] != endpoint1[1])) { 11790 printf("Internal error in segmentintersection():\n"); 11791 printf(" Topological inconsistency after splitting a segment.\n"); 11792 internalerror(); 11793 } 11794 /* `splittri' should have destination endpoint1. */ 11795 } 11796 11797 /*****************************************************************************/ 11798 /* */ 11799 /* scoutsegment() Scout the first triangle on the path from one endpoint */ 11800 /* to another, and check for completion (reaching the */ 11801 /* second endpoint), a collinear vertex, or the */ 11802 /* intersection of two segments. */ 11803 /* */ 11804 /* Returns one if the entire segment is successfully inserted, and zero if */ 11805 /* the job must be finished by conformingedge() or constrainededge(). */ 11806 /* */ 11807 /* If the first triangle on the path has the second endpoint as its */ 11808 /* destination or apex, a subsegment is inserted and the job is done. */ 11809 /* */ 11810 /* If the first triangle on the path has a destination or apex that lies on */ 11811 /* the segment, a subsegment is inserted connecting the first endpoint to */ 11812 /* the collinear vertex, and the search is continued from the collinear */ 11813 /* vertex. */ 11814 /* */ 11815 /* If the first triangle on the path has a subsegment opposite its origin, */ 11816 /* then there is a segment that intersects the segment being inserted. */ 11817 /* Their intersection vertex is inserted, splitting the subsegment. */ 11818 /* */ 11819 /*****************************************************************************/ 11820 11821 #ifdef ANSI_DECLARATORS 11822 int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, 11823 vertex endpoint2, int newmark) 11824 #else /* not ANSI_DECLARATORS */ 11825 int scoutsegment(m, b, searchtri, endpoint2, newmark) 11826 struct mesh *m; 11827 struct behavior *b; 11828 struct otri *searchtri; 11829 vertex endpoint2; 11830 int newmark; 11831 #endif /* not ANSI_DECLARATORS */ 11832 11833 { 11834 struct otri crosstri; 11835 struct osub crosssubseg; 11836 vertex leftvertex, rightvertex; 11837 enum finddirectionresult collinear; 11838 subseg sptr; /* Temporary variable used by tspivot(). */ 11839 11840 collinear = finddirection(m, b, searchtri, endpoint2); 11841 dest(*searchtri, rightvertex); 11842 apex(*searchtri, leftvertex); 11843 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) || 11844 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) { 11845 /* The segment is already an edge in the mesh. */ 11846 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) { 11847 lprevself(*searchtri); 11848 } 11849 /* Insert a subsegment, if there isn't already one there. */ 11850 insertsubseg(m, b, searchtri, newmark); 11851 return 1; 11852 } else if (collinear == LEFTCOLLINEAR) { 11853 /* We've collided with a vertex between the segment's endpoints. */ 11854 /* Make the collinear vertex be the triangle's origin. */ 11855 lprevself(*searchtri); 11856 insertsubseg(m, b, searchtri, newmark); 11857 /* Insert the remainder of the segment. */ 11858 return scoutsegment(m, b, searchtri, endpoint2, newmark); 11859 } else if (collinear == RIGHTCOLLINEAR) { 11860 /* We've collided with a vertex between the segment's endpoints. */ 11861 insertsubseg(m, b, searchtri, newmark); 11862 /* Make the collinear vertex be the triangle's origin. */ 11863 lnextself(*searchtri); 11864 /* Insert the remainder of the segment. */ 11865 return scoutsegment(m, b, searchtri, endpoint2, newmark); 11866 } else { 11867 lnext(*searchtri, crosstri); 11868 tspivot(crosstri, crosssubseg); 11869 /* Check for a crossing segment. */ 11870 if (crosssubseg.ss == m->dummysub) { 11871 return 0; 11872 } else { 11873 /* Insert a vertex at the intersection. */ 11874 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2); 11875 otricopy(crosstri, *searchtri); 11876 insertsubseg(m, b, searchtri, newmark); 11877 /* Insert the remainder of the segment. */ 11878 return scoutsegment(m, b, searchtri, endpoint2, newmark); 11879 } 11880 } 11881 } 11882 11883 /*****************************************************************************/ 11884 /* */ 11885 /* conformingedge() Force a segment into a conforming Delaunay */ 11886 /* triangulation by inserting a vertex at its midpoint, */ 11887 /* and recursively forcing in the two half-segments if */ 11888 /* necessary. */ 11889 /* */ 11890 /* Generates a sequence of subsegments connecting `endpoint1' to */ 11891 /* `endpoint2'. `newmark' is the boundary marker of the segment, assigned */ 11892 /* to each new splitting vertex and subsegment. */ 11893 /* */ 11894 /* Note that conformingedge() does not always maintain the conforming */ 11895 /* Delaunay property. Once inserted, segments are locked into place; */ 11896 /* vertices inserted later (to force other segments in) may render these */ 11897 /* fixed segments non-Delaunay. The conforming Delaunay property will be */ 11898 /* restored by enforcequality() by splitting encroached subsegments. */ 11899 /* */ 11900 /*****************************************************************************/ 11901 11902 #ifndef REDUCED 11903 #ifndef CDT_ONLY 11904 11905 #ifdef ANSI_DECLARATORS 11906 void conformingedge(struct mesh *m, struct behavior *b, 11907 vertex endpoint1, vertex endpoint2, int newmark) 11908 #else /* not ANSI_DECLARATORS */ 11909 void conformingedge(m, b, endpoint1, endpoint2, newmark) 11910 struct mesh *m; 11911 struct behavior *b; 11912 vertex endpoint1; 11913 vertex endpoint2; 11914 int newmark; 11915 #endif /* not ANSI_DECLARATORS */ 11916 11917 { 11918 struct otri searchtri1, searchtri2; 11919 struct osub brokensubseg; 11920 vertex newvertex; 11921 vertex midvertex1, midvertex2; 11922 enum insertvertexresult success; 11923 int i; 11924 subseg sptr; /* Temporary variable used by tspivot(). */ 11925 11926 if (b->verbose > 2) { 11927 printf("Forcing segment into triangulation by recursive splitting:\n"); 11928 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1], 11929 endpoint2[0], endpoint2[1]); 11930 } 11931 /* Create a new vertex to insert in the middle of the segment. */ 11932 newvertex = (vertex) poolalloc(&m->vertices); 11933 /* Interpolate coordinates and attributes. */ 11934 for (i = 0; i < 2 + m->nextras; i++) { 11935 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]); 11936 } 11937 setvertexmark(newvertex, newmark); 11938 setvertextype(newvertex, SEGMENTVERTEX); 11939 /* No known triangle to search from. */ 11940 searchtri1.tri = m->dummytri; 11941 /* Attempt to insert the new vertex. */ 11942 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL, 11943 0, 0); 11944 if (success == DUPLICATEVERTEX) { 11945 if (b->verbose > 2) { 11946 printf(" Segment intersects existing vertex (%.12g, %.12g).\n", 11947 newvertex[0], newvertex[1]); 11948 } 11949 /* Use the vertex that's already there. */ 11950 vertexdealloc(m, newvertex); 11951 org(searchtri1, newvertex); 11952 } else { 11953 if (success == VIOLATINGVERTEX) { 11954 if (b->verbose > 2) { 11955 printf(" Two segments intersect at (%.12g, %.12g).\n", 11956 newvertex[0], newvertex[1]); 11957 } 11958 /* By fluke, we've landed right on another segment. Split it. */ 11959 tspivot(searchtri1, brokensubseg); 11960 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg, 11961 0, 0); 11962 if (success != SUCCESSFULVERTEX) { 11963 printf("Internal error in conformingedge():\n"); 11964 printf(" Failure to split a segment.\n"); 11965 internalerror(); 11966 } 11967 } 11968 /* The vertex has been inserted successfully. */ 11969 if (m->steinerleft > 0) { 11970 m->steinerleft--; 11971 } 11972 } 11973 otricopy(searchtri1, searchtri2); 11974 /* `searchtri1' and `searchtri2' are fastened at their origins to */ 11975 /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */ 11976 /* respectively. First, we must get `searchtri2' out of the way so it */ 11977 /* won't be invalidated during the insertion of the first half of the */ 11978 /* segment. */ 11979 finddirection(m, b, &searchtri2, endpoint2); 11980 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) { 11981 /* The origin of searchtri1 may have changed if a collision with an */ 11982 /* intervening vertex on the segment occurred. */ 11983 org(searchtri1, midvertex1); 11984 conformingedge(m, b, midvertex1, endpoint1, newmark); 11985 } 11986 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) { 11987 /* The origin of searchtri2 may have changed if a collision with an */ 11988 /* intervening vertex on the segment occurred. */ 11989 org(searchtri2, midvertex2); 11990 conformingedge(m, b, midvertex2, endpoint2, newmark); 11991 } 11992 } 11993 11994 #endif /* not CDT_ONLY */ 11995 #endif /* not REDUCED */ 11996 11997 /*****************************************************************************/ 11998 /* */ 11999 /* delaunayfixup() Enforce the Delaunay condition at an edge, fanning out */ 12000 /* recursively from an existing vertex. Pay special */ 12001 /* attention to stacking inverted triangles. */ 12002 /* */ 12003 /* This is a support routine for inserting segments into a constrained */ 12004 /* Delaunay triangulation. */ 12005 /* */ 12006 /* The origin of fixuptri is treated as if it has just been inserted, and */ 12007 /* the local Delaunay condition needs to be enforced. It is only enforced */ 12008 /* in one sector, however, that being the angular range defined by */ 12009 /* fixuptri. */ 12010 /* */ 12011 /* This routine also needs to make decisions regarding the "stacking" of */ 12012 /* triangles. (Read the description of constrainededge() below before */ 12013 /* reading on here, so you understand the algorithm.) If the position of */ 12014 /* the new vertex (the origin of fixuptri) indicates that the vertex before */ 12015 /* it on the polygon is a reflex vertex, then "stack" the triangle by */ 12016 /* doing nothing. (fixuptri is an inverted triangle, which is how stacked */ 12017 /* triangles are identified.) */ 12018 /* */ 12019 /* Otherwise, check whether the vertex before that was a reflex vertex. */ 12020 /* If so, perform an edge flip, thereby eliminating an inverted triangle */ 12021 /* (popping it off the stack). The edge flip may result in the creation */ 12022 /* of a new inverted triangle, depending on whether or not the new vertex */ 12023 /* is visible to the vertex three edges behind on the polygon. */ 12024 /* */ 12025 /* If neither of the two vertices behind the new vertex are reflex */ 12026 /* vertices, fixuptri and fartri, the triangle opposite it, are not */ 12027 /* inverted; hence, ensure that the edge between them is locally Delaunay. */ 12028 /* */ 12029 /* `leftside' indicates whether or not fixuptri is to the left of the */ 12030 /* segment being inserted. (Imagine that the segment is pointing up from */ 12031 /* endpoint1 to endpoint2.) */ 12032 /* */ 12033 /*****************************************************************************/ 12034 12035 #ifdef ANSI_DECLARATORS 12036 void delaunayfixup(struct mesh *m, struct behavior *b, 12037 struct otri *fixuptri, int leftside) 12038 #else /* not ANSI_DECLARATORS */ 12039 void delaunayfixup(m, b, fixuptri, leftside) 12040 struct mesh *m; 12041 struct behavior *b; 12042 struct otri *fixuptri; 12043 int leftside; 12044 #endif /* not ANSI_DECLARATORS */ 12045 12046 { 12047 struct otri neartri; 12048 struct otri fartri; 12049 struct osub faredge; 12050 vertex nearvertex, leftvertex, rightvertex, farvertex; 12051 triangle ptr; /* Temporary variable used by sym(). */ 12052 subseg sptr; /* Temporary variable used by tspivot(). */ 12053 12054 lnext(*fixuptri, neartri); 12055 sym(neartri, fartri); 12056 /* Check if the edge opposite the origin of fixuptri can be flipped. */ 12057 if (fartri.tri == m->dummytri) { 12058 return; 12059 } 12060 tspivot(neartri, faredge); 12061 if (faredge.ss != m->dummysub) { 12062 return; 12063 } 12064 /* Find all the relevant vertices. */ 12065 apex(neartri, nearvertex); 12066 org(neartri, leftvertex); 12067 dest(neartri, rightvertex); 12068 apex(fartri, farvertex); 12069 /* Check whether the previous polygon vertex is a reflex vertex. */ 12070 if (leftside) { 12071 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) { 12072 /* leftvertex is a reflex vertex too. Nothing can */ 12073 /* be done until a convex section is found. */ 12074 return; 12075 } 12076 } else { 12077 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) { 12078 /* rightvertex is a reflex vertex too. Nothing can */ 12079 /* be done until a convex section is found. */ 12080 return; 12081 } 12082 } 12083 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) { 12084 /* fartri is not an inverted triangle, and farvertex is not a reflex */ 12085 /* vertex. As there are no reflex vertices, fixuptri isn't an */ 12086 /* inverted triangle, either. Hence, test the edge between the */ 12087 /* triangles to ensure it is locally Delaunay. */ 12088 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <= 12089 0.0) { 12090 return; 12091 } 12092 /* Not locally Delaunay; go on to an edge flip. */ 12093 } /* else fartri is inverted; remove it from the stack by flipping. */ 12094 flip(m, b, &neartri); 12095 lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */ 12096 /* Recursively process the two triangles that result from the flip. */ 12097 delaunayfixup(m, b, fixuptri, leftside); 12098 delaunayfixup(m, b, &fartri, leftside); 12099 } 12100 12101 /*****************************************************************************/ 12102 /* */ 12103 /* constrainededge() Force a segment into a constrained Delaunay */ 12104 /* triangulation by deleting the triangles it */ 12105 /* intersects, and triangulating the polygons that */ 12106 /* form on each side of it. */ 12107 /* */ 12108 /* Generates a single subsegment connecting `endpoint1' to `endpoint2'. */ 12109 /* The triangle `starttri' has `endpoint1' as its origin. `newmark' is the */ 12110 /* boundary marker of the segment. */ 12111 /* */ 12112 /* To insert a segment, every triangle whose interior intersects the */ 12113 /* segment is deleted. The union of these deleted triangles is a polygon */ 12114 /* (which is not necessarily monotone, but is close enough), which is */ 12115 /* divided into two polygons by the new segment. This routine's task is */ 12116 /* to generate the Delaunay triangulation of these two polygons. */ 12117 /* */ 12118 /* You might think of this routine's behavior as a two-step process. The */ 12119 /* first step is to walk from endpoint1 to endpoint2, flipping each edge */ 12120 /* encountered. This step creates a fan of edges connected to endpoint1, */ 12121 /* including the desired edge to endpoint2. The second step enforces the */ 12122 /* Delaunay condition on each side of the segment in an incremental manner: */ 12123 /* proceeding along the polygon from endpoint1 to endpoint2 (this is done */ 12124 /* independently on each side of the segment), each vertex is "enforced" */ 12125 /* as if it had just been inserted, but affecting only the previous */ 12126 /* vertices. The result is the same as if the vertices had been inserted */ 12127 /* in the order they appear on the polygon, so the result is Delaunay. */ 12128 /* */ 12129 /* In truth, constrainededge() interleaves these two steps. The procedure */ 12130 /* walks from endpoint1 to endpoint2, and each time an edge is encountered */ 12131 /* and flipped, the newly exposed vertex (at the far end of the flipped */ 12132 /* edge) is "enforced" upon the previously flipped edges, usually affecting */ 12133 /* only one side of the polygon (depending upon which side of the segment */ 12134 /* the vertex falls on). */ 12135 /* */ 12136 /* The algorithm is complicated by the need to handle polygons that are not */ 12137 /* convex. Although the polygon is not necessarily monotone, it can be */ 12138 /* triangulated in a manner similar to the stack-based algorithms for */ 12139 /* monotone polygons. For each reflex vertex (local concavity) of the */ 12140 /* polygon, there will be an inverted triangle formed by one of the edge */ 12141 /* flips. (An inverted triangle is one with negative area - that is, its */ 12142 /* vertices are arranged in clockwise order - and is best thought of as a */ 12143 /* wrinkle in the fabric of the mesh.) Each inverted triangle can be */ 12144 /* thought of as a reflex vertex pushed on the stack, waiting to be fixed */ 12145 /* later. */ 12146 /* */ 12147 /* A reflex vertex is popped from the stack when a vertex is inserted that */ 12148 /* is visible to the reflex vertex. (However, if the vertex behind the */ 12149 /* reflex vertex is not visible to the reflex vertex, a new inverted */ 12150 /* triangle will take its place on the stack.) These details are handled */ 12151 /* by the delaunayfixup() routine above. */ 12152 /* */ 12153 /*****************************************************************************/ 12154 12155 #ifdef ANSI_DECLARATORS 12156 void constrainededge(struct mesh *m, struct behavior *b, 12157 struct otri *starttri, vertex endpoint2, int newmark) 12158 #else /* not ANSI_DECLARATORS */ 12159 void constrainededge(m, b, starttri, endpoint2, newmark) 12160 struct mesh *m; 12161 struct behavior *b; 12162 struct otri *starttri; 12163 vertex endpoint2; 12164 int newmark; 12165 #endif /* not ANSI_DECLARATORS */ 12166 12167 { 12168 struct otri fixuptri, fixuptri2; 12169 struct osub crosssubseg; 12170 vertex endpoint1; 12171 vertex farvertex; 12172 REAL area; 12173 int collision; 12174 int done; 12175 triangle ptr; /* Temporary variable used by sym() and oprev(). */ 12176 subseg sptr; /* Temporary variable used by tspivot(). */ 12177 12178 org(*starttri, endpoint1); 12179 lnext(*starttri, fixuptri); 12180 flip(m, b, &fixuptri); 12181 /* `collision' indicates whether we have found a vertex directly */ 12182 /* between endpoint1 and endpoint2. */ 12183 collision = 0; 12184 done = 0; 12185 do { 12186 org(fixuptri, farvertex); 12187 /* `farvertex' is the extreme point of the polygon we are "digging" */ 12188 /* to get from endpoint1 to endpoint2. */ 12189 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) { 12190 oprev(fixuptri, fixuptri2); 12191 /* Enforce the Delaunay condition around endpoint2. */ 12192 delaunayfixup(m, b, &fixuptri, 0); 12193 delaunayfixup(m, b, &fixuptri2, 1); 12194 done = 1; 12195 } else { 12196 /* Check whether farvertex is to the left or right of the segment */ 12197 /* being inserted, to decide which edge of fixuptri to dig */ 12198 /* through next. */ 12199 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex); 12200 if (area == 0.0) { 12201 /* We've collided with a vertex between endpoint1 and endpoint2. */ 12202 collision = 1; 12203 oprev(fixuptri, fixuptri2); 12204 /* Enforce the Delaunay condition around farvertex. */ 12205 delaunayfixup(m, b, &fixuptri, 0); 12206 delaunayfixup(m, b, &fixuptri2, 1); 12207 done = 1; 12208 } else { 12209 if (area > 0.0) { /* farvertex is to the left of the segment. */ 12210 oprev(fixuptri, fixuptri2); 12211 /* Enforce the Delaunay condition around farvertex, on the */ 12212 /* left side of the segment only. */ 12213 delaunayfixup(m, b, &fixuptri2, 1); 12214 /* Flip the edge that crosses the segment. After the edge is */ 12215 /* flipped, one of its endpoints is the fan vertex, and the */ 12216 /* destination of fixuptri is the fan vertex. */ 12217 lprevself(fixuptri); 12218 } else { /* farvertex is to the right of the segment. */ 12219 delaunayfixup(m, b, &fixuptri, 0); 12220 /* Flip the edge that crosses the segment. After the edge is */ 12221 /* flipped, one of its endpoints is the fan vertex, and the */ 12222 /* destination of fixuptri is the fan vertex. */ 12223 oprevself(fixuptri); 12224 } 12225 /* Check for two intersecting segments. */ 12226 tspivot(fixuptri, crosssubseg); 12227 if (crosssubseg.ss == m->dummysub) { 12228 flip(m, b, &fixuptri); /* May create inverted triangle at left. */ 12229 } else { 12230 /* We've collided with a segment between endpoint1 and endpoint2. */ 12231 collision = 1; 12232 /* Insert a vertex at the intersection. */ 12233 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2); 12234 done = 1; 12235 } 12236 } 12237 } 12238 } while (!done); 12239 /* Insert a subsegment to make the segment permanent. */ 12240 insertsubseg(m, b, &fixuptri, newmark); 12241 /* If there was a collision with an interceding vertex, install another */ 12242 /* segment connecting that vertex with endpoint2. */ 12243 if (collision) { 12244 /* Insert the remainder of the segment. */ 12245 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) { 12246 constrainededge(m, b, &fixuptri, endpoint2, newmark); 12247 } 12248 } 12249 } 12250 12251 /*****************************************************************************/ 12252 /* */ 12253 /* insertsegment() Insert a PSLG segment into a triangulation. */ 12254 /* */ 12255 /*****************************************************************************/ 12256 12257 #ifdef ANSI_DECLARATORS 12258 void insertsegment(struct mesh *m, struct behavior *b, 12259 vertex endpoint1, vertex endpoint2, int newmark) 12260 #else /* not ANSI_DECLARATORS */ 12261 void insertsegment(m, b, endpoint1, endpoint2, newmark) 12262 struct mesh *m; 12263 struct behavior *b; 12264 vertex endpoint1; 12265 vertex endpoint2; 12266 int newmark; 12267 #endif /* not ANSI_DECLARATORS */ 12268 12269 { 12270 struct otri searchtri1, searchtri2; 12271 triangle encodedtri; 12272 vertex checkvertex; 12273 triangle ptr; /* Temporary variable used by sym(). */ 12274 12275 if (b->verbose > 1) { 12276 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n", 12277 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]); 12278 } 12279 12280 /* Find a triangle whose origin is the segment's first endpoint. */ 12281 checkvertex = (vertex) NULL; 12282 encodedtri = vertex2tri(endpoint1); 12283 if (encodedtri != (triangle) NULL) { 12284 decode(encodedtri, searchtri1); 12285 org(searchtri1, checkvertex); 12286 } 12287 if (checkvertex != endpoint1) { 12288 /* Find a boundary triangle to search from. */ 12289 searchtri1.tri = m->dummytri; 12290 searchtri1.orient = 0; 12291 symself(searchtri1); 12292 /* Search for the segment's first endpoint by point location. */ 12293 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) { 12294 printf( 12295 "Internal error in insertsegment(): Unable to locate PSLG vertex\n"); 12296 printf(" (%.12g, %.12g) in triangulation.\n", 12297 endpoint1[0], endpoint1[1]); 12298 internalerror(); 12299 } 12300 } 12301 /* Remember this triangle to improve subsequent point location. */ 12302 otricopy(searchtri1, m->recenttri); 12303 /* Scout the beginnings of a path from the first endpoint */ 12304 /* toward the second. */ 12305 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) { 12306 /* The segment was easily inserted. */ 12307 return; 12308 } 12309 /* The first endpoint may have changed if a collision with an intervening */ 12310 /* vertex on the segment occurred. */ 12311 org(searchtri1, endpoint1); 12312 12313 /* Find a triangle whose origin is the segment's second endpoint. */ 12314 checkvertex = (vertex) NULL; 12315 encodedtri = vertex2tri(endpoint2); 12316 if (encodedtri != (triangle) NULL) { 12317 decode(encodedtri, searchtri2); 12318 org(searchtri2, checkvertex); 12319 } 12320 if (checkvertex != endpoint2) { 12321 /* Find a boundary triangle to search from. */ 12322 searchtri2.tri = m->dummytri; 12323 searchtri2.orient = 0; 12324 symself(searchtri2); 12325 /* Search for the segment's second endpoint by point location. */ 12326 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) { 12327 printf( 12328 "Internal error in insertsegment(): Unable to locate PSLG vertex\n"); 12329 printf(" (%.12g, %.12g) in triangulation.\n", 12330 endpoint2[0], endpoint2[1]); 12331 internalerror(); 12332 } 12333 } 12334 /* Remember this triangle to improve subsequent point location. */ 12335 otricopy(searchtri2, m->recenttri); 12336 /* Scout the beginnings of a path from the second endpoint */ 12337 /* toward the first. */ 12338 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) { 12339 /* The segment was easily inserted. */ 12340 return; 12341 } 12342 /* The second endpoint may have changed if a collision with an intervening */ 12343 /* vertex on the segment occurred. */ 12344 org(searchtri2, endpoint2); 12345 12346 #ifndef REDUCED 12347 #ifndef CDT_ONLY 12348 if (b->splitseg) { 12349 /* Insert vertices to force the segment into the triangulation. */ 12350 conformingedge(m, b, endpoint1, endpoint2, newmark); 12351 } else { 12352 #endif /* not CDT_ONLY */ 12353 #endif /* not REDUCED */ 12354 /* Insert the segment directly into the triangulation. */ 12355 constrainededge(m, b, &searchtri1, endpoint2, newmark); 12356 #ifndef REDUCED 12357 #ifndef CDT_ONLY 12358 } 12359 #endif /* not CDT_ONLY */ 12360 #endif /* not REDUCED */ 12361 } 12362 12363 /*****************************************************************************/ 12364 /* */ 12365 /* markhull() Cover the convex hull of a triangulation with subsegments. */ 12366 /* */ 12367 /*****************************************************************************/ 12368 12369 #ifdef ANSI_DECLARATORS 12370 void markhull(struct mesh *m, struct behavior *b) 12371 #else /* not ANSI_DECLARATORS */ 12372 void markhull(m, b) 12373 struct mesh *m; 12374 struct behavior *b; 12375 #endif /* not ANSI_DECLARATORS */ 12376 12377 { 12378 struct otri hulltri; 12379 struct otri nexttri; 12380 struct otri starttri; 12381 triangle ptr; /* Temporary variable used by sym() and oprev(). */ 12382 12383 /* Find a triangle handle on the hull. */ 12384 hulltri.tri = m->dummytri; 12385 hulltri.orient = 0; 12386 symself(hulltri); 12387 /* Remember where we started so we know when to stop. */ 12388 otricopy(hulltri, starttri); 12389 /* Go once counterclockwise around the convex hull. */ 12390 do { 12391 /* Create a subsegment if there isn't already one here. */ 12392 insertsubseg(m, b, &hulltri, 1); 12393 /* To find the next hull edge, go clockwise around the next vertex. */ 12394 lnextself(hulltri); 12395 oprev(hulltri, nexttri); 12396 while (nexttri.tri != m->dummytri) { 12397 otricopy(nexttri, hulltri); 12398 oprev(hulltri, nexttri); 12399 } 12400 } while (!otriequal(hulltri, starttri)); 12401 } 12402 12403 /*****************************************************************************/ 12404 /* */ 12405 /* formskeleton() Create the segments of a triangulation, including PSLG */ 12406 /* segments and edges on the convex hull. */ 12407 /* */ 12408 /* The PSLG segments are read from a .poly file. The return value is the */ 12409 /* number of segments in the file. */ 12410 /* */ 12411 /*****************************************************************************/ 12412 12413 #ifdef TRILIBRARY 12414 12415 #ifdef ANSI_DECLARATORS 12416 void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, 12417 int *segmentmarkerlist, int numberofsegments) 12418 #else /* not ANSI_DECLARATORS */ 12419 void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments) 12420 struct mesh *m; 12421 struct behavior *b; 12422 int *segmentlist; 12423 int *segmentmarkerlist; 12424 int numberofsegments; 12425 #endif /* not ANSI_DECLARATORS */ 12426 12427 #else /* not TRILIBRARY */ 12428 12429 #ifdef ANSI_DECLARATORS 12430 void formskeleton(struct mesh *m, struct behavior *b, 12431 FILE* polyfile, char* polyfilename) 12432 #else /* not ANSI_DECLARATORS */ 12433 void formskeleton(m, b, polyfile, polyfilename) 12434 struct mesh *m; 12435 struct behavior *b; 12436 FILE* polyfile; 12437 char* polyfilename; 12438 #endif /* not ANSI_DECLARATORS */ 12439 12440 #endif /* not TRILIBRARY */ 12441 12442 { 12443 #ifdef TRILIBRARY 12444 char polyfilename[6]; 12445 int index; 12446 #else /* not TRILIBRARY */ 12447 char inputline[INPUTLINESIZE]; 12448 char *stringptr; 12449 #endif /* not TRILIBRARY */ 12450 vertex endpoint1, endpoint2; 12451 int segmentmarkers; 12452 int end1, end2; 12453 int boundmarker; 12454 int i; 12455 12456 if (b->poly) { 12457 if (!b->quiet) { 12458 printf("Recovering segments in Delaunay triangulation.\n"); 12459 } 12460 #ifdef TRILIBRARY 12461 strcpy(polyfilename, "input"); 12462 m->insegments = numberofsegments; 12463 segmentmarkers = segmentmarkerlist != (int *) NULL; 12464 index = 0; 12465 #else /* not TRILIBRARY */ 12466 /* Read the segments from a .poly file. */ 12467 /* Read number of segments and number of boundary markers. */ 12468 stringptr = readline(inputline, polyfile, polyfilename); 12469 m->insegments = (int) strtol(stringptr, &stringptr, 0); 12470 stringptr = findfield(stringptr); 12471 if (*stringptr == '\0') { 12472 segmentmarkers = 0; 12473 } else { 12474 segmentmarkers = (int) strtol(stringptr, &stringptr, 0); 12475 } 12476 #endif /* not TRILIBRARY */ 12477 /* If the input vertices are collinear, there is no triangulation, */ 12478 /* so don't try to insert segments. */ 12479 if (m->triangles.items == 0) { 12480 return; 12481 } 12482 12483 /* If segments are to be inserted, compute a mapping */ 12484 /* from vertices to triangles. */ 12485 if (m->insegments > 0) { 12486 makevertexmap(m, b); 12487 if (b->verbose) { 12488 printf(" Recovering PSLG segments.\n"); 12489 } 12490 } 12491 12492 boundmarker = 0; 12493 /* Read and insert the segments. */ 12494 for (i = 0; i < m->insegments; i++) { 12495 #ifdef TRILIBRARY 12496 end1 = segmentlist[index++]; 12497 end2 = segmentlist[index++]; 12498 if (segmentmarkers) { 12499 boundmarker = segmentmarkerlist[i]; 12500 } 12501 #else /* not TRILIBRARY */ 12502 stringptr = readline(inputline, polyfile, b->inpolyfilename); 12503 stringptr = findfield(stringptr); 12504 if (*stringptr == '\0') { 12505 printf("Error: Segment %d has no endpoints in %s.\n", 12506 b->firstnumber + i, polyfilename); 12507 triexit(1); 12508 } else { 12509 end1 = (int) strtol(stringptr, &stringptr, 0); 12510 } 12511 stringptr = findfield(stringptr); 12512 if (*stringptr == '\0') { 12513 printf("Error: Segment %d is missing its second endpoint in %s.\n", 12514 b->firstnumber + i, polyfilename); 12515 triexit(1); 12516 } else { 12517 end2 = (int) strtol(stringptr, &stringptr, 0); 12518 } 12519 if (segmentmarkers) { 12520 stringptr = findfield(stringptr); 12521 if (*stringptr == '\0') { 12522 boundmarker = 0; 12523 } else { 12524 boundmarker = (int) strtol(stringptr, &stringptr, 0); 12525 } 12526 } 12527 #endif /* not TRILIBRARY */ 12528 if ((end1 < b->firstnumber) || 12529 (end1 >= b->firstnumber + m->invertices)) { 12530 if (!b->quiet) { 12531 printf("Warning: Invalid first endpoint of segment %d in %s.\n", 12532 b->firstnumber + i, polyfilename); 12533 } 12534 } else if ((end2 < b->firstnumber) || 12535 (end2 >= b->firstnumber + m->invertices)) { 12536 if (!b->quiet) { 12537 printf("Warning: Invalid second endpoint of segment %d in %s.\n", 12538 b->firstnumber + i, polyfilename); 12539 } 12540 } else { 12541 /* Find the vertices numbered `end1' and `end2'. */ 12542 endpoint1 = getvertex(m, b, end1); 12543 endpoint2 = getvertex(m, b, end2); 12544 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) { 12545 if (!b->quiet) { 12546 printf("Warning: Endpoints of segment %d are coincident in %s.\n", 12547 b->firstnumber + i, polyfilename); 12548 } 12549 } else { 12550 insertsegment(m, b, endpoint1, endpoint2, boundmarker); 12551 } 12552 } 12553 } 12554 } else { 12555 m->insegments = 0; 12556 } 12557 if (b->convex || !b->poly) { 12558 /* Enclose the convex hull with subsegments. */ 12559 if (b->verbose) { 12560 printf(" Enclosing convex hull with segments.\n"); 12561 } 12562 markhull(m, b); 12563 } 12564 } 12565 12568 /********* Segment insertion ends here *********/ 12569 12570 /********* Carving out holes and concavities begins here *********/ 12574 /*****************************************************************************/ 12575 /* */ 12576 /* infecthull() Virally infect all of the triangles of the convex hull */ 12577 /* that are not protected by subsegments. Where there are */ 12578 /* subsegments, set boundary markers as appropriate. */ 12579 /* */ 12580 /*****************************************************************************/ 12581 12582 #ifdef ANSI_DECLARATORS 12583 void infecthull(struct mesh *m, struct behavior *b) 12584 #else /* not ANSI_DECLARATORS */ 12585 void infecthull(m, b) 12586 struct mesh *m; 12587 struct behavior *b; 12588 #endif /* not ANSI_DECLARATORS */ 12589 12590 { 12591 struct otri hulltri; 12592 struct otri nexttri; 12593 struct otri starttri; 12594 struct osub hullsubseg; 12595 triangle **deadtriangle; 12596 vertex horg, hdest; 12597 triangle ptr; /* Temporary variable used by sym(). */ 12598 subseg sptr; /* Temporary variable used by tspivot(). */ 12599 12600 if (b->verbose) { 12601 printf(" Marking concavities (external triangles) for elimination.\n"); 12602 } 12603 /* Find a triangle handle on the hull. */ 12604 hulltri.tri = m->dummytri; 12605 hulltri.orient = 0; 12606 symself(hulltri); 12607 /* Remember where we started so we know when to stop. */ 12608 otricopy(hulltri, starttri); 12609 /* Go once counterclockwise around the convex hull. */ 12610 do { 12611 /* Ignore triangles that are already infected. */ 12612 if (!infected(hulltri)) { 12613 /* Is the triangle protected by a subsegment? */ 12614 tspivot(hulltri, hullsubseg); 12615 if (hullsubseg.ss == m->dummysub) { 12616 /* The triangle is not protected; infect it. */ 12617 if (!infected(hulltri)) { 12618 infect(hulltri); 12619 deadtriangle = (triangle **) poolalloc(&m->viri); 12620 *deadtriangle = hulltri.tri; 12621 } 12622 } else { 12623 /* The triangle is protected; set boundary markers if appropriate. */ 12624 if (mark(hullsubseg) == 0) { 12625 setmark(hullsubseg, 1); 12626 org(hulltri, horg); 12627 dest(hulltri, hdest); 12628 if (vertexmark(horg) == 0) { 12629 setvertexmark(horg, 1); 12630 } 12631 if (vertexmark(hdest) == 0) { 12632 setvertexmark(hdest, 1); 12633 } 12634 } 12635 } 12636 } 12637 /* To find the next hull edge, go clockwise around the next vertex. */ 12638 lnextself(hulltri); 12639 oprev(hulltri, nexttri); 12640 while (nexttri.tri != m->dummytri) { 12641 otricopy(nexttri, hulltri); 12642 oprev(hulltri, nexttri); 12643 } 12644 } while (!otriequal(hulltri, starttri)); 12645 } 12646 12647 /*****************************************************************************/ 12648 /* */ 12649 /* plague() Spread the virus from all infected triangles to any neighbors */ 12650 /* not protected by subsegments. Delete all infected triangles. */ 12651 /* */ 12652 /* This is the procedure that actually creates holes and concavities. */ 12653 /* */ 12654 /* This procedure operates in two phases. The first phase identifies all */ 12655 /* the triangles that will die, and marks them as infected. They are */ 12656 /* marked to ensure that each triangle is added to the virus pool only */ 12657 /* once, so the procedure will terminate. */ 12658 /* */ 12659 /* The second phase actually eliminates the infected triangles. It also */ 12660 /* eliminates orphaned vertices. */ 12661 /* */ 12662 /*****************************************************************************/ 12663 12664 #ifdef ANSI_DECLARATORS 12665 void plague(struct mesh *m, struct behavior *b) 12666 #else /* not ANSI_DECLARATORS */ 12667 void plague(m, b) 12668 struct mesh *m; 12669 struct behavior *b; 12670 #endif /* not ANSI_DECLARATORS */ 12671 12672 { 12673 struct otri testtri; 12674 struct otri neighbor; 12675 triangle **virusloop; 12676 triangle **deadtriangle; 12677 struct osub neighborsubseg; 12678 vertex testvertex; 12679 vertex norg, ndest; 12680 vertex deadorg, deaddest, deadapex; 12681 int killorg; 12682 triangle ptr; /* Temporary variable used by sym() and onext(). */ 12683 subseg sptr; /* Temporary variable used by tspivot(). */ 12684 12685 if (b->verbose) { 12686 printf(" Marking neighbors of marked triangles.\n"); 12687 } 12688 /* Loop through all the infected triangles, spreading the virus to */ 12689 /* their neighbors, then to their neighbors' neighbors. */ 12690 traversalinit(&m->viri); 12691 virusloop = (triangle **) traverse(&m->viri); 12692 while (virusloop != (triangle **) NULL) { 12693 testtri.tri = *virusloop; 12694 /* A triangle is marked as infected by messing with one of its pointers */ 12695 /* to subsegments, setting it to an illegal value. Hence, we have to */ 12696 /* temporarily uninfect this triangle so that we can examine its */ 12697 /* adjacent subsegments. */ 12698 uninfect(testtri); 12699 if (b->verbose > 2) { 12700 /* Assign the triangle an orientation for convenience in */ 12701 /* checking its vertices. */ 12702 testtri.orient = 0; 12703 org(testtri, deadorg); 12704 dest(testtri, deaddest); 12705 apex(testtri, deadapex); 12706 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 12707 deadorg[0], deadorg[1], deaddest[0], deaddest[1], 12708 deadapex[0], deadapex[1]); 12709 } 12710 /* Check each of the triangle's three neighbors. */ 12711 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { 12712 /* Find the neighbor. */ 12713 sym(testtri, neighbor); 12714 /* Check for a subsegment between the triangle and its neighbor. */ 12715 tspivot(testtri, neighborsubseg); 12716 /* Check if the neighbor is nonexistent or already infected. */ 12717 if ((neighbor.tri == m->dummytri) || infected(neighbor)) { 12718 if (neighborsubseg.ss != m->dummysub) { 12719 /* There is a subsegment separating the triangle from its */ 12720 /* neighbor, but both triangles are dying, so the subsegment */ 12721 /* dies too. */ 12722 subsegdealloc(m, neighborsubseg.ss); 12723 if (neighbor.tri != m->dummytri) { 12724 /* Make sure the subsegment doesn't get deallocated again */ 12725 /* later when the infected neighbor is visited. */ 12726 uninfect(neighbor); 12727 tsdissolve(neighbor); 12728 infect(neighbor); 12729 } 12730 } 12731 } else { /* The neighbor exists and is not infected. */ 12732 if (neighborsubseg.ss == m->dummysub) { 12733 /* There is no subsegment protecting the neighbor, so */ 12734 /* the neighbor becomes infected. */ 12735 if (b->verbose > 2) { 12736 org(neighbor, deadorg); 12737 dest(neighbor, deaddest); 12738 apex(neighbor, deadapex); 12739 printf( 12740 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 12741 deadorg[0], deadorg[1], deaddest[0], deaddest[1], 12742 deadapex[0], deadapex[1]); 12743 } 12744 infect(neighbor); 12745 /* Ensure that the neighbor's neighbors will be infected. */ 12746 deadtriangle = (triangle **) poolalloc(&m->viri); 12747 *deadtriangle = neighbor.tri; 12748 } else { /* The neighbor is protected by a subsegment. */ 12749 /* Remove this triangle from the subsegment. */ 12750 stdissolve(neighborsubseg); 12751 /* The subsegment becomes a boundary. Set markers accordingly. */ 12752 if (mark(neighborsubseg) == 0) { 12753 setmark(neighborsubseg, 1); 12754 } 12755 org(neighbor, norg); 12756 dest(neighbor, ndest); 12757 if (vertexmark(norg) == 0) { 12758 setvertexmark(norg, 1); 12759 } 12760 if (vertexmark(ndest) == 0) { 12761 setvertexmark(ndest, 1); 12762 } 12763 } 12764 } 12765 } 12766 /* Remark the triangle as infected, so it doesn't get added to the */ 12767 /* virus pool again. */ 12768 infect(testtri); 12769 virusloop = (triangle **) traverse(&m->viri); 12770 } 12771 12772 if (b->verbose) { 12773 printf(" Deleting marked triangles.\n"); 12774 } 12775 12776 traversalinit(&m->viri); 12777 virusloop = (triangle **) traverse(&m->viri); 12778 while (virusloop != (triangle **) NULL) { 12779 testtri.tri = *virusloop; 12780 12781 /* Check each of the three corners of the triangle for elimination. */ 12782 /* This is done by walking around each vertex, checking if it is */ 12783 /* still connected to at least one live triangle. */ 12784 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { 12785 org(testtri, testvertex); 12786 /* Check if the vertex has already been tested. */ 12787 if (testvertex != (vertex) NULL) { 12788 killorg = 1; 12789 /* Mark the corner of the triangle as having been tested. */ 12790 setorg(testtri, NULL); 12791 /* Walk counterclockwise about the vertex. */ 12792 onext(testtri, neighbor); 12793 /* Stop upon reaching a boundary or the starting triangle. */ 12794 while ((neighbor.tri != m->dummytri) && 12795 (!otriequal(neighbor, testtri))) { 12796 if (infected(neighbor)) { 12797 /* Mark the corner of this triangle as having been tested. */ 12798 setorg(neighbor, NULL); 12799 } else { 12800 /* A live triangle. The vertex survives. */ 12801 killorg = 0; 12802 } 12803 /* Walk counterclockwise about the vertex. */ 12804 onextself(neighbor); 12805 } 12806 /* If we reached a boundary, we must walk clockwise as well. */ 12807 if (neighbor.tri == m->dummytri) { 12808 /* Walk clockwise about the vertex. */ 12809 oprev(testtri, neighbor); 12810 /* Stop upon reaching a boundary. */ 12811 while (neighbor.tri != m->dummytri) { 12812 if (infected(neighbor)) { 12813 /* Mark the corner of this triangle as having been tested. */ 12814 setorg(neighbor, NULL); 12815 } else { 12816 /* A live triangle. The vertex survives. */ 12817 killorg = 0; 12818 } 12819 /* Walk clockwise about the vertex. */ 12820 oprevself(neighbor); 12821 } 12822 } 12823 if (killorg) { 12824 if (b->verbose > 1) { 12825 printf(" Deleting vertex (%.12g, %.12g)\n", 12826 testvertex[0], testvertex[1]); 12827 } 12828 setvertextype(testvertex, UNDEADVERTEX); 12829 m->undeads++; 12830 } 12831 } 12832 } 12833 12834 /* Record changes in the number of boundary edges, and disconnect */ 12835 /* dead triangles from their neighbors. */ 12836 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { 12837 sym(testtri, neighbor); 12838 if (neighbor.tri == m->dummytri) { 12839 /* There is no neighboring triangle on this edge, so this edge */ 12840 /* is a boundary edge. This triangle is being deleted, so this */ 12841 /* boundary edge is deleted. */ 12842 m->hullsize--; 12843 } else { 12844 /* Disconnect the triangle from its neighbor. */ 12845 dissolve(neighbor); 12846 /* There is a neighboring triangle on this edge, so this edge */ 12847 /* becomes a boundary edge when this triangle is deleted. */ 12848 m->hullsize++; 12849 } 12850 } 12851 /* Return the dead triangle to the pool of triangles. */ 12852 triangledealloc(m, testtri.tri); 12853 virusloop = (triangle **) traverse(&m->viri); 12854 } 12855 /* Empty the virus pool. */ 12856 poolrestart(&m->viri); 12857 } 12858 12859 /*****************************************************************************/ 12860 /* */ 12861 /* regionplague() Spread regional attributes and/or area constraints */ 12862 /* (from a .poly file) throughout the mesh. */ 12863 /* */ 12864 /* This procedure operates in two phases. The first phase spreads an */ 12865 /* attribute and/or an area constraint through a (segment-bounded) region. */ 12866 /* The triangles are marked to ensure that each triangle is added to the */ 12867 /* virus pool only once, so the procedure will terminate. */ 12868 /* */ 12869 /* The second phase uninfects all infected triangles, returning them to */ 12870 /* normal. */ 12871 /* */ 12872 /*****************************************************************************/ 12873 12874 #ifdef ANSI_DECLARATORS 12875 void regionplague(struct mesh *m, struct behavior *b, 12876 REAL attribute, REAL area) 12877 #else /* not ANSI_DECLARATORS */ 12878 void regionplague(m, b, attribute, area) 12879 struct mesh *m; 12880 struct behavior *b; 12881 REAL attribute; 12882 REAL area; 12883 #endif /* not ANSI_DECLARATORS */ 12884 12885 { 12886 struct otri testtri; 12887 struct otri neighbor; 12888 triangle **virusloop; 12889 triangle **regiontri; 12890 struct osub neighborsubseg; 12891 vertex regionorg, regiondest, regionapex; 12892 triangle ptr; /* Temporary variable used by sym() and onext(). */ 12893 subseg sptr; /* Temporary variable used by tspivot(). */ 12894 12895 if (b->verbose > 1) { 12896 printf(" Marking neighbors of marked triangles.\n"); 12897 } 12898 /* Loop through all the infected triangles, spreading the attribute */ 12899 /* and/or area constraint to their neighbors, then to their neighbors' */ 12900 /* neighbors. */ 12901 traversalinit(&m->viri); 12902 virusloop = (triangle **) traverse(&m->viri); 12903 while (virusloop != (triangle **) NULL) { 12904 testtri.tri = *virusloop; 12905 /* A triangle is marked as infected by messing with one of its pointers */ 12906 /* to subsegments, setting it to an illegal value. Hence, we have to */ 12907 /* temporarily uninfect this triangle so that we can examine its */ 12908 /* adjacent subsegments. */ 12909 uninfect(testtri); 12910 if (b->regionattrib) { 12911 /* Set an attribute. */ 12912 setelemattribute(testtri, m->eextras, attribute); 12913 } 12914 if (b->vararea) { 12915 /* Set an area constraint. */ 12916 setareabound(testtri, area); 12917 } 12918 if (b->verbose > 2) { 12919 /* Assign the triangle an orientation for convenience in */ 12920 /* checking its vertices. */ 12921 testtri.orient = 0; 12922 org(testtri, regionorg); 12923 dest(testtri, regiondest); 12924 apex(testtri, regionapex); 12925 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 12926 regionorg[0], regionorg[1], regiondest[0], regiondest[1], 12927 regionapex[0], regionapex[1]); 12928 } 12929 /* Check each of the triangle's three neighbors. */ 12930 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { 12931 /* Find the neighbor. */ 12932 sym(testtri, neighbor); 12933 /* Check for a subsegment between the triangle and its neighbor. */ 12934 tspivot(testtri, neighborsubseg); 12935 /* Make sure the neighbor exists, is not already infected, and */ 12936 /* isn't protected by a subsegment. */ 12937 if ((neighbor.tri != m->dummytri) && !infected(neighbor) 12938 && (neighborsubseg.ss == m->dummysub)) { 12939 if (b->verbose > 2) { 12940 org(neighbor, regionorg); 12941 dest(neighbor, regiondest); 12942 apex(neighbor, regionapex); 12943 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 12944 regionorg[0], regionorg[1], regiondest[0], regiondest[1], 12945 regionapex[0], regionapex[1]); 12946 } 12947 /* Infect the neighbor. */ 12948 infect(neighbor); 12949 /* Ensure that the neighbor's neighbors will be infected. */ 12950 regiontri = (triangle **) poolalloc(&m->viri); 12951 *regiontri = neighbor.tri; 12952 } 12953 } 12954 /* Remark the triangle as infected, so it doesn't get added to the */ 12955 /* virus pool again. */ 12956 infect(testtri); 12957 virusloop = (triangle **) traverse(&m->viri); 12958 } 12959 12960 /* Uninfect all triangles. */ 12961 if (b->verbose > 1) { 12962 printf(" Unmarking marked triangles.\n"); 12963 } 12964 traversalinit(&m->viri); 12965 virusloop = (triangle **) traverse(&m->viri); 12966 while (virusloop != (triangle **) NULL) { 12967 testtri.tri = *virusloop; 12968 uninfect(testtri); 12969 virusloop = (triangle **) traverse(&m->viri); 12970 } 12971 /* Empty the virus pool. */ 12972 poolrestart(&m->viri); 12973 } 12974 12975 /*****************************************************************************/ 12976 /* */ 12977 /* carveholes() Find the holes and infect them. Find the area */ 12978 /* constraints and infect them. Infect the convex hull. */ 12979 /* Spread the infection and kill triangles. Spread the */ 12980 /* area constraints. */ 12981 /* */ 12982 /* This routine mainly calls other routines to carry out all these */ 12983 /* functions. */ 12984 /* */ 12985 /*****************************************************************************/ 12986 12987 #ifdef ANSI_DECLARATORS 12988 void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, 12989 REAL *regionlist, int regions) 12990 #else /* not ANSI_DECLARATORS */ 12991 void carveholes(m, b, holelist, holes, regionlist, regions) 12992 struct mesh *m; 12993 struct behavior *b; 12994 REAL *holelist; 12995 int holes; 12996 REAL *regionlist; 12997 int regions; 12998 #endif /* not ANSI_DECLARATORS */ 12999 13000 { 13001 struct otri searchtri; 13002 struct otri triangleloop; 13003 struct otri *regiontris; 13004 triangle **holetri; 13005 triangle **regiontri; 13006 vertex searchorg, searchdest; 13007 enum locateresult intersect; 13008 int i; 13009 triangle ptr; /* Temporary variable used by sym(). */ 13010 13011 if (!(b->quiet || (b->noholes && b->convex))) { 13012 printf("Removing unwanted triangles.\n"); 13013 if (b->verbose && (holes > 0)) { 13014 printf(" Marking holes for elimination.\n"); 13015 } 13016 } 13017 13018 if (regions > 0) { 13019 /* Allocate storage for the triangles in which region points fall. */ 13020 regiontris = (struct otri *) trimalloc(regions * 13021 (int) sizeof(struct otri)); 13022 } else { 13023 regiontris = (struct otri *) NULL; 13024 } 13025 13026 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) { 13027 /* Initialize a pool of viri to be used for holes, concavities, */ 13028 /* regional attributes, and/or regional area constraints. */ 13029 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0); 13030 } 13031 13032 if (!b->convex) { 13033 /* Mark as infected any unprotected triangles on the boundary. */ 13034 /* This is one way by which concavities are created. */ 13035 infecthull(m, b); 13036 } 13037 13038 if ((holes > 0) && !b->noholes) { 13039 /* Infect each triangle in which a hole lies. */ 13040 for (i = 0; i < 2 * holes; i += 2) { 13041 /* Ignore holes that aren't within the bounds of the mesh. */ 13042 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax) 13043 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) { 13044 /* Start searching from some triangle on the outer boundary. */ 13045 searchtri.tri = m->dummytri; 13046 searchtri.orient = 0; 13047 symself(searchtri); 13048 /* Ensure that the hole is to the left of this boundary edge; */ 13049 /* otherwise, locate() will falsely report that the hole */ 13050 /* falls within the starting triangle. */ 13051 org(searchtri, searchorg); 13052 dest(searchtri, searchdest); 13053 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) > 13054 0.0) { 13055 /* Find a triangle that contains the hole. */ 13056 intersect = locate(m, b, &holelist[i], &searchtri); 13057 if ((intersect != OUTSIDE) && (!infected(searchtri))) { 13058 /* Infect the triangle. This is done by marking the triangle */ 13059 /* as infected and including the triangle in the virus pool. */ 13060 infect(searchtri); 13061 holetri = (triangle **) poolalloc(&m->viri); 13062 *holetri = searchtri.tri; 13063 } 13064 } 13065 } 13066 } 13067 } 13068 13069 /* Now, we have to find all the regions BEFORE we carve the holes, because */ 13070 /* locate() won't work when the triangulation is no longer convex. */ 13071 /* (Incidentally, this is the reason why regional attributes and area */ 13072 /* constraints can't be used when refining a preexisting mesh, which */ 13073 /* might not be convex; they can only be used with a freshly */ 13074 /* triangulated PSLG.) */ 13075 if (regions > 0) { 13076 /* Find the starting triangle for each region. */ 13077 for (i = 0; i < regions; i++) { 13078 regiontris[i].tri = m->dummytri; 13079 /* Ignore region points that aren't within the bounds of the mesh. */ 13080 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) && 13081 (regionlist[4 * i + 1] >= m->ymin) && 13082 (regionlist[4 * i + 1] <= m->ymax)) { 13083 /* Start searching from some triangle on the outer boundary. */ 13084 searchtri.tri = m->dummytri; 13085 searchtri.orient = 0; 13086 symself(searchtri); 13087 /* Ensure that the region point is to the left of this boundary */ 13088 /* edge; otherwise, locate() will falsely report that the */ 13089 /* region point falls within the starting triangle. */ 13090 org(searchtri, searchorg); 13091 dest(searchtri, searchdest); 13092 if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) > 13093 0.0) { 13094 /* Find a triangle that contains the region point. */ 13095 intersect = locate(m, b, ®ionlist[4 * i], &searchtri); 13096 if ((intersect != OUTSIDE) && (!infected(searchtri))) { 13097 /* Record the triangle for processing after the */ 13098 /* holes have been carved. */ 13099 otricopy(searchtri, regiontris[i]); 13100 } 13101 } 13102 } 13103 } 13104 } 13105 13106 if (m->viri.items > 0) { 13107 /* Carve the holes and concavities. */ 13108 plague(m, b); 13109 } 13110 /* The virus pool should be empty now. */ 13111 13112 if (regions > 0) { 13113 if (!b->quiet) { 13114 if (b->regionattrib) { 13115 if (b->vararea) { 13116 printf("Spreading regional attributes and area constraints.\n"); 13117 } else { 13118 printf("Spreading regional attributes.\n"); 13119 } 13120 } else { 13121 printf("Spreading regional area constraints.\n"); 13122 } 13123 } 13124 if (b->regionattrib && !b->refine) { 13125 /* Assign every triangle a regional attribute of zero. */ 13126 traversalinit(&m->triangles); 13127 triangleloop.orient = 0; 13128 triangleloop.tri = triangletraverse(m); 13129 while (triangleloop.tri != (triangle *) NULL) { 13130 setelemattribute(triangleloop, m->eextras, 0.0); 13131 triangleloop.tri = triangletraverse(m); 13132 } 13133 } 13134 for (i = 0; i < regions; i++) { 13135 if (regiontris[i].tri != m->dummytri) { 13136 /* Make sure the triangle under consideration still exists. */ 13137 /* It may have been eaten by the virus. */ 13138 if (!deadtri(regiontris[i].tri)) { 13139 /* Put one triangle in the virus pool. */ 13140 infect(regiontris[i]); 13141 regiontri = (triangle **) poolalloc(&m->viri); 13142 *regiontri = regiontris[i].tri; 13143 /* Apply one region's attribute and/or area constraint. */ 13144 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]); 13145 /* The virus pool should be empty now. */ 13146 } 13147 } 13148 } 13149 if (b->regionattrib && !b->refine) { 13150 /* Note the fact that each triangle has an additional attribute. */ 13151 m->eextras++; 13152 } 13153 } 13154 13155 /* Free up memory. */ 13156 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) { 13157 pooldeinit(&m->viri); 13158 } 13159 if (regions > 0) { 13160 trifree((VOID *) regiontris); 13161 } 13162 } 13163 13166 /********* Carving out holes and concavities ends here *********/ 13167 13168 /********* Mesh quality maintenance begins here *********/ 13172 /*****************************************************************************/ 13173 /* */ 13174 /* tallyencs() Traverse the entire list of subsegments, and check each */ 13175 /* to see if it is encroached. If so, add it to the list. */ 13176 /* */ 13177 /*****************************************************************************/ 13178 13179 #ifndef CDT_ONLY 13180 13181 #ifdef ANSI_DECLARATORS 13182 void tallyencs(struct mesh *m, struct behavior *b) 13183 #else /* not ANSI_DECLARATORS */ 13184 void tallyencs(m, b) 13185 struct mesh *m; 13186 struct behavior *b; 13187 #endif /* not ANSI_DECLARATORS */ 13188 13189 { 13190 struct osub subsegloop; 13191 //int dummy; 13192 13193 traversalinit(&m->subsegs); 13194 subsegloop.ssorient = 0; 13195 subsegloop.ss = subsegtraverse(m); 13196 while (subsegloop.ss != (subseg *) NULL) { 13197 /* If the segment is encroached, add it to the list. */ 13198 // dummy = checkseg4encroach(m, b, &subsegloop); // "dummy =" commented out to get gcc 4.6 working 13199 checkseg4encroach(m, b, &subsegloop); // "dummy =" commented out to get gcc 4.6 working 13200 subsegloop.ss = subsegtraverse(m); 13201 } 13202 } 13203 13204 #endif /* not CDT_ONLY */ 13205 13206 /*****************************************************************************/ 13207 /* */ 13208 /* precisionerror() Print an error message for precision problems. */ 13209 /* */ 13210 /*****************************************************************************/ 13211 13212 #ifndef CDT_ONLY 13213 13214 void precisionerror() 13215 { 13216 printf("Try increasing the area criterion and/or reducing the minimum\n"); 13217 printf(" allowable angle so that tiny triangles are not created.\n"); 13218 #ifdef SINGLE 13219 printf("Alternatively, try recompiling me with double precision\n"); 13220 printf(" arithmetic (by removing \"#define SINGLE\" from the\n"); 13221 printf(" source file or \"-DSINGLE\" from the makefile).\n"); 13222 #endif /* SINGLE */ 13223 } 13224 13225 #endif /* not CDT_ONLY */ 13226 13227 /*****************************************************************************/ 13228 /* */ 13229 /* splitencsegs() Split all the encroached subsegments. */ 13230 /* */ 13231 /* Each encroached subsegment is repaired by splitting it - inserting a */ 13232 /* vertex at or near its midpoint. Newly inserted vertices may encroach */ 13233 /* upon other subsegments; these are also repaired. */ 13234 /* */ 13235 /* `triflaws' is a flag that specifies whether one should take note of new */ 13236 /* bad triangles that result from inserting vertices to repair encroached */ 13237 /* subsegments. */ 13238 /* */ 13239 /*****************************************************************************/ 13240 13241 #ifndef CDT_ONLY 13242 13243 #ifdef ANSI_DECLARATORS 13244 void splitencsegs(struct mesh *m, struct behavior *b, int triflaws) 13245 #else /* not ANSI_DECLARATORS */ 13246 void splitencsegs(m, b, triflaws) 13247 struct mesh *m; 13248 struct behavior *b; 13249 int triflaws; 13250 #endif /* not ANSI_DECLARATORS */ 13251 13252 { 13253 struct otri enctri; 13254 struct otri testtri; 13255 struct osub testsh; 13256 struct osub currentenc; 13257 struct badsubseg *encloop; 13258 vertex eorg, edest, eapex; 13259 vertex newvertex; 13260 enum insertvertexresult success; 13261 REAL segmentlength, nearestpoweroftwo; 13262 REAL split; 13263 REAL multiplier, divisor; 13264 int acuteorg, acuteorg2, acutedest, acutedest2; 13265 //int dummy; 13266 int i; 13267 triangle ptr; /* Temporary variable used by stpivot(). */ 13268 subseg sptr; /* Temporary variable used by snext(). */ 13269 13270 /* Note that steinerleft == -1 if an unlimited number */ 13271 /* of Steiner points is allowed. */ 13272 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) { 13273 traversalinit(&m->badsubsegs); 13274 encloop = badsubsegtraverse(m); 13275 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) { 13276 sdecode(encloop->encsubseg, currentenc); 13277 sorg(currentenc, eorg); 13278 sdest(currentenc, edest); 13279 /* Make sure that this segment is still the same segment it was */ 13280 /* when it was determined to be encroached. If the segment was */ 13281 /* enqueued multiple times (because several newly inserted */ 13282 /* vertices encroached it), it may have already been split. */ 13283 if (!deadsubseg(currentenc.ss) && 13284 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) { 13285 /* To decide where to split a segment, we need to know if the */ 13286 /* segment shares an endpoint with an adjacent segment. */ 13287 /* The concern is that, if we simply split every encroached */ 13288 /* segment in its center, two adjacent segments with a small */ 13289 /* angle between them might lead to an infinite loop; each */ 13290 /* vertex added to split one segment will encroach upon the */ 13291 /* other segment, which must then be split with a vertex that */ 13292 /* will encroach upon the first segment, and so on forever. */ 13293 /* To avoid this, imagine a set of concentric circles, whose */ 13294 /* radii are powers of two, about each segment endpoint. */ 13295 /* These concentric circles determine where the segment is */ 13296 /* split. (If both endpoints are shared with adjacent */ 13297 /* segments, split the segment in the middle, and apply the */ 13298 /* concentric circles for later splittings.) */ 13299 13300 /* Is the origin shared with another segment? */ 13301 stpivot(currentenc, enctri); 13302 lnext(enctri, testtri); 13303 tspivot(testtri, testsh); 13304 acuteorg = testsh.ss != m->dummysub; 13305 /* Is the destination shared with another segment? */ 13306 lnextself(testtri); 13307 tspivot(testtri, testsh); 13308 acutedest = testsh.ss != m->dummysub; 13309 13310 /* If we're using Chew's algorithm (rather than Ruppert's) */ 13311 /* to define encroachment, delete free vertices from the */ 13312 /* subsegment's diametral circle. */ 13313 if (!b->conformdel && !acuteorg && !acutedest) { 13314 apex(enctri, eapex); 13315 while ((vertextype(eapex) == FREEVERTEX) && 13316 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + 13317 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) { 13318 deletevertex(m, b, &testtri); 13319 stpivot(currentenc, enctri); 13320 apex(enctri, eapex); 13321 lprev(enctri, testtri); 13322 } 13323 } 13324 13325 /* Now, check the other side of the segment, if there's a triangle */ 13326 /* there. */ 13327 sym(enctri, testtri); 13328 if (testtri.tri != m->dummytri) { 13329 /* Is the destination shared with another segment? */ 13330 lnextself(testtri); 13331 tspivot(testtri, testsh); 13332 acutedest2 = testsh.ss != m->dummysub; 13333 acutedest = acutedest || acutedest2; 13334 /* Is the origin shared with another segment? */ 13335 lnextself(testtri); 13336 tspivot(testtri, testsh); 13337 acuteorg2 = testsh.ss != m->dummysub; 13338 acuteorg = acuteorg || acuteorg2; 13339 13340 /* Delete free vertices from the subsegment's diametral circle. */ 13341 if (!b->conformdel && !acuteorg2 && !acutedest2) { 13342 org(testtri, eapex); 13343 while ((vertextype(eapex) == FREEVERTEX) && 13344 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) + 13345 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) { 13346 deletevertex(m, b, &testtri); 13347 sym(enctri, testtri); 13348 apex(testtri, eapex); 13349 lprevself(testtri); 13350 } 13351 } 13352 } 13353 13354 /* Use the concentric circles if exactly one endpoint is shared */ 13355 /* with another adjacent segment. */ 13356 if (acuteorg || acutedest) { 13357 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) + 13358 (edest[1] - eorg[1]) * (edest[1] - eorg[1])); 13359 /* Find the power of two that most evenly splits the segment. */ 13360 /* The worst case is a 2:1 ratio between subsegment lengths. */ 13361 nearestpoweroftwo = 1.0; 13362 while (segmentlength > 3.0 * nearestpoweroftwo) { 13363 nearestpoweroftwo *= 2.0; 13364 } 13365 while (segmentlength < 1.5 * nearestpoweroftwo) { 13366 nearestpoweroftwo *= 0.5; 13367 } 13368 /* Where do we split the segment? */ 13369 split = nearestpoweroftwo / segmentlength; 13370 if (acutedest) { 13371 split = 1.0 - split; 13372 } 13373 } else { 13374 /* If we're not worried about adjacent segments, split */ 13375 /* this segment in the middle. */ 13376 split = 0.5; 13377 } 13378 13379 /* Create the new vertex. */ 13380 newvertex = (vertex) poolalloc(&m->vertices); 13381 /* Interpolate its coordinate and attributes. */ 13382 for (i = 0; i < 2 + m->nextras; i++) { 13383 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]); 13384 } 13385 13386 if (!b->noexact) { 13387 /* Roundoff in the above calculation may yield a `newvertex' */ 13388 /* that is not precisely collinear with `eorg' and `edest'. */ 13389 /* Improve collinearity by one step of iterative refinement. */ 13390 multiplier = counterclockwise(m, b, eorg, edest, newvertex); 13391 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) + 13392 (eorg[1] - edest[1]) * (eorg[1] - edest[1])); 13393 if ((multiplier != 0.0) && (divisor != 0.0)) { 13394 multiplier = multiplier / divisor; 13395 /* Watch out for NANs. */ 13396 if (multiplier == multiplier) { 13397 newvertex[0] += multiplier * (edest[1] - eorg[1]); 13398 newvertex[1] += multiplier * (eorg[0] - edest[0]); 13399 } 13400 } 13401 } 13402 13403 setvertexmark(newvertex, mark(currentenc)); 13404 setvertextype(newvertex, SEGMENTVERTEX); 13405 if (b->verbose > 1) { 13406 printf( 13407 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n", 13408 eorg[0], eorg[1], edest[0], edest[1], 13409 newvertex[0], newvertex[1]); 13410 } 13411 /* Check whether the new vertex lies on an endpoint. */ 13412 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) || 13413 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) { 13414 printf("Error: Ran out of precision at (%.12g, %.12g).\n", 13415 newvertex[0], newvertex[1]); 13416 printf("I attempted to split a segment to a smaller size than\n"); 13417 printf(" can be accommodated by the finite precision of\n"); 13418 printf(" floating point arithmetic.\n"); 13419 precisionerror(); 13420 triexit(1); 13421 } 13422 /* Insert the splitting vertex. This should always succeed. */ 13423 success = insertvertex(m, b, newvertex, &enctri, ¤tenc, 13424 1, triflaws); 13425 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) { 13426 printf("Internal error in splitencsegs():\n"); 13427 printf(" Failure to split a segment.\n"); 13428 internalerror(); 13429 } 13430 if (m->steinerleft > 0) { 13431 m->steinerleft--; 13432 } 13433 /* Check the two new subsegments to see if they're encroached. */ 13434 //dummy = checkseg4encroach(m, b, ¤tenc); // commented out to get gcc 4.6 working 13435 checkseg4encroach(m, b, ¤tenc); // "dummy =" commented out to get gcc 4.6 working 13436 snextself(currentenc); 13437 //dummy = checkseg4encroach(m, b, ¤tenc); // commented out to get gcc 4.6 working 13438 checkseg4encroach(m, b, ¤tenc); // "dummy =" commented out to get gcc 4.6 working 13439 } 13440 13441 badsubsegdealloc(m, encloop); 13442 encloop = badsubsegtraverse(m); 13443 } 13444 } 13445 } 13446 13447 #endif /* not CDT_ONLY */ 13448 13449 /*****************************************************************************/ 13450 /* */ 13451 /* tallyfaces() Test every triangle in the mesh for quality measures. */ 13452 /* */ 13453 /*****************************************************************************/ 13454 13455 #ifndef CDT_ONLY 13456 13457 #ifdef ANSI_DECLARATORS 13458 void tallyfaces(struct mesh *m, struct behavior *b) 13459 #else /* not ANSI_DECLARATORS */ 13460 void tallyfaces(m, b) 13461 struct mesh *m; 13462 struct behavior *b; 13463 #endif /* not ANSI_DECLARATORS */ 13464 13465 { 13466 struct otri triangleloop; 13467 13468 if (b->verbose) { 13469 printf(" Making a list of bad triangles.\n"); 13470 } 13471 traversalinit(&m->triangles); 13472 triangleloop.orient = 0; 13473 triangleloop.tri = triangletraverse(m); 13474 while (triangleloop.tri != (triangle *) NULL) { 13475 /* If the triangle is bad, enqueue it. */ 13476 testtriangle(m, b, &triangleloop); 13477 triangleloop.tri = triangletraverse(m); 13478 } 13479 } 13480 13481 #endif /* not CDT_ONLY */ 13482 13483 /*****************************************************************************/ 13484 /* */ 13485 /* splittriangle() Inserts a vertex at the circumcenter of a triangle. */ 13486 /* Deletes the newly inserted vertex if it encroaches */ 13487 /* upon a segment. */ 13488 /* */ 13489 /*****************************************************************************/ 13490 13491 #ifndef CDT_ONLY 13492 13493 #ifdef ANSI_DECLARATORS 13494 void splittriangle(struct mesh *m, struct behavior *b, 13495 struct badtriang *badtri) 13496 #else /* not ANSI_DECLARATORS */ 13497 void splittriangle(m, b, badtri) 13498 struct mesh *m; 13499 struct behavior *b; 13500 struct badtriang *badtri; 13501 #endif /* not ANSI_DECLARATORS */ 13502 13503 { 13504 struct otri badotri; 13505 vertex borg, bdest, bapex; 13506 vertex newvertex; 13507 REAL xi, eta; 13508 enum insertvertexresult success; 13509 int errorflag; 13510 int i; 13511 13512 decode(badtri->poortri, badotri); 13513 org(badotri, borg); 13514 dest(badotri, bdest); 13515 apex(badotri, bapex); 13516 /* Make sure that this triangle is still the same triangle it was */ 13517 /* when it was tested and determined to be of bad quality. */ 13518 /* Subsequent transformations may have made it a different triangle. */ 13519 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) && 13520 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) { 13521 if (b->verbose > 1) { 13522 printf(" Splitting this triangle at its circumcenter:\n"); 13523 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0], 13524 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]); 13525 } 13526 13527 errorflag = 0; 13528 /* Create a new vertex at the triangle's circumcenter. */ 13529 newvertex = (vertex) poolalloc(&m->vertices); 13530 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1); 13531 13532 /* Check whether the new vertex lies on a triangle vertex. */ 13533 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) || 13534 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) || 13535 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) { 13536 if (!b->quiet) { 13537 printf( 13538 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n", 13539 newvertex[0], newvertex[1]); 13540 errorflag = 1; 13541 } 13542 vertexdealloc(m, newvertex); 13543 } else { 13544 for (i = 2; i < 2 + m->nextras; i++) { 13545 /* Interpolate the vertex attributes at the circumcenter. */ 13546 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i]) 13547 + eta * (bapex[i] - borg[i]); 13548 } 13549 /* The new vertex must be in the interior, and therefore is a */ 13550 /* free vertex with a marker of zero. */ 13551 setvertexmark(newvertex, 0); 13552 setvertextype(newvertex, FREEVERTEX); 13553 13554 /* Ensure that the handle `badotri' does not represent the longest */ 13555 /* edge of the triangle. This ensures that the circumcenter must */ 13556 /* fall to the left of this edge, so point location will work. */ 13557 /* (If the angle org-apex-dest exceeds 90 degrees, then the */ 13558 /* circumcenter lies outside the org-dest edge, and eta is */ 13559 /* negative. Roundoff error might prevent eta from being */ 13560 /* negative when it should be, so I test eta against xi.) */ 13561 if (eta < xi) { 13562 lprevself(badotri); 13563 } 13564 13565 /* Insert the circumcenter, searching from the edge of the triangle, */ 13566 /* and maintain the Delaunay property of the triangulation. */ 13567 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL, 13568 1, 1); 13569 if (success == SUCCESSFULVERTEX) { 13570 if (m->steinerleft > 0) { 13571 m->steinerleft--; 13572 } 13573 } else if (success == ENCROACHINGVERTEX) { 13574 /* If the newly inserted vertex encroaches upon a subsegment, */ 13575 /* delete the new vertex. */ 13576 undovertex(m, b); 13577 if (b->verbose > 1) { 13578 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]); 13579 } 13580 vertexdealloc(m, newvertex); 13581 } else if (success == VIOLATINGVERTEX) { 13582 /* Failed to insert the new vertex, but some subsegment was */ 13583 /* marked as being encroached. */ 13584 vertexdealloc(m, newvertex); 13585 } else { /* success == DUPLICATEVERTEX */ 13586 /* Couldn't insert the new vertex because a vertex is already there. */ 13587 if (!b->quiet) { 13588 printf( 13589 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n", 13590 newvertex[0], newvertex[1]); 13591 errorflag = 1; 13592 } 13593 vertexdealloc(m, newvertex); 13594 } 13595 } 13596 if (errorflag) { 13597 if (b->verbose) { 13598 printf(" The new vertex is at the circumcenter of triangle\n"); 13599 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", 13600 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]); 13601 } 13602 printf("This probably means that I am trying to refine triangles\n"); 13603 printf(" to a smaller size than can be accommodated by the finite\n"); 13604 printf(" precision of floating point arithmetic. (You can be\n"); 13605 printf(" sure of this if I fail to terminate.)\n"); 13606 precisionerror(); 13607 } 13608 } 13609 } 13610 13611 #endif /* not CDT_ONLY */ 13612 13613 /*****************************************************************************/ 13614 /* */ 13615 /* enforcequality() Remove all the encroached subsegments and bad */ 13616 /* triangles from the triangulation. */ 13617 /* */ 13618 /*****************************************************************************/ 13619 13620 #ifndef CDT_ONLY 13621 13622 #ifdef ANSI_DECLARATORS 13623 void enforcequality(struct mesh *m, struct behavior *b) 13624 #else /* not ANSI_DECLARATORS */ 13625 void enforcequality(m, b) 13626 struct mesh *m; 13627 struct behavior *b; 13628 #endif /* not ANSI_DECLARATORS */ 13629 13630 { 13631 struct badtriang *badtri; 13632 int i; 13633 13634 if (!b->quiet) { 13635 printf("Adding Steiner points to enforce quality.\n"); 13636 } 13637 /* Initialize the pool of encroached subsegments. */ 13638 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK, 13639 BADSUBSEGPERBLOCK, 0); 13640 if (b->verbose) { 13641 printf(" Looking for encroached subsegments.\n"); 13642 } 13643 /* Test all segments to see if they're encroached. */ 13644 tallyencs(m, b); 13645 if (b->verbose && (m->badsubsegs.items > 0)) { 13646 printf(" Splitting encroached subsegments.\n"); 13647 } 13648 /* Fix encroached subsegments without noting bad triangles. */ 13649 splitencsegs(m, b, 0); 13650 /* At this point, if we haven't run out of Steiner points, the */ 13651 /* triangulation should be (conforming) Delaunay. */ 13652 13653 /* Next, we worry about enforcing triangle quality. */ 13654 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) { 13655 /* Initialize the pool of bad triangles. */ 13656 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK, 13657 BADTRIPERBLOCK, 0); 13658 /* Initialize the queues of bad triangles. */ 13659 for (i = 0; i < 4096; i++) { 13660 m->queuefront[i] = (struct badtriang *) NULL; 13661 } 13662 m->firstnonemptyq = -1; 13663 /* Test all triangles to see if they're bad. */ 13664 tallyfaces(m, b); 13665 /* Initialize the pool of recently flipped triangles. */ 13666 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK, 13667 FLIPSTACKERPERBLOCK, 0); 13668 m->checkquality = 1; 13669 if (b->verbose) { 13670 printf(" Splitting bad triangles.\n"); 13671 } 13672 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) { 13673 /* Fix one bad triangle by inserting a vertex at its circumcenter. */ 13674 badtri = dequeuebadtriang(m); 13675 splittriangle(m, b, badtri); 13676 if (m->badsubsegs.items > 0) { 13677 /* Put bad triangle back in queue for another try later. */ 13678 enqueuebadtriang(m, b, badtri); 13679 /* Fix any encroached subsegments that resulted. */ 13680 /* Record any new bad triangles that result. */ 13681 splitencsegs(m, b, 1); 13682 } else { 13683 /* Return the bad triangle to the pool. */ 13684 pooldealloc(&m->badtriangles, (VOID *) badtri); 13685 } 13686 } 13687 } 13688 /* At this point, if the "-D" switch was selected and we haven't run out */ 13689 /* of Steiner points, the triangulation should be (conforming) Delaunay */ 13690 /* and have no low-quality triangles. */ 13691 13692 /* Might we have run out of Steiner points too soon? */ 13693 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) && 13694 (m->steinerleft == 0)) { 13695 printf("\nWarning: I ran out of Steiner points, but the mesh has\n"); 13696 if (m->badsubsegs.items == 1) { 13697 printf(" one encroached subsegment, and therefore might not be truly\n" 13698 ); 13699 } else { 13700 printf(" %ld encroached subsegments, and therefore might not be truly\n" 13701 , m->badsubsegs.items); 13702 } 13703 printf(" Delaunay. If the Delaunay property is important to you,\n"); 13704 printf(" try increasing the number of Steiner points (controlled by\n"); 13705 printf(" the -S switch) slightly and try again.\n\n"); 13706 } 13707 } 13708 13709 #endif /* not CDT_ONLY */ 13710 13713 /********* Mesh quality maintenance ends here *********/ 13714 13715 /*****************************************************************************/ 13716 /* */ 13717 /* highorder() Create extra nodes for quadratic subparametric elements. */ 13718 /* */ 13719 /*****************************************************************************/ 13720 13721 #ifdef ANSI_DECLARATORS 13722 void highorder(struct mesh *m, struct behavior *b) 13723 #else /* not ANSI_DECLARATORS */ 13724 void highorder(m, b) 13725 struct mesh *m; 13726 struct behavior *b; 13727 #endif /* not ANSI_DECLARATORS */ 13728 13729 { 13730 struct otri triangleloop, trisym; 13731 struct osub checkmark; 13732 vertex newvertex; 13733 vertex torg, tdest; 13734 int i; 13735 triangle ptr; /* Temporary variable used by sym(). */ 13736 subseg sptr; /* Temporary variable used by tspivot(). */ 13737 13738 if (!b->quiet) { 13739 printf("Adding vertices for second-order triangles.\n"); 13740 } 13741 /* The following line ensures that dead items in the pool of nodes */ 13742 /* cannot be allocated for the extra nodes associated with high */ 13743 /* order elements. This ensures that the primary nodes (at the */ 13744 /* corners of elements) will occur earlier in the output files, and */ 13745 /* have lower indices, than the extra nodes. */ 13746 m->vertices.deaditemstack = (VOID *) NULL; 13747 13748 traversalinit(&m->triangles); 13749 triangleloop.tri = triangletraverse(m); 13750 /* To loop over the set of edges, loop over all triangles, and look at */ 13751 /* the three edges of each triangle. If there isn't another triangle */ 13752 /* adjacent to the edge, operate on the edge. If there is another */ 13753 /* adjacent triangle, operate on the edge only if the current triangle */ 13754 /* has a smaller pointer than its neighbor. This way, each edge is */ 13755 /* considered only once. */ 13756 while (triangleloop.tri != (triangle *) NULL) { 13757 for (triangleloop.orient = 0; triangleloop.orient < 3; 13758 triangleloop.orient++) { 13759 sym(triangleloop, trisym); 13760 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) { 13761 org(triangleloop, torg); 13762 dest(triangleloop, tdest); 13763 /* Create a new node in the middle of the edge. Interpolate */ 13764 /* its attributes. */ 13765 newvertex = (vertex) poolalloc(&m->vertices); 13766 for (i = 0; i < 2 + m->nextras; i++) { 13767 newvertex[i] = 0.5 * (torg[i] + tdest[i]); 13768 } 13769 /* Set the new node's marker to zero or one, depending on */ 13770 /* whether it lies on a boundary. */ 13771 setvertexmark(newvertex, trisym.tri == m->dummytri); 13772 setvertextype(newvertex, 13773 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX); 13774 if (b->usesegments) { 13775 tspivot(triangleloop, checkmark); 13776 /* If this edge is a segment, transfer the marker to the new node. */ 13777 if (checkmark.ss != m->dummysub) { 13778 setvertexmark(newvertex, mark(checkmark)); 13779 setvertextype(newvertex, SEGMENTVERTEX); 13780 } 13781 } 13782 if (b->verbose > 1) { 13783 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]); 13784 } 13785 /* Record the new node in the (one or two) adjacent elements. */ 13786 triangleloop.tri[m->highorderindex + triangleloop.orient] = 13787 (triangle) newvertex; 13788 if (trisym.tri != m->dummytri) { 13789 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex; 13790 } 13791 } 13792 } 13793 triangleloop.tri = triangletraverse(m); 13794 } 13795 } 13796 13797 /********* File I/O routines begin here *********/ 13801 /*****************************************************************************/ 13802 /* */ 13803 /* readline() Read a nonempty line from a file. */ 13804 /* */ 13805 /* A line is considered "nonempty" if it contains something that looks like */ 13806 /* a number. Comments (prefaced by `#') are ignored. */ 13807 /* */ 13808 /*****************************************************************************/ 13809 13810 #ifndef TRILIBRARY 13811 13812 #ifdef ANSI_DECLARATORS 13813 char *readline(char *string, FILE *infile, char *infilename) 13814 #else /* not ANSI_DECLARATORS */ 13815 char *readline(string, infile, infilename) 13816 char *string; 13817 FILE *infile; 13818 char *infilename; 13819 #endif /* not ANSI_DECLARATORS */ 13820 13821 { 13822 char *result; 13823 13824 /* Search for something that looks like a number. */ 13825 do { 13826 result = fgets(string, INPUTLINESIZE, infile); 13827 if (result == (char *) NULL) { 13828 printf(" Error: Unexpected end of file in %s.\n", infilename); 13829 triexit(1); 13830 } 13831 /* Skip anything that doesn't look like a number, a comment, */ 13832 /* or the end of a line. */ 13833 while ((*result != '\0') && (*result != '#') 13834 && (*result != '.') && (*result != '+') && (*result != '-') 13835 && ((*result < '0') || (*result > '9'))) { 13836 result++; 13837 } 13838 /* If it's a comment or end of line, read another line and try again. */ 13839 } while ((*result == '#') || (*result == '\0')); 13840 return result; 13841 } 13842 13843 #endif /* not TRILIBRARY */ 13844 13845 /*****************************************************************************/ 13846 /* */ 13847 /* findfield() Find the next field of a string. */ 13848 /* */ 13849 /* Jumps past the current field by searching for whitespace, then jumps */ 13850 /* past the whitespace to find the next field. */ 13851 /* */ 13852 /*****************************************************************************/ 13853 13854 #ifndef TRILIBRARY 13855 13856 #ifdef ANSI_DECLARATORS 13857 char *findfield(char *string) 13858 #else /* not ANSI_DECLARATORS */ 13859 char *findfield(string) 13860 char *string; 13861 #endif /* not ANSI_DECLARATORS */ 13862 13863 { 13864 char *result; 13865 13866 result = string; 13867 /* Skip the current field. Stop upon reaching whitespace. */ 13868 while ((*result != '\0') && (*result != '#') 13869 && (*result != ' ') && (*result != '\t')) { 13870 result++; 13871 } 13872 /* Now skip the whitespace and anything else that doesn't look like a */ 13873 /* number, a comment, or the end of a line. */ 13874 while ((*result != '\0') && (*result != '#') 13875 && (*result != '.') && (*result != '+') && (*result != '-') 13876 && ((*result < '0') || (*result > '9'))) { 13877 result++; 13878 } 13879 /* Check for a comment (prefixed with `#'). */ 13880 if (*result == '#') { 13881 *result = '\0'; 13882 } 13883 return result; 13884 } 13885 13886 #endif /* not TRILIBRARY */ 13887 13888 /*****************************************************************************/ 13889 /* */ 13890 /* readnodes() Read the vertices from a file, which may be a .node or */ 13891 /* .poly file. */ 13892 /* */ 13893 /*****************************************************************************/ 13894 13895 #ifndef TRILIBRARY 13896 13897 #ifdef ANSI_DECLARATORS 13898 void readnodes(struct mesh *m, struct behavior *b, char *nodefilename, 13899 char* polyfilename, FILE **polyfile) 13900 #else /* not ANSI_DECLARATORS */ 13901 void readnodes(m, b, nodefilename, polyfilename, polyfile) 13902 struct mesh *m; 13903 struct behavior *b; 13904 char *nodefilename; 13905 char* polyfilename; 13906 FILE **polyfile; 13907 #endif /* not ANSI_DECLARATORS */ 13908 13909 { 13910 FILE *infile; 13911 vertex vertexloop; 13912 char inputline[INPUTLINESIZE]; 13913 char *stringptr; 13914 char *infilename; 13915 REAL x, y; 13916 int firstnode; 13917 int nodemarkers; 13918 int currentmarker; 13919 int i, j; 13920 13921 if (b->poly) { 13922 /* Read the vertices from a .poly file. */ 13923 if (!b->quiet) { 13924 printf("Opening %s.\n", polyfilename); 13925 } 13926 * polyfile = fopen(polyfilename, "r"); 13927 if (*polyfile == (FILE *) NULL) { 13928 printf(" Error: Cannot access file %s.\n", polyfilename); 13929 triexit(1); 13930 } 13931 /* Read number of vertices, number of dimensions, number of vertex */ 13932 /* attributes, and number of boundary markers. */ 13933 stringptr = readline(inputline,* polyfile, polyfilename); 13934 m->invertices = (int) strtol(stringptr, &stringptr, 0); 13935 stringptr = findfield(stringptr); 13936 if (*stringptr == '\0') { 13937 m->mesh_dim = 2; 13938 } else { 13939 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0); 13940 } 13941 stringptr = findfield(stringptr); 13942 if (*stringptr == '\0') { 13943 m->nextras = 0; 13944 } else { 13945 m->nextras = (int) strtol(stringptr, &stringptr, 0); 13946 } 13947 stringptr = findfield(stringptr); 13948 if (*stringptr == '\0') { 13949 nodemarkers = 0; 13950 } else { 13951 nodemarkers = (int) strtol(stringptr, &stringptr, 0); 13952 } 13953 if (m->invertices > 0) { 13954 infile =* polyfile; 13955 infilename = polyfilename; 13956 m->readnodefile = 0; 13957 } else { 13958 /* If the .poly file claims there are zero vertices, that means that */ 13959 /* the vertices should be read from a separate .node file. */ 13960 m->readnodefile = 1; 13961 infilename = nodefilename; 13962 } 13963 } else { 13964 m->readnodefile = 1; 13965 infilename = nodefilename; 13966 * polyfile = (FILE *) NULL; 13967 } 13968 13969 if (m->readnodefile) { 13970 /* Read the vertices from a .node file. */ 13971 if (!b->quiet) { 13972 printf("Opening %s.\n", nodefilename); 13973 } 13974 infile = fopen(nodefilename, "r"); 13975 if (infile == (FILE *) NULL) { 13976 printf(" Error: Cannot access file %s.\n", nodefilename); 13977 triexit(1); 13978 } 13979 /* Read number of vertices, number of dimensions, number of vertex */ 13980 /* attributes, and number of boundary markers. */ 13981 stringptr = readline(inputline, infile, nodefilename); 13982 m->invertices = (int) strtol(stringptr, &stringptr, 0); 13983 stringptr = findfield(stringptr); 13984 if (*stringptr == '\0') { 13985 m->mesh_dim = 2; 13986 } else { 13987 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0); 13988 } 13989 stringptr = findfield(stringptr); 13990 if (*stringptr == '\0') { 13991 m->nextras = 0; 13992 } else { 13993 m->nextras = (int) strtol(stringptr, &stringptr, 0); 13994 } 13995 stringptr = findfield(stringptr); 13996 if (*stringptr == '\0') { 13997 nodemarkers = 0; 13998 } else { 13999 nodemarkers = (int) strtol(stringptr, &stringptr, 0); 14000 } 14001 } 14002 14003 if (m->invertices < 3) { 14004 printf("Error: Input must have at least three input vertices.\n"); 14005 triexit(1); 14006 } 14007 if (m->mesh_dim != 2) { 14008 printf("Error: Triangle only works with two-dimensional meshes.\n"); 14009 triexit(1); 14010 } 14011 if (m->nextras == 0) { 14012 b->weighted = 0; 14013 } 14014 14015 initializevertexpool(m, b); 14016 14017 /* Read the vertices. */ 14018 for (i = 0; i < m->invertices; i++) { 14019 vertexloop = (vertex) poolalloc(&m->vertices); 14020 stringptr = readline(inputline, infile, infilename); 14021 if (i == 0) { 14022 firstnode = (int) strtol(stringptr, &stringptr, 0); 14023 if ((firstnode == 0) || (firstnode == 1)) { 14024 b->firstnumber = firstnode; 14025 } 14026 } 14027 stringptr = findfield(stringptr); 14028 if (*stringptr == '\0') { 14029 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i); 14030 triexit(1); 14031 } 14032 x = (REAL) strtod(stringptr, &stringptr); 14033 stringptr = findfield(stringptr); 14034 if (*stringptr == '\0') { 14035 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i); 14036 triexit(1); 14037 } 14038 y = (REAL) strtod(stringptr, &stringptr); 14039 vertexloop[0] = x; 14040 vertexloop[1] = y; 14041 /* Read the vertex attributes. */ 14042 for (j = 2; j < 2 + m->nextras; j++) { 14043 stringptr = findfield(stringptr); 14044 if (*stringptr == '\0') { 14045 vertexloop[j] = 0.0; 14046 } else { 14047 vertexloop[j] = (REAL) strtod(stringptr, &stringptr); 14048 } 14049 } 14050 if (nodemarkers) { 14051 /* Read a vertex marker. */ 14052 stringptr = findfield(stringptr); 14053 if (*stringptr == '\0') { 14054 setvertexmark(vertexloop, 0); 14055 } else { 14056 currentmarker = (int) strtol(stringptr, &stringptr, 0); 14057 setvertexmark(vertexloop, currentmarker); 14058 } 14059 } else { 14060 /* If no markers are specified in the file, they default to zero. */ 14061 setvertexmark(vertexloop, 0); 14062 } 14063 setvertextype(vertexloop, INPUTVERTEX); 14064 /* Determine the smallest and largest x and y coordinates. */ 14065 if (i == 0) { 14066 m->xmin = m->xmax = x; 14067 m->ymin = m->ymax = y; 14068 } else { 14069 m->xmin = (x < m->xmin) ? x : m->xmin; 14070 m->xmax = (x > m->xmax) ? x : m->xmax; 14071 m->ymin = (y < m->ymin) ? y : m->ymin; 14072 m->ymax = (y > m->ymax) ? y : m->ymax; 14073 } 14074 } 14075 if (m->readnodefile) { 14076 fclose(infile); 14077 } 14078 14079 /* Nonexistent x value used as a flag to mark circle events in sweepline */ 14080 /* Delaunay algorithm. */ 14081 m->xminextreme = 10 * m->xmin - 9 * m->xmax; 14082 } 14083 14084 #endif /* not TRILIBRARY */ 14085 14086 /*****************************************************************************/ 14087 /* */ 14088 /* transfernodes() Read the vertices from memory. */ 14089 /* */ 14090 /*****************************************************************************/ 14091 14092 #ifdef TRILIBRARY 14093 14094 #ifdef ANSI_DECLARATORS 14095 void transfernodes(struct mesh *m, struct behavior *b, REAL* pointlist, 14096 REAL* pointattriblist, int* pointmarkerlist, 14097 int numberofpoints, int numberofpointattribs) 14098 #else /* not ANSI_DECLARATORS */ 14099 void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist, 14100 numberofpoints, numberofpointattribs) 14101 struct mesh *m; 14102 struct behavior *b; 14103 REAL* pointlist; 14104 REAL* pointattriblist; 14105 int* pointmarkerlist; 14106 int numberofpoints; 14107 int numberofpointattribs; 14108 #endif /* not ANSI_DECLARATORS */ 14109 14110 { 14111 vertex vertexloop; 14112 REAL x, y; 14113 int i, j; 14114 int coordindex; 14115 int attribindex; 14116 14117 m->invertices = numberofpoints; 14118 m->mesh_dim = 2; 14119 m->nextras = numberofpointattribs; 14120 m->readnodefile = 0; 14121 if (m->invertices < 3) { 14122 printf("Error: Input must have at least three input vertices.\n"); 14123 triexit(1); 14124 } 14125 if (m->nextras == 0) { 14126 b->weighted = 0; 14127 } 14128 14129 initializevertexpool(m, b); 14130 14131 /* Read the vertices. */ 14132 coordindex = 0; 14133 attribindex = 0; 14134 for (i = 0; i < m->invertices; i++) { 14135 vertexloop = (vertex) poolalloc(&m->vertices); 14136 /* Read the vertex coordinates. */ 14137 x = vertexloop[0] = pointlist[coordindex++]; 14138 y = vertexloop[1] = pointlist[coordindex++]; 14139 /* Read the vertex attributes. */ 14140 for (j = 0; j < numberofpointattribs; j++) { 14141 vertexloop[2 + j] = pointattriblist[attribindex++]; 14142 } 14143 if (pointmarkerlist != (int *) NULL) { 14144 /* Read a vertex marker. */ 14145 setvertexmark(vertexloop, pointmarkerlist[i]); 14146 } else { 14147 /* If no markers are specified, they default to zero. */ 14148 setvertexmark(vertexloop, 0); 14149 } 14150 setvertextype(vertexloop, INPUTVERTEX); 14151 /* Determine the smallest and largest x and y coordinates. */ 14152 if (i == 0) { 14153 m->xmin = m->xmax = x; 14154 m->ymin = m->ymax = y; 14155 } else { 14156 m->xmin = (x < m->xmin) ? x : m->xmin; 14157 m->xmax = (x > m->xmax) ? x : m->xmax; 14158 m->ymin = (y < m->ymin) ? y : m->ymin; 14159 m->ymax = (y > m->ymax) ? y : m->ymax; 14160 } 14161 } 14162 14163 /* Nonexistent x value used as a flag to mark circle events in sweepline */ 14164 /* Delaunay algorithm. */ 14165 m->xminextreme = 10 * m->xmin - 9 * m->xmax; 14166 } 14167 14168 #endif /* TRILIBRARY */ 14169 14170 /*****************************************************************************/ 14171 /* */ 14172 /* readholes() Read the holes, and possibly regional attributes and area */ 14173 /* constraints, from a .poly file. */ 14174 /* */ 14175 /*****************************************************************************/ 14176 14177 #ifndef TRILIBRARY 14178 14179 #ifdef ANSI_DECLARATORS 14180 void readholes(struct mesh *m, struct behavior *b, 14181 FILE* polyfile, char* polyfilename, REAL **hlist, int *holes, 14182 REAL **rlist, int *regions) 14183 #else /* not ANSI_DECLARATORS */ 14184 void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions) 14185 struct mesh *m; 14186 struct behavior *b; 14187 FILE* polyfile; 14188 char* polyfilename; 14189 REAL **hlist; 14190 int *holes; 14191 REAL **rlist; 14192 int *regions; 14193 #endif /* not ANSI_DECLARATORS */ 14194 14195 { 14196 REAL *holelist; 14197 REAL *regionlist; 14198 char inputline[INPUTLINESIZE]; 14199 char *stringptr; 14200 int index; 14201 int i; 14202 14203 /* Read the holes. */ 14204 stringptr = readline(inputline, polyfile, polyfilename); 14205 *holes = (int) strtol(stringptr, &stringptr, 0); 14206 if (*holes > 0) { 14207 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL)); 14208 *hlist = holelist; 14209 for (i = 0; i < 2 * *holes; i += 2) { 14210 stringptr = readline(inputline, polyfile, polyfilename); 14211 stringptr = findfield(stringptr); 14212 if (*stringptr == '\0') { 14213 printf("Error: Hole %d has no x coordinate.\n", 14214 b->firstnumber + (i >> 1)); 14215 triexit(1); 14216 } else { 14217 holelist[i] = (REAL) strtod(stringptr, &stringptr); 14218 } 14219 stringptr = findfield(stringptr); 14220 if (*stringptr == '\0') { 14221 printf("Error: Hole %d has no y coordinate.\n", 14222 b->firstnumber + (i >> 1)); 14223 triexit(1); 14224 } else { 14225 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr); 14226 } 14227 } 14228 } else { 14229 *hlist = (REAL *) NULL; 14230 } 14231 14232 #ifndef CDT_ONLY 14233 if ((b->regionattrib || b->vararea) && !b->refine) { 14234 /* Read the area constraints. */ 14235 stringptr = readline(inputline, polyfile, polyfilename); 14236 *regions = (int) strtol(stringptr, &stringptr, 0); 14237 if (*regions > 0) { 14238 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL)); 14239 *rlist = regionlist; 14240 index = 0; 14241 for (i = 0; i < *regions; i++) { 14242 stringptr = readline(inputline, polyfile, polyfilename); 14243 stringptr = findfield(stringptr); 14244 if (*stringptr == '\0') { 14245 printf("Error: Region %d has no x coordinate.\n", 14246 b->firstnumber + i); 14247 triexit(1); 14248 } else { 14249 regionlist[index++] = (REAL) strtod(stringptr, &stringptr); 14250 } 14251 stringptr = findfield(stringptr); 14252 if (*stringptr == '\0') { 14253 printf("Error: Region %d has no y coordinate.\n", 14254 b->firstnumber + i); 14255 triexit(1); 14256 } else { 14257 regionlist[index++] = (REAL) strtod(stringptr, &stringptr); 14258 } 14259 stringptr = findfield(stringptr); 14260 if (*stringptr == '\0') { 14261 printf( 14262 "Error: Region %d has no region attribute or area constraint.\n", 14263 b->firstnumber + i); 14264 triexit(1); 14265 } else { 14266 regionlist[index++] = (REAL) strtod(stringptr, &stringptr); 14267 } 14268 stringptr = findfield(stringptr); 14269 if (*stringptr == '\0') { 14270 regionlist[index] = regionlist[index - 1]; 14271 } else { 14272 regionlist[index] = (REAL) strtod(stringptr, &stringptr); 14273 } 14274 index++; 14275 } 14276 } 14277 } else { 14278 /* Set `*regions' to zero to avoid an accidental free() later. */ 14279 *regions = 0; 14280 *rlist = (REAL *) NULL; 14281 } 14282 #endif /* not CDT_ONLY */ 14283 14284 fclose(polyfile); 14285 } 14286 14287 #endif /* not TRILIBRARY */ 14288 14289 /*****************************************************************************/ 14290 /* */ 14291 /* finishfile() Write the command line to the output file so the user */ 14292 /* can remember how the file was generated. Close the file. */ 14293 /* */ 14294 /*****************************************************************************/ 14295 14296 #ifndef TRILIBRARY 14297 14298 #ifdef ANSI_DECLARATORS 14299 void finishfile(FILE *outfile, int argc, char **argv) 14300 #else /* not ANSI_DECLARATORS */ 14301 void finishfile(outfile, argc, argv) 14302 FILE *outfile; 14303 int argc; 14304 char **argv; 14305 #endif /* not ANSI_DECLARATORS */ 14306 14307 { 14308 int i; 14309 14310 fprintf(outfile, "# Generated by"); 14311 for (i = 0; i < argc; i++) { 14312 fprintf(outfile, " "); 14313 fputs(argv[i], outfile); 14314 } 14315 fprintf(outfile, "\n"); 14316 fclose(outfile); 14317 } 14318 14319 #endif /* not TRILIBRARY */ 14320 14321 /*****************************************************************************/ 14322 /* */ 14323 /* writenodes() Number the vertices and write them to a .node file. */ 14324 /* */ 14325 /* To save memory, the vertex numbers are written over the boundary markers */ 14326 /* after the vertices are written to a file. */ 14327 /* */ 14328 /*****************************************************************************/ 14329 14330 #ifdef TRILIBRARY 14331 14332 #ifdef ANSI_DECLARATORS 14333 void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, 14334 REAL **pointattriblist, int **pointmarkerlist) 14335 #else /* not ANSI_DECLARATORS */ 14336 void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist) 14337 struct mesh *m; 14338 struct behavior *b; 14339 REAL **pointlist; 14340 REAL **pointattriblist; 14341 int **pointmarkerlist; 14342 #endif /* not ANSI_DECLARATORS */ 14343 14344 #else /* not TRILIBRARY */ 14345 14346 #ifdef ANSI_DECLARATORS 14347 void writenodes(struct mesh *m, struct behavior *b, char *nodefilename, 14348 int argc, char **argv) 14349 #else /* not ANSI_DECLARATORS */ 14350 void writenodes(m, b, nodefilename, argc, argv) 14351 struct mesh *m; 14352 struct behavior *b; 14353 char *nodefilename; 14354 int argc; 14355 char **argv; 14356 #endif /* not ANSI_DECLARATORS */ 14357 14358 #endif /* not TRILIBRARY */ 14359 14360 { 14361 #ifdef TRILIBRARY 14362 REAL* plist; 14363 REAL* palist; 14364 int* pmlist; 14365 int coordindex; 14366 int attribindex; 14367 #else /* not TRILIBRARY */ 14368 FILE *outfile; 14369 #endif /* not TRILIBRARY */ 14370 vertex vertexloop; 14371 long outvertices; 14372 int vertexnumber; 14373 int i; 14374 14375 if (b->jettison) { 14376 outvertices = m->vertices.items - m->undeads; 14377 } else { 14378 outvertices = m->vertices.items; 14379 } 14380 14381 #ifdef TRILIBRARY 14382 if (!b->quiet) { 14383 printf("Writing vertices.\n"); 14384 } 14385 /* Allocate memory for output vertices if necessary. */ 14386 if (*pointlist == (REAL *) NULL) { 14387 * pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL))); 14388 } 14389 /* Allocate memory for output vertex attributes if necessary. */ 14390 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) { 14391 * pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras * 14392 sizeof(REAL))); 14393 } 14394 /* Allocate memory for output vertex markers if necessary. */ 14395 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) { 14396 * pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int))); 14397 } 14398 plist =* pointlist; 14399 palist =* pointattriblist; 14400 pmlist =* pointmarkerlist; 14401 coordindex = 0; 14402 attribindex = 0; 14403 #else /* not TRILIBRARY */ 14404 if (!b->quiet) { 14405 printf("Writing %s.\n", nodefilename); 14406 } 14407 outfile = fopen(nodefilename, "w"); 14408 if (outfile == (FILE *) NULL) { 14409 printf(" Error: Cannot create file %s.\n", nodefilename); 14410 triexit(1); 14411 } 14412 /* Number of vertices, number of dimensions, number of vertex attributes, */ 14413 /* and number of boundary markers (zero or one). */ 14414 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim, 14415 m->nextras, 1 - b->nobound); 14416 #endif /* not TRILIBRARY */ 14417 14418 traversalinit(&m->vertices); 14419 vertexnumber = b->firstnumber; 14420 vertexloop = vertextraverse(m); 14421 while (vertexloop != (vertex) NULL) { 14422 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) { 14423 #ifdef TRILIBRARY 14424 /* X and y coordinates. */ 14425 plist[coordindex++] = vertexloop[0]; 14426 plist[coordindex++] = vertexloop[1]; 14427 /* Vertex attributes. */ 14428 for (i = 0; i < m->nextras; i++) { 14429 palist[attribindex++] = vertexloop[2 + i]; 14430 } 14431 if (!b->nobound) { 14432 /* Copy the boundary marker. */ 14433 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop); 14434 } 14435 #else /* not TRILIBRARY */ 14436 /* Vertex number, x and y coordinates. */ 14437 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0], 14438 vertexloop[1]); 14439 for (i = 0; i < m->nextras; i++) { 14440 /* Write an attribute. */ 14441 fprintf(outfile, " %.17g", vertexloop[i + 2]); 14442 } 14443 if (b->nobound) { 14444 fprintf(outfile, "\n"); 14445 } else { 14446 /* Write the boundary marker. */ 14447 fprintf(outfile, " %d\n", vertexmark(vertexloop)); 14448 } 14449 #endif /* not TRILIBRARY */ 14450 14451 setvertexmark(vertexloop, vertexnumber); 14452 vertexnumber++; 14453 } 14454 vertexloop = vertextraverse(m); 14455 } 14456 14457 #ifndef TRILIBRARY 14458 finishfile(outfile, argc, argv); 14459 #endif /* not TRILIBRARY */ 14460 } 14461 14462 /*****************************************************************************/ 14463 /* */ 14464 /* numbernodes() Number the vertices. */ 14465 /* */ 14466 /* Each vertex is assigned a marker equal to its number. */ 14467 /* */ 14468 /* Used when writenodes() is not called because no .node file is written. */ 14469 /* */ 14470 /*****************************************************************************/ 14471 14472 #ifdef ANSI_DECLARATORS 14473 void numbernodes(struct mesh *m, struct behavior *b) 14474 #else /* not ANSI_DECLARATORS */ 14475 void numbernodes(m, b) 14476 struct mesh *m; 14477 struct behavior *b; 14478 #endif /* not ANSI_DECLARATORS */ 14479 14480 { 14481 vertex vertexloop; 14482 int vertexnumber; 14483 14484 traversalinit(&m->vertices); 14485 vertexnumber = b->firstnumber; 14486 vertexloop = vertextraverse(m); 14487 while (vertexloop != (vertex) NULL) { 14488 setvertexmark(vertexloop, vertexnumber); 14489 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) { 14490 vertexnumber++; 14491 } 14492 vertexloop = vertextraverse(m); 14493 } 14494 } 14495 14496 /*****************************************************************************/ 14497 /* */ 14498 /* writeelements() Write the triangles to an .ele file. */ 14499 /* */ 14500 /*****************************************************************************/ 14501 14502 #ifdef TRILIBRARY 14503 14504 #ifdef ANSI_DECLARATORS 14505 void writeelements(struct mesh *m, struct behavior *b, 14506 int **trianglelist, REAL **triangleattriblist) 14507 #else /* not ANSI_DECLARATORS */ 14508 void writeelements(m, b, trianglelist, triangleattriblist) 14509 struct mesh *m; 14510 struct behavior *b; 14511 int **trianglelist; 14512 REAL **triangleattriblist; 14513 #endif /* not ANSI_DECLARATORS */ 14514 14515 #else /* not TRILIBRARY */ 14516 14517 #ifdef ANSI_DECLARATORS 14518 void writeelements(struct mesh *m, struct behavior *b, char *elefilename, 14519 int argc, char **argv) 14520 #else /* not ANSI_DECLARATORS */ 14521 void writeelements(m, b, elefilename, argc, argv) 14522 struct mesh *m; 14523 struct behavior *b; 14524 char *elefilename; 14525 int argc; 14526 char **argv; 14527 #endif /* not ANSI_DECLARATORS */ 14528 14529 #endif /* not TRILIBRARY */ 14530 14531 { 14532 #ifdef TRILIBRARY 14533 int *tlist; 14534 REAL *talist; 14535 int vertexindex; 14536 int attribindex; 14537 #else /* not TRILIBRARY */ 14538 FILE *outfile; 14539 #endif /* not TRILIBRARY */ 14540 struct otri triangleloop; 14541 vertex p1, p2, p3; 14542 vertex mid1, mid2, mid3; 14543 long elementnumber; 14544 int i; 14545 14546 #ifdef TRILIBRARY 14547 if (!b->quiet) { 14548 printf("Writing triangles.\n"); 14549 } 14550 /* Allocate memory for output triangles if necessary. */ 14551 if (*trianglelist == (int *) NULL) { 14552 *trianglelist = (int *) trimalloc((int) (m->triangles.items * 14553 ((b->order + 1) * (b->order + 2) / 14554 2) * sizeof(int))); 14555 } 14556 /* Allocate memory for output triangle attributes if necessary. */ 14557 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) { 14558 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items * 14559 m->eextras * 14560 sizeof(REAL))); 14561 } 14562 tlist = *trianglelist; 14563 talist = *triangleattriblist; 14564 vertexindex = 0; 14565 attribindex = 0; 14566 #else /* not TRILIBRARY */ 14567 if (!b->quiet) { 14568 printf("Writing %s.\n", elefilename); 14569 } 14570 outfile = fopen(elefilename, "w"); 14571 if (outfile == (FILE *) NULL) { 14572 printf(" Error: Cannot create file %s.\n", elefilename); 14573 triexit(1); 14574 } 14575 /* Number of triangles, vertices per triangle, attributes per triangle. */ 14576 fprintf(outfile, "%ld %d %d\n", m->triangles.items, 14577 (b->order + 1) * (b->order + 2) / 2, m->eextras); 14578 #endif /* not TRILIBRARY */ 14579 14580 traversalinit(&m->triangles); 14581 triangleloop.tri = triangletraverse(m); 14582 triangleloop.orient = 0; 14583 elementnumber = b->firstnumber; 14584 while (triangleloop.tri != (triangle *) NULL) { 14585 org(triangleloop, p1); 14586 dest(triangleloop, p2); 14587 apex(triangleloop, p3); 14588 if (b->order == 1) { 14589 #ifdef TRILIBRARY 14590 tlist[vertexindex++] = vertexmark(p1); 14591 tlist[vertexindex++] = vertexmark(p2); 14592 tlist[vertexindex++] = vertexmark(p3); 14593 #else /* not TRILIBRARY */ 14594 /* Triangle number, indices for three vertices. */ 14595 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber, 14596 vertexmark(p1), vertexmark(p2), vertexmark(p3)); 14597 #endif /* not TRILIBRARY */ 14598 } else { 14599 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1]; 14600 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2]; 14601 mid3 = (vertex) triangleloop.tri[m->highorderindex]; 14602 #ifdef TRILIBRARY 14603 tlist[vertexindex++] = vertexmark(p1); 14604 tlist[vertexindex++] = vertexmark(p2); 14605 tlist[vertexindex++] = vertexmark(p3); 14606 tlist[vertexindex++] = vertexmark(mid1); 14607 tlist[vertexindex++] = vertexmark(mid2); 14608 tlist[vertexindex++] = vertexmark(mid3); 14609 #else /* not TRILIBRARY */ 14610 /* Triangle number, indices for six vertices. */ 14611 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber, 14612 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1), 14613 vertexmark(mid2), vertexmark(mid3)); 14614 #endif /* not TRILIBRARY */ 14615 } 14616 14617 #ifdef TRILIBRARY 14618 for (i = 0; i < m->eextras; i++) { 14619 talist[attribindex++] = elemattribute(triangleloop, i); 14620 } 14621 #else /* not TRILIBRARY */ 14622 for (i = 0; i < m->eextras; i++) { 14623 fprintf(outfile, " %.17g", elemattribute(triangleloop, i)); 14624 } 14625 fprintf(outfile, "\n"); 14626 #endif /* not TRILIBRARY */ 14627 14628 triangleloop.tri = triangletraverse(m); 14629 elementnumber++; 14630 } 14631 14632 #ifndef TRILIBRARY 14633 finishfile(outfile, argc, argv); 14634 #endif /* not TRILIBRARY */ 14635 } 14636 14637 /*****************************************************************************/ 14638 /* */ 14639 /* writepoly() Write the segments and holes to a .poly file. */ 14640 /* */ 14641 /*****************************************************************************/ 14642 14643 #ifdef TRILIBRARY 14644 14645 #ifdef ANSI_DECLARATORS 14646 void writepoly(struct mesh *m, struct behavior *b, 14647 int **segmentlist, int **segmentmarkerlist) 14648 #else /* not ANSI_DECLARATORS */ 14649 void writepoly(m, b, segmentlist, segmentmarkerlist) 14650 struct mesh *m; 14651 struct behavior *b; 14652 int **segmentlist; 14653 int **segmentmarkerlist; 14654 #endif /* not ANSI_DECLARATORS */ 14655 14656 #else /* not TRILIBRARY */ 14657 14658 #ifdef ANSI_DECLARATORS 14659 void writepoly(struct mesh *m, struct behavior *b, char* polyfilename, 14660 REAL *holelist, int holes, REAL *regionlist, int regions, 14661 int argc, char **argv) 14662 #else /* not ANSI_DECLARATORS */ 14663 void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions, 14664 argc, argv) 14665 struct mesh *m; 14666 struct behavior *b; 14667 char* polyfilename; 14668 REAL *holelist; 14669 int holes; 14670 REAL *regionlist; 14671 int regions; 14672 int argc; 14673 char **argv; 14674 #endif /* not ANSI_DECLARATORS */ 14675 14676 #endif /* not TRILIBRARY */ 14677 14678 { 14679 #ifdef TRILIBRARY 14680 int *slist; 14681 int *smlist; 14682 int index; 14683 #else /* not TRILIBRARY */ 14684 FILE *outfile; 14685 long holenumber, regionnumber; 14686 #endif /* not TRILIBRARY */ 14687 struct osub subsegloop; 14688 vertex endpoint1, endpoint2; 14689 long subsegnumber; 14690 14691 #ifdef TRILIBRARY 14692 if (!b->quiet) { 14693 printf("Writing segments.\n"); 14694 } 14695 /* Allocate memory for output segments if necessary. */ 14696 if (*segmentlist == (int *) NULL) { 14697 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 * 14698 sizeof(int))); 14699 } 14700 /* Allocate memory for output segment markers if necessary. */ 14701 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) { 14702 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items * 14703 sizeof(int))); 14704 } 14705 slist = *segmentlist; 14706 smlist = *segmentmarkerlist; 14707 index = 0; 14708 #else /* not TRILIBRARY */ 14709 if (!b->quiet) { 14710 printf("Writing %s.\n", polyfilename); 14711 } 14712 outfile = fopen(polyfilename, "w"); 14713 if (outfile == (FILE *) NULL) { 14714 printf(" Error: Cannot create file %s.\n", polyfilename); 14715 triexit(1); 14716 } 14717 /* The zero indicates that the vertices are in a separate .node file. */ 14718 /* Followed by number of dimensions, number of vertex attributes, */ 14719 /* and number of boundary markers (zero or one). */ 14720 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras, 14721 1 - b->nobound); 14722 /* Number of segments, number of boundary markers (zero or one). */ 14723 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound); 14724 #endif /* not TRILIBRARY */ 14725 14726 traversalinit(&m->subsegs); 14727 subsegloop.ss = subsegtraverse(m); 14728 subsegloop.ssorient = 0; 14729 subsegnumber = b->firstnumber; 14730 while (subsegloop.ss != (subseg *) NULL) { 14731 sorg(subsegloop, endpoint1); 14732 sdest(subsegloop, endpoint2); 14733 #ifdef TRILIBRARY 14734 /* Copy indices of the segment's two endpoints. */ 14735 slist[index++] = vertexmark(endpoint1); 14736 slist[index++] = vertexmark(endpoint2); 14737 if (!b->nobound) { 14738 /* Copy the boundary marker. */ 14739 smlist[subsegnumber - b->firstnumber] = mark(subsegloop); 14740 } 14741 #else /* not TRILIBRARY */ 14742 /* Segment number, indices of its two endpoints, and possibly a marker. */ 14743 if (b->nobound) { 14744 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber, 14745 vertexmark(endpoint1), vertexmark(endpoint2)); 14746 } else { 14747 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber, 14748 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop)); 14749 } 14750 #endif /* not TRILIBRARY */ 14751 14752 subsegloop.ss = subsegtraverse(m); 14753 subsegnumber++; 14754 } 14755 14756 #ifndef TRILIBRARY 14757 #ifndef CDT_ONLY 14758 fprintf(outfile, "%d\n", holes); 14759 if (holes > 0) { 14760 for (holenumber = 0; holenumber < holes; holenumber++) { 14761 /* Hole number, x and y coordinates. */ 14762 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber, 14763 holelist[2 * holenumber], holelist[2 * holenumber + 1]); 14764 } 14765 } 14766 if (regions > 0) { 14767 fprintf(outfile, "%d\n", regions); 14768 for (regionnumber = 0; regionnumber < regions; regionnumber++) { 14769 /* Region number, x and y coordinates, attribute, maximum area. */ 14770 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n", 14771 b->firstnumber + regionnumber, 14772 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1], 14773 regionlist[4 * regionnumber + 2], 14774 regionlist[4 * regionnumber + 3]); 14775 } 14776 } 14777 #endif /* not CDT_ONLY */ 14778 14779 finishfile(outfile, argc, argv); 14780 #endif /* not TRILIBRARY */ 14781 } 14782 14783 /*****************************************************************************/ 14784 /* */ 14785 /* writeedges() Write the edges to an .edge file. */ 14786 /* */ 14787 /*****************************************************************************/ 14788 14789 #ifdef TRILIBRARY 14790 14791 #ifdef ANSI_DECLARATORS 14792 void writeedges(struct mesh *m, struct behavior *b, 14793 int **edgelist, int **edgemarkerlist) 14794 #else /* not ANSI_DECLARATORS */ 14795 void writeedges(m, b, edgelist, edgemarkerlist) 14796 struct mesh *m; 14797 struct behavior *b; 14798 int **edgelist; 14799 int **edgemarkerlist; 14800 #endif /* not ANSI_DECLARATORS */ 14801 14802 #else /* not TRILIBRARY */ 14803 14804 #ifdef ANSI_DECLARATORS 14805 void writeedges(struct mesh *m, struct behavior *b, char *edgefilename, 14806 int argc, char **argv) 14807 #else /* not ANSI_DECLARATORS */ 14808 void writeedges(m, b, edgefilename, argc, argv) 14809 struct mesh *m; 14810 struct behavior *b; 14811 char *edgefilename; 14812 int argc; 14813 char **argv; 14814 #endif /* not ANSI_DECLARATORS */ 14815 14816 #endif /* not TRILIBRARY */ 14817 14818 { 14819 #ifdef TRILIBRARY 14820 int *elist; 14821 int *emlist; 14822 int index; 14823 #else /* not TRILIBRARY */ 14824 FILE *outfile; 14825 #endif /* not TRILIBRARY */ 14826 struct otri triangleloop, trisym; 14827 struct osub checkmark; 14828 vertex p1, p2; 14829 long edgenumber; 14830 triangle ptr; /* Temporary variable used by sym(). */ 14831 subseg sptr; /* Temporary variable used by tspivot(). */ 14832 14833 #ifdef TRILIBRARY 14834 if (!b->quiet) { 14835 printf("Writing edges.\n"); 14836 } 14837 /* Allocate memory for edges if necessary. */ 14838 if (*edgelist == (int *) NULL) { 14839 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int))); 14840 } 14841 /* Allocate memory for edge markers if necessary. */ 14842 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) { 14843 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int))); 14844 } 14845 elist = *edgelist; 14846 emlist = *edgemarkerlist; 14847 index = 0; 14848 #else /* not TRILIBRARY */ 14849 if (!b->quiet) { 14850 printf("Writing %s.\n", edgefilename); 14851 } 14852 outfile = fopen(edgefilename, "w"); 14853 if (outfile == (FILE *) NULL) { 14854 printf(" Error: Cannot create file %s.\n", edgefilename); 14855 triexit(1); 14856 } 14857 /* Number of edges, number of boundary markers (zero or one). */ 14858 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound); 14859 #endif /* not TRILIBRARY */ 14860 14861 traversalinit(&m->triangles); 14862 triangleloop.tri = triangletraverse(m); 14863 edgenumber = b->firstnumber; 14864 /* To loop over the set of edges, loop over all triangles, and look at */ 14865 /* the three edges of each triangle. If there isn't another triangle */ 14866 /* adjacent to the edge, operate on the edge. If there is another */ 14867 /* adjacent triangle, operate on the edge only if the current triangle */ 14868 /* has a smaller pointer than its neighbor. This way, each edge is */ 14869 /* considered only once. */ 14870 while (triangleloop.tri != (triangle *) NULL) { 14871 for (triangleloop.orient = 0; triangleloop.orient < 3; 14872 triangleloop.orient++) { 14873 sym(triangleloop, trisym); 14874 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) { 14875 org(triangleloop, p1); 14876 dest(triangleloop, p2); 14877 #ifdef TRILIBRARY 14878 elist[index++] = vertexmark(p1); 14879 elist[index++] = vertexmark(p2); 14880 #endif /* TRILIBRARY */ 14881 if (b->nobound) { 14882 #ifndef TRILIBRARY 14883 /* Edge number, indices of two endpoints. */ 14884 fprintf(outfile, "%4ld %d %d\n", edgenumber, 14885 vertexmark(p1), vertexmark(p2)); 14886 #endif /* not TRILIBRARY */ 14887 } else { 14888 /* Edge number, indices of two endpoints, and a boundary marker. */ 14889 /* If there's no subsegment, the boundary marker is zero. */ 14890 if (b->usesegments) { 14891 tspivot(triangleloop, checkmark); 14892 if (checkmark.ss == m->dummysub) { 14893 #ifdef TRILIBRARY 14894 emlist[edgenumber - b->firstnumber] = 0; 14895 #else /* not TRILIBRARY */ 14896 fprintf(outfile, "%4ld %d %d %d\n", edgenumber, 14897 vertexmark(p1), vertexmark(p2), 0); 14898 #endif /* not TRILIBRARY */ 14899 } else { 14900 #ifdef TRILIBRARY 14901 emlist[edgenumber - b->firstnumber] = mark(checkmark); 14902 #else /* not TRILIBRARY */ 14903 fprintf(outfile, "%4ld %d %d %d\n", edgenumber, 14904 vertexmark(p1), vertexmark(p2), mark(checkmark)); 14905 #endif /* not TRILIBRARY */ 14906 } 14907 } else { 14908 #ifdef TRILIBRARY 14909 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri; 14910 #else /* not TRILIBRARY */ 14911 fprintf(outfile, "%4ld %d %d %d\n", edgenumber, 14912 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri); 14913 #endif /* not TRILIBRARY */ 14914 } 14915 } 14916 edgenumber++; 14917 } 14918 } 14919 triangleloop.tri = triangletraverse(m); 14920 } 14921 14922 #ifndef TRILIBRARY 14923 finishfile(outfile, argc, argv); 14924 #endif /* not TRILIBRARY */ 14925 } 14926 14927 /*****************************************************************************/ 14928 /* */ 14929 /* writevoronoi() Write the Voronoi diagram to a .v.node and .v.edge */ 14930 /* file. */ 14931 /* */ 14932 /* The Voronoi diagram is the geometric dual of the Delaunay triangulation. */ 14933 /* Hence, the Voronoi vertices are listed by traversing the Delaunay */ 14934 /* triangles, and the Voronoi edges are listed by traversing the Delaunay */ 14935 /* edges. */ 14936 /* */ 14937 /* WARNING: In order to assign numbers to the Voronoi vertices, this */ 14938 /* procedure messes up the subsegments or the extra nodes of every */ 14939 /* element. Hence, you should call this procedure last. */ 14940 /* */ 14941 /*****************************************************************************/ 14942 14943 #ifdef TRILIBRARY 14944 14945 #ifdef ANSI_DECLARATORS 14946 void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, 14947 REAL **vpointattriblist, int **vpointmarkerlist, 14948 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist) 14949 #else /* not ANSI_DECLARATORS */ 14950 void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist, 14951 vedgelist, vedgemarkerlist, vnormlist) 14952 struct mesh *m; 14953 struct behavior *b; 14954 REAL **vpointlist; 14955 REAL **vpointattriblist; 14956 int **vpointmarkerlist; 14957 int **vedgelist; 14958 int **vedgemarkerlist; 14959 REAL **vnormlist; 14960 #endif /* not ANSI_DECLARATORS */ 14961 14962 #else /* not TRILIBRARY */ 14963 14964 #ifdef ANSI_DECLARATORS 14965 void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename, 14966 char *vedgefilename, int argc, char **argv) 14967 #else /* not ANSI_DECLARATORS */ 14968 void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv) 14969 struct mesh *m; 14970 struct behavior *b; 14971 char *vnodefilename; 14972 char *vedgefilename; 14973 int argc; 14974 char **argv; 14975 #endif /* not ANSI_DECLARATORS */ 14976 14977 #endif /* not TRILIBRARY */ 14978 14979 { 14980 #ifdef TRILIBRARY 14981 REAL* plist; 14982 REAL* palist; 14983 int *elist; 14984 REAL *normlist; 14985 int coordindex; 14986 int attribindex; 14987 #else /* not TRILIBRARY */ 14988 FILE *outfile; 14989 #endif /* not TRILIBRARY */ 14990 struct otri triangleloop, trisym; 14991 vertex torg, tdest, tapex; 14992 REAL circumcenter[2]; 14993 REAL xi, eta; 14994 long vnodenumber, vedgenumber; 14995 int p1, p2; 14996 int i; 14997 triangle ptr; /* Temporary variable used by sym(). */ 14998 14999 #ifdef TRILIBRARY 15000 if (!b->quiet) { 15001 printf("Writing Voronoi vertices.\n"); 15002 } 15003 /* Allocate memory for Voronoi vertices if necessary. */ 15004 if (*vpointlist == (REAL *) NULL) { 15005 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 * 15006 sizeof(REAL))); 15007 } 15008 /* Allocate memory for Voronoi vertex attributes if necessary. */ 15009 if (*vpointattriblist == (REAL *) NULL) { 15010 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items * 15011 m->nextras * sizeof(REAL))); 15012 } 15013 *vpointmarkerlist = (int *) NULL; 15014 plist = *vpointlist; 15015 palist = *vpointattriblist; 15016 coordindex = 0; 15017 attribindex = 0; 15018 #else /* not TRILIBRARY */ 15019 if (!b->quiet) { 15020 printf("Writing %s.\n", vnodefilename); 15021 } 15022 outfile = fopen(vnodefilename, "w"); 15023 if (outfile == (FILE *) NULL) { 15024 printf(" Error: Cannot create file %s.\n", vnodefilename); 15025 triexit(1); 15026 } 15027 /* Number of triangles, two dimensions, number of vertex attributes, */ 15028 /* no markers. */ 15029 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0); 15030 #endif /* not TRILIBRARY */ 15031 15032 traversalinit(&m->triangles); 15033 triangleloop.tri = triangletraverse(m); 15034 triangleloop.orient = 0; 15035 vnodenumber = b->firstnumber; 15036 while (triangleloop.tri != (triangle *) NULL) { 15037 org(triangleloop, torg); 15038 dest(triangleloop, tdest); 15039 apex(triangleloop, tapex); 15040 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0); 15041 #ifdef TRILIBRARY 15042 /* X and y coordinates. */ 15043 plist[coordindex++] = circumcenter[0]; 15044 plist[coordindex++] = circumcenter[1]; 15045 for (i = 2; i < 2 + m->nextras; i++) { 15046 /* Interpolate the vertex attributes at the circumcenter. */ 15047 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i]) 15048 + eta * (tapex[i] - torg[i]); 15049 } 15050 #else /* not TRILIBRARY */ 15051 /* Voronoi vertex number, x and y coordinates. */ 15052 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0], 15053 circumcenter[1]); 15054 for (i = 2; i < 2 + m->nextras; i++) { 15055 /* Interpolate the vertex attributes at the circumcenter. */ 15056 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i]) 15057 + eta * (tapex[i] - torg[i])); 15058 } 15059 fprintf(outfile, "\n"); 15060 #endif /* not TRILIBRARY */ 15061 15062 * (int *) (triangleloop.tri + 6) = (int) vnodenumber; 15063 triangleloop.tri = triangletraverse(m); 15064 vnodenumber++; 15065 } 15066 15067 #ifndef TRILIBRARY 15068 finishfile(outfile, argc, argv); 15069 #endif /* not TRILIBRARY */ 15070 15071 #ifdef TRILIBRARY 15072 if (!b->quiet) { 15073 printf("Writing Voronoi edges.\n"); 15074 } 15075 /* Allocate memory for output Voronoi edges if necessary. */ 15076 if (*vedgelist == (int *) NULL) { 15077 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int))); 15078 } 15079 *vedgemarkerlist = (int *) NULL; 15080 /* Allocate memory for output Voronoi norms if necessary. */ 15081 if (*vnormlist == (REAL *) NULL) { 15082 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL))); 15083 } 15084 elist = *vedgelist; 15085 normlist = *vnormlist; 15086 coordindex = 0; 15087 #else /* not TRILIBRARY */ 15088 if (!b->quiet) { 15089 printf("Writing %s.\n", vedgefilename); 15090 } 15091 outfile = fopen(vedgefilename, "w"); 15092 if (outfile == (FILE *) NULL) { 15093 printf(" Error: Cannot create file %s.\n", vedgefilename); 15094 triexit(1); 15095 } 15096 /* Number of edges, zero boundary markers. */ 15097 fprintf(outfile, "%ld %d\n", m->edges, 0); 15098 #endif /* not TRILIBRARY */ 15099 15100 traversalinit(&m->triangles); 15101 triangleloop.tri = triangletraverse(m); 15102 vedgenumber = b->firstnumber; 15103 /* To loop over the set of edges, loop over all triangles, and look at */ 15104 /* the three edges of each triangle. If there isn't another triangle */ 15105 /* adjacent to the edge, operate on the edge. If there is another */ 15106 /* adjacent triangle, operate on the edge only if the current triangle */ 15107 /* has a smaller pointer than its neighbor. This way, each edge is */ 15108 /* considered only once. */ 15109 while (triangleloop.tri != (triangle *) NULL) { 15110 for (triangleloop.orient = 0; triangleloop.orient < 3; 15111 triangleloop.orient++) { 15112 sym(triangleloop, trisym); 15113 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) { 15114 /* Find the number of this triangle (and Voronoi vertex). */ 15115 p1 = * (int *) (triangleloop.tri + 6); 15116 if (trisym.tri == m->dummytri) { 15117 org(triangleloop, torg); 15118 dest(triangleloop, tdest); 15119 #ifdef TRILIBRARY 15120 /* Copy an infinite ray. Index of one endpoint, and -1. */ 15121 elist[coordindex] = p1; 15122 normlist[coordindex++] = tdest[1] - torg[1]; 15123 elist[coordindex] = -1; 15124 normlist[coordindex++] = torg[0] - tdest[0]; 15125 #else /* not TRILIBRARY */ 15126 /* Write an infinite ray. Edge number, index of one endpoint, -1, */ 15127 /* and x and y coordinates of a vector representing the */ 15128 /* direction of the ray. */ 15129 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber, 15130 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]); 15131 #endif /* not TRILIBRARY */ 15132 } else { 15133 /* Find the number of the adjacent triangle (and Voronoi vertex). */ 15134 p2 = * (int *) (trisym.tri + 6); 15135 /* Finite edge. Write indices of two endpoints. */ 15136 #ifdef TRILIBRARY 15137 elist[coordindex] = p1; 15138 normlist[coordindex++] = 0.0; 15139 elist[coordindex] = p2; 15140 normlist[coordindex++] = 0.0; 15141 #else /* not TRILIBRARY */ 15142 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2); 15143 #endif /* not TRILIBRARY */ 15144 } 15145 vedgenumber++; 15146 } 15147 } 15148 triangleloop.tri = triangletraverse(m); 15149 } 15150 15151 #ifndef TRILIBRARY 15152 finishfile(outfile, argc, argv); 15153 #endif /* not TRILIBRARY */ 15154 } 15155 15156 #ifdef TRILIBRARY 15157 15158 #ifdef ANSI_DECLARATORS 15159 void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist) 15160 #else /* not ANSI_DECLARATORS */ 15161 void writeneighbors(m, b, neighborlist) 15162 struct mesh *m; 15163 struct behavior *b; 15164 int **neighborlist; 15165 #endif /* not ANSI_DECLARATORS */ 15166 15167 #else /* not TRILIBRARY */ 15168 15169 #ifdef ANSI_DECLARATORS 15170 void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename, 15171 int argc, char **argv) 15172 #else /* not ANSI_DECLARATORS */ 15173 void writeneighbors(m, b, neighborfilename, argc, argv) 15174 struct mesh *m; 15175 struct behavior *b; 15176 char *neighborfilename; 15177 int argc; 15178 char **argv; 15179 #endif /* not ANSI_DECLARATORS */ 15180 15181 #endif /* not TRILIBRARY */ 15182 15183 { 15184 #ifdef TRILIBRARY 15185 int *nlist; 15186 int index; 15187 #else /* not TRILIBRARY */ 15188 FILE *outfile; 15189 #endif /* not TRILIBRARY */ 15190 struct otri triangleloop, trisym; 15191 long elementnumber; 15192 int neighbor1, neighbor2, neighbor3; 15193 triangle ptr; /* Temporary variable used by sym(). */ 15194 15195 #ifdef TRILIBRARY 15196 if (!b->quiet) { 15197 printf("Writing neighbors.\n"); 15198 } 15199 /* Allocate memory for neighbors if necessary. */ 15200 if (*neighborlist == (int *) NULL) { 15201 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 * 15202 sizeof(int))); 15203 } 15204 nlist = *neighborlist; 15205 index = 0; 15206 #else /* not TRILIBRARY */ 15207 if (!b->quiet) { 15208 printf("Writing %s.\n", neighborfilename); 15209 } 15210 outfile = fopen(neighborfilename, "w"); 15211 if (outfile == (FILE *) NULL) { 15212 printf(" Error: Cannot create file %s.\n", neighborfilename); 15213 triexit(1); 15214 } 15215 /* Number of triangles, three neighbors per triangle. */ 15216 fprintf(outfile, "%ld %d\n", m->triangles.items, 3); 15217 #endif /* not TRILIBRARY */ 15218 15219 traversalinit(&m->triangles); 15220 triangleloop.tri = triangletraverse(m); 15221 triangleloop.orient = 0; 15222 elementnumber = b->firstnumber; 15223 while (triangleloop.tri != (triangle *) NULL) { 15224 * (int *) (triangleloop.tri + 6) = (int) elementnumber; 15225 triangleloop.tri = triangletraverse(m); 15226 elementnumber++; 15227 } 15228 * (int *) (m->dummytri + 6) = -1; 15229 15230 traversalinit(&m->triangles); 15231 triangleloop.tri = triangletraverse(m); 15232 elementnumber = b->firstnumber; 15233 while (triangleloop.tri != (triangle *) NULL) { 15234 triangleloop.orient = 1; 15235 sym(triangleloop, trisym); 15236 neighbor1 = * (int *) (trisym.tri + 6); 15237 triangleloop.orient = 2; 15238 sym(triangleloop, trisym); 15239 neighbor2 = * (int *) (trisym.tri + 6); 15240 triangleloop.orient = 0; 15241 sym(triangleloop, trisym); 15242 neighbor3 = * (int *) (trisym.tri + 6); 15243 #ifdef TRILIBRARY 15244 nlist[index++] = neighbor1; 15245 nlist[index++] = neighbor2; 15246 nlist[index++] = neighbor3; 15247 #else /* not TRILIBRARY */ 15248 /* Triangle number, neighboring triangle numbers. */ 15249 fprintf(outfile, "%4ld %d %d %d\n", elementnumber, 15250 neighbor1, neighbor2, neighbor3); 15251 #endif /* not TRILIBRARY */ 15252 15253 triangleloop.tri = triangletraverse(m); 15254 elementnumber++; 15255 } 15256 15257 #ifndef TRILIBRARY 15258 finishfile(outfile, argc, argv); 15259 #endif /* not TRILIBRARY */ 15260 } 15261 15262 /*****************************************************************************/ 15263 /* */ 15264 /* writeoff() Write the triangulation to an .off file. */ 15265 /* */ 15266 /* OFF stands for the Object File Format, a format used by the Geometry */ 15267 /* Center's Geomview package. */ 15268 /* */ 15269 /*****************************************************************************/ 15270 15271 #ifndef TRILIBRARY 15272 15273 #ifdef ANSI_DECLARATORS 15274 void writeoff(struct mesh *m, struct behavior *b, char *offfilename, 15275 int argc, char **argv) 15276 #else /* not ANSI_DECLARATORS */ 15277 void writeoff(m, b, offfilename, argc, argv) 15278 struct mesh *m; 15279 struct behavior *b; 15280 char *offfilename; 15281 int argc; 15282 char **argv; 15283 #endif /* not ANSI_DECLARATORS */ 15284 15285 { 15286 FILE *outfile; 15287 struct otri triangleloop; 15288 vertex vertexloop; 15289 vertex p1, p2, p3; 15290 long outvertices; 15291 15292 if (!b->quiet) { 15293 printf("Writing %s.\n", offfilename); 15294 } 15295 15296 if (b->jettison) { 15297 outvertices = m->vertices.items - m->undeads; 15298 } else { 15299 outvertices = m->vertices.items; 15300 } 15301 15302 outfile = fopen(offfilename, "w"); 15303 if (outfile == (FILE *) NULL) { 15304 printf(" Error: Cannot create file %s.\n", offfilename); 15305 triexit(1); 15306 } 15307 /* Number of vertices, triangles, and edges. */ 15308 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items, 15309 m->edges); 15310 15311 /* Write the vertices. */ 15312 traversalinit(&m->vertices); 15313 vertexloop = vertextraverse(m); 15314 while (vertexloop != (vertex) NULL) { 15315 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) { 15316 /* The "0.0" is here because the OFF format uses 3D coordinates. */ 15317 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1], 15318 0.0); 15319 } 15320 vertexloop = vertextraverse(m); 15321 } 15322 15323 /* Write the triangles. */ 15324 traversalinit(&m->triangles); 15325 triangleloop.tri = triangletraverse(m); 15326 triangleloop.orient = 0; 15327 while (triangleloop.tri != (triangle *) NULL) { 15328 org(triangleloop, p1); 15329 dest(triangleloop, p2); 15330 apex(triangleloop, p3); 15331 /* The "3" means a three-vertex polygon. */ 15332 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber, 15333 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber); 15334 triangleloop.tri = triangletraverse(m); 15335 } 15336 finishfile(outfile, argc, argv); 15337 } 15338 15339 #endif /* not TRILIBRARY */ 15340 15343 /********* File I/O routines end here *********/ 15344 15345 /*****************************************************************************/ 15346 /* */ 15347 /* quality_statistics() Print statistics about the quality of the mesh. */ 15348 /* */ 15349 /*****************************************************************************/ 15350 15351 #ifdef ANSI_DECLARATORS 15352 void quality_statistics(struct mesh *m, struct behavior *b) 15353 #else /* not ANSI_DECLARATORS */ 15354 void quality_statistics(m, b) 15355 struct mesh *m; 15356 struct behavior *b; 15357 #endif /* not ANSI_DECLARATORS */ 15358 15359 { 15360 struct otri triangleloop; 15361 vertex p[3]; 15362 REAL cossquaretable[8]; 15363 REAL ratiotable[16]; 15364 REAL dx[3], dy[3]; 15365 REAL edgelength[3]; 15366 REAL dotproduct; 15367 REAL cossquare; 15368 REAL triarea; 15369 REAL shortest, longest; 15370 REAL trilongest2; 15371 REAL smallestarea, biggestarea; 15372 REAL triminaltitude2; 15373 REAL minaltitude; 15374 REAL triaspect2; 15375 REAL worstaspect; 15376 REAL smallestangle, biggestangle; 15377 REAL radconst, degconst; 15378 int angletable[18]; 15379 int aspecttable[16]; 15380 int aspectindex; 15381 int tendegree; 15382 int acutebiggest; 15383 int i, ii, j, k; 15384 15385 printf("Mesh quality statistics:\n\n"); 15386 radconst = PI / 18.0; 15387 degconst = 180.0 / PI; 15388 for (i = 0; i < 8; i++) { 15389 cossquaretable[i] = cos(radconst * (REAL) (i + 1)); 15390 cossquaretable[i] = cossquaretable[i] * cossquaretable[i]; 15391 } 15392 for (i = 0; i < 18; i++) { 15393 angletable[i] = 0; 15394 } 15395 15396 ratiotable[0] = 1.5; ratiotable[1] = 2.0; 15397 ratiotable[2] = 2.5; ratiotable[3] = 3.0; 15398 ratiotable[4] = 4.0; ratiotable[5] = 6.0; 15399 ratiotable[6] = 10.0; ratiotable[7] = 15.0; 15400 ratiotable[8] = 25.0; ratiotable[9] = 50.0; 15401 ratiotable[10] = 100.0; ratiotable[11] = 300.0; 15402 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0; 15403 ratiotable[14] = 100000.0; ratiotable[15] = 0.0; 15404 for (i = 0; i < 16; i++) { 15405 aspecttable[i] = 0; 15406 } 15407 15408 worstaspect = 0.0; 15409 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin; 15410 minaltitude = minaltitude * minaltitude; 15411 shortest = minaltitude; 15412 longest = 0.0; 15413 smallestarea = minaltitude; 15414 biggestarea = 0.0; 15415 worstaspect = 0.0; 15416 smallestangle = 0.0; 15417 biggestangle = 2.0; 15418 acutebiggest = 1; 15419 15420 traversalinit(&m->triangles); 15421 triangleloop.tri = triangletraverse(m); 15422 triangleloop.orient = 0; 15423 while (triangleloop.tri != (triangle *) NULL) { 15424 org(triangleloop, p[0]); 15425 dest(triangleloop, p[1]); 15426 apex(triangleloop, p[2]); 15427 trilongest2 = 0.0; 15428 15429 for (i = 0; i < 3; i++) { 15430 j = plus1mod3[i]; 15431 k = minus1mod3[i]; 15432 dx[i] = p[j][0] - p[k][0]; 15433 dy[i] = p[j][1] - p[k][1]; 15434 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i]; 15435 if (edgelength[i] > trilongest2) { 15436 trilongest2 = edgelength[i]; 15437 } 15438 if (edgelength[i] > longest) { 15439 longest = edgelength[i]; 15440 } 15441 if (edgelength[i] < shortest) { 15442 shortest = edgelength[i]; 15443 } 15444 } 15445 15446 triarea = counterclockwise(m, b, p[0], p[1], p[2]); 15447 if (triarea < smallestarea) { 15448 smallestarea = triarea; 15449 } 15450 if (triarea > biggestarea) { 15451 biggestarea = triarea; 15452 } 15453 triminaltitude2 = triarea * triarea / trilongest2; 15454 if (triminaltitude2 < minaltitude) { 15455 minaltitude = triminaltitude2; 15456 } 15457 triaspect2 = trilongest2 / triminaltitude2; 15458 if (triaspect2 > worstaspect) { 15459 worstaspect = triaspect2; 15460 } 15461 aspectindex = 0; 15462 while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex]) 15463 && (aspectindex < 15)) { 15464 aspectindex++; 15465 } 15466 aspecttable[aspectindex]++; 15467 15468 for (i = 0; i < 3; i++) { 15469 j = plus1mod3[i]; 15470 k = minus1mod3[i]; 15471 dotproduct = dx[j] * dx[k] + dy[j] * dy[k]; 15472 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]); 15473 tendegree = 8; 15474 for (ii = 7; ii >= 0; ii--) { 15475 if (cossquare > cossquaretable[ii]) { 15476 tendegree = ii; 15477 } 15478 } 15479 if (dotproduct <= 0.0) { 15480 angletable[tendegree]++; 15481 if (cossquare > smallestangle) { 15482 smallestangle = cossquare; 15483 } 15484 if (acutebiggest && (cossquare < biggestangle)) { 15485 biggestangle = cossquare; 15486 } 15487 } else { 15488 angletable[17 - tendegree]++; 15489 if (acutebiggest || (cossquare > biggestangle)) { 15490 biggestangle = cossquare; 15491 acutebiggest = 0; 15492 } 15493 } 15494 } 15495 triangleloop.tri = triangletraverse(m); 15496 } 15497 15498 shortest = sqrt(shortest); 15499 longest = sqrt(longest); 15500 minaltitude = sqrt(minaltitude); 15501 worstaspect = sqrt(worstaspect); 15502 smallestarea *= 0.5; 15503 biggestarea *= 0.5; 15504 if (smallestangle >= 1.0) { 15505 smallestangle = 0.0; 15506 } else { 15507 smallestangle = degconst * acos(sqrt(smallestangle)); 15508 } 15509 if (biggestangle >= 1.0) { 15510 biggestangle = 180.0; 15511 } else { 15512 if (acutebiggest) { 15513 biggestangle = degconst * acos(sqrt(biggestangle)); 15514 } else { 15515 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle)); 15516 } 15517 } 15518 15519 printf(" Smallest area: %16.5g | Largest area: %16.5g\n", 15520 smallestarea, biggestarea); 15521 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n", 15522 shortest, longest); 15523 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n", 15524 minaltitude, worstaspect); 15525 15526 printf(" Triangle aspect ratio histogram:\n"); 15527 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", 15528 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8], 15529 aspecttable[8]); 15530 for (i = 1; i < 7; i++) { 15531 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n", 15532 ratiotable[i - 1], ratiotable[i], aspecttable[i], 15533 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]); 15534 } 15535 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n", 15536 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14], 15537 aspecttable[15]); 15538 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n"); 15539 15540 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n", 15541 smallestangle, biggestangle); 15542 15543 printf(" Angle histogram:\n"); 15544 for (i = 0; i < 9; i++) { 15545 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n", 15546 i * 10, i * 10 + 10, angletable[i], 15547 i * 10 + 90, i * 10 + 100, angletable[i + 9]); 15548 } 15549 printf("\n"); 15550 } 15551 15552 /*****************************************************************************/ 15553 /* */ 15554 /* statistics() Print all sorts of cool facts. */ 15555 /* */ 15556 /*****************************************************************************/ 15557 15558 #ifdef ANSI_DECLARATORS 15559 void statistics(struct mesh *m, struct behavior *b) 15560 #else /* not ANSI_DECLARATORS */ 15561 void statistics(m, b) 15562 struct mesh *m; 15563 struct behavior *b; 15564 #endif /* not ANSI_DECLARATORS */ 15565 15566 { 15567 printf("\nStatistics:\n\n"); 15568 printf(" Input vertices: %d\n", m->invertices); 15569 if (b->refine) { 15570 printf(" Input triangles: %d\n", m->inelements); 15571 } 15572 if (b->poly) { 15573 printf(" Input segments: %d\n", m->insegments); 15574 if (!b->refine) { 15575 printf(" Input holes: %d\n", m->holes); 15576 } 15577 } 15578 15579 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads); 15580 printf(" Mesh triangles: %ld\n", m->triangles.items); 15581 printf(" Mesh edges: %ld\n", m->edges); 15582 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize); 15583 if (b->poly || b->refine) { 15584 printf(" Mesh interior boundary edges: %ld\n", 15585 m->subsegs.items - m->hullsize); 15586 printf(" Mesh subsegments (constrained edges): %ld\n", 15587 m->subsegs.items); 15588 } 15589 printf("\n"); 15590 15591 if (b->verbose) { 15592 quality_statistics(m, b); 15593 printf("Memory allocation statistics:\n\n"); 15594 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems); 15595 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems); 15596 if (m->subsegs.maxitems > 0) { 15597 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems); 15598 } 15599 if (m->viri.maxitems > 0) { 15600 printf(" Maximum number of viri: %ld\n", m->viri.maxitems); 15601 } 15602 if (m->badsubsegs.maxitems > 0) { 15603 printf(" Maximum number of encroached subsegments: %ld\n", 15604 m->badsubsegs.maxitems); 15605 } 15606 if (m->badtriangles.maxitems > 0) { 15607 printf(" Maximum number of bad triangles: %ld\n", 15608 m->badtriangles.maxitems); 15609 } 15610 if (m->flipstackers.maxitems > 0) { 15611 printf(" Maximum number of stacked triangle flips: %ld\n", 15612 m->flipstackers.maxitems); 15613 } 15614 if (m->splaynodes.maxitems > 0) { 15615 printf(" Maximum number of splay tree nodes: %ld\n", 15616 m->splaynodes.maxitems); 15617 } 15618 printf(" Approximate heap memory use (bytes): %ld\n\n", 15619 m->vertices.maxitems * m->vertices.itembytes + 15620 m->triangles.maxitems * m->triangles.itembytes + 15621 m->subsegs.maxitems * m->subsegs.itembytes + 15622 m->viri.maxitems * m->viri.itembytes + 15623 m->badsubsegs.maxitems * m->badsubsegs.itembytes + 15624 m->badtriangles.maxitems * m->badtriangles.itembytes + 15625 m->flipstackers.maxitems * m->flipstackers.itembytes + 15626 m->splaynodes.maxitems * m->splaynodes.itembytes); 15627 15628 printf("Algorithmic statistics:\n\n"); 15629 if (!b->weighted) { 15630 printf(" Number of incircle tests: %ld\n", m->incirclecount); 15631 } else { 15632 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount); 15633 } 15634 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount); 15635 if (m->hyperbolacount > 0) { 15636 printf(" Number of right-of-hyperbola tests: %ld\n", 15637 m->hyperbolacount); 15638 } 15639 if (m->circletopcount > 0) { 15640 printf(" Number of circle top computations: %ld\n", 15641 m->circletopcount); 15642 } 15643 if (m->circumcentercount > 0) { 15644 printf(" Number of triangle circumcenter computations: %ld\n", 15645 m->circumcentercount); 15646 } 15647 printf("\n"); 15648 } 15649 } 15650 15651 /*****************************************************************************/ 15652 /* */ 15653 /* main() or triangulate() Gosh, do everything. */ 15654 /* */ 15655 /* The sequence is roughly as follows. Many of these steps can be skipped, */ 15656 /* depending on the command line switches. */ 15657 /* */ 15658 /* - Initialize constants and parse the command line. */ 15659 /* - Read the vertices from a file and either */ 15660 /* - triangulate them (no -r), or */ 15661 /* - read an old mesh from files and reconstruct it (-r). */ 15662 /* - Insert the PSLG segments (-p), and possibly segments on the convex */ 15663 /* hull (-c). */ 15664 /* - Read the holes (-p), regional attributes (-pA), and regional area */ 15665 /* constraints (-pa). Carve the holes and concavities, and spread the */ 15666 /* regional attributes and area constraints. */ 15667 /* - Enforce the constraints on minimum angle (-q) and maximum area (-a). */ 15668 /* Also enforce the conforming Delaunay property (-q and -a). */ 15669 /* - Compute the number of edges in the resulting mesh. */ 15670 /* - Promote the mesh's linear triangles to higher order elements (-o). */ 15671 /* - Write the output files and print the statistics. */ 15672 /* - Check the consistency and Delaunay property of the mesh (-C). */ 15673 /* */ 15674 /*****************************************************************************/ 15675 15676 #ifdef TRILIBRARY 15677 15678 #ifdef ANSI_DECLARATORS 15679 void triangulate(char *triswitches, struct triangulateio *in, 15680 struct triangulateio *out, struct triangulateio *vorout) 15681 #else /* not ANSI_DECLARATORS */ 15682 void triangulate(triswitches, in, out, vorout) 15683 char *triswitches; 15684 struct triangulateio *in; 15685 struct triangulateio *out; 15686 struct triangulateio *vorout; 15687 #endif /* not ANSI_DECLARATORS */ 15688 15689 #else /* not TRILIBRARY */ 15690 15691 #ifdef ANSI_DECLARATORS 15692 int main(int argc, char **argv) 15693 #else /* not ANSI_DECLARATORS */ 15694 int main(argc, argv) 15695 int argc; 15696 char **argv; 15697 #endif /* not ANSI_DECLARATORS */ 15698 15699 #endif /* not TRILIBRARY */ 15700 15701 { 15702 struct mesh m; 15703 struct behavior b; 15704 REAL *holearray; /* Array of holes. */ 15705 REAL *regionarray; /* Array of regional attributes and area constraints. */ 15706 #ifndef TRILIBRARY 15707 FILE* polyfile; 15708 #endif /* not TRILIBRARY */ 15709 #ifndef NO_TIMER 15710 /* Variables for timing the performance of Triangle. The types are */ 15711 /* defined in sys/time.h. */ 15712 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6; 15713 struct timezone tz; 15714 #endif /* not NO_TIMER */ 15715 15716 #ifndef NO_TIMER 15717 gettimeofday(&tv0, &tz); 15718 #endif /* not NO_TIMER */ 15719 15720 triangleinit(&m); 15721 #ifdef TRILIBRARY 15722 parsecommandline(1, &triswitches, &b); 15723 #else /* not TRILIBRARY */ 15724 parsecommandline(argc, argv, &b); 15725 #endif /* not TRILIBRARY */ 15726 m.steinerleft = b.steiner; 15727 15728 #ifdef TRILIBRARY 15729 transfernodes(&m, &b, in->pointlist, in->pointattributelist, 15730 in->pointmarkerlist, in->numberofpoints, 15731 in->numberofpointattributes); 15732 #else /* not TRILIBRARY */ 15733 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile); 15734 #endif /* not TRILIBRARY */ 15735 15736 #ifndef NO_TIMER 15737 if (!b.quiet) { 15738 gettimeofday(&tv1, &tz); 15739 } 15740 #endif /* not NO_TIMER */ 15741 15742 #ifdef CDT_ONLY 15743 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */ 15744 #else /* not CDT_ONLY */ 15745 if (b.refine) { 15746 /* Read and reconstruct a mesh. */ 15747 #ifdef TRILIBRARY 15748 m.hullsize = reconstruct(&m, &b, in->trianglelist, 15749 in->triangleattributelist, in->trianglearealist, 15750 in->numberoftriangles, in->numberofcorners, 15751 in->numberoftriangleattributes, 15752 in->segmentlist, in->segmentmarkerlist, 15753 in->numberofsegments); 15754 #else /* not TRILIBRARY */ 15755 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename, 15756 b.inpolyfilename, polyfile); 15757 #endif /* not TRILIBRARY */ 15758 } else { 15759 m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */ 15760 } 15761 #endif /* not CDT_ONLY */ 15762 15763 #ifndef NO_TIMER 15764 if (!b.quiet) { 15765 gettimeofday(&tv2, &tz); 15766 if (b.refine) { 15767 printf("Mesh reconstruction"); 15768 } else { 15769 printf("Delaunay"); 15770 } 15771 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) + 15772 (tv2.tv_usec - tv1.tv_usec) / 1000l); 15773 } 15774 #endif /* not NO_TIMER */ 15775 15776 /* Ensure that no vertex can be mistaken for a triangular bounding */ 15777 /* box vertex in insertvertex(). */ 15778 m.infvertex1 = (vertex) NULL; 15779 m.infvertex2 = (vertex) NULL; 15780 m.infvertex3 = (vertex) NULL; 15781 15782 if (b.usesegments) { 15783 m.checksegments = 1; /* Segments will be introduced next. */ 15784 if (!b.refine) { 15785 /* Insert PSLG segments and/or convex hull segments. */ 15786 #ifdef TRILIBRARY 15787 formskeleton(&m, &b, in->segmentlist, 15788 in->segmentmarkerlist, in->numberofsegments); 15789 #else /* not TRILIBRARY */ 15790 formskeleton(&m, &b, polyfile, b.inpolyfilename); 15791 #endif /* not TRILIBRARY */ 15792 } 15793 } 15794 15795 #ifndef NO_TIMER 15796 if (!b.quiet) { 15797 gettimeofday(&tv3, &tz); 15798 if (b.usesegments && !b.refine) { 15799 printf("Segment milliseconds: %ld\n", 15800 1000l * (tv3.tv_sec - tv2.tv_sec) + 15801 (tv3.tv_usec - tv2.tv_usec) / 1000l); 15802 } 15803 } 15804 #endif /* not NO_TIMER */ 15805 15806 if (b.poly && (m.triangles.items > 0)) { 15807 #ifdef TRILIBRARY 15808 holearray = in->holelist; 15809 m.holes = in->numberofholes; 15810 regionarray = in->regionlist; 15811 m.regions = in->numberofregions; 15812 #else /* not TRILIBRARY */ 15813 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes, 15814 ®ionarray, &m.regions); 15815 #endif /* not TRILIBRARY */ 15816 if (!b.refine) { 15817 /* Carve out holes and concavities. */ 15818 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions); 15819 } 15820 } else { 15821 /* Without a PSLG, there can be no holes or regional attributes */ 15822 /* or area constraints. The following are set to zero to avoid */ 15823 /* an accidental free() later. */ 15824 m.holes = 0; 15825 m.regions = 0; 15826 } 15827 15828 #ifndef NO_TIMER 15829 if (!b.quiet) { 15830 gettimeofday(&tv4, &tz); 15831 if (b.poly && !b.refine) { 15832 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) + 15833 (tv4.tv_usec - tv3.tv_usec) / 1000l); 15834 } 15835 } 15836 #endif /* not NO_TIMER */ 15837 15838 #ifndef CDT_ONLY 15839 if (b.quality && (m.triangles.items > 0)) { 15840 enforcequality(&m, &b); /* Enforce angle and area constraints. */ 15841 } 15842 #endif /* not CDT_ONLY */ 15843 15844 #ifndef NO_TIMER 15845 if (!b.quiet) { 15846 gettimeofday(&tv5, &tz); 15847 #ifndef CDT_ONLY 15848 if (b.quality) { 15849 printf("Quality milliseconds: %ld\n", 15850 1000l * (tv5.tv_sec - tv4.tv_sec) + 15851 (tv5.tv_usec - tv4.tv_usec) / 1000l); 15852 } 15853 #endif /* not CDT_ONLY */ 15854 } 15855 #endif /* not NO_TIMER */ 15856 15857 /* Calculate the number of edges. */ 15858 m.edges = (3l * m.triangles.items + m.hullsize) / 2l; 15859 15860 if (b.order > 1) { 15861 highorder(&m, &b); /* Promote elements to higher polynomial order. */ 15862 } 15863 if (!b.quiet) { 15864 printf("\n"); 15865 } 15866 15867 #ifdef TRILIBRARY 15868 if (b.jettison) { 15869 out->numberofpoints = m.vertices.items - m.undeads; 15870 } else { 15871 out->numberofpoints = m.vertices.items; 15872 } 15873 out->numberofpointattributes = m.nextras; 15874 out->numberoftriangles = m.triangles.items; 15875 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2; 15876 out->numberoftriangleattributes = m.eextras; 15877 out->numberofedges = m.edges; 15878 if (b.usesegments) { 15879 out->numberofsegments = m.subsegs.items; 15880 } else { 15881 out->numberofsegments = m.hullsize; 15882 } 15883 if (vorout != (struct triangulateio *) NULL) { 15884 vorout->numberofpoints = m.triangles.items; 15885 vorout->numberofpointattributes = m.nextras; 15886 vorout->numberofedges = m.edges; 15887 } 15888 #endif /* TRILIBRARY */ 15889 /* If not using iteration numbers, don't write a .node file if one was */ 15890 /* read, because the original one would be overwritten! */ 15891 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) { 15892 if (!b.quiet) { 15893 #ifdef TRILIBRARY 15894 printf("NOT writing vertices.\n"); 15895 #else /* not TRILIBRARY */ 15896 printf("NOT writing a .node file.\n"); 15897 #endif /* not TRILIBRARY */ 15898 } 15899 numbernodes(&m, &b); /* We must remember to number the vertices. */ 15900 } else { 15901 /* writenodes() numbers the vertices too. */ 15902 #ifdef TRILIBRARY 15903 writenodes(&m, &b, &out->pointlist, &out->pointattributelist, 15904 &out->pointmarkerlist); 15905 #else /* not TRILIBRARY */ 15906 writenodes(&m, &b, b.outnodefilename, argc, argv); 15907 #endif /* TRILIBRARY */ 15908 } 15909 if (b.noelewritten) { 15910 if (!b.quiet) { 15911 #ifdef TRILIBRARY 15912 printf("NOT writing triangles.\n"); 15913 #else /* not TRILIBRARY */ 15914 printf("NOT writing an .ele file.\n"); 15915 #endif /* not TRILIBRARY */ 15916 } 15917 } else { 15918 #ifdef TRILIBRARY 15919 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist); 15920 #else /* not TRILIBRARY */ 15921 writeelements(&m, &b, b.outelefilename, argc, argv); 15922 #endif /* not TRILIBRARY */ 15923 } 15924 /* The -c switch (convex switch) causes a PSLG to be written */ 15925 /* even if none was read. */ 15926 if (b.poly || b.convex) { 15927 /* If not using iteration numbers, don't overwrite the .poly file. */ 15928 if (b.nopolywritten || b.noiterationnum) { 15929 if (!b.quiet) { 15930 #ifdef TRILIBRARY 15931 printf("NOT writing segments.\n"); 15932 #else /* not TRILIBRARY */ 15933 printf("NOT writing a .poly file.\n"); 15934 #endif /* not TRILIBRARY */ 15935 } 15936 } else { 15937 #ifdef TRILIBRARY 15938 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist); 15939 out->numberofholes = m.holes; 15940 out->numberofregions = m.regions; 15941 if (b.poly) { 15942 out->holelist = in->holelist; 15943 out->regionlist = in->regionlist; 15944 } else { 15945 out->holelist = (REAL *) NULL; 15946 out->regionlist = (REAL *) NULL; 15947 } 15948 #else /* not TRILIBRARY */ 15949 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray, 15950 m.regions, argc, argv); 15951 #endif /* not TRILIBRARY */ 15952 } 15953 } 15954 #ifndef TRILIBRARY 15955 #ifndef CDT_ONLY 15956 if (m.regions > 0) { 15957 trifree((VOID *) regionarray); 15958 } 15959 #endif /* not CDT_ONLY */ 15960 if (m.holes > 0) { 15961 trifree((VOID *) holearray); 15962 } 15963 if (b.geomview) { 15964 writeoff(&m, &b, b.offfilename, argc, argv); 15965 } 15966 #endif /* not TRILIBRARY */ 15967 if (b.edgesout) { 15968 #ifdef TRILIBRARY 15969 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist); 15970 #else /* not TRILIBRARY */ 15971 writeedges(&m, &b, b.edgefilename, argc, argv); 15972 #endif /* not TRILIBRARY */ 15973 } 15974 if (b.voronoi) { 15975 #ifdef TRILIBRARY 15976 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist, 15977 &vorout->pointmarkerlist, &vorout->edgelist, 15978 &vorout->edgemarkerlist, &vorout->normlist); 15979 #else /* not TRILIBRARY */ 15980 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv); 15981 #endif /* not TRILIBRARY */ 15982 } 15983 if (b.neighbors) { 15984 #ifdef TRILIBRARY 15985 writeneighbors(&m, &b, &out->neighborlist); 15986 #else /* not TRILIBRARY */ 15987 writeneighbors(&m, &b, b.neighborfilename, argc, argv); 15988 #endif /* not TRILIBRARY */ 15989 } 15990 15991 if (!b.quiet) { 15992 #ifndef NO_TIMER 15993 gettimeofday(&tv6, &tz); 15994 printf("\nOutput milliseconds: %ld\n", 15995 1000l * (tv6.tv_sec - tv5.tv_sec) + 15996 (tv6.tv_usec - tv5.tv_usec) / 1000l); 15997 printf("Total running milliseconds: %ld\n", 15998 1000l * (tv6.tv_sec - tv0.tv_sec) + 15999 (tv6.tv_usec - tv0.tv_usec) / 1000l); 16000 #endif /* not NO_TIMER */ 16001 16002 statistics(&m, &b); 16003 } 16004 16005 #ifndef REDUCED 16006 if (b.docheck) { 16007 checkmesh(&m, &b); 16008 checkdelaunay(&m, &b); 16009 } 16010 #endif /* not REDUCED */ 16011 16012 triangledeinit(&m, &b); 16013 #ifndef TRILIBRARY 16014 return 0; 16015 #endif /* not TRILIBRARY */ 16016 }