255#define FILENAMESIZE 2048
260#define INPUTLINESIZE 1024
266#define TRIPERBLOCK 4092
267#define SUBSEGPERBLOCK 508
268#define VERTEXPERBLOCK 4092
269#define VIRUSPERBLOCK 1020
271#define BADSUBSEGPERBLOCK 252
273#define BADTRIPERBLOCK 4092
275#define FLIPSTACKERPERBLOCK 252
277#define SPLAYNODEPERBLOCK 508
284#define SEGMENTVERTEX 1
286#define DEADVERTEX -32768
287#define UNDEADVERTEX -32767
295#define SAMPLEFACTOR 11
305#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
309#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
313#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
326#include <fpu_control.h>
519 vertex subsegorg, subsegdest;
529 vertex triangorg, triangdest, triangapex;
530 struct badtriang *nexttriang;
539 struct flipstacker *prevflip;
572 struct splaynode *lchild, *rchild;
599 VOID **firstblock, **nowblock;
608 long items, maxitems;
609 int unallocateditems;
637 struct memorypool triangles;
638 struct memorypool subsegs;
639 struct memorypool vertices;
640 struct memorypool viri;
641 struct memorypool badsubsegs;
642 struct memorypool badtriangles;
643 struct memorypool flipstackers;
644 struct memorypool splaynodes;
649 struct badtriang *queuefront[4096];
650 struct badtriang *queuetail[4096];
651 int nextnonemptyq[4096];
656 struct flipstacker *lastflip;
685 long counterclockcount;
688 long circumcentercount;
693 vertex infvertex1, infvertex2, infvertex3;
710 struct otri recenttri;
753 int poly, refine, quality, vararea, fixedarea, usertest;
754 int regionattrib, convex, weighted, jettison;
756 int edgesout, voronoi, neighbors, geomview;
757 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
758 int noholes, noexact, conformdel;
759 int incremental, sweepline, dwyer;
767 REAL minangle, goodangle, offconstant;
912#define decode(ptr, otri) \
913 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
914 (otri).tri = (triangle *) \
915 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
921#define encode(otri) \
922 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
932#define sym(otri1, otri2) \
933 ptr = (otri1).tri[(otri1).orient]; \
936#define symself(otri) \
937 ptr = (otri).tri[(otri).orient]; \
942#define lnext(otri1, otri2) \
943 (otri2).tri = (otri1).tri; \
944 (otri2).orient = plus1mod3[(otri1).orient]
946#define lnextself(otri) \
947 (otri).orient = plus1mod3[(otri).orient]
951#define lprev(otri1, otri2) \
952 (otri2).tri = (otri1).tri; \
953 (otri2).orient = minus1mod3[(otri1).orient]
955#define lprevself(otri) \
956 (otri).orient = minus1mod3[(otri).orient]
962#define onext(otri1, otri2) \
963 lprev(otri1, otri2); \
966#define onextself(otri) \
974#define oprev(otri1, otri2) \
978#define oprevself(otri) \
986#define dnext(otri1, otri2) \
990#define dnextself(otri) \
998#define dprev(otri1, otri2) \
999 lnext(otri1, otri2); \
1002#define dprevself(otri) \
1010#define rnext(otri1, otri2) \
1011 sym(otri1, otri2); \
1015#define rnextself(otri) \
1024#define rprev(otri1, otri2) \
1025 sym(otri1, otri2); \
1029#define rprevself(otri) \
1037#define org(otri, vertexptr) \
1038 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
1040#define dest(otri, vertexptr) \
1041 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
1043#define apex(otri, vertexptr) \
1044 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
1046#define setorg(otri, vertexptr) \
1047 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1049#define setdest(otri, vertexptr) \
1050 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1052#define setapex(otri, vertexptr) \
1053 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
1057#define bond(otri1, otri2) \
1058 (otri1).tri[(otri1).orient] = encode(otri2); \
1059 (otri2).tri[(otri2).orient] = encode(otri1)
1066#define dissolve(otri) \
1067 (otri).tri[(otri).orient] = (triangle) m->dummytri
1071#define otricopy(otri1, otri2) \
1072 (otri2).tri = (otri1).tri; \
1073 (otri2).orient = (otri1).orient
1077#define otriequal(otri1, otri2) \
1078 (((otri1).tri == (otri2).tri) && \
1079 ((otri1).orient == (otri2).orient))
1084#define infect(otri) \
1085 (otri).tri[6] = (triangle) \
1086 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
1088#define uninfect(otri) \
1089 (otri).tri[6] = (triangle) \
1090 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
1094#define infected(otri) \
1095 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
1099#define elemattribute(otri, attnum) \
1100 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
1102#define setelemattribute(otri, attnum, value) \
1103 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
1107#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
1109#define setareabound(otri, value) \
1110 ((REAL *) (otri).tri)[m->areaboundindex] = value
1117#define deadtri(tria) ((tria)[1] == (triangle) NULL)
1119#define killtri(tria) \
1120 (tria)[1] = (triangle) NULL; \
1121 (tria)[3] = (triangle) NULL
1132#define sdecode(sptr, osub) \
1133 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
1134 (osub).ss = (subseg *) \
1135 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
1141#define sencode(osub) \
1142 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
1146#define ssym(osub1, osub2) \
1147 (osub2).ss = (osub1).ss; \
1148 (osub2).ssorient = 1 - (osub1).ssorient
1150#define ssymself(osub) \
1151 (osub).ssorient = 1 - (osub).ssorient
1156#define spivot(osub1, osub2) \
1157 sptr = (osub1).ss[(osub1).ssorient]; \
1158 sdecode(sptr, osub2)
1160#define spivotself(osub) \
1161 sptr = (osub).ss[(osub).ssorient]; \
1167#define snext(osub1, osub2) \
1168 sptr = (osub1).ss[1 - (osub1).ssorient]; \
1169 sdecode(sptr, osub2)
1171#define snextself(osub) \
1172 sptr = (osub).ss[1 - (osub).ssorient]; \
1178#define sorg(osub, vertexptr) \
1179 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
1181#define sdest(osub, vertexptr) \
1182 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
1184#define setsorg(osub, vertexptr) \
1185 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
1187#define setsdest(osub, vertexptr) \
1188 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
1190#define segorg(osub, vertexptr) \
1191 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
1193#define segdest(osub, vertexptr) \
1194 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
1196#define setsegorg(osub, vertexptr) \
1197 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
1199#define setsegdest(osub, vertexptr) \
1200 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
1206#define mark(osub) (* (int *) ((osub).ss + 8))
1208#define setmark(osub, value) \
1209 * (int *) ((osub).ss + 8) = value
1213#define sbond(osub1, osub2) \
1214 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
1215 (osub2).ss[(osub2).ssorient] = sencode(osub1)
1220#define sdissolve(osub) \
1221 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
1225#define subsegcopy(osub1, osub2) \
1226 (osub2).ss = (osub1).ss; \
1227 (osub2).ssorient = (osub1).ssorient
1231#define subsegequal(osub1, osub2) \
1232 (((osub1).ss == (osub2).ss) && \
1233 ((osub1).ssorient == (osub2).ssorient))
1240#define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
1242#define killsubseg(sub) \
1243 (sub)[1] = (subseg) NULL; \
1244 (sub)[2] = (subseg) NULL
1252#define tspivot(otri, osub) \
1253 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
1259#define stpivot(osub, otri) \
1260 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
1265#define tsbond(otri, osub) \
1266 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
1267 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
1271#define tsdissolve(otri) \
1272 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
1276#define stdissolve(osub) \
1277 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
1283#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
1285#define setvertexmark(vx, value) \
1286 ((int *) (vx))[m->vertexmarkindex] = value
1288#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
1290#define setvertextype(vx, value) \
1291 ((int *) (vx))[m->vertexmarkindex + 1] = value
1293#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
1295#define setvertex2tri(vx, value) \
1296 ((triangle *) (vx))[m->vertex2triindex] = value
1335#ifdef ANSI_DECLARATORS
1346 REAL dxoa, dxda, dxod;
1347 REAL dyoa, dyda, dyod;
1348 REAL oalen, dalen, odlen;
1353 dxoa = triorg[0] - triapex[0];
1354 dyoa = triorg[1] - triapex[1];
1355 dxda = tridest[0] - triapex[0];
1356 dyda = tridest[1] - triapex[1];
1357 dxod = triorg[0] - tridest[0];
1358 dyod = triorg[1] - tridest[1];
1360 oalen = dxoa * dxoa + dyoa * dyoa;
1361 dalen = dxda * dxda + dyda * dyda;
1362 odlen = dxod * dxod + dyod * dyod;
1364 maxlen = (dalen > oalen) ? dalen : oalen;
1365 maxlen = (odlen > maxlen) ? odlen : maxlen;
1367 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
1384#ifdef ANSI_DECLARATORS
1395#ifdef ANSI_DECLARATORS
1405 memptr = (
VOID *)
malloc((
unsigned int) size);
1406 if (memptr == (
VOID *) NULL) {
1407 printf(
"Error: Out of memory.\n");
1413#ifdef ANSI_DECLARATORS
1444 printf(
"triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
1446 printf(
"triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
1450 printf(
"triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
1452 printf(
"triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
1456 printf(
" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
1458 printf(
" -r Refines a previously generated mesh.\n");
1460 " -q Quality mesh generation. A minimum angle may be specified.\n");
1461 printf(
" -a Applies a maximum triangle area constraint.\n");
1462 printf(
" -u Applies a user-defined triangle constraint.\n");
1465 " -A Applies attributes to identify triangles in certain regions.\n");
1466 printf(
" -c Encloses the convex hull with segments.\n");
1468 printf(
" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
1474 printf(
" -j Jettison unused vertices from output .node file.\n");
1475 printf(
" -e Generates an edge list.\n");
1476 printf(
" -v Generates a Voronoi diagram.\n");
1477 printf(
" -n Generates a list of triangle neighbors.\n");
1478 printf(
" -g Generates an .off file for Geomview.\n");
1479 printf(
" -B Suppresses output of boundary information.\n");
1480 printf(
" -P Suppresses output of .poly file.\n");
1481 printf(
" -N Suppresses output of .node file.\n");
1482 printf(
" -E Suppresses output of .ele file.\n");
1483 printf(
" -I Suppresses mesh iteration numbers.\n");
1484 printf(
" -O Ignores holes in .poly file.\n");
1485 printf(
" -X Suppresses use of exact arithmetic.\n");
1486 printf(
" -z Numbers all items starting from zero (rather than one).\n");
1487 printf(
" -o2 Generates second-order subparametric elements.\n");
1489 printf(
" -Y Suppresses boundary segment splitting.\n");
1490 printf(
" -S Specifies maximum number of added Steiner points.\n");
1493 printf(
" -i Uses incremental method, rather than divide-and-conquer.\n");
1494 printf(
" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
1496 printf(
" -l Uses vertical cuts only, rather than alternating cuts.\n");
1500 " -s Force segments into mesh by splitting (instead of using CDT).\n");
1502 printf(
" -C Check consistency of final mesh.\n");
1504 printf(
" -Q Quiet: No terminal output except errors.\n");
1505 printf(
" -V Verbose: Detailed information on what I'm doing.\n");
1506 printf(
" -h Help: Detailed instructions for Triangle.\n");
1522 printf(
"Triangle\n");
1524"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
1525 printf(
"Version 1.6\n\n");
1527"Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
1528 printf(
"2360 Woolsey #H / Berkeley, California 94705-1927\n");
1529 printf(
"Bugs/comments to jrs@cs.berkeley.edu\n");
1531"Created as part of the Quake project (tools for earthquake simulation).\n");
1533"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
1534 printf(
"There is no warranty whatsoever. Use at your own risk.\n");
1536 printf(
"This executable is compiled for single precision arithmetic.\n\n\n");
1538 printf(
"This executable is compiled for double precision arithmetic.\n\n\n");
1541"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
1543"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
1545"high-quality triangular meshes. The latter can be generated with no small\n"
1548"or large angles, and are thus suitable for finite element analysis. If no\n"
1551"command line switch is specified, your .node input file is read, and the\n");
1553"Delaunay triangulation is returned in .node and .ele output files. The\n");
1554 printf(
"command syntax is:\n\n");
1555 printf(
"triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
1557"Underscores indicate that numbers may optionally follow certain switches.\n");
1559"Do not leave any space between a switch and its numeric parameter.\n");
1561"input_file must be a file with extension .node, or extension .poly if the\n");
1563"-p switch is used. If -r is used, you must supply .node and .ele files,\n");
1565"and possibly a .poly file and an .area file as well. The formats of these\n"
1567 printf(
"files are described below.\n\n");
1568 printf(
"Command Line Switches:\n\n");
1570" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
1573" vertices, segments, holes, regional attributes, and regional area\n");
1575" constraints. Generates a constrained Delaunay triangulation (CDT)\n"
1578" fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
1580" constrained Delaunay triangulation (CCDT). If you want a truly\n");
1582" Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
1584" well. When -p is not used, Triangle reads a .node file by default.\n"
1587" -r Refines a previously generated mesh. The mesh is read from a .node\n"
1590" file and an .ele file. If -p is also used, a .poly file is read\n");
1592" and used to constrain segments in the mesh. If -a is also used\n");
1594" (with no number following), an .area file is read and used to\n");
1596" impose area constraints on the mesh. Further details on refinement\n"
1598 printf(
" appear below.\n");
1600" -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
1602" Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
1605" ensure that all angles are between 20 and 140 degrees. An\n");
1607" alternative bound on the minimum angle, replacing 20 degrees, may\n");
1609" be specified after the `q'. The specified angle may include a\n");
1611" decimal point, but not exponential notation. Note that a bound of\n"
1614" theta degrees on the smallest angle also implies a bound of\n");
1616" (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
1619" degrees or smaller, Triangle is mathematically guaranteed to\n");
1621" terminate (assuming infinite precision arithmetic--Triangle may\n");
1623" fail to terminate if you run out of precision). In practice,\n");
1625" Triangle often succeeds for minimum angles up to 34 degrees. For\n");
1627" some meshes, however, you might need to reduce the minimum angle to\n"
1630" avoid problems associated with insufficient floating-point\n");
1631 printf(
" precision.\n");
1633" -a Imposes a maximum triangle area. If a number follows the `a', no\n");
1635" triangle is generated whose area is larger than that number. If no\n"
1638" number is specified, an .area file (if -r is used) or .poly file\n");
1640" (if -r is not used) specifies a set of maximum area constraints.\n");
1642" An .area file contains a separate area constraint for each\n");
1644" triangle, and is useful for refining a finite element mesh based on\n"
1647" a posteriori error estimates. A .poly file can optionally contain\n"
1650" an area constraint for each segment-bounded region, thereby\n");
1652" controlling triangle densities in a first triangulation of a PSLG.\n"
1655" You can impose both a fixed area constraint and a varying area\n");
1657" constraint by invoking the -a switch twice, once with and once\n");
1659" without a number following. Each area specified may include a\n");
1660 printf(
" decimal point.\n");
1662" -u Imposes a user-defined constraint on triangle size. There are two\n"
1665" ways to use this feature. One is to edit the triunsuitable()\n");
1667" procedure in triangle.c to encode any constraint you like, then\n");
1669" recompile Triangle. The other is to compile triangle.c with the\n");
1671" EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
1673" link Triangle with a separate object file that implements\n");
1675" triunsuitable(). In either case, the -u switch causes the user-\n");
1676 printf(
" defined test to be applied to every triangle.\n");
1678" -A Assigns an additional floating-point attribute to each triangle\n");
1680" that identifies what segment-bounded region each triangle belongs\n");
1682" to. Attributes are assigned to regions by the .poly file. If a\n");
1684" region is not explicitly marked by the .poly file, triangles in\n");
1686" that region are assigned an attribute of zero. The -A switch has\n");
1688" an effect only when the -p switch is used and the -r switch is not.\n"
1691" -c Creates segments on the convex hull of the triangulation. If you\n");
1693" are triangulating a vertex set, this switch causes a .poly file to\n"
1696" be written, containing all edges of the convex hull. If you are\n");
1698" triangulating a PSLG, this switch specifies that the whole convex\n");
1700" hull of the PSLG should be triangulated, regardless of what\n");
1702" segments the PSLG has. If you do not use this switch when\n");
1704" triangulating a PSLG, Triangle assumes that you have identified the\n"
1707" region to be triangulated by surrounding it with segments of the\n");
1709" input PSLG. Beware: if you are not careful, this switch can cause\n"
1712" the introduction of an extremely thin angle between a PSLG segment\n"
1715" and a convex hull segment, which can cause overrefinement (and\n");
1717" possibly failure if Triangle runs out of precision). If you are\n");
1719" refining a mesh, the -c switch works differently: it causes a\n");
1721" .poly file to be written containing the boundary edges of the mesh\n"
1723 printf(
" (useful if no .poly file was read).\n");
1725" -D Conforming Delaunay triangulation: use this switch if you want to\n"
1728" ensure that all the triangles in the mesh are Delaunay, and not\n");
1730" merely constrained Delaunay; or if you want to ensure that all the\n"
1733" Voronoi vertices lie within the triangulation. (Some finite volume\n"
1736" methods have this requirement.) This switch invokes Ruppert's\n");
1738" original algorithm, which splits every subsegment whose diametral\n");
1740" circle is encroached. It usually increases the number of vertices\n"
1742 printf(
" and triangles.\n");
1744" -j Jettisons vertices that are not part of the final triangulation\n");
1746" from the output .node file. By default, Triangle copies all\n");
1748" vertices in the input .node file to the output .node file, in the\n");
1750" same order, so their indices do not change. The -j switch prevents\n"
1753" duplicated input vertices, or vertices `eaten' by holes, from\n");
1755" appearing in the output .node file. Thus, if two input vertices\n");
1757" have exactly the same coordinates, only the first appears in the\n");
1759" output. If any vertices are jettisoned, the vertex numbering in\n");
1761" the output .node file differs from that of the input .node file.\n");
1763" -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
1765" -v Outputs the Voronoi diagram associated with the triangulation.\n");
1767" Does not attempt to detect degeneracies, so some Voronoi vertices\n");
1769" may be duplicated. See the discussion of Voronoi diagrams below.\n");
1771" -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
1772 printf(
" triangle.\n");
1774" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
1776 printf(
" viewing with the Geometry Center's Geomview package.\n");
1778" -B No boundary markers in the output .node, .poly, and .edge output\n");
1780" files. See the detailed discussion of boundary markers below.\n");
1782" -P No output .poly file. Saves disk space, but you lose the ability\n");
1784" to maintain constraining segments on later refinements of the mesh.\n"
1786 printf(
" -N No output .node file.\n");
1787 printf(
" -E No output .ele file.\n");
1789" -I No iteration numbers. Suppresses the output of .node and .poly\n");
1791" files, so your input files won't be overwritten. (If your input is\n"
1794" a .poly file only, a .node file is written.) Cannot be used with\n");
1796" the -r switch, because that would overwrite your input .ele file.\n");
1798" Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
1800" using a .node file for input, because no .node file is written, so\n"
1802 printf(
" there is no record of any added Steiner points.\n");
1803 printf(
" -O No holes. Ignores the holes in the .poly file.\n");
1805" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
1808" arithmetic for certain tests if it thinks the inexact tests are not\n"
1811" accurate enough. Exact arithmetic ensures the robustness of the\n");
1813" triangulation algorithms, despite floating-point roundoff error.\n");
1815" Disabling exact arithmetic with the -X switch causes a small\n");
1817" improvement in speed and creates the possibility that Triangle will\n"
1819 printf(
" fail to produce a valid mesh. Not recommended.\n");
1821" -z Numbers all items starting from zero (rather than one). Note that\n"
1824" this switch is normally overridden by the value used to number the\n"
1827" first vertex of the input .node or .poly file. However, this\n");
1829" switch is useful when calling Triangle from another program.\n");
1831" -o2 Generates second-order subparametric elements with six nodes each.\n"
1834" -Y No new vertices on the boundary. This switch is useful when the\n");
1836" mesh boundary must be preserved so that it conforms to some\n");
1838" adjacent mesh. Be forewarned that you will probably sacrifice much\n"
1841" of the quality of the mesh; Triangle will try, but the resulting\n");
1843" mesh may contain poorly shaped triangles. Works well if all the\n");
1845" boundary vertices are closely spaced. Specify this switch twice\n");
1847" (`-YY') to prevent all segment splitting, including internal\n");
1848 printf(
" boundaries.\n");
1850" -S Specifies the maximum number of Steiner points (vertices that are\n");
1852" not in the input, but are added to meet the constraints on minimum\n"
1855" angle and maximum area). The default is to allow an unlimited\n");
1857" number. If you specify this switch with no number after it,\n");
1859" the limit is set to zero. Triangle always adds vertices at segment\n"
1862" intersections, even if it needs to use more vertices than the limit\n"
1865" you set. When Triangle inserts segments by splitting (-s), it\n");
1867" always adds enough vertices to ensure that all the segments of the\n"
1869 printf(
" PLSG are recovered, ignoring the limit if necessary.\n");
1871" -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
1873" construct a Delaunay triangulation. Try it if the divide-and-\n");
1874 printf(
" conquer algorithm fails.\n");
1876" -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
1878" triangulation. Warning: does not use exact arithmetic for all\n");
1879 printf(
" calculations. An exact result is not guaranteed.\n");
1881" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
1883" default, Triangle alternates between vertical and horizontal cuts,\n"
1886" which usually improve the speed except with vertex sets that are\n");
1888" small or short and wide. This switch is primarily of theoretical\n");
1889 printf(
" interest.\n");
1891" -s Specifies that segments should be forced into the triangulation by\n"
1894" recursively splitting them at their midpoints, rather than by\n");
1896" generating a constrained Delaunay triangulation. Segment splitting\n"
1899" is true to Ruppert's original algorithm, but can create needlessly\n"
1902" small triangles. This switch is primarily of theoretical interest.\n"
1905" -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
1908" checking, even if the -X switch is used. Useful if you suspect\n");
1909 printf(
" Triangle is buggy.\n");
1911" -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
1912 printf(
" unless an error occurs.\n");
1914" -V Verbose: Gives detailed information about what Triangle is doing.\n"
1917" Add more `V's for increasing amount of detail. `-V' is most\n");
1919" useful; itgives information on algorithmic progress and much more\n");
1921" detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
1923" prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
1925 printf(
" information only a debugger could love.\n");
1926 printf(
" -h Help: Displays these instructions.\n");
1928 printf(
"Definitions:\n");
1931" A Delaunay triangulation of a vertex set is a triangulation whose\n");
1933" vertices are the vertex set, that covers the convex hull of the vertex\n");
1935" set. A Delaunay triangulation has the property that no vertex lies\n");
1937" inside the circumscribing circle (circle that passes through all three\n");
1938 printf(
" vertices) of any triangle in the triangulation.\n\n");
1940" A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
1942" polygonal cells (some of which may be unbounded, meaning infinitely\n");
1944" large), where each cell is the set of points in the plane that are closer\n"
1947" to some input vertex than to any other input vertex. The Voronoi diagram\n"
1949 printf(
" is a geometric dual of the Delaunay triangulation.\n\n");
1951" A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
1953" Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
1956" Segments may intersect each other only at their endpoints. The file\n");
1957 printf(
" format for PSLGs (.poly files) is described below.\n\n");
1959" A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
1961" Delaunay triangulation, but each PSLG segment is present as a single edge\n"
1964" of the CDT. (A constrained Delaunay triangulation is not truly a\n");
1966" Delaunay triangulation, because some of its triangles might not be\n");
1968" Delaunay.) By definition, a CDT does not have any vertices other than\n");
1970" those specified in the input PSLG. Depending on context, a CDT might\n");
1972" cover the convex hull of the PSLG, or it might cover only a segment-\n");
1973 printf(
" bounded region (e.g. a polygon).\n\n");
1975" A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
1978" each triangle is truly Delaunay, and each PSLG segment is represented by\n"
1981" a linear contiguous sequence of edges of the triangulation. New vertices\n"
1984" (not part of the PSLG) may appear, and each input segment may have been\n");
1986" subdivided into shorter edges (subsegments) by these additional vertices.\n"
1989" The new vertices are frequently necessary to maintain the Delaunay\n");
1990 printf(
" property while ensuring that every segment is represented.\n\n");
1992" A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
1994" triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
1995 printf(
" vertices may appear, and input segments may be subdivided into\n");
1997" subsegments, but not to guarantee that segments are respected; rather, to\n"
2000" improve the quality of the triangles. The high-quality meshes produced\n");
2002" by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
2003 printf(
" with the -D switch.\n\n");
2004 printf(
"File Formats:\n\n");
2006" All files may contain comments prefixed by the character '#'. Vertices,\n"
2009" triangles, edges, holes, and maximum area constraints must be numbered\n");
2011" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
2013" input files must be consistent; if the vertices are numbered from 1, so\n");
2015" must be all other objects. Triangle automatically detects your choice\n");
2017" while reading the .node (or .poly) file. (When calling Triangle from\n");
2019" another program, use the -z switch if you wish to number objects from\n");
2020 printf(
" zero.) Examples of these file formats are given below.\n\n");
2021 printf(
" .node files:\n");
2023" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2026" <# of boundary markers (0 or 1)>\n"
2029" Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2032" The attributes, which are typically floating-point values of physical\n");
2034" quantities (such as mass or conductivity) associated with the nodes of\n"
2037" a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
2040" -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
2042 printf(
" has attributes assigned to it by linear interpolation.\n\n");
2044" If the fourth entry of the first line is `1', the last column of the\n");
2046" remainder of the file is assumed to contain boundary markers. Boundary\n"
2049" markers are used to identify boundary vertices and vertices resting on\n"
2052" PSLG segments; a complete description appears in a section below. The\n"
2055" .node file produced by Triangle contains boundary markers in the last\n");
2056 printf(
" column unless they are suppressed by the -B switch.\n\n");
2057 printf(
" .ele files:\n");
2059" First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
2061" Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
2064" Nodes are indices into the corresponding .node file. The first three\n");
2066" nodes are the corner vertices, and are listed in counterclockwise order\n"
2069" around each triangle. (The remaining nodes, if any, depend on the type\n"
2071 printf(
" of finite element used.)\n\n");
2073" The attributes are just like those of .node files. Because there is no\n"
2076" simple mapping from input to output triangles, Triangle attempts to\n");
2078" interpolate attributes, and may cause a lot of diffusion of attributes\n"
2081" among nearby triangles as the triangulation is refined. Attributes do\n"
2083 printf(
" not diffuse across segments, so attributes used to identify\n");
2084 printf(
" segment-bounded regions remain intact.\n\n");
2086" In .ele files produced by Triangle, each triangular element has three\n");
2088" nodes (vertices) unless the -o2 switch is used, in which case\n");
2090" subparametric quadratic elements with six nodes each are generated.\n");
2092" The first three nodes are the corners in counterclockwise order, and\n");
2094" the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
2096" opposite the first, second, and third vertices, respectively.\n");
2098 printf(
" .poly files:\n");
2100" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2103" <# of boundary markers (0 or 1)>\n"
2106" Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2107 printf(
" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
2109" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
2110 printf(
" One line: <# of holes>\n");
2111 printf(
" Following lines: <hole #> <x> <y>\n");
2113" Optional line: <# of regional attributes and/or area constraints>\n");
2115" Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
2118" A .poly file represents a PSLG, as well as some additional information.\n"
2121" The first section lists all the vertices, and is identical to the\n");
2123" format of .node files. <# of vertices> may be set to zero to indicate\n"
2126" that the vertices are listed in a separate .node file; .poly files\n");
2128" produced by Triangle always have this format. A vertex set represented\n"
2131" this way has the advantage that it may easily be triangulated with or\n");
2133" without segments (depending on whether the -p switch is invoked).\n");
2136" The second section lists the segments. Segments are edges whose\n");
2138" presence in the triangulation is enforced. (Depending on the choice of\n"
2141" switches, segment might be subdivided into smaller edges). Each\n");
2143" segment is specified by listing the indices of its two endpoints. This\n"
2146" means that you must include its endpoints in the vertex list. Each\n");
2147 printf(
" segment, like each point, may have a boundary marker.\n\n");
2149" If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
2152" Delaunay triangulation (CDT), in which each segment appears as a single\n"
2155" edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
2158" produces a conforming constrained Delaunay triangulation (CCDT), in\n");
2160" which segments may be subdivided into smaller edges. If -D is\n");
2162" selected, Triangle produces a conforming Delaunay triangulation, so\n");
2164" that every triangle is Delaunay, and not just constrained Delaunay.\n");
2167" The third section lists holes (and concavities, if -c is selected) in\n");
2169" the triangulation. Holes are specified by identifying a point inside\n");
2171" each hole. After the triangulation is formed, Triangle creates holes\n");
2173" by eating triangles, spreading out from each hole point until its\n");
2175" progress is blocked by segments in the PSLG. You must be careful to\n");
2177" enclose each hole in segments, or your whole triangulation might be\n");
2179" eaten away. If the two triangles abutting a segment are eaten, the\n");
2181" segment itself is also eaten. Do not place a hole directly on a\n");
2182 printf(
" segment; if you do, Triangle chooses one side of the segment\n");
2183 printf(
" arbitrarily.\n\n");
2185" The optional fourth section lists regional attributes (to be assigned\n");
2187" to all triangles in a region) and regional constraints on the maximum\n");
2189" triangle area. Triangle reads this section only if the -A switch is\n");
2191" used or the -a switch is used without a number following it, and the -r\n"
2194" switch is not used. Regional attributes and area constraints are\n");
2196" propagated in the same manner as holes: you specify a point for each\n");
2198" attribute and/or constraint, and the attribute and/or constraint\n");
2200" affects the whole region (bounded by segments) containing the point.\n");
2202" If two values are written on a line after the x and y coordinate, the\n");
2204" first such value is assumed to be a regional attribute (but is only\n");
2206" applied if the -A switch is selected), and the second value is assumed\n"
2209" to be a regional area constraint (but is only applied if the -a switch\n"
2212" is selected). You may specify just one value after the coordinates,\n");
2214" which can serve as both an attribute and an area constraint, depending\n"
2217" on the choice of switches. If you are using the -A and -a switches\n");
2219" simultaneously and wish to assign an attribute to some region without\n");
2220 printf(
" imposing an area constraint, use a negative maximum area.\n\n");
2222" When a triangulation is created from a .poly file, you must either\n");
2224" enclose the entire region to be triangulated in PSLG segments, or\n");
2226" use the -c switch, which automatically creates extra segments that\n");
2228" enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
2231" Triangle eats all triangles that are not enclosed by segments; if you\n");
2233" are not careful, your whole triangulation may be eaten away. If you do\n"
2236" use the -c switch, you can still produce concavities by the appropriate\n"
2239" placement of holes just inside the boundary of the convex hull.\n");
2242" An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
2244" upon segments (except, of course, the endpoints of each segment). You\n"
2247" aren't required to make your .poly files ideal, but you should be aware\n"
2250" of what can go wrong. Segment intersections are relatively safe--\n");
2252" Triangle calculates the intersection points for you and adds them to\n");
2254" the triangulation--as long as your machine's floating-point precision\n");
2256" doesn't become a problem. You are tempting the fates if you have three\n"
2259" segments that cross at the same location, and expect Triangle to figure\n"
2262" out where the intersection point is. Thanks to floating-point roundoff\n"
2265" error, Triangle will probably decide that the three segments intersect\n"
2268" at three different points, and you will find a minuscule triangle in\n");
2270" your output--unless Triangle tries to refine the tiny triangle, uses\n");
2272" up the last bit of machine precision, and fails to terminate at all.\n");
2274" You're better off putting the intersection point in the input files,\n");
2276" and manually breaking up each segment into two. Similarly, if you\n");
2278" place a vertex at the middle of a segment, and hope that Triangle will\n"
2281" break up the segment at that vertex, you might get lucky. On the other\n"
2284" hand, Triangle might decide that the vertex doesn't lie precisely on\n");
2286" the segment, and you'll have a needle-sharp triangle in your output--or\n"
2288 printf(
" a lot of tiny triangles if you're generating a quality mesh.\n");
2291" When Triangle reads a .poly file, it also writes a .poly file, which\n");
2293" includes all the subsegments--the edges that are parts of input\n");
2295" segments. If the -c switch is used, the output .poly file also\n");
2297" includes all of the edges on the convex hull. Hence, the output .poly\n"
2300" file is useful for finding edges associated with input segments and for\n"
2303" setting boundary conditions in finite element simulations. Moreover,\n");
2305" you will need the output .poly file if you plan to refine the output\n");
2307" mesh, and don't want segments to be missing in later triangulations.\n");
2309 printf(
" .area files:\n");
2310 printf(
" First line: <# of triangles>\n");
2311 printf(
" Following lines: <triangle #> <maximum area>\n");
2314" An .area file associates with each triangle a maximum area that is used\n"
2317" for mesh refinement. As with other file formats, every triangle must\n");
2319" be represented, and the triangles must be numbered consecutively. A\n");
2321" triangle may be left unconstrained by assigning it a negative maximum\n");
2322 printf(
" area.\n\n");
2323 printf(
" .edge files:\n");
2324 printf(
" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
2326" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
2329" Endpoints are indices into the corresponding .node file. Triangle can\n"
2332" produce .edge files (use the -e switch), but cannot read them. The\n");
2334" optional column of boundary markers is suppressed by the -B switch.\n");
2337" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
2339" infinite ray with only one endpoint. For these edges, a different\n");
2340 printf(
" format is used:\n\n");
2341 printf(
" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
2343" The `direction' is a floating-point vector that indicates the direction\n"
2345 printf(
" of the infinite ray.\n\n");
2346 printf(
" .neigh files:\n");
2348" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
2351" Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
2354" Neighbors are indices into the corresponding .ele file. An index of -1\n"
2357" indicates no neighbor (because the triangle is on an exterior\n");
2359" boundary). The first neighbor of triangle i is opposite the first\n");
2360 printf(
" corner of triangle i, and so on.\n\n");
2362" Triangle can produce .neigh files (use the -n switch), but cannot read\n"
2364 printf(
" them.\n\n");
2365 printf(
"Boundary Markers:\n\n");
2367" Boundary markers are tags used mainly to identify which output vertices\n");
2369" and edges are associated with which PSLG segment, and to identify which\n");
2371" vertices and edges occur on a boundary of the triangulation. A common\n");
2373" use is to determine where boundary conditions should be applied to a\n");
2375" finite element mesh. You can prevent boundary markers from being written\n"
2377 printf(
" into files produced by Triangle by using the -B switch.\n\n");
2379" The boundary marker associated with each segment in an output .poly file\n"
2381 printf(
" and each edge in an output .edge file is chosen as follows:\n");
2383" - If an output edge is part or all of a PSLG segment with a nonzero\n");
2385" boundary marker, then the edge is assigned the same marker.\n");
2387" - Otherwise, if the edge lies on a boundary of the triangulation\n");
2389" (even the boundary of a hole), then the edge is assigned the marker\n");
2390 printf(
" one (1).\n");
2391 printf(
" - Otherwise, the edge is assigned the marker zero (0).\n");
2393" The boundary marker associated with each vertex in an output .node file\n");
2394 printf(
" is chosen as follows:\n");
2396" - If a vertex is assigned a nonzero boundary marker in the input file,\n"
2399" then it is assigned the same marker in the output .node file.\n");
2401" - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
2403" endpoint of the segment) with a nonzero boundary marker, then the\n");
2405" vertex is assigned the same marker. If the vertex lies on several\n");
2406 printf(
" such segments, one of the markers is chosen arbitrarily.\n");
2408" - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
2409 printf(
" then the vertex is assigned the marker one (1).\n");
2410 printf(
" - Otherwise, the vertex is assigned the marker zero (0).\n");
2413" If you want Triangle to determine for you which vertices and edges are on\n"
2416" the boundary, assign them the boundary marker zero (or use no markers at\n"
2419" all) in your input files. In the output files, all boundary vertices,\n");
2420 printf(
" edges, and segments will be assigned the value one.\n\n");
2421 printf(
"Triangulation Iteration Numbers:\n\n");
2423" Because Triangle can read and refine its own triangulations, input\n");
2425" and output files have iteration numbers. For instance, Triangle might\n");
2427" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
2429" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
2430 printf(
" mesh.4.poly. Files with no iteration number are treated as if\n");
2432" their iteration number is zero; hence, Triangle might read the file\n");
2434" points.node, triangulate it, and produce the files points.1.node and\n");
2435 printf(
" points.1.ele.\n\n");
2437" Iteration numbers allow you to create a sequence of successively finer\n");
2439" meshes suitable for multigrid methods. They also allow you to produce a\n"
2442" sequence of meshes using error estimate-driven mesh refinement.\n");
2445" If you're not using refinement or quality meshing, and you don't like\n");
2447" iteration numbers, use the -I switch to disable them. This switch also\n");
2449" disables output of .node and .poly files to prevent your input files from\n"
2452" being overwritten. (If the input is a .poly file that contains its own\n");
2454" points, a .node file is written. This can be quite convenient for\n");
2455 printf(
" computing CDTs or quality meshes.)\n\n");
2456 printf(
"Examples of How to Use Triangle:\n\n");
2458" `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
2461" triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
2463" to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
2465" instead. (No additional .node file is needed, so none is written.)\n");
2468" `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
2470" object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
2473" its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
2476" The segments are copied to object.2.poly, and all edges are written to\n");
2477 printf(
" object.2.edge.\n\n");
2479" `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
2482" object.node), generates a mesh whose angles are all between 31.5 and 117\n"
2485" degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
2488" mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
2489 printf(
" into multiple subsegments; these are written to object.1.poly.\n");
2492" Here is a sample file `box.poly' describing a square with a square hole:\n"
2496" # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
2498 printf(
" 8 2 0 1\n");
2499 printf(
" # Outer box has these vertices:\n");
2500 printf(
" 1 0 0 0\n");
2501 printf(
" 2 0 3 0\n");
2502 printf(
" 3 3 0 0\n");
2503 printf(
" 4 3 3 33 # A special marker for this vertex.\n");
2504 printf(
" # Inner square has these vertices:\n");
2505 printf(
" 5 1 1 0\n");
2506 printf(
" 6 1 2 0\n");
2507 printf(
" 7 2 1 0\n");
2508 printf(
" 8 2 2 0\n");
2509 printf(
" # Five segments with boundary markers.\n");
2511 printf(
" 1 1 2 5 # Left side of outer box.\n");
2512 printf(
" # Square hole has these segments:\n");
2513 printf(
" 2 5 7 0\n");
2514 printf(
" 3 7 8 0\n");
2515 printf(
" 4 8 6 10\n");
2516 printf(
" 5 6 5 0\n");
2517 printf(
" # One hole in the middle of the inner square.\n");
2519 printf(
" 1 1.5 1.5\n");
2522" Note that some segments are missing from the outer square, so you must\n");
2524" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
2527" file `box.1.node', with twelve vertices. The last four vertices were\n");
2529" added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
2531" from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
2533" other vertices but 4 have been marked to indicate that they lie on a\n");
2534 printf(
" boundary.\n\n");
2535 printf(
" 12 2 0 1\n");
2536 printf(
" 1 0 0 5\n");
2537 printf(
" 2 0 3 5\n");
2538 printf(
" 3 3 0 1\n");
2539 printf(
" 4 3 3 33\n");
2540 printf(
" 5 1 1 1\n");
2541 printf(
" 6 1 2 10\n");
2542 printf(
" 7 2 1 1\n");
2543 printf(
" 8 2 2 10\n");
2544 printf(
" 9 0 1.5 5\n");
2545 printf(
" 10 1.5 0 1\n");
2546 printf(
" 11 3 1.5 1\n");
2547 printf(
" 12 1.5 3 1\n");
2548 printf(
" # Generated by triangle -pqc box.poly\n");
2550 printf(
" Here is the output file `box.1.ele', with twelve triangles.\n");
2552 printf(
" 12 3 0\n");
2553 printf(
" 1 5 6 9\n");
2554 printf(
" 2 10 3 7\n");
2555 printf(
" 3 6 8 12\n");
2556 printf(
" 4 9 1 5\n");
2557 printf(
" 5 6 2 9\n");
2558 printf(
" 6 7 3 11\n");
2559 printf(
" 7 11 4 8\n");
2560 printf(
" 8 7 5 10\n");
2561 printf(
" 9 12 2 6\n");
2562 printf(
" 10 8 7 11\n");
2563 printf(
" 11 5 1 10\n");
2564 printf(
" 12 8 4 12\n");
2565 printf(
" # Generated by triangle -pqc box.poly\n\n");
2567" Here is the output file `box.1.poly'. Note that segments have been added\n"
2570" to represent the convex hull, and some segments have been subdivided by\n");
2572" newly added vertices. Note also that <# of vertices> is set to zero to\n");
2573 printf(
" indicate that the vertices should be read from the .node file.\n");
2575 printf(
" 0 2 0 1\n");
2577 printf(
" 1 1 9 5\n");
2578 printf(
" 2 5 7 1\n");
2579 printf(
" 3 8 7 1\n");
2580 printf(
" 4 6 8 10\n");
2581 printf(
" 5 5 6 1\n");
2582 printf(
" 6 3 10 1\n");
2583 printf(
" 7 4 11 1\n");
2584 printf(
" 8 2 12 1\n");
2585 printf(
" 9 9 2 5\n");
2586 printf(
" 10 10 1 1\n");
2587 printf(
" 11 11 3 1\n");
2588 printf(
" 12 12 4 1\n");
2590 printf(
" 1 1.5 1.5\n");
2591 printf(
" # Generated by triangle -pqc box.poly\n");
2593 printf(
"Refinement and Area Constraints:\n");
2596" The -r switch causes a mesh (.node and .ele files) to be read and\n");
2598" refined. If the -p switch is also used, a .poly file is read and used to\n"
2601" specify edges that are constrained and cannot be eliminated (although\n");
2603" they can be subdivided into smaller edges) by the refinement process.\n");
2606" When you refine a mesh, you generally want to impose tighter constraints.\n"
2609" One way to accomplish this is to use -q with a larger angle, or -a\n");
2611" followed by a smaller area than you used to generate the mesh you are\n");
2613" refining. Another way to do this is to create an .area file, which\n");
2615" specifies a maximum area for each triangle, and use the -a switch\n");
2617" (without a number following). Each triangle's area constraint is applied\n"
2620" to that triangle. Area constraints tend to diffuse as the mesh is\n");
2622" refined, so if there are large variations in area constraint between\n");
2624" adjacent triangles, you may not get the results you want. In that case,\n"
2627" consider instead using the -u switch and writing a C procedure that\n");
2628 printf(
" determines which triangles are too large.\n\n");
2630" If you are refining a mesh composed of linear (three-node) elements, the\n"
2633" output mesh contains all the nodes present in the input mesh, in the same\n"
2636" order, with new nodes added at the end of the .node file. However, the\n");
2638" refinement is not hierarchical: there is no guarantee that each output\n");
2640" element is contained in a single input element. Often, an output element\n"
2643" can overlap two or three input elements, and some input edges are not\n");
2645" present in the output mesh. Hence, a sequence of refined meshes forms a\n"
2648" hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
2650" mesh of higher-order elements, the hierarchical property applies only to\n"
2653" the nodes at the corners of an element; the midpoint nodes on each edge\n");
2654 printf(
" are discarded before the mesh is refined.\n\n");
2656" Maximum area constraints in .poly files operate differently from those in\n"
2659" .area files. A maximum area in a .poly file applies to the whole\n");
2661" (segment-bounded) region in which a point falls, whereas a maximum area\n");
2663" in an .area file applies to only one triangle. Area constraints in .poly\n"
2666" files are used only when a mesh is first generated, whereas area\n");
2668" constraints in .area files are used only to refine an existing mesh, and\n"
2671" are typically based on a posteriori error estimates resulting from a\n");
2672 printf(
" finite element simulation on that mesh.\n\n");
2674" `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
2676" refines the triangulation to enforce a 25 degree minimum angle, and then\n"
2679" writes the refined triangulation to object.2.node and object.2.ele.\n");
2682" `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
2685" After reconstructing the mesh and its subsegments, Triangle refines the\n");
2687" mesh so that no triangle has area greater than 6.2, and furthermore the\n");
2689" triangles satisfy the maximum area constraints in z.3.area. No angle\n");
2691" bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
2693 printf(
" z.4.poly.\n\n");
2695" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
2697" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
2698 printf(
" suitable for multigrid.\n\n");
2699 printf(
"Convex Hulls and Mesh Boundaries:\n\n");
2701" If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
2703" hull as a by-product in the output .poly file if you use the -c switch.\n");
2705" There are faster algorithms for finding a two-dimensional convex hull\n");
2706 printf(
" than triangulation, of course, but this one comes for free.\n\n");
2708" If the input is an unconstrained mesh (you are using the -r switch but\n");
2710" not the -p switch), Triangle produces a list of its boundary edges\n");
2712" (including hole boundaries) as a by-product when you use the -c switch.\n");
2714" If you also use the -p switch, the output .poly file contains all the\n");
2715 printf(
" segments from the input .poly file as well.\n\n");
2716 printf(
"Voronoi Diagrams:\n\n");
2718" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
2720" .v.edge. For example, `triangle -v points' reads points.node, produces\n");
2722" its Delaunay triangulation in points.1.node and points.1.ele, and\n");
2724" produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
2727" .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
2729" file contains a list of all Voronoi edges, some of which may be infinite\n"
2732" rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
2733 printf(
" vertices through Triangle, if so desired.)\n\n");
2735" This implementation does not use exact arithmetic to compute the Voronoi\n"
2738" vertices, and does not check whether neighboring vertices are identical.\n"
2741" Be forewarned that if the Delaunay triangulation is degenerate or\n");
2743" near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
2744 printf(
" crossing edges.\n\n");
2746" The result is a valid Voronoi diagram only if Triangle's output is a true\n"
2749" Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
2751" may contain crossing edges and other pathology) if the output is a CDT or\n"
2754" CCDT, or if it has holes or concavities. If the triangulated domain is\n");
2756" convex and has no holes, you can use -D switch to force Triangle to\n");
2758" construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
2759 printf(
" Voronoi diagram will be valid.\n\n");
2760 printf(
"Mesh Topology:\n\n");
2762" You may wish to know which triangles are adjacent to a certain Delaunay\n");
2764" edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
2766" Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
2768" each other. All of this information can be found by cross-referencing\n");
2770" output files with the recollection that the Delaunay triangulation and\n");
2771 printf(
" the Voronoi diagram are planar duals.\n\n");
2773" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
2775" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
2777" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
2779" vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
2780 printf(
" of vertex k of the corresponding .node file.\n\n");
2782" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
2784" vertices of the corresponding Voronoi edge. If the endpoints of a\n");
2786" Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
2789" and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
2792" respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
2795" at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
2798" a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
2801" adjoin the right and left sides of the corresponding Voronoi edge,\n");
2803" respectively. To find which Voronoi cells are adjacent to each other,\n");
2804 printf(
" just read the list of Delaunay edges.\n\n");
2806" Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
2809" but you can reconstructed it straightforwardly. For instance, to find\n");
2811" all the edges of Voronoi cell 1, search the output .edge file for every\n");
2813" edge that has input vertex 1 as an endpoint. The corresponding dual\n");
2815" edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
2818" For each Voronoi vertex, the .neigh file gives a list of the three\n");
2820" Voronoi vertices attached to it. You might find this more convenient\n");
2821 printf(
" than the .v.edge file.\n\n");
2822 printf(
"Quadratic Elements:\n\n");
2824" Triangle generates meshes with subparametric quadratic elements if the\n");
2826" -o2 switch is specified. Quadratic elements have six nodes per element,\n"
2829" rather than three. `Subparametric' means that the edges of the triangles\n"
2832" are always straight, so that subparametric quadratic elements are\n");
2834" geometrically identical to linear elements, even though they can be used\n"
2837" with quadratic interpolating functions. The three extra nodes of an\n");
2839" element fall at the midpoints of the three edges, with the fourth, fifth,\n"
2842" and sixth nodes appearing opposite the first, second, and third corners\n");
2843 printf(
" respectively.\n\n");
2844 printf(
"Domains with Small Angles:\n\n");
2846" If two input segments adjoin each other at a small angle, clearly the -q\n"
2849" switch cannot remove the small angle. Moreover, Triangle may have no\n");
2851" choice but to generate additional triangles whose smallest angles are\n");
2853" smaller than the specified bound. However, these triangles only appear\n");
2855" between input segments separated by small angles. Moreover, if you\n");
2857" request a minimum angle of theta degrees, Triangle will generally produce\n"
2860" no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
2862 printf(
" the minimum angle.\n\n");
2863 printf(
"Statistics:\n\n");
2865" After generating a mesh, Triangle prints a count of entities in the\n");
2867" output mesh, including the number of vertices, triangles, edges, exterior\n"
2870" boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
2872" including hole boundaries), interior boundary edges (i.e. subsegments of\n"
2875" input segments not on the boundary), and total subsegments. If you've\n");
2877" forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
2880" with the -rNEP switches to read the mesh and print the statistics without\n"
2883" writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
2886" The -V switch produces extended statistics, including a rough estimate\n");
2888" of memory use, the number of calls to geometric predicates, and\n");
2890" histograms of the angles and the aspect ratios of the triangles in the\n");
2891 printf(
" mesh.\n\n");
2892 printf(
"Exact Arithmetic:\n\n");
2894" Triangle uses adaptive exact arithmetic to perform what computational\n");
2896" geometers call the `orientation' and `incircle' tests. If the floating-\n"
2899" point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
2901" most workstations do), and does not use extended precision internal\n");
2903" floating-point registers, then your output is guaranteed to be an\n");
2905" absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
2908" error notwithstanding. The word `adaptive' implies that these arithmetic\n"
2911" routines compute the result only to the precision necessary to guarantee\n"
2914" correctness, so they are usually nearly as fast as their approximate\n");
2915 printf(
" counterparts.\n\n");
2917" May CPUs, including Intel x86 processors, have extended precision\n");
2919" floating-point registers. These must be reconfigured so their precision\n"
2922" is reduced to memory precision. Triangle does this if it is compiled\n");
2923 printf(
" correctly. See the makefile for details.\n\n");
2925" The exact tests can be disabled with the -X switch. On most inputs, this\n"
2928" switch reduces the computation time by about eight percent--it's not\n");
2930" worth the risk. There are rare difficult inputs (having many collinear\n");
2932" and cocircular vertices), however, for which the difference in speed\n");
2934" could be a factor of two. Be forewarned that these are precisely the\n");
2936" inputs most likely to cause errors if you use the -X switch. Hence, the\n"
2938 printf(
" -X switch is not recommended.\n\n");
2940" Unfortunately, the exact tests don't solve every numerical problem.\n");
2942" Exact arithmetic is not used to compute the positions of new vertices,\n");
2944" because the bit complexity of vertex coordinates would grow without\n");
2946" bound. Hence, segment intersections aren't computed exactly; in very\n");
2948" unusual cases, roundoff error in computing an intersection point might\n");
2950" actually lead to an inverted triangle and an invalid triangulation.\n");
2952" (This is one reason to specify your own intersection points in your .poly\n"
2955" files.) Similarly, exact arithmetic is not used to compute the vertices\n"
2957 printf(
" of the Voronoi diagram.\n\n");
2959" Another pair of problems not solved by the exact arithmetic routines is\n");
2961" underflow and overflow. If Triangle is compiled for double precision\n");
2963" arithmetic, I believe that Triangle's geometric predicates work correctly\n"
2966" if the exponent of every input coordinate falls in the range [-148, 201].\n"
2969" Underflow can silently prevent the orientation and incircle tests from\n");
2971" being performed exactly, while overflow typically causes a floating\n");
2972 printf(
" exception.\n\n");
2973 printf(
"Calling Triangle from Another Program:\n\n");
2974 printf(
" Read the file triangle.h for details.\n\n");
2975 printf(
"Troubleshooting:\n\n");
2976 printf(
" Please read this section before mailing me bugs.\n\n");
2977 printf(
" `My output mesh has no triangles!'\n\n");
2979" If you're using a PSLG, you've probably failed to specify a proper set\n"
2982" of bounding segments, or forgotten to use the -c switch. Or you may\n");
2984" have placed a hole badly, thereby eating all your triangles. To test\n");
2985 printf(
" these possibilities, try again with the -c and -O switches.\n");
2987" Alternatively, all your input vertices may be collinear, in which case\n"
2989 printf(
" you can hardly expect to triangulate them.\n\n");
2990 printf(
" `Triangle doesn't terminate, or just crashes.'\n\n");
2992" Bad things can happen when triangles get so small that the distance\n");
2994" between their vertices isn't much larger than the precision of your\n");
2996" machine's arithmetic. If you've compiled Triangle for single-precision\n"
2999" arithmetic, you might do better by recompiling it for double-precision.\n"
3002" Then again, you might just have to settle for more lenient constraints\n"
3005" on the minimum angle and the maximum area than you had planned.\n");
3008" You can minimize precision problems by ensuring that the origin lies\n");
3010" inside your vertex set, or even inside the densest part of your\n");
3012" mesh. If you're triangulating an object whose x-coordinates all fall\n");
3014" between 6247133 and 6247134, you're not leaving much floating-point\n");
3015 printf(
" precision for Triangle to work with.\n\n");
3017" Precision problems can occur covertly if the input PSLG contains two\n");
3019" segments that meet (or intersect) at an extremely small angle, or if\n");
3021" such an angle is introduced by the -c switch. If you don't realize\n");
3023" that a tiny angle is being formed, you might never discover why\n");
3025" Triangle is crashing. To check for this possibility, use the -S switch\n"
3028" (with an appropriate limit on the number of Steiner points, found by\n");
3030" trial-and-error) to stop Triangle early, and view the output .poly file\n"
3033" with Show Me (described below). Look carefully for regions where dense\n"
3036" clusters of vertices are forming and for small angles between segments.\n"
3039" Zoom in closely, as such segments might look like a single segment from\n"
3041 printf(
" a distance.\n\n");
3043" If some of the input values are too large, Triangle may suffer a\n");
3045" floating exception due to overflow when attempting to perform an\n");
3047" orientation or incircle test. (Read the section on exact arithmetic\n");
3049" above.) Again, I recommend compiling Triangle for double (rather\n");
3050 printf(
" than single) precision arithmetic.\n\n");
3052" Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
3054" -u) with an input that is not segment-bounded--that is, if your input\n");
3056" is a vertex set, or you're using the -c switch. If the convex hull of\n"
3059" your input vertices has collinear vertices on its boundary, an input\n");
3061" vertex that you think lies on the convex hull might actually lie just\n");
3063" inside the convex hull. If so, the vertex and the nearby convex hull\n");
3065" edge form an extremely thin triangle. When Triangle tries to refine\n");
3067" the mesh to enforce angle and area constraints, Triangle might generate\n"
3070" extremely tiny triangles, or it might fail because of insufficient\n");
3071 printf(
" floating-point precision.\n\n");
3073" `The numbering of the output vertices doesn't match the input vertices.'\n"
3077" You may have had duplicate input vertices, or you may have eaten some\n");
3079" of your input vertices with a hole, or by placing them outside the area\n"
3082" enclosed by segments. In any case, you can solve the problem by not\n");
3083 printf(
" using the -j switch.\n\n");
3085" `Triangle executes without incident, but when I look at the resulting\n");
3087" mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
3090" If you select the -X switch, Triangle occasionally makes mistakes due\n");
3092" to floating-point roundoff error. Although these errors are rare,\n");
3094" don't use the -X switch. If you still have problems, please report the\n"
3096 printf(
" bug.\n\n");
3098" `Triangle executes without incident, but when I look at the resulting\n");
3099 printf(
" Voronoi diagram, it has overlapping edges or other geometric\n");
3100 printf(
" inconsistencies.'\n");
3103" If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
3106" diagram if the domain you are triangulating is convex and free of\n");
3108" holes, and you use the -D switch to construct a conforming Delaunay\n");
3109 printf(
" triangulation (instead of a CDT or CCDT).\n\n");
3111" Strange things can happen if you've taken liberties with your PSLG. Do\n");
3113" you have a vertex lying in the middle of a segment? Triangle sometimes\n");
3115" copes poorly with that sort of thing. Do you want to lay out a collinear\n"
3118" row of evenly spaced, segment-connected vertices? Have you simply\n");
3120" defined one long segment connecting the leftmost vertex to the rightmost\n"
3123" vertex, and a bunch of vertices lying along it? This method occasionally\n"
3126" works, especially with horizontal and vertical lines, but often it\n");
3128" doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
3130 printf(
" separate segment. If you don't like it, tough.\n\n");
3132" Furthermore, if you have segments that intersect other than at their\n");
3134" endpoints, try not to let the intersections fall extremely close to PSLG\n"
3136 printf(
" vertices or each other.\n\n");
3138" If you have problems refining a triangulation not produced by Triangle:\n");
3140" Are you sure the triangulation is geometrically valid? Is it formatted\n");
3142" correctly for Triangle? Are the triangles all listed so the first three\n"
3145" vertices are their corners in counterclockwise order? Are all of the\n");
3147" triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
3149 printf(
" assumes that it starts with a CDT.\n\n");
3150 printf(
"Show Me:\n\n");
3152" Triangle comes with a separate program named `Show Me', whose primary\n");
3154" purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
3157" purpose is to check the validity of your input files, and do so more\n");
3159" thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
3161" you have the X Windows system. Sorry, Microsoft Windows users.\n");
3163 printf(
"Triangle on the Web:\n");
3165 printf(
" To see an illustrated version of these instructions, check out\n");
3167 printf(
" http://www.cs.cmu.edu/~quake/triangle.html\n");
3169 printf(
"A Brief Plea:\n");
3172" If you use Triangle, and especially if you use it to accomplish real\n");
3174" work, I would like very much to hear from you. A short letter or email\n");
3176" (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
3179" to me. The more people I know are using this program, the more easily I\n"
3182" can justify spending time on improvements, which in turn will benefit\n");
3184" you. Also, I can put you on a list to receive email whenever a new\n");
3185 printf(
" version of Triangle is available.\n\n");
3187" If you use a mesh generated by Triangle in a publication, please include\n"
3190" an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
3193" If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
3195" ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
3197" Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
3199" Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
3201" Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
3203" Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
3205 printf(
" Geometry.)'\n\n");
3206 printf(
"Research credit:\n\n");
3208" Of course, I can take credit for only a fraction of the ideas that made\n");
3210" this mesh generator possible. Triangle owes its existence to the efforts\n"
3213" of many fine computational geometers and other researchers, including\n");
3215" Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
3218" Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
3220" Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
3222" Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
3224" Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
3226 printf(
" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
3228" Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
3229 printf(
" source code for references.\n\n");
3243 printf(
" Please report this bug to jrs@cs.berkeley.edu\n");
3244 printf(
" Include the message above, your input data set, and the exact\n");
3245 printf(
" command line you used to run Triangle.\n");
3256#ifdef ANSI_DECLARATORS
3277 b->poly =
b->refine =
b->quality = 0;
3278 b->vararea =
b->fixedarea =
b->usertest = 0;
3279 b->regionattrib =
b->convex =
b->weighted =
b->jettison = 0;
3281 b->edgesout =
b->voronoi =
b->neighbors =
b->geomview = 0;
3282 b->nobound =
b->nopolywritten =
b->nonodewritten =
b->noelewritten = 0;
3283 b->noiterationnum = 0;
3284 b->noholes =
b->noexact = 0;
3285 b->incremental =
b->sweepline = 0;
3295 b->quiet =
b->verbose = 0;
3297 b->innodefilename[0] =
'\0';
3302 if (argv[i][0] ==
'-') {
3304 for (j =
STARTINDEX; argv[i][j] !=
'\0'; j++) {
3305 if (argv[i][j] ==
'p') {
3309 if (argv[i][j] ==
'r') {
3312 if (argv[i][j] ==
'q') {
3314 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3315 (argv[i][j + 1] ==
'.')) {
3317 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3318 (argv[i][j + 1] ==
'.')) {
3320 workstring[k] = argv[i][j];
3323 workstring[k] =
'\0';
3324 b->minangle = (
REAL) strtod(workstring, (
char **) NULL);
3329 if (argv[i][j] ==
'a') {
3331 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3332 (argv[i][j + 1] ==
'.')) {
3335 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3336 (argv[i][j + 1] ==
'.')) {
3338 workstring[k] = argv[i][j];
3341 workstring[k] =
'\0';
3342 b->maxarea = (
REAL) strtod(workstring, (
char **) NULL);
3343 if (
b->maxarea <= 0.0) {
3344 printf(
"Error: Maximum area must be greater than zero.\n");
3351 if (argv[i][j] ==
'u') {
3356 if (argv[i][j] ==
'A') {
3357 b->regionattrib = 1;
3359 if (argv[i][j] ==
'c') {
3362 if (argv[i][j] ==
'w') {
3365 if (argv[i][j] ==
'W') {
3368 if (argv[i][j] ==
'j') {
3371 if (argv[i][j] ==
'z') {
3374 if (argv[i][j] ==
'e') {
3377 if (argv[i][j] ==
'v') {
3380 if (argv[i][j] ==
'n') {
3383 if (argv[i][j] ==
'g') {
3386 if (argv[i][j] ==
'B') {
3389 if (argv[i][j] ==
'P') {
3390 b->nopolywritten = 1;
3392 if (argv[i][j] ==
'N') {
3393 b->nonodewritten = 1;
3395 if (argv[i][j] ==
'E') {
3396 b->noelewritten = 1;
3399 if (argv[i][j] ==
'I') {
3400 b->noiterationnum = 1;
3403 if (argv[i][j] ==
'O') {
3406 if (argv[i][j] ==
'X') {
3409 if (argv[i][j] ==
'o') {
3410 if (argv[i][j + 1] ==
'2') {
3416 if (argv[i][j] ==
'Y') {
3419 if (argv[i][j] ==
'S') {
3421 while ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3423 b->steiner =
b->steiner * 10 + (
int) (argv[i][j] -
'0');
3428 if (argv[i][j] ==
'i') {
3431 if (argv[i][j] ==
'F') {
3435 if (argv[i][j] ==
'l') {
3440 if (argv[i][j] ==
's') {
3443 if ((argv[i][j] ==
'D') || (argv[i][j] ==
'L')) {
3448 if (argv[i][j] ==
'C') {
3452 if (argv[i][j] ==
'Q') {
3455 if (argv[i][j] ==
'V') {
3459 if ((argv[i][j] ==
'h') || (argv[i][j] ==
'H') ||
3460 (argv[i][j] ==
'?')) {
3473 if (
b->innodefilename[0] ==
'\0') {
3476 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 5],
".node")) {
3477 b->innodefilename[strlen(
b->innodefilename) - 5] =
'\0';
3479 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 5],
".poly")) {
3480 b->innodefilename[strlen(
b->innodefilename) - 5] =
'\0';
3484 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 4],
".ele")) {
3485 b->innodefilename[strlen(
b->innodefilename) - 4] =
'\0';
3488 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 5],
".area")) {
3489 b->innodefilename[strlen(
b->innodefilename) - 5] =
'\0';
3496 b->usesegments =
b->poly ||
b->refine ||
b->quality ||
b->convex;
3497 b->goodangle =
cos(
b->minangle *
PI / 180.0);
3498 if (
b->goodangle == 1.0) {
3499 b->offconstant = 0.0;
3501 b->offconstant = 0.475 *
sqrt((1.0 +
b->goodangle) / (1.0 -
b->goodangle));
3503 b->goodangle *=
b->goodangle;
3504 if (
b->refine &&
b->noiterationnum) {
3506 "Error: You cannot use the -I switch when refining a triangulation.\n");
3511 if (!
b->refine && !
b->poly) {
3516 if (
b->refine || !
b->poly) {
3517 b->regionattrib = 0;
3521 if (
b->weighted && (
b->poly ||
b->quality)) {
3524 printf(
"Warning: weighted triangulations (-w, -W) are incompatible\n");
3525 printf(
" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
3529 if (
b->jettison &&
b->nonodewritten && !
b->quiet) {
3530 printf(
"Warning: -j and -N switches are somewhat incompatible.\n");
3531 printf(
" If any vertices are jettisoned, you will need the output\n");
3532 printf(
" .node file to reconstruct the new node indices.");
3536 strcpy(
b->inpolyfilename,
b->innodefilename);
3537 strcpy(
b->inelefilename,
b->innodefilename);
3538 strcpy(
b->areafilename,
b->innodefilename);
3540 strcpy(workstring,
b->innodefilename);
3542 while (workstring[j] !=
'\0') {
3543 if ((workstring[j] ==
'.') && (workstring[j + 1] !=
'\0')) {
3549 if (increment > 0) {
3552 if ((workstring[j] >=
'0') && (workstring[j] <=
'9')) {
3553 meshnumber = meshnumber * 10 + (
int) (workstring[j] -
'0');
3558 }
while (workstring[j] !=
'\0');
3560 if (
b->noiterationnum) {
3561 strcpy(
b->outnodefilename,
b->innodefilename);
3562 strcpy(
b->outelefilename,
b->innodefilename);
3563 strcpy(
b->edgefilename,
b->innodefilename);
3564 strcpy(
b->vnodefilename,
b->innodefilename);
3565 strcpy(
b->vedgefilename,
b->innodefilename);
3566 strcpy(
b->neighborfilename,
b->innodefilename);
3567 strcpy(
b->offfilename,
b->innodefilename);
3568 strcat(
b->outnodefilename,
".node");
3569 strcat(
b->outelefilename,
".ele");
3570 strcat(
b->edgefilename,
".edge");
3571 strcat(
b->vnodefilename,
".v.node");
3572 strcat(
b->vedgefilename,
".v.edge");
3573 strcat(
b->neighborfilename,
".neigh");
3574 strcat(
b->offfilename,
".off");
3575 }
else if (increment == 0) {
3576 strcpy(
b->outnodefilename,
b->innodefilename);
3577 strcpy(
b->outpolyfilename,
b->innodefilename);
3578 strcpy(
b->outelefilename,
b->innodefilename);
3579 strcpy(
b->edgefilename,
b->innodefilename);
3580 strcpy(
b->vnodefilename,
b->innodefilename);
3581 strcpy(
b->vedgefilename,
b->innodefilename);
3582 strcpy(
b->neighborfilename,
b->innodefilename);
3583 strcpy(
b->offfilename,
b->innodefilename);
3584 strcat(
b->outnodefilename,
".1.node");
3585 strcat(
b->outpolyfilename,
".1.poly");
3586 strcat(
b->outelefilename,
".1.ele");
3587 strcat(
b->edgefilename,
".1.edge");
3588 strcat(
b->vnodefilename,
".1.v.node");
3589 strcat(
b->vedgefilename,
".1.v.edge");
3590 strcat(
b->neighborfilename,
".1.neigh");
3591 strcat(
b->offfilename,
".1.off");
3593 workstring[increment] =
'%';
3594 workstring[increment + 1] =
'd';
3595 workstring[increment + 2] =
'\0';
3596 sprintf(
b->outnodefilename, workstring, meshnumber + 1);
3597 strcpy(
b->outpolyfilename,
b->outnodefilename);
3598 strcpy(
b->outelefilename,
b->outnodefilename);
3599 strcpy(
b->edgefilename,
b->outnodefilename);
3600 strcpy(
b->vnodefilename,
b->outnodefilename);
3601 strcpy(
b->vedgefilename,
b->outnodefilename);
3602 strcpy(
b->neighborfilename,
b->outnodefilename);
3603 strcpy(
b->offfilename,
b->outnodefilename);
3604 strcat(
b->outnodefilename,
".node");
3605 strcat(
b->outpolyfilename,
".poly");
3606 strcat(
b->outelefilename,
".ele");
3607 strcat(
b->edgefilename,
".edge");
3608 strcat(
b->vnodefilename,
".v.node");
3609 strcat(
b->vedgefilename,
".v.edge");
3610 strcat(
b->neighborfilename,
".neigh");
3611 strcat(
b->offfilename,
".off");
3613 strcat(
b->innodefilename,
".node");
3614 strcat(
b->inpolyfilename,
".poly");
3615 strcat(
b->inelefilename,
".ele");
3616 strcat(
b->areafilename,
".area");
3639#ifdef ANSI_DECLARATORS
3649 struct otri printtri;
3650 struct osub printsh;
3653 printf(
"triangle x%lx with orientation %d:\n", (
unsigned long) t->tri,
3655 decode(t->tri[0], printtri);
3656 if (printtri.tri ==
m->dummytri) {
3657 printf(
" [0] = Outer space\n");
3659 printf(
" [0] = x%lx %d\n", (
unsigned long) printtri.tri,
3662 decode(t->tri[1], printtri);
3663 if (printtri.tri ==
m->dummytri) {
3664 printf(
" [1] = Outer space\n");
3666 printf(
" [1] = x%lx %d\n", (
unsigned long) printtri.tri,
3669 decode(t->tri[2], printtri);
3670 if (printtri.tri ==
m->dummytri) {
3671 printf(
" [2] = Outer space\n");
3673 printf(
" [2] = x%lx %d\n", (
unsigned long) printtri.tri,
3677 org(*t, printvertex);
3678 if (printvertex == (
vertex) NULL)
3679 printf(
" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
3681 printf(
" Origin[%d] = x%lx (%.12g, %.12g)\n",
3682 (t->orient + 1) % 3 + 3, (
unsigned long) printvertex,
3683 printvertex[0], printvertex[1]);
3684 dest(*t, printvertex);
3685 if (printvertex == (
vertex) NULL)
3686 printf(
" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
3688 printf(
" Dest [%d] = x%lx (%.12g, %.12g)\n",
3689 (t->orient + 2) % 3 + 3, (
unsigned long) printvertex,
3690 printvertex[0], printvertex[1]);
3691 apex(*t, printvertex);
3692 if (printvertex == (
vertex) NULL)
3693 printf(
" Apex [%d] = NULL\n", t->orient + 3);
3695 printf(
" Apex [%d] = x%lx (%.12g, %.12g)\n",
3696 t->orient + 3, (
unsigned long) printvertex,
3697 printvertex[0], printvertex[1]);
3699 if (
b->usesegments) {
3701 if (printsh.ss !=
m->dummysub) {
3702 printf(
" [6] = x%lx %d\n", (
unsigned long) printsh.ss,
3706 if (printsh.ss !=
m->dummysub) {
3707 printf(
" [7] = x%lx %d\n", (
unsigned long) printsh.ss,
3711 if (printsh.ss !=
m->dummysub) {
3712 printf(
" [8] = x%lx %d\n", (
unsigned long) printsh.ss,
3718 printf(
" Area constraint: %.4g\n",
areabound(*t));
3733#ifdef ANSI_DECLARATORS
3743 struct osub printsh;
3744 struct otri printtri;
3749 printf(
"subsegment x%lx with orientation %d and mark %d:\n",
3750 (
unsigned long) s->ss, s->ssorient,
mark(*s));
3752 if (printsh.ss ==
m->dummysub) {
3753 printf(
" [0] = No subsegment\n");
3755 printf(
" [0] = x%lx %d\n", (
unsigned long) printsh.ss,
3759 if (printsh.ss ==
m->dummysub) {
3760 printf(
" [1] = No subsegment\n");
3762 printf(
" [1] = x%lx %d\n", (
unsigned long) printsh.ss,
3766 sorg(*s, printvertex);
3767 if (printvertex == (
vertex) NULL)
3768 printf(
" Origin[%d] = NULL\n", 2 + s->ssorient);
3770 printf(
" Origin[%d] = x%lx (%.12g, %.12g)\n",
3771 2 + s->ssorient, (
unsigned long) printvertex,
3772 printvertex[0], printvertex[1]);
3773 sdest(*s, printvertex);
3774 if (printvertex == (
vertex) NULL)
3775 printf(
" Dest [%d] = NULL\n", 3 - s->ssorient);
3777 printf(
" Dest [%d] = x%lx (%.12g, %.12g)\n",
3778 3 - s->ssorient, (
unsigned long) printvertex,
3779 printvertex[0], printvertex[1]);
3781 decode(s->ss[6], printtri);
3782 if (printtri.tri ==
m->dummytri) {
3783 printf(
" [6] = Outer space\n");
3785 printf(
" [6] = x%lx %d\n", (
unsigned long) printtri.tri,
3788 decode(s->ss[7], printtri);
3789 if (printtri.tri ==
m->dummytri) {
3790 printf(
" [7] = Outer space\n");
3792 printf(
" [7] = x%lx %d\n", (
unsigned long) printtri.tri,
3797 if (printvertex == (
vertex) NULL)
3798 printf(
" Segment origin[%d] = NULL\n", 4 + s->ssorient);
3800 printf(
" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
3801 4 + s->ssorient, (
unsigned long) printvertex,
3802 printvertex[0], printvertex[1]);
3804 if (printvertex == (
vertex) NULL)
3805 printf(
" Segment dest [%d] = NULL\n", 5 - s->ssorient);
3807 printf(
" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
3808 5 - s->ssorient, (
unsigned long) printvertex,
3809 printvertex[0], printvertex[1]);
3829#ifdef ANSI_DECLARATORS
3833struct memorypool *pool;
3837 pool->firstblock = (
VOID **) NULL;
3838 pool->nowblock = (
VOID **) NULL;
3839 pool->nextitem = (
VOID *) NULL;
3840 pool->deaditemstack = (
VOID *) NULL;
3841 pool->pathblock = (
VOID **) NULL;
3842 pool->pathitem = (
VOID *) NULL;
3843 pool->alignbytes = 0;
3844 pool->itembytes = 0;
3845 pool->itemsperblock = 0;
3846 pool->itemsfirstblock = 0;
3849 pool->unallocateditems = 0;
3850 pool->pathitemsleft = 0;
3863#ifdef ANSI_DECLARATORS
3867struct memorypool *pool;
3871 unsigned long alignptr;
3877 pool->nowblock = pool->firstblock;
3879 alignptr = (
unsigned long) (pool->nowblock + 1);
3881 pool->nextitem = (
VOID *)
3882 (alignptr + (
unsigned long) pool->alignbytes -
3883 (alignptr % (
unsigned long) pool->alignbytes));
3885 pool->unallocateditems = pool->itemsfirstblock;
3887 pool->deaditemstack = (
VOID *) NULL;
3909#ifdef ANSI_DECLARATORS
3910void poolinit(
struct memorypool *pool,
int bytecount,
int itemcount,
3914struct memorypool *pool;
3929 pool->alignbytes =
sizeof(
VOID *);
3931 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
3933 pool->itemsperblock = itemcount;
3934 if (firstitemcount == 0) {
3935 pool->itemsfirstblock = itemcount;
3937 pool->itemsfirstblock = firstitemcount;
3943 pool->firstblock = (
VOID **)
3944 trimalloc(pool->itemsfirstblock * pool->itembytes + (
int)
sizeof(
VOID *) +
3947 *(pool->firstblock) = (
VOID *) NULL;
3957#ifdef ANSI_DECLARATORS
3961struct memorypool *pool;
3965 while (pool->firstblock != (
VOID **) NULL) {
3966 pool->nowblock = (
VOID **) *(pool->firstblock);
3968 pool->firstblock = pool->nowblock;
3978#ifdef ANSI_DECLARATORS
3982struct memorypool *pool;
3988 unsigned long alignptr;
3992 if (pool->deaditemstack != (
VOID *) NULL) {
3993 newitem = pool->deaditemstack;
3994 pool->deaditemstack = * (
VOID **) pool->deaditemstack;
3997 if (pool->unallocateditems == 0) {
3999 if (*(pool->nowblock) == (
VOID *) NULL) {
4001 newblock = (
VOID **)
trimalloc(pool->itemsperblock * pool->itembytes +
4002 (
int)
sizeof(
VOID *) +
4004 *(pool->nowblock) = (
VOID *) newblock;
4006 *newblock = (
VOID *) NULL;
4010 pool->nowblock = (
VOID **) *(pool->nowblock);
4013 alignptr = (
unsigned long) (pool->nowblock + 1);
4015 pool->nextitem = (
VOID *)
4016 (alignptr + (
unsigned long) pool->alignbytes -
4017 (alignptr % (
unsigned long) pool->alignbytes));
4019 pool->unallocateditems = pool->itemsperblock;
4023 newitem = pool->nextitem;
4025 pool->nextitem = (
VOID *) ((
char *) pool->nextitem + pool->itembytes);
4026 pool->unallocateditems--;
4041#ifdef ANSI_DECLARATORS
4045struct memorypool *pool;
4051 *((
VOID **) dyingitem) = pool->deaditemstack;
4052 pool->deaditemstack = dyingitem;
4064#ifdef ANSI_DECLARATORS
4068struct memorypool *pool;
4072 unsigned long alignptr;
4075 pool->pathblock = pool->firstblock;
4077 alignptr = (
unsigned long) (pool->pathblock + 1);
4079 pool->pathitem = (
VOID *)
4080 (alignptr + (
unsigned long) pool->alignbytes -
4081 (alignptr % (
unsigned long) pool->alignbytes));
4083 pool->pathitemsleft = pool->itemsfirstblock;
4100#ifdef ANSI_DECLARATORS
4104struct memorypool *pool;
4109 unsigned long alignptr;
4112 if (pool->pathitem == pool->nextitem) {
4113 return (
VOID *) NULL;
4117 if (pool->pathitemsleft == 0) {
4119 pool->pathblock = (
VOID **) *(pool->pathblock);
4121 alignptr = (
unsigned long) (pool->pathblock + 1);
4123 pool->pathitem = (
VOID *)
4124 (alignptr + (
unsigned long) pool->alignbytes -
4125 (alignptr % (
unsigned long) pool->alignbytes));
4127 pool->pathitemsleft = pool->itemsperblock;
4130 newitem = pool->pathitem;
4132 pool->pathitem = (
VOID *) ((
char *) pool->pathitem + pool->itembytes);
4133 pool->pathitemsleft--;
4165#ifdef ANSI_DECLARATORS
4177 unsigned long alignptr;
4181 m->triangles.alignbytes);
4183 alignptr = (
unsigned long)
m->dummytribase;
4185 (alignptr + (
unsigned long)
m->triangles.alignbytes -
4186 (alignptr % (
unsigned long)
m->triangles.alignbytes));
4199 if (
b->usesegments) {
4204 m->subsegs.alignbytes);
4206 alignptr = (
unsigned long)
m->dummysubbase;
4208 (alignptr + (
unsigned long)
m->subsegs.alignbytes -
4209 (alignptr % (
unsigned long)
m->subsegs.alignbytes));
4214 m->dummysub[0] = (
subseg)
m->dummysub;
4215 m->dummysub[1] = (
subseg)
m->dummysub;
4217 m->dummysub[2] = (
subseg) NULL;
4218 m->dummysub[3] = (
subseg) NULL;
4219 m->dummysub[4] = (
subseg) NULL;
4220 m->dummysub[5] = (
subseg) NULL;
4222 m->dummysub[6] = (
subseg)
m->dummytri;
4223 m->dummysub[7] = (
subseg)
m->dummytri;
4225 * (
int *) (
m->dummysub + 8) = 0;
4245#ifdef ANSI_DECLARATORS
4259 m->vertexmarkindex = ((
m->mesh_dim +
m->nextras) *
sizeof(
REAL) +
4262 vertexsize = (
m->vertexmarkindex + 2) *
sizeof(
int);
4266 m->vertex2triindex = (vertexsize +
sizeof(
triangle) - 1) /
4268 vertexsize = (
m->vertex2triindex + 1) *
sizeof(
triangle);
4288#ifdef ANSI_DECLARATORS
4303 m->highorderindex = 6 + (
b->usesegments * 3);
4305 trisize = ((
b->order + 1) * (
b->order + 2) / 2 + (
m->highorderindex - 3)) *
4309 m->elemattribindex = (trisize +
sizeof(
REAL) - 1) /
sizeof(
REAL);
4313 m->areaboundindex =
m->elemattribindex +
m->eextras +
b->regionattrib;
4317 trisize = (
m->areaboundindex + 1) *
sizeof(
REAL);
4318 }
else if (
m->eextras +
b->regionattrib > 0) {
4319 trisize =
m->areaboundindex *
sizeof(
REAL);
4325 if ((
b->voronoi ||
b->neighbors) &&
4327 trisize = 6 *
sizeof(
triangle) +
sizeof(
int);
4332 (2 *
m->invertices - 2) >
TRIPERBLOCK ? (2 *
m->invertices - 2) :
4335 if (
b->usesegments) {
4342 dummyinit(
m,
b,
m->triangles.itembytes,
m->subsegs.itembytes);
4355#ifdef ANSI_DECLARATORS
4376#ifdef ANSI_DECLARATORS
4388 if (newtriangle == (
triangle *) NULL) {
4391 }
while (
deadtri(newtriangle));
4401#ifdef ANSI_DECLARATORS
4422#ifdef ANSI_DECLARATORS
4434 if (newsubseg == (
subseg *) NULL) {
4447#ifdef ANSI_DECLARATORS
4468#ifdef ANSI_DECLARATORS
4480 if (newvertex == (
vertex) NULL) {
4496#ifdef ANSI_DECLARATORS
4497void badsubsegdealloc(
struct mesh *
m,
struct badsubseg *dyingseg)
4499void badsubsegdealloc(
m, dyingseg)
4501struct badsubseg *dyingseg;
4507 dyingseg->subsegorg = (
vertex) NULL;
4521#ifdef ANSI_DECLARATORS
4522struct badsubseg *badsubsegtraverse(
struct mesh *
m)
4524struct badsubseg *badsubsegtraverse(
m)
4529 struct badsubseg *newseg;
4532 newseg = (
struct badsubseg *)
traverse(&
m->badsubsegs);
4533 if (newseg == (
struct badsubseg *) NULL) {
4534 return (
struct badsubseg *) NULL;
4536 }
while (newseg->subsegorg == (
vertex) NULL);
4554#ifdef ANSI_DECLARATORS
4566 unsigned long alignptr;
4569 getblock =
m->vertices.firstblock;
4570 current =
b->firstnumber;
4573 if (current +
m->vertices.itemsfirstblock <= number) {
4574 getblock = (
VOID **) *getblock;
4575 current +=
m->vertices.itemsfirstblock;
4576 while (current +
m->vertices.itemsperblock <= number) {
4577 getblock = (
VOID **) *getblock;
4578 current +=
m->vertices.itemsperblock;
4583 alignptr = (
unsigned long) (getblock + 1);
4584 foundvertex = (
char *) (alignptr + (
unsigned long)
m->vertices.alignbytes -
4585 (alignptr % (
unsigned long)
m->vertices.alignbytes));
4586 return (
vertex) (foundvertex +
m->vertices.itembytes * (number - current));
4595#ifdef ANSI_DECLARATORS
4606 if (
b->usesegments) {
4614 if ((
b->minangle > 0.0) ||
b->vararea ||
b->fixedarea ||
b->usertest) {
4636#ifdef ANSI_DECLARATORS
4642struct otri *newotri;
4650 newotri->tri[0] = (
triangle)
m->dummytri;
4651 newotri->tri[1] = (
triangle)
m->dummytri;
4652 newotri->tri[2] = (
triangle)
m->dummytri;
4657 if (
b->usesegments) {
4660 newotri->tri[6] = (
triangle)
m->dummysub;
4661 newotri->tri[7] = (
triangle)
m->dummysub;
4662 newotri->tri[8] = (
triangle)
m->dummysub;
4664 for (i = 0; i <
m->eextras; i++) {
4671 newotri->orient = 0;
4680#ifdef ANSI_DECLARATORS
4685struct osub *newsubseg;
4692 newsubseg->ss[0] = (
subseg)
m->dummysub;
4693 newsubseg->ss[1] = (
subseg)
m->dummysub;
4695 newsubseg->ss[2] = (
subseg) NULL;
4696 newsubseg->ss[3] = (
subseg) NULL;
4697 newsubseg->ss[4] = (
subseg) NULL;
4698 newsubseg->ss[5] = (
subseg) NULL;
4700 newsubseg->ss[6] = (
subseg)
m->dummytri;
4701 newsubseg->ss[7] = (
subseg)
m->dummytri;
4705 newsubseg->ssorient = 0;
4729#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
4745#define Fast_Two_Sum_Tail(a, b, x, y) \
4749#define Fast_Two_Sum(a, b, x, y) \
4750 x = (REAL) (a + b); \
4751 Fast_Two_Sum_Tail(a, b, x, y)
4753#define Two_Sum_Tail(a, b, x, y) \
4754 bvirt = (REAL) (x - a); \
4755 avirt = x - bvirt; \
4756 bround = b - bvirt; \
4757 around = a - avirt; \
4760#define Two_Sum(a, b, x, y) \
4761 x = (REAL) (a + b); \
4762 Two_Sum_Tail(a, b, x, y)
4764#define Two_Diff_Tail(a, b, x, y) \
4765 bvirt = (REAL) (a - x); \
4766 avirt = x + bvirt; \
4767 bround = bvirt - b; \
4768 around = a - avirt; \
4771#define Two_Diff(a, b, x, y) \
4772 x = (REAL) (a - b); \
4773 Two_Diff_Tail(a, b, x, y)
4775#define Split(a, ahi, alo) \
4776 c = (REAL) (splitter * a); \
4777 abig = (REAL) (c - a); \
4781#define Two_Product_Tail(a, b, x, y) \
4782 Split(a, ahi, alo); \
4783 Split(b, bhi, blo); \
4784 err1 = x - (ahi * bhi); \
4785 err2 = err1 - (alo * bhi); \
4786 err3 = err2 - (ahi * blo); \
4787 y = (alo * blo) - err3
4789#define Two_Product(a, b, x, y) \
4790 x = (REAL) (a * b); \
4791 Two_Product_Tail(a, b, x, y)
4796#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
4797 x = (REAL) (a * b); \
4798 Split(a, ahi, alo); \
4799 err1 = x - (ahi * bhi); \
4800 err2 = err1 - (alo * bhi); \
4801 err3 = err2 - (ahi * blo); \
4802 y = (alo * blo) - err3
4806#define Square_Tail(a, x, y) \
4807 Split(a, ahi, alo); \
4808 err1 = x - (ahi * ahi); \
4809 err3 = err1 - ((ahi + ahi) * alo); \
4810 y = (alo * alo) - err3
4812#define Square(a, x, y) \
4813 x = (REAL) (a * a); \
4814 Square_Tail(a, x, y)
4819#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
4820 Two_Sum(a0, b , _i, x0); \
4821 Two_Sum(a1, _i, x2, x1)
4823#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
4824 Two_Diff(a0, b , _i, x0); \
4825 Two_Sum( a1, _i, x2, x1)
4827#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
4828 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
4829 Two_One_Sum(_j, _0, b1, x3, x2, x1)
4831#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
4832 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
4833 Two_One_Diff(_j, _0, b1, x3, x2, x1)
4837#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
4838 Split(b, bhi, blo); \
4839 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
4840 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
4841 Two_Sum(_i, _0, _k, x1); \
4842 Fast_Two_Sum(_j, _k, x3, x2)
4866 REAL check, lastcheck;
4874 _control87(_PC_24, _MCW_PC);
4876 _control87(_PC_53, _MCW_PC);
4905 every_other = !every_other;
4907 }
while ((check != 1.0) && (check != lastcheck));
4936#ifdef ANSI_DECLARATORS
4952 REAL avirt, bround, around;
4953 int eindex, findex, hindex;
4958 eindex = findex = 0;
4959 if ((fnow > enow) == (fnow > -enow)) {
4967 if ((eindex < elen) && (findex < flen)) {
4968 if ((fnow > enow) == (fnow > -enow)) {
4979 while ((eindex < elen) && (findex < flen)) {
4980 if ((fnow > enow) == (fnow > -enow)) {
4993 while (eindex < elen) {
5001 while (findex < flen) {
5009 if ((Q != 0.0) || (hindex == 0)) {
5030#ifdef ANSI_DECLARATORS
5048 REAL avirt, bround, around;
5051 REAL ahi, alo, bhi, blo;
5052 REAL err1, err2, err3;
5060 for (eindex = 1; eindex < elen; eindex++) {
5072 if ((Q != 0.0) || (hindex == 0)) {
5086#ifdef ANSI_DECLARATORS
5099 for (eindex = 1; eindex < elen; eindex++) {
5125#ifdef ANSI_DECLARATORS
5137 REAL acxtail, acytail, bcxtail, bcytail;
5139 REAL detlefttail, detrighttail;
5141 REAL B[4], C1[8], C2[12], D[16];
5143 int C1length, C2length, Dlength;
5150 REAL avirt, bround, around;
5153 REAL ahi, alo, bhi, blo;
5154 REAL err1, err2, err3;
5158 acx = (
REAL) (pa[0] - pc[0]);
5159 bcx = (
REAL) (pb[0] - pc[0]);
5160 acy = (
REAL) (pa[1] - pc[1]);
5161 bcy = (
REAL) (pb[1] - pc[1]);
5166 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
5167 B3, B[2], B[1], B[0]);
5172 if ((det >= errbound) || (-det >= errbound)) {
5181 if ((acxtail == 0.0) && (acytail == 0.0)
5182 && (bcxtail == 0.0) && (bcytail == 0.0)) {
5187 det += (acx * bcytail + bcy * acxtail)
5188 - (acy * bcxtail + bcx * acytail);
5189 if ((det >= errbound) || (-det >= errbound)) {
5211 return(D[Dlength - 1]);
5214#ifdef ANSI_DECLARATORS
5227 REAL detleft, detright, det;
5228 REAL detsum, errbound;
5230 m->counterclockcount++;
5232 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
5233 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
5234 det = detleft - detright;
5240 if (detleft > 0.0) {
5241 if (detright <= 0.0) {
5244 detsum = detleft + detright;
5246 }
else if (detleft < 0.0) {
5247 if (detright >= 0.0) {
5250 detsum = -detleft - detright;
5257 if ((det >= errbound) || (-det >= errbound)) {
5283#ifdef ANSI_DECLARATORS
5298 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5299 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5300 REAL bc[4], ca[4], ab[4];
5302 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
5303 int axbclen, axxbclen, aybclen, ayybclen, alen;
5304 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
5305 int bxcalen, bxxcalen, bycalen, byycalen, blen;
5306 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
5307 int cxablen, cxxablen, cyablen, cyyablen, clen;
5310 REAL fin1[1152], fin2[1152];
5311 REAL *finnow, *finother, *finswap;
5314 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
5315 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
5316 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
5317 REAL aa[4], bb[4], cc[4];
5323 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
5324 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
5325 int temp8len, temp16alen, temp16blen, temp16clen;
5326 int temp32alen, temp32blen, temp48len, temp64len;
5327 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
5328 int axtbblen, axtcclen, aytbblen, aytcclen;
5329 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
5330 int bxtaalen, bxtcclen, bytaalen, bytcclen;
5331 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
5332 int cxtaalen, cxtbblen, cytaalen, cytbblen;
5333 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
5334 int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
5335 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
5336 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
5337 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
5338 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
5339 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
5340 REAL abt[8], bct[8], cat[8];
5341 int abtlen, bctlen, catlen;
5342 REAL abtt[4], bctt[4], catt[4];
5343 int abttlen, bcttlen, cattlen;
5348 REAL avirt, bround, around;
5351 REAL ahi, alo, bhi, blo;
5352 REAL err1, err2, err3;
5356 adx = (
REAL) (pa[0] - pd[0]);
5357 bdx = (
REAL) (pb[0] - pd[0]);
5358 cdx = (
REAL) (pc[0] - pd[0]);
5359 ady = (
REAL) (pa[1] - pd[1]);
5360 bdy = (
REAL) (pb[1] - pd[1]);
5361 cdy = (
REAL) (pc[1] - pd[1]);
5365 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
5375 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
5385 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
5398 if ((det >= errbound) || (-det >= errbound)) {
5408 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
5409 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
5414 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
5415 - (bdy * cdxtail + cdx * bdytail))
5416 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
5417 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
5418 - (cdy * adxtail + adx * cdytail))
5419 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
5420 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
5421 - (ady * bdxtail + bdx * adytail))
5422 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
5423 if ((det >= errbound) || (-det >= errbound)) {
5430 if ((bdxtail != 0.0) || (bdytail != 0.0)
5431 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5432 Square(adx, adxadx1, adxadx0);
5433 Square(ady, adyady1, adyady0);
5434 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
5437 if ((cdxtail != 0.0) || (cdytail != 0.0)
5438 || (adxtail != 0.0) || (adytail != 0.0)) {
5439 Square(bdx, bdxbdx1, bdxbdx0);
5440 Square(bdy, bdybdy1, bdybdy0);
5441 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
5444 if ((adxtail != 0.0) || (adytail != 0.0)
5445 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5446 Square(cdx, cdxcdx1, cdxcdx0);
5447 Square(cdy, cdycdy1, cdycdy0);
5448 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
5452 if (adxtail != 0.0) {
5464 temp16blen, temp16b, temp32a);
5466 temp32alen, temp32a, temp48);
5469 finswap = finnow; finnow = finother; finother = finswap;
5471 if (adytail != 0.0) {
5483 temp16blen, temp16b, temp32a);
5485 temp32alen, temp32a, temp48);
5488 finswap = finnow; finnow = finother; finother = finswap;
5490 if (bdxtail != 0.0) {
5502 temp16blen, temp16b, temp32a);
5504 temp32alen, temp32a, temp48);
5507 finswap = finnow; finnow = finother; finother = finswap;
5509 if (bdytail != 0.0) {
5521 temp16blen, temp16b, temp32a);
5523 temp32alen, temp32a, temp48);
5526 finswap = finnow; finnow = finother; finother = finswap;
5528 if (cdxtail != 0.0) {
5540 temp16blen, temp16b, temp32a);
5542 temp32alen, temp32a, temp48);
5545 finswap = finnow; finnow = finother; finother = finswap;
5547 if (cdytail != 0.0) {
5559 temp16blen, temp16b, temp32a);
5561 temp32alen, temp32a, temp48);
5564 finswap = finnow; finnow = finother; finother = finswap;
5567 if ((adxtail != 0.0) || (adytail != 0.0)) {
5568 if ((bdxtail != 0.0) || (bdytail != 0.0)
5569 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5572 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5584 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
5594 if (adxtail != 0.0) {
5600 temp32alen, temp32a, temp48);
5603 finswap = finnow; finnow = finother; finother = finswap;
5604 if (bdytail != 0.0) {
5610 finswap = finnow; finnow = finother; finother = finswap;
5612 if (cdytail != 0.0) {
5618 finswap = finnow; finnow = finother; finother = finswap;
5629 temp16blen, temp16b, temp32b);
5631 temp32blen, temp32b, temp64);
5634 finswap = finnow; finnow = finother; finother = finswap;
5636 if (adytail != 0.0) {
5642 temp32alen, temp32a, temp48);
5645 finswap = finnow; finnow = finother; finother = finswap;
5656 temp16blen, temp16b, temp32b);
5658 temp32blen, temp32b, temp64);
5661 finswap = finnow; finnow = finother; finother = finswap;
5664 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
5665 if ((cdxtail != 0.0) || (cdytail != 0.0)
5666 || (adxtail != 0.0) || (adytail != 0.0)) {
5669 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5681 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
5691 if (bdxtail != 0.0) {
5697 temp32alen, temp32a, temp48);
5700 finswap = finnow; finnow = finother; finother = finswap;
5701 if (cdytail != 0.0) {
5707 finswap = finnow; finnow = finother; finother = finswap;
5709 if (adytail != 0.0) {
5715 finswap = finnow; finnow = finother; finother = finswap;
5726 temp16blen, temp16b, temp32b);
5728 temp32blen, temp32b, temp64);
5731 finswap = finnow; finnow = finother; finother = finswap;
5733 if (bdytail != 0.0) {
5739 temp32alen, temp32a, temp48);
5742 finswap = finnow; finnow = finother; finother = finswap;
5753 temp16blen, temp16b, temp32b);
5755 temp32blen, temp32b, temp64);
5758 finswap = finnow; finnow = finother; finother = finswap;
5761 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
5762 if ((adxtail != 0.0) || (adytail != 0.0)
5763 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5766 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5778 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
5788 if (cdxtail != 0.0) {
5794 temp32alen, temp32a, temp48);
5797 finswap = finnow; finnow = finother; finother = finswap;
5798 if (adytail != 0.0) {
5804 finswap = finnow; finnow = finother; finother = finswap;
5806 if (bdytail != 0.0) {
5812 finswap = finnow; finnow = finother; finother = finswap;
5823 temp16blen, temp16b, temp32b);
5825 temp32blen, temp32b, temp64);
5828 finswap = finnow; finnow = finother; finother = finswap;
5830 if (cdytail != 0.0) {
5836 temp32alen, temp32a, temp48);
5839 finswap = finnow; finnow = finother; finother = finswap;
5850 temp16blen, temp16b, temp32b);
5852 temp32blen, temp32b, temp64);
5855 finswap = finnow; finnow = finother; finother = finswap;
5859 return finnow[finlength - 1];
5862#ifdef ANSI_DECLARATORS
5876 REAL adx, bdx, cdx, ady, bdy, cdy;
5877 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
5878 REAL alift, blift, clift;
5880 REAL permanent, errbound;
5884 adx = pa[0] - pd[0];
5885 bdx = pb[0] - pd[0];
5886 cdx = pc[0] - pd[0];
5887 ady = pa[1] - pd[1];
5888 bdy = pb[1] - pd[1];
5889 cdy = pc[1] - pd[1];
5893 alift = adx * adx + ady * ady;
5897 blift = bdx * bdx + bdy * bdy;
5901 clift = cdx * cdx + cdy * cdy;
5903 det = alift * (bdxcdy - cdxbdy)
5904 + blift * (cdxady - adxcdy)
5905 + clift * (adxbdy - bdxady);
5915 if ((det > errbound) || (-det > errbound)) {
5944#ifdef ANSI_DECLARATORS
5950 aheight, bheight, cheight, dheight, permanent)
5963 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
5966 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5967 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5968 REAL bc[4], ca[4], ab[4];
5970 REAL adet[8], bdet[8], cdet[8];
5971 int alen, blen, clen;
5974 REAL *finnow, *finother, *finswap;
5975 REAL fin1[192], fin2[192];
5978 REAL adxtail, bdxtail, cdxtail;
5979 REAL adytail, bdytail, cdytail;
5980 REAL adheighttail, bdheighttail, cdheighttail;
5984 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
5985 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
5988 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
5989 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
5992 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
5993 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
5994 REAL bct[8], cat[8], abt[8];
5995 int bctlen, catlen, abtlen;
5998 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
5999 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
6000 REAL u[4],
v[12], w[16];
6002 int vlength, wlength;
6006 REAL avirt, bround, around;
6009 REAL ahi, alo, bhi, blo;
6010 REAL err1, err2, err3;
6014 adx = (
REAL) (pa[0] - pd[0]);
6015 bdx = (
REAL) (pb[0] - pd[0]);
6016 cdx = (
REAL) (pc[0] - pd[0]);
6017 ady = (
REAL) (pa[1] - pd[1]);
6018 bdy = (
REAL) (pb[1] - pd[1]);
6019 cdy = (
REAL) (pc[1] - pd[1]);
6020 adheight = (
REAL) (aheight - dheight);
6021 bdheight = (
REAL) (bheight - dheight);
6022 cdheight = (
REAL) (cheight - dheight);
6026 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
6032 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
6038 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
6047 if ((det >= errbound) || (-det >= errbound)) {
6061 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
6062 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
6063 (adheighttail == 0.0) &&
6064 (bdheighttail == 0.0) &&
6065 (cdheighttail == 0.0)) {
6070 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
6071 (bdy * cdxtail + cdx * bdytail)) +
6072 adheighttail * (bdx * cdy - bdy * cdx)) +
6073 (bdheight * ((cdx * adytail + ady * cdxtail) -
6074 (cdy * adxtail + adx * cdytail)) +
6075 bdheighttail * (cdx * ady - cdy * adx)) +
6076 (cdheight * ((adx * bdytail + bdy * adxtail) -
6077 (ady * bdxtail + bdx * adytail)) +
6078 cdheighttail * (adx * bdy - ady * bdx));
6079 if ((det >= errbound) || (-det >= errbound)) {
6086 if (adxtail == 0.0) {
6087 if (adytail == 0.0) {
6095 at_b[1] = at_blarge;
6098 at_c[1] = at_clarge;
6102 if (adytail == 0.0) {
6104 at_b[1] = at_blarge;
6108 at_c[1] = at_clarge;
6113 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
6114 at_blarge, at_b[2], at_b[1], at_b[0]);
6115 at_b[3] = at_blarge;
6119 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
6120 at_clarge, at_c[2], at_c[1], at_c[0]);
6121 at_c[3] = at_clarge;
6125 if (bdxtail == 0.0) {
6126 if (bdytail == 0.0) {
6134 bt_c[1] = bt_clarge;
6137 bt_a[1] = bt_alarge;
6141 if (bdytail == 0.0) {
6143 bt_c[1] = bt_clarge;
6147 bt_a[1] = bt_alarge;
6152 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
6153 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
6154 bt_c[3] = bt_clarge;
6158 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
6159 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
6160 bt_a[3] = bt_alarge;
6164 if (cdxtail == 0.0) {
6165 if (cdytail == 0.0) {
6173 ct_a[1] = ct_alarge;
6176 ct_b[1] = ct_blarge;
6180 if (cdytail == 0.0) {
6182 ct_a[1] = ct_alarge;
6186 ct_b[1] = ct_blarge;
6191 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
6192 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
6193 ct_a[3] = ct_alarge;
6197 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
6198 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
6199 ct_b[3] = ct_blarge;
6208 finswap = finnow; finnow = finother; finother = finswap;
6214 finswap = finnow; finnow = finother; finother = finswap;
6220 finswap = finnow; finnow = finother; finother = finswap;
6222 if (adheighttail != 0.0) {
6226 finswap = finnow; finnow = finother; finother = finswap;
6228 if (bdheighttail != 0.0) {
6232 finswap = finnow; finnow = finother; finother = finswap;
6234 if (cdheighttail != 0.0) {
6238 finswap = finnow; finnow = finother; finother = finswap;
6241 if (adxtail != 0.0) {
6242 if (bdytail != 0.0) {
6243 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
6244 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
6248 finswap = finnow; finnow = finother; finother = finswap;
6249 if (cdheighttail != 0.0) {
6251 u3, u[2], u[1], u[0]);
6255 finswap = finnow; finnow = finother; finother = finswap;
6258 if (cdytail != 0.0) {
6260 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
6261 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
6265 finswap = finnow; finnow = finother; finother = finswap;
6266 if (bdheighttail != 0.0) {
6268 u3, u[2], u[1], u[0]);
6272 finswap = finnow; finnow = finother; finother = finswap;
6276 if (bdxtail != 0.0) {
6277 if (cdytail != 0.0) {
6278 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
6279 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
6283 finswap = finnow; finnow = finother; finother = finswap;
6284 if (adheighttail != 0.0) {
6286 u3, u[2], u[1], u[0]);
6290 finswap = finnow; finnow = finother; finother = finswap;
6293 if (adytail != 0.0) {
6295 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
6296 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
6300 finswap = finnow; finnow = finother; finother = finswap;
6301 if (cdheighttail != 0.0) {
6303 u3, u[2], u[1], u[0]);
6307 finswap = finnow; finnow = finother; finother = finswap;
6311 if (cdxtail != 0.0) {
6312 if (adytail != 0.0) {
6313 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
6314 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
6318 finswap = finnow; finnow = finother; finother = finswap;
6319 if (bdheighttail != 0.0) {
6321 u3, u[2], u[1], u[0]);
6325 finswap = finnow; finnow = finother; finother = finswap;
6328 if (bdytail != 0.0) {
6330 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
6331 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
6335 finswap = finnow; finnow = finother; finother = finswap;
6336 if (adheighttail != 0.0) {
6338 u3, u[2], u[1], u[0]);
6342 finswap = finnow; finnow = finother; finother = finswap;
6347 if (adheighttail != 0.0) {
6351 finswap = finnow; finnow = finother; finother = finswap;
6353 if (bdheighttail != 0.0) {
6357 finswap = finnow; finnow = finother; finother = finswap;
6359 if (cdheighttail != 0.0) {
6363 finswap = finnow; finnow = finother; finother = finswap;
6366 return finnow[finlength - 1];
6369#ifdef ANSI_DECLARATORS
6374REAL orient3d(
m,
b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
6388 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6389 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
6391 REAL permanent, errbound;
6395 adx = pa[0] - pd[0];
6396 bdx = pb[0] - pd[0];
6397 cdx = pc[0] - pd[0];
6398 ady = pa[1] - pd[1];
6399 bdy = pb[1] - pd[1];
6400 cdy = pc[1] - pd[1];
6401 adheight = aheight - dheight;
6402 bdheight = bheight - dheight;
6403 cdheight = cheight - dheight;
6414 det = adheight * (bdxcdy - cdxbdy)
6415 + bdheight * (cdxady - adxcdy)
6416 + cdheight * (adxbdy - bdxady);
6426 if ((det > errbound) || (-det > errbound)) {
6430 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
6452#ifdef ANSI_DECLARATORS
6466 if (
b->weighted == 0) {
6468 }
else if (
b->weighted == 1) {
6470 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
6471 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
6472 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
6473 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
6475 return orient3d(
m,
b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
6493#ifdef ANSI_DECLARATORS
6512 REAL xdo, ydo, xao, yao;
6513 REAL dodist, aodist, dadist;
6515 REAL dx, dy, dxoff, dyoff;
6517 m->circumcentercount++;
6520 xdo = tdest[0] - torg[0];
6521 ydo = tdest[1] - torg[1];
6522 xao = tapex[0] - torg[0];
6523 yao = tapex[1] - torg[1];
6524 dodist = xdo * xdo + ydo * ydo;
6525 aodist = xao * xao + yao * yao;
6526 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
6527 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
6529 denominator = 0.5 / (xdo * yao - xao * ydo);
6536 m->counterclockcount--;
6538 dx = (yao * dodist - ydo * aodist) * denominator;
6539 dy = (xdo * aodist - xao * dodist) * denominator;
6546 if ((dodist < aodist) && (dodist < dadist)) {
6547 if (offcenter && (
b->offconstant > 0.0)) {
6549 dxoff = 0.5 * xdo -
b->offconstant * ydo;
6550 dyoff = 0.5 * ydo +
b->offconstant * xdo;
6553 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6558 }
else if (aodist < dadist) {
6559 if (offcenter && (
b->offconstant > 0.0)) {
6560 dxoff = 0.5 * xao +
b->offconstant * yao;
6561 dyoff = 0.5 * yao -
b->offconstant * xao;
6564 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6570 if (offcenter && (
b->offconstant > 0.0)) {
6571 dxoff = 0.5 * (tapex[0] - tdest[0]) -
6572 b->offconstant * (tapex[1] - tdest[1]);
6573 dyoff = 0.5 * (tapex[1] - tdest[1]) +
6574 b->offconstant * (tapex[0] - tdest[0]);
6577 if (dxoff * dxoff + dyoff * dyoff <
6578 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
6585 circumcenter[0] = torg[0] + dx;
6586 circumcenter[1] = torg[1] + dy;
6593 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
6594 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
6607#ifdef ANSI_DECLARATORS
6627 m->checksegments = 0;
6628 m->checkquality = 0;
6629 m->incirclecount =
m->counterclockcount =
m->orient3dcount = 0;
6630 m->hyperbolacount =
m->circletopcount =
m->circumcentercount = 0;
6646#ifdef ANSI_DECLARATORS
6650unsigned int choices;
6670#ifdef ANSI_DECLARATORS
6671void checkmesh(
struct mesh *
m,
struct behavior *
b)
6679 struct otri triangleloop;
6680 struct otri oppotri, oppooppotri;
6681 vertex triorg, tridest, triapex;
6682 vertex oppoorg, oppodest;
6688 saveexact =
b->noexact;
6691 printf(
" Checking consistency of mesh...\n");
6697 while (triangleloop.tri != (
triangle *) NULL) {
6699 for (triangleloop.orient = 0; triangleloop.orient < 3;
6700 triangleloop.orient++) {
6701 org(triangleloop, triorg);
6702 dest(triangleloop, tridest);
6703 if (triangleloop.orient == 0) {
6705 apex(triangleloop, triapex);
6707 printf(
" !! !! Inverted ");
6713 sym(triangleloop, oppotri);
6714 if (oppotri.tri !=
m->dummytri) {
6716 sym(oppotri, oppooppotri);
6717 if ((triangleloop.tri != oppooppotri.tri)
6718 || (triangleloop.orient != oppooppotri.orient)) {
6719 printf(
" !! !! Asymmetric triangle-triangle bond:\n");
6720 if (triangleloop.tri == oppooppotri.tri) {
6721 printf(
" (Right triangle, wrong orientation)\n");
6725 printf(
" Second (nonreciprocating) ");
6731 org(oppotri, oppoorg);
6732 dest(oppotri, oppodest);
6733 if ((triorg != oppodest) || (tridest != oppoorg)) {
6734 printf(
" !! !! Mismatched edge coordinates between two triangles:\n"
6736 printf(
" First mismatched ");
6738 printf(
" Second mismatched ");
6748 printf(
" In my studied opinion, the mesh appears to be consistent.\n");
6750 }
else if (horrors == 1) {
6751 printf(
" !! !! !! !! Precisely one festering wound discovered.\n");
6753 printf(
" !! !! !! !! %d abominations witnessed.\n", horrors);
6756 b->noexact = saveexact;
6769#ifdef ANSI_DECLARATORS
6770void checkdelaunay(
struct mesh *
m,
struct behavior *
b)
6772void checkdelaunay(
m,
b)
6778 struct otri triangleloop;
6779 struct otri oppotri;
6780 struct osub opposubseg;
6781 vertex triorg, tridest, triapex;
6783 int shouldbedelaunay;
6790 saveexact =
b->noexact;
6793 printf(
" Checking Delaunay property of mesh...\n");
6799 while (triangleloop.tri != (
triangle *) NULL) {
6801 for (triangleloop.orient = 0; triangleloop.orient < 3;
6802 triangleloop.orient++) {
6803 org(triangleloop, triorg);
6804 dest(triangleloop, tridest);
6805 apex(triangleloop, triapex);
6806 sym(triangleloop, oppotri);
6807 apex(oppotri, oppoapex);
6811 shouldbedelaunay = (oppotri.tri !=
m->dummytri) &&
6812 !
deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
6813 (triorg !=
m->infvertex1) && (triorg !=
m->infvertex2) &&
6814 (triorg !=
m->infvertex3) &&
6815 (tridest !=
m->infvertex1) && (tridest !=
m->infvertex2) &&
6816 (tridest !=
m->infvertex3) &&
6817 (triapex !=
m->infvertex1) && (triapex !=
m->infvertex2) &&
6818 (triapex !=
m->infvertex3) &&
6819 (oppoapex !=
m->infvertex1) && (oppoapex !=
m->infvertex2) &&
6820 (oppoapex !=
m->infvertex3);
6821 if (
m->checksegments && shouldbedelaunay) {
6824 tspivot(triangleloop, opposubseg);
6825 if (opposubseg.ss !=
m->dummysub){
6826 shouldbedelaunay = 0;
6829 if (shouldbedelaunay) {
6830 if (
nonregular(
m,
b, triorg, tridest, triapex, oppoapex) > 0.0) {
6832 printf(
" !! !! Non-Delaunay pair of triangles:\n");
6833 printf(
" First non-Delaunay ");
6835 printf(
" Second non-Delaunay ");
6837 printf(
" !! !! Non-regular pair of triangles:\n");
6838 printf(
" First non-regular ");
6840 printf(
" Second non-regular ");
6852 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
6854 }
else if (horrors == 1) {
6856 " !! !! !! !! Precisely one terrifying transgression identified.\n");
6858 printf(
" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
6861 b->noexact = saveexact;
6879#ifdef ANSI_DECLARATORS
6880void enqueuebadtriang(
struct mesh *
m,
struct behavior *
b,
6881 struct badtriang *badtri)
6883void enqueuebadtriang(
m,
b, badtri)
6886struct badtriang *badtri;
6890 REAL length, multiplier;
6891 int exponent, expincrement;
6896 if (
b->verbose > 2) {
6897 printf(
" Queueing bad triangle:\n");
6898 printf(
" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
6899 badtri->triangorg[0], badtri->triangorg[1],
6900 badtri->triangdest[0], badtri->triangdest[1],
6901 badtri->triangapex[0], badtri->triangapex[1]);
6906 if (badtri->key >= 1.0) {
6907 length = badtri->key;
6912 length = 1.0 / badtri->key;
6918 while (length > 2.0) {
6922 while (length * multiplier * multiplier > 1.0) {
6924 multiplier *= multiplier;
6927 exponent += expincrement;
6928 length *= multiplier;
6936 queuenumber = 2047 - exponent;
6938 queuenumber = 2048 + exponent;
6942 if (
m->queuefront[queuenumber] == (
struct badtriang *) NULL) {
6945 if (queuenumber >
m->firstnonemptyq) {
6947 m->nextnonemptyq[queuenumber] =
m->firstnonemptyq;
6948 m->firstnonemptyq = queuenumber;
6952 i = queuenumber + 1;
6953 while (
m->queuefront[i] == (
struct badtriang *) NULL) {
6957 m->nextnonemptyq[queuenumber] =
m->nextnonemptyq[i];
6958 m->nextnonemptyq[i] = queuenumber;
6961 m->queuefront[queuenumber] = badtri;
6964 m->queuetail[queuenumber]->nexttriang = badtri;
6967 m->queuetail[queuenumber] = badtri;
6969 badtri->nexttriang = (
struct badtriang *) NULL;
6985#ifdef ANSI_DECLARATORS
6986void enqueuebadtri(
struct mesh *
m,
struct behavior *
b,
struct otri *enqtri,
6989void enqueuebadtri(
m,
b, enqtri, minedge, enqapex, enqorg, enqdest)
7000 struct badtriang *newbad;
7003 newbad = (
struct badtriang *)
poolalloc(&
m->badtriangles);
7004 newbad->poortri =
encode(*enqtri);
7005 newbad->key = minedge;
7006 newbad->triangapex = enqapex;
7007 newbad->triangorg = enqorg;
7008 newbad->triangdest = enqdest;
7009 enqueuebadtriang(
m,
b, newbad);
7022#ifdef ANSI_DECLARATORS
7023struct badtriang *dequeuebadtriang(
struct mesh *
m)
7025struct badtriang *dequeuebadtriang(
m)
7030 struct badtriang *result;
7033 if (
m->firstnonemptyq < 0) {
7034 return (
struct badtriang *) NULL;
7037 result =
m->queuefront[
m->firstnonemptyq];
7039 m->queuefront[
m->firstnonemptyq] = result->nexttriang;
7042 if (result ==
m->queuetail[
m->firstnonemptyq]) {
7043 m->firstnonemptyq =
m->nextnonemptyq[
m->firstnonemptyq];
7075#ifdef ANSI_DECLARATORS
7076int checkseg4encroach(
struct mesh *
m,
struct behavior *
b,
7077 struct osub *testsubseg)
7079int checkseg4encroach(
m,
b, testsubseg)
7082struct osub *testsubseg;
7086 struct otri neighbortri;
7087 struct osub testsym;
7088 struct badsubseg *encroachedseg;
7092 vertex eorg, edest, eapex;
7098 sorg(*testsubseg, eorg);
7099 sdest(*testsubseg, edest);
7101 stpivot(*testsubseg, neighbortri);
7103 if (neighbortri.tri !=
m->dummytri) {
7106 apex(neighbortri, eapex);
7112 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7113 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7114 if (dotproduct < 0.0) {
7115 if (
b->conformdel ||
7116 (dotproduct * dotproduct >=
7117 (2.0 *
b->goodangle - 1.0) * (2.0 *
b->goodangle - 1.0) *
7118 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7119 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7120 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7121 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7127 ssym(*testsubseg, testsym);
7128 stpivot(testsym, neighbortri);
7130 if (neighbortri.tri !=
m->dummytri) {
7133 apex(neighbortri, eapex);
7136 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7137 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7138 if (dotproduct < 0.0) {
7139 if (
b->conformdel ||
7140 (dotproduct * dotproduct >=
7141 (2.0 *
b->goodangle - 1.0) * (2.0 *
b->goodangle - 1.0) *
7142 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7143 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7144 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7145 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7151 if (encroached && (!
b->nobisect || ((
b->nobisect == 1) && (sides == 2)))) {
7152 if (
b->verbose > 2) {
7154 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
7155 eorg[0], eorg[1], edest[0], edest[1]);
7159 encroachedseg = (
struct badsubseg *)
poolalloc(&
m->badsubsegs);
7160 if (encroached == 1) {
7161 encroachedseg->encsubseg =
sencode(*testsubseg);
7162 encroachedseg->subsegorg = eorg;
7163 encroachedseg->subsegdest = edest;
7165 encroachedseg->encsubseg =
sencode(testsym);
7166 encroachedseg->subsegorg = edest;
7167 encroachedseg->subsegdest = eorg;
7188#ifdef ANSI_DECLARATORS
7189void testtriangle(
struct mesh *
m,
struct behavior *
b,
struct otri *testtri)
7191void testtriangle(
m,
b, testtri)
7194struct otri *testtri;
7198 struct otri tri1, tri2;
7199 struct osub testsub;
7200 vertex torg, tdest, tapex;
7202 vertex org1, dest1, org2, dest2;
7204 REAL dxod, dyod, dxda, dyda, dxao, dyao;
7205 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
7206 REAL apexlen, orglen, destlen, minedge;
7213 org(*testtri, torg);
7214 dest(*testtri, tdest);
7215 apex(*testtri, tapex);
7216 dxod = torg[0] - tdest[0];
7217 dyod = torg[1] - tdest[1];
7218 dxda = tdest[0] - tapex[0];
7219 dyda = tdest[1] - tapex[1];
7220 dxao = tapex[0] - torg[0];
7221 dyao = tapex[1] - torg[1];
7222 dxod2 = dxod * dxod;
7223 dyod2 = dyod * dyod;
7224 dxda2 = dxda * dxda;
7225 dyda2 = dyda * dyda;
7226 dxao2 = dxao * dxao;
7227 dyao2 = dyao * dyao;
7229 apexlen = dxod2 + dyod2;
7230 orglen = dxda2 + dyda2;
7231 destlen = dxao2 + dyao2;
7233 if ((apexlen < orglen) && (apexlen < destlen)) {
7237 angle = dxda * dxao + dyda * dyao;
7238 angle = angle * angle / (orglen * destlen);
7242 }
else if (orglen < destlen) {
7246 angle = dxod * dxao + dyod * dyao;
7247 angle = angle * angle / (apexlen * destlen);
7250 lnext(*testtri, tri1);
7255 angle = dxod * dxda + dyod * dyda;
7256 angle = angle * angle / (apexlen * orglen);
7259 lprev(*testtri, tri1);
7262 if (
b->vararea ||
b->fixedarea ||
b->usertest) {
7264 area = 0.5 * (dxod * dyda - dyod * dxda);
7265 if (
b->fixedarea && (area >
b->maxarea)) {
7267 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7272 if ((
b->vararea) && (area >
areabound(*testtri)) &&
7275 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7282 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7289 if (angle >
b->goodangle) {
7304 if (testsub.ss ==
m->dummysub) {
7310 }
while (testsub.ss ==
m->dummysub);
7318 }
while (testsub.ss ==
m->dummysub);
7323 joinvertex = (
vertex) NULL;
7324 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
7326 }
else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
7329 if (joinvertex != (
vertex) NULL) {
7332 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
7333 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
7334 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
7335 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
7337 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
7346 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7374#ifdef ANSI_DECLARATORS
7383 struct otri triangleloop;
7387 printf(
" Constructing mapping from vertices to triangles.\n");
7391 while (triangleloop.tri != (
triangle *) NULL) {
7393 for (triangleloop.orient = 0; triangleloop.orient < 3;
7394 triangleloop.orient++) {
7395 org(triangleloop, triorg);
7469#ifdef ANSI_DECLARATORS
7471 vertex searchpoint,
struct otri *searchtri,
7472 int stopatsubsegment)
7478struct otri *searchtri;
7479int stopatsubsegment;
7483 struct otri backtracktri;
7484 struct osub checkedge;
7485 vertex forg, fdest, fapex;
7486 REAL orgorient, destorient;
7491 if (
b->verbose > 2) {
7492 printf(
" Searching for point (%.12g, %.12g).\n",
7493 searchpoint[0], searchpoint[1]);
7496 org(*searchtri, forg);
7497 dest(*searchtri, fdest);
7498 apex(*searchtri, fapex);
7500 if (
b->verbose > 2) {
7501 printf(
" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7502 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
7505 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
7515 if (destorient > 0.0) {
7516 if (orgorient > 0.0) {
7522 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
7523 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
7528 if (orgorient > 0.0) {
7533 if (destorient == 0.0) {
7537 if (orgorient == 0.0) {
7549 lprev(*searchtri, backtracktri);
7552 lnext(*searchtri, backtracktri);
7555 sym(backtracktri, *searchtri);
7557 if (
m->checksegments && stopatsubsegment) {
7559 tspivot(backtracktri, checkedge);
7560 if (checkedge.ss !=
m->dummysub) {
7562 otricopy(backtracktri, *searchtri);
7567 if (searchtri->tri ==
m->dummytri) {
7569 otricopy(backtracktri, *searchtri);
7573 apex(*searchtri, fapex);
7613#ifdef ANSI_DECLARATORS
7615 vertex searchpoint,
struct otri *searchtri)
7621struct otri *searchtri;
7627 struct otri sampletri;
7629 unsigned long alignptr;
7630 REAL searchdist, dist;
7632 long samplesperblock, totalsamplesleft, samplesleft;
7633 long population, totalpopulation;
7636 if (
b->verbose > 2) {
7637 printf(
" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
7638 searchpoint[0], searchpoint[1]);
7642 org(*searchtri, torg);
7643 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7644 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7645 if (
b->verbose > 2) {
7646 printf(
" Boundary triangle has origin (%.12g, %.12g).\n",
7652 if (
m->recenttri.tri != (
triangle *) NULL) {
7654 org(
m->recenttri, torg);
7655 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7659 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7660 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7661 if (dist < searchdist) {
7664 if (
b->verbose > 2) {
7665 printf(
" Choosing recent triangle with origin (%.12g, %.12g).\n",
7677 m->triangles.items) {
7685 samplesperblock = (
m->samples *
TRIPERBLOCK - 1) /
m->triangles.maxitems + 1;
7688 samplesleft = (
m->samples *
m->triangles.itemsfirstblock - 1) /
7689 m->triangles.maxitems + 1;
7690 totalsamplesleft =
m->samples;
7691 population =
m->triangles.itemsfirstblock;
7692 totalpopulation =
m->triangles.maxitems;
7693 sampleblock =
m->triangles.firstblock;
7694 sampletri.orient = 0;
7695 while (totalsamplesleft > 0) {
7697 if (population > totalpopulation) {
7698 population = totalpopulation;
7701 alignptr = (
unsigned long) (sampleblock + 1);
7702 firsttri = (
char *) (alignptr +
7703 (
unsigned long)
m->triangles.alignbytes -
7705 (
unsigned long)
m->triangles.alignbytes));
7709 sampletri.tri = (
triangle *) (firsttri +
7711 m->triangles.itembytes));
7712 if (!
deadtri(sampletri.tri)) {
7713 org(sampletri, torg);
7714 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7715 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7716 if (dist < searchdist) {
7719 if (
b->verbose > 2) {
7720 printf(
" Choosing triangle with origin (%.12g, %.12g).\n",
7728 }
while ((samplesleft > 0) && (totalsamplesleft > 0));
7730 if (totalsamplesleft > 0) {
7731 sampleblock = (
VOID **) *sampleblock;
7732 samplesleft = samplesperblock;
7733 totalpopulation -= population;
7739 org(*searchtri, torg);
7740 dest(*searchtri, tdest);
7742 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7745 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
7755 }
else if (ahead == 0.0) {
7757 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
7758 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
7784#ifdef ANSI_DECLARATORS
7796 struct otri oppotri;
7797 struct osub newsubseg;
7803 dest(*tri, tridest);
7813 if (newsubseg.ss ==
m->dummysub) {
7827 tsbond(oppotri, newsubseg);
7828 setmark(newsubseg, subsegmark);
7829 if (
b->verbose > 2) {
7830 printf(
" Inserting new ");
7834 if (
mark(newsubseg) == 0) {
7835 setmark(newsubseg, subsegmark);
7888#ifdef ANSI_DECLARATORS
7889void flip(
struct mesh *
m,
struct behavior *
b,
struct otri *flipedge)
7894struct otri *flipedge;
7898 struct otri botleft, botright;
7899 struct otri topleft, topright;
7901 struct otri botlcasing, botrcasing;
7902 struct otri toplcasing, toprcasing;
7903 struct osub botlsubseg, botrsubseg;
7904 struct osub toplsubseg, toprsubseg;
7905 vertex leftvertex, rightvertex, botvertex;
7911 org(*flipedge, rightvertex);
7912 dest(*flipedge, leftvertex);
7913 apex(*flipedge, botvertex);
7914 sym(*flipedge, top);
7916 if (top.tri ==
m->dummytri) {
7917 printf(
"Internal error in flip(): Attempt to flip on boundary.\n");
7921 if (
m->checksegments) {
7922 tspivot(*flipedge, toplsubseg);
7923 if (toplsubseg.ss !=
m->dummysub) {
7924 printf(
"Internal error in flip(): Attempt to flip a segment.\n");
7930 apex(top, farvertex);
7933 lprev(top, topleft);
7934 sym(topleft, toplcasing);
7935 lnext(top, topright);
7936 sym(topright, toprcasing);
7937 lnext(*flipedge, botleft);
7938 sym(botleft, botlcasing);
7939 lprev(*flipedge, botright);
7940 sym(botright, botrcasing);
7942 bond(topleft, botlcasing);
7943 bond(botleft, botrcasing);
7944 bond(botright, toprcasing);
7945 bond(topright, toplcasing);
7947 if (
m->checksegments) {
7951 tspivot(botright, botrsubseg);
7952 tspivot(topright, toprsubseg);
7953 if (toplsubseg.ss ==
m->dummysub) {
7956 tsbond(topright, toplsubseg);
7958 if (botlsubseg.ss ==
m->dummysub) {
7961 tsbond(topleft, botlsubseg);
7963 if (botrsubseg.ss ==
m->dummysub) {
7966 tsbond(botleft, botrsubseg);
7968 if (toprsubseg.ss ==
m->dummysub) {
7971 tsbond(botright, toprsubseg);
7976 setorg(*flipedge, farvertex);
7977 setdest(*flipedge, botvertex);
7978 setapex(*flipedge, rightvertex);
7982 if (
b->verbose > 2) {
7983 printf(
" Edge flip results in left ");
7985 printf(
" and right ");
8023#ifdef ANSI_DECLARATORS
8024void unflip(
struct mesh *
m,
struct behavior *
b,
struct otri *flipedge)
8029struct otri *flipedge;
8033 struct otri botleft, botright;
8034 struct otri topleft, topright;
8036 struct otri botlcasing, botrcasing;
8037 struct otri toplcasing, toprcasing;
8038 struct osub botlsubseg, botrsubseg;
8039 struct osub toplsubseg, toprsubseg;
8040 vertex leftvertex, rightvertex, botvertex;
8046 org(*flipedge, rightvertex);
8047 dest(*flipedge, leftvertex);
8048 apex(*flipedge, botvertex);
8049 sym(*flipedge, top);
8051 if (top.tri ==
m->dummytri) {
8052 printf(
"Internal error in unflip(): Attempt to flip on boundary.\n");
8056 if (
m->checksegments) {
8057 tspivot(*flipedge, toplsubseg);
8058 if (toplsubseg.ss !=
m->dummysub) {
8059 printf(
"Internal error in unflip(): Attempt to flip a subsegment.\n");
8065 apex(top, farvertex);
8068 lprev(top, topleft);
8069 sym(topleft, toplcasing);
8070 lnext(top, topright);
8071 sym(topright, toprcasing);
8072 lnext(*flipedge, botleft);
8073 sym(botleft, botlcasing);
8074 lprev(*flipedge, botright);
8075 sym(botright, botrcasing);
8077 bond(topleft, toprcasing);
8078 bond(botleft, toplcasing);
8079 bond(botright, botlcasing);
8080 bond(topright, botrcasing);
8082 if (
m->checksegments) {
8086 tspivot(botright, botrsubseg);
8087 tspivot(topright, toprsubseg);
8088 if (toplsubseg.ss ==
m->dummysub) {
8091 tsbond(botleft, toplsubseg);
8093 if (botlsubseg.ss ==
m->dummysub) {
8096 tsbond(botright, botlsubseg);
8098 if (botrsubseg.ss ==
m->dummysub) {
8101 tsbond(topright, botrsubseg);
8103 if (toprsubseg.ss ==
m->dummysub) {
8106 tsbond(topleft, toprsubseg);
8111 setorg(*flipedge, botvertex);
8112 setdest(*flipedge, farvertex);
8113 setapex(*flipedge, leftvertex);
8117 if (
b->verbose > 2) {
8118 printf(
" Edge unflip results in left ");
8120 printf(
" and right ");
8172#ifdef ANSI_DECLARATORS
8174 vertex newvertex,
struct otri *searchtri,
8175 struct osub *splitseg,
8176 int segmentflaws,
int triflaws )
8179 segmentflaws, triflaws)
8183struct otri *searchtri;
8184struct osub *splitseg;
8193 struct otri botleft, botright;
8194 struct otri topleft, topright;
8195 struct otri newbotleft, newbotright;
8196 struct otri newtopright;
8197 struct otri botlcasing, botrcasing;
8198 struct otri toplcasing, toprcasing;
8199 struct otri testtri;
8200 struct osub botlsubseg, botrsubseg;
8201 struct osub toplsubseg, toprsubseg;
8202 struct osub brokensubseg;
8203 struct osub checksubseg;
8204 struct osub rightsubseg;
8205 struct osub newsubseg;
8206 struct badsubseg *encroached;
8207 struct flipstacker *newflip;
8209 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
8210 vertex segmentorg, segmentdest;
8225 if (
b->verbose > 1) {
8226 printf(
" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
8229 if (splitseg == (
struct osub *) NULL) {
8232 if (searchtri->tri ==
m->dummytri) {
8234 horiz.tri =
m->dummytri;
8238 intersect =
locate(
m,
b, newvertex, &horiz);
8260 if (
m->checksegments && (splitseg == (
struct osub *) NULL)) {
8263 if (brokensubseg.ss !=
m->dummysub) {
8266 enq =
b->nobisect != 2;
8267 if (enq && (
b->nobisect == 1)) {
8270 sym(horiz, testtri);
8271 enq = testtri.tri !=
m->dummytri;
8275 encroached = (
struct badsubseg *)
poolalloc(&
m->badsubsegs);
8276 encroached->encsubseg =
sencode(brokensubseg);
8277 sorg(brokensubseg, encroached->subsegorg);
8278 sdest(brokensubseg, encroached->subsegdest);
8279 if (
b->verbose > 2) {
8281 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
8282 encroached->subsegorg[0], encroached->subsegorg[1],
8283 encroached->subsegdest[0], encroached->subsegdest[1]);
8297 lprev(horiz, botright);
8298 sym(botright, botrcasing);
8299 sym(horiz, topright);
8301 mirrorflag = topright.tri !=
m->dummytri;
8304 sym(topright, toprcasing);
8313 org(horiz, rightvertex);
8314 dest(horiz, leftvertex);
8315 apex(horiz, botvertex);
8316 setorg(newbotright, botvertex);
8317 setdest(newbotright, rightvertex);
8318 setapex(newbotright, newvertex);
8319 setorg(horiz, newvertex);
8320 for (i = 0; i <
m->eextras; i++) {
8329 dest(topright, topvertex);
8330 setorg(newtopright, rightvertex);
8331 setdest(newtopright, topvertex);
8332 setapex(newtopright, newvertex);
8333 setorg(topright, newvertex);
8334 for (i = 0; i <
m->eextras; i++) {
8346 if (
m->checksegments) {
8347 tspivot(botright, botrsubseg);
8348 if (botrsubseg.ss !=
m->dummysub) {
8350 tsbond(newbotright, botrsubseg);
8353 tspivot(topright, toprsubseg);
8354 if (toprsubseg.ss !=
m->dummysub) {
8356 tsbond(newtopright, toprsubseg);
8362 bond(newbotright, botrcasing);
8364 bond(newbotright, botright);
8367 bond(newtopright, toprcasing);
8369 bond(newtopright, topright);
8371 bond(newtopright, newbotright);
8374 if (splitseg != (
struct osub *) NULL) {
8377 segorg(*splitseg, segmentorg);
8378 segdest(*splitseg, segmentdest);
8380 spivot(*splitseg, rightsubseg);
8382 tspivot(newbotright, newsubseg);
8385 sbond(*splitseg, newsubseg);
8387 sbond(newsubseg, rightsubseg);
8396 if (
m->checkquality) {
8398 m->lastflip = (
struct flipstacker *)
poolalloc(&
m->flipstackers);
8399 m->lastflip->flippedtri =
encode(horiz);
8400 m->lastflip->prevflip = (
struct flipstacker *) &
insertvertex;
8405 printf(
"Internal error in insertvertex():\n");
8407 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
8411 printf(
"Internal error in insertvertex():\n");
8412 printf(
" Clockwise triangle prior to edge vertex insertion (top).\n");
8415 printf(
"Internal error in insertvertex():\n");
8417 " Clockwise triangle after edge vertex insertion (top right).\n");
8420 printf(
"Internal error in insertvertex():\n");
8422 " Clockwise triangle after edge vertex insertion (top left).\n");
8426 printf(
"Internal error in insertvertex():\n");
8428 " Clockwise triangle after edge vertex insertion (bottom left).\n");
8431 printf(
"Internal error in insertvertex():\n");
8433 " Clockwise triangle after edge vertex insertion (bottom right).\n");
8436 if (
b->verbose > 2) {
8437 printf(
" Updating bottom left ");
8440 printf(
" Updating top left ");
8442 printf(
" Creating top right ");
8445 printf(
" Creating bottom right ");
8454 lnext(horiz, botleft);
8455 lprev(horiz, botright);
8456 sym(botleft, botlcasing);
8457 sym(botright, botrcasing);
8462 org(horiz, rightvertex);
8463 dest(horiz, leftvertex);
8464 apex(horiz, botvertex);
8465 setorg(newbotleft, leftvertex);
8466 setdest(newbotleft, botvertex);
8467 setapex(newbotleft, newvertex);
8468 setorg(newbotright, botvertex);
8469 setdest(newbotright, rightvertex);
8470 setapex(newbotright, newvertex);
8472 for (i = 0; i <
m->eextras; i++) {
8487 if (
m->checksegments) {
8489 if (botlsubseg.ss !=
m->dummysub) {
8491 tsbond(newbotleft, botlsubseg);
8493 tspivot(botright, botrsubseg);
8494 if (botrsubseg.ss !=
m->dummysub) {
8496 tsbond(newbotright, botrsubseg);
8501 bond(newbotleft, botlcasing);
8502 bond(newbotright, botrcasing);
8505 bond(newbotleft, newbotright);
8507 bond(botleft, newbotleft);
8509 bond(botright, newbotright);
8511 if (
m->checkquality) {
8513 m->lastflip = (
struct flipstacker *)
poolalloc(&
m->flipstackers);
8514 m->lastflip->flippedtri =
encode(horiz);
8515 m->lastflip->prevflip = (
struct flipstacker *) NULL;
8520 printf(
"Internal error in insertvertex():\n");
8521 printf(
" Clockwise triangle prior to vertex insertion.\n");
8524 printf(
"Internal error in insertvertex():\n");
8525 printf(
" Clockwise triangle after vertex insertion (top).\n");
8528 printf(
"Internal error in insertvertex():\n");
8529 printf(
" Clockwise triangle after vertex insertion (left).\n");
8532 printf(
"Internal error in insertvertex():\n");
8533 printf(
" Clockwise triangle after vertex insertion (right).\n");
8536 if (
b->verbose > 2) {
8537 printf(
" Updating top ");
8539 printf(
" Creating left ");
8541 printf(
" Creating right ");
8554 rightvertex =
first;
8555 dest(horiz, leftvertex);
8561 if (
m->checksegments) {
8564 if (checksubseg.ss !=
m->dummysub) {
8570 if (checkseg4encroach(
m,
b, &checksubseg)) {
8581 if (top.tri ==
m->dummytri) {
8586 apex(top, farvertex);
8592 if ((leftvertex ==
m->infvertex1) || (leftvertex ==
m->infvertex2) ||
8593 (leftvertex ==
m->infvertex3)) {
8600 }
else if ((rightvertex ==
m->infvertex1) ||
8601 (rightvertex ==
m->infvertex2) ||
8602 (rightvertex ==
m->infvertex3)) {
8609 }
else if ((farvertex ==
m->infvertex1) ||
8610 (farvertex ==
m->infvertex2) ||
8611 (farvertex ==
m->infvertex3)) {
8617 doflip =
incircle(
m,
b, leftvertex, newvertex, rightvertex,
8624 lprev(top, topleft);
8625 sym(topleft, toplcasing);
8626 lnext(top, topright);
8627 sym(topright, toprcasing);
8628 lnext(horiz, botleft);
8629 sym(botleft, botlcasing);
8630 lprev(horiz, botright);
8631 sym(botright, botrcasing);
8633 bond(topleft, botlcasing);
8634 bond(botleft, botrcasing);
8635 bond(botright, toprcasing);
8636 bond(topright, toplcasing);
8637 if (
m->checksegments) {
8641 tspivot(botright, botrsubseg);
8642 tspivot(topright, toprsubseg);
8643 if (toplsubseg.ss ==
m->dummysub) {
8646 tsbond(topright, toplsubseg);
8648 if (botlsubseg.ss ==
m->dummysub) {
8651 tsbond(topleft, botlsubseg);
8653 if (botrsubseg.ss ==
m->dummysub) {
8656 tsbond(botleft, botrsubseg);
8658 if (toprsubseg.ss ==
m->dummysub) {
8661 tsbond(botright, toprsubseg);
8665 setorg(horiz, farvertex);
8671 for (i = 0; i <
m->eextras; i++) {
8690 if (
m->checkquality) {
8691 newflip = (
struct flipstacker *)
poolalloc(&
m->flipstackers);
8692 newflip->flippedtri =
encode(horiz);
8693 newflip->prevflip =
m->lastflip;
8694 m->lastflip = newflip;
8698 if (newvertex != (
vertex) NULL) {
8701 printf(
"Internal error in insertvertex():\n");
8702 printf(
" Clockwise triangle prior to edge flip (bottom).\n");
8716 printf(
"Internal error in insertvertex():\n");
8717 printf(
" Clockwise triangle after edge flip (left).\n");
8721 printf(
"Internal error in insertvertex():\n");
8722 printf(
" Clockwise triangle after edge flip (right).\n");
8726 if (
b->verbose > 2) {
8727 printf(
" Edge flip results in left ");
8730 printf(
" and right ");
8737 leftvertex = farvertex;
8746 testtriangle(
m,
b, &horiz);
8751 sym(horiz, testtri);
8755 if ((leftvertex ==
first) || (testtri.tri ==
m->dummytri)) {
8757 lnext(horiz, *searchtri);
8758 lnext(horiz,
m->recenttri);
8762 lnext(testtri, horiz);
8763 rightvertex = leftvertex;
8764 dest(horiz, leftvertex);
8833#ifdef ANSI_DECLARATORS
8835 struct otri *firstedge,
struct otri *lastedge,
8836 int edgecount,
int doflip,
int triflaws)
8841struct otri *firstedge;
8842struct otri *lastedge;
8849 struct otri testtri;
8850 struct otri besttri;
8851 struct otri tempedge;
8852 vertex leftbasevertex, rightbasevertex;
8860 apex(*lastedge, leftbasevertex);
8861 dest(*firstedge, rightbasevertex);
8862 if (
b->verbose > 2) {
8863 printf(
" Triangulating interior polygon at edge\n");
8864 printf(
" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
8865 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
8868 onext(*firstedge, besttri);
8869 dest(besttri, bestvertex);
8872 for (i = 2; i <= edgecount - 2; i++) {
8874 dest(testtri, testvertex);
8876 if (
incircle(
m,
b, leftbasevertex, rightbasevertex, bestvertex,
8877 testvertex) > 0.0) {
8879 bestvertex = testvertex;
8883 if (
b->verbose > 2) {
8884 printf(
" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
8887 if (bestnumber > 1) {
8889 oprev(besttri, tempedge);
8893 if (bestnumber < edgecount - 2) {
8895 sym(besttri, tempedge);
8899 sym(tempedge, besttri);
8907 sym(besttri, testtri);
8908 testtriangle(
m,
b, &testtri);
8932#ifdef ANSI_DECLARATORS
8933void deletevertex(
struct mesh *
m,
struct behavior *
b,
struct otri *deltri)
8935void deletevertex(
m,
b, deltri)
8942 struct otri countingtri;
8943 struct otri firstedge, lastedge;
8944 struct otri deltriright;
8945 struct otri lefttri, righttri;
8946 struct otri leftcasing, rightcasing;
8947 struct osub leftsubseg, rightsubseg;
8954 org(*deltri, delvertex);
8955 if (
b->verbose > 1) {
8956 printf(
" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
8961 onext(*deltri, countingtri);
8963 while (!
otriequal(*deltri, countingtri)) {
8965 if (countingtri.tri ==
m->dummytri) {
8966 printf(
"Internal error in deletevertex():\n");
8967 printf(
" Attempt to delete boundary vertex.\n");
8976 if (edgecount < 3) {
8977 printf(
"Internal error in deletevertex():\n Vertex has degree %d.\n",
8982 if (edgecount > 3) {
8986 onext(*deltri, firstedge);
8987 oprev(*deltri, lastedge);
8992 lprev(*deltri, deltriright);
8993 dnext(*deltri, lefttri);
8994 sym(lefttri, leftcasing);
8995 oprev(deltriright, righttri);
8996 sym(righttri, rightcasing);
8997 bond(*deltri, leftcasing);
8998 bond(deltriright, rightcasing);
9000 if (leftsubseg.ss !=
m->dummysub) {
9001 tsbond(*deltri, leftsubseg);
9003 tspivot(righttri, rightsubseg);
9004 if (rightsubseg.ss !=
m->dummysub) {
9005 tsbond(deltriright, rightsubseg);
9009 org(lefttri, neworg);
9012 testtriangle(
m,
b, deltri);
9035#ifdef ANSI_DECLARATORS
9036void undovertex(
struct mesh *
m,
struct behavior *
b)
9038void undovertex(
m,
b)
9044 struct otri fliptri;
9045 struct otri botleft, botright, topright;
9046 struct otri botlcasing, botrcasing, toprcasing;
9047 struct otri gluetri;
9048 struct osub botlsubseg, botrsubseg, toprsubseg;
9049 vertex botvertex, rightvertex;
9055 while (
m->lastflip != (
struct flipstacker *) NULL) {
9057 decode(
m->lastflip->flippedtri, fliptri);
9063 if (
m->lastflip->prevflip == (
struct flipstacker *) NULL) {
9066 dprev(fliptri, botleft);
9068 onext(fliptri, botright);
9070 sym(botleft, botlcasing);
9071 sym(botright, botrcasing);
9072 dest(botleft, botvertex);
9076 bond(fliptri, botlcasing);
9078 tsbond(fliptri, botlsubseg);
9080 bond(fliptri, botrcasing);
9081 tspivot(botright, botrsubseg);
9082 tsbond(fliptri, botrsubseg);
9087 }
else if (
m->lastflip->prevflip == (
struct flipstacker *) &
insertvertex) {
9090 lprev(fliptri, gluetri);
9091 sym(gluetri, botright);
9093 sym(botright, botrcasing);
9094 dest(botright, rightvertex);
9096 setorg(fliptri, rightvertex);
9097 bond(gluetri, botrcasing);
9098 tspivot(botright, botrsubseg);
9099 tsbond(gluetri, botrsubseg);
9104 sym(fliptri, gluetri);
9105 if (gluetri.tri !=
m->dummytri) {
9107 dnext(gluetri, topright);
9108 sym(topright, toprcasing);
9110 setorg(gluetri, rightvertex);
9111 bond(gluetri, toprcasing);
9112 tspivot(topright, toprsubseg);
9113 tsbond(gluetri, toprsubseg);
9120 m->lastflip->prevflip = (
struct flipstacker *) NULL;
9127 m->lastflip =
m->lastflip->prevflip;
9182#ifdef ANSI_DECLARATORS
9193 REAL pivotx, pivoty;
9196 if (arraysize == 2) {
9198 if ((sortarray[0][0] > sortarray[1][0]) ||
9199 ((sortarray[0][0] == sortarray[1][0]) &&
9200 (sortarray[0][1] > sortarray[1][1]))) {
9201 temp = sortarray[1];
9202 sortarray[1] = sortarray[0];
9203 sortarray[0] = temp;
9209 pivotx = sortarray[pivot][0];
9210 pivoty = sortarray[pivot][1];
9214 while (left < right) {
9218 }
while ((left <= right) && ((sortarray[left][0] < pivotx) ||
9219 ((sortarray[left][0] == pivotx) &&
9220 (sortarray[left][1] < pivoty))));
9224 }
while ((left <= right) && ((sortarray[right][0] > pivotx) ||
9225 ((sortarray[right][0] == pivotx) &&
9226 (sortarray[right][1] > pivoty))));
9229 temp = sortarray[left];
9230 sortarray[left] = sortarray[right];
9231 sortarray[right] = temp;
9238 if (right < arraysize - 2) {
9240 vertexsort(&sortarray[right + 1], arraysize - right - 1);
9256#ifdef ANSI_DECLARATORS
9269 REAL pivot1, pivot2;
9272 if (arraysize == 2) {
9274 if ((sortarray[0][axis] > sortarray[1][axis]) ||
9275 ((sortarray[0][axis] == sortarray[1][axis]) &&
9276 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
9277 temp = sortarray[1];
9278 sortarray[1] = sortarray[0];
9279 sortarray[0] = temp;
9285 pivot1 = sortarray[pivot][axis];
9286 pivot2 = sortarray[pivot][1 - axis];
9290 while (left < right) {
9294 }
while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
9295 ((sortarray[left][axis] == pivot1) &&
9296 (sortarray[left][1 - axis] < pivot2))));
9300 }
while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
9301 ((sortarray[right][axis] == pivot1) &&
9302 (sortarray[right][1 - axis] > pivot2))));
9305 temp = sortarray[left];
9306 sortarray[left] = sortarray[right];
9307 sortarray[right] = temp;
9312 if (left > median) {
9316 if (right < median - 1) {
9318 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
9319 median - right - 1, axis);
9334#ifdef ANSI_DECLARATORS
9346 divider = arraysize >> 1;
9347 if (arraysize <= 3) {
9355 if (arraysize - divider >= 2) {
9359 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
9398#ifdef ANSI_DECLARATORS
9400 struct otri *innerleft,
struct otri *innerright,
9401 struct otri *farright,
int axis)
9403void mergehulls(
m,
b, farleft, innerleft, innerright, farright, axis)
9406struct otri *farleft;
9407struct otri *innerleft;
9408struct otri *innerright;
9409struct otri *farright;
9414 struct otri leftcand, rightcand;
9415 struct otri baseedge;
9416 struct otri nextedge;
9417 struct otri sidecasing, topcasing, outercasing;
9418 struct otri checkedge;
9421 vertex innerleftapex, innerrightapex;
9422 vertex farleftpt, farrightpt;
9423 vertex farleftapex, farrightapex;
9424 vertex lowerleft, lowerright;
9425 vertex upperleft, upperright;
9430 int leftfinished, rightfinished;
9433 dest(*innerleft, innerleftdest);
9434 apex(*innerleft, innerleftapex);
9435 org(*innerright, innerrightorg);
9436 apex(*innerright, innerrightapex);
9438 if (
b->dwyer && (axis == 1)) {
9439 org(*farleft, farleftpt);
9440 apex(*farleft, farleftapex);
9441 dest(*farright, farrightpt);
9442 apex(*farright, farrightapex);
9446 while (farleftapex[1] < farleftpt[1]) {
9449 farleftpt = farleftapex;
9450 apex(*farleft, farleftapex);
9452 sym(*innerleft, checkedge);
9453 apex(checkedge, checkvertex);
9454 while (checkvertex[1] > innerleftdest[1]) {
9455 lnext(checkedge, *innerleft);
9456 innerleftapex = innerleftdest;
9457 innerleftdest = checkvertex;
9458 sym(*innerleft, checkedge);
9459 apex(checkedge, checkvertex);
9461 while (innerrightapex[1] < innerrightorg[1]) {
9464 innerrightorg = innerrightapex;
9465 apex(*innerright, innerrightapex);
9467 sym(*farright, checkedge);
9468 apex(checkedge, checkvertex);
9469 while (checkvertex[1] > farrightpt[1]) {
9470 lnext(checkedge, *farright);
9471 farrightapex = farrightpt;
9472 farrightpt = checkvertex;
9473 sym(*farright, checkedge);
9474 apex(checkedge, checkvertex);
9485 innerleftdest = innerleftapex;
9486 apex(*innerleft, innerleftapex);
9494 innerrightorg = innerrightapex;
9495 apex(*innerright, innerrightapex);
9498 }
while (changemade);
9500 sym(*innerleft, leftcand);
9501 sym(*innerright, rightcand);
9505 bond(baseedge, *innerleft);
9507 bond(baseedge, *innerright);
9509 setorg(baseedge, innerrightorg);
9510 setdest(baseedge, innerleftdest);
9512 if (
b->verbose > 2) {
9513 printf(
" Creating base bounding ");
9517 org(*farleft, farleftpt);
9518 if (innerleftdest == farleftpt) {
9519 lnext(baseedge, *farleft);
9521 dest(*farright, farrightpt);
9522 if (innerrightorg == farrightpt) {
9523 lprev(baseedge, *farright);
9526 lowerleft = innerleftdest;
9527 lowerright = innerrightorg;
9529 apex(leftcand, upperleft);
9530 apex(rightcand, upperright);
9541 if (leftfinished && rightfinished) {
9544 setorg(nextedge, lowerleft);
9545 setdest(nextedge, lowerright);
9548 bond(nextedge, baseedge);
9550 bond(nextedge, rightcand);
9552 bond(nextedge, leftcand);
9553 if (
b->verbose > 2) {
9554 printf(
" Creating top bounding ");
9558 if (
b->dwyer && (axis == 1)) {
9559 org(*farleft, farleftpt);
9560 apex(*farleft, farleftapex);
9561 dest(*farright, farrightpt);
9562 apex(*farright, farrightapex);
9563 sym(*farleft, checkedge);
9564 apex(checkedge, checkvertex);
9568 while (checkvertex[0] < farleftpt[0]) {
9569 lprev(checkedge, *farleft);
9570 farleftapex = farleftpt;
9571 farleftpt = checkvertex;
9572 sym(*farleft, checkedge);
9573 apex(checkedge, checkvertex);
9575 while (farrightapex[0] > farrightpt[0]) {
9578 farrightpt = farrightapex;
9579 apex(*farright, farrightapex);
9585 if (!leftfinished) {
9587 lprev(leftcand, nextedge);
9589 apex(nextedge, nextapex);
9592 if (nextapex != (
vertex) NULL) {
9594 badedge =
incircle(
m,
b, lowerleft, lowerright, upperleft, nextapex) >
9600 sym(nextedge, topcasing);
9602 sym(nextedge, sidecasing);
9603 bond(nextedge, topcasing);
9604 bond(leftcand, sidecasing);
9606 sym(leftcand, outercasing);
9608 bond(nextedge, outercasing);
9610 setorg(leftcand, lowerleft);
9617 upperleft = nextapex;
9620 apex(nextedge, nextapex);
9621 if (nextapex != (
vertex) NULL) {
9623 badedge =
incircle(
m,
b, lowerleft, lowerright, upperleft,
9633 if (!rightfinished) {
9635 lnext(rightcand, nextedge);
9637 apex(nextedge, nextapex);
9640 if (nextapex != (
vertex) NULL) {
9642 badedge =
incircle(
m,
b, lowerleft, lowerright, upperright, nextapex) >
9648 sym(nextedge, topcasing);
9650 sym(nextedge, sidecasing);
9651 bond(nextedge, topcasing);
9652 bond(rightcand, sidecasing);
9654 sym(rightcand, outercasing);
9656 bond(nextedge, outercasing);
9659 setdest(rightcand, lowerright);
9661 setorg(nextedge, upperright);
9665 upperright = nextapex;
9668 apex(nextedge, nextapex);
9669 if (nextapex != (
vertex) NULL) {
9671 badedge =
incircle(
m,
b, lowerleft, lowerright, upperright,
9680 if (leftfinished || (!rightfinished &&
9681 (
incircle(
m,
b, upperleft, lowerleft, lowerright, upperright) >
9685 bond(baseedge, rightcand);
9686 lprev(rightcand, baseedge);
9688 lowerright = upperright;
9689 sym(baseedge, rightcand);
9690 apex(rightcand, upperright);
9694 bond(baseedge, leftcand);
9695 lnext(leftcand, baseedge);
9696 setorg(baseedge, lowerright);
9697 lowerleft = upperleft;
9698 sym(baseedge, leftcand);
9699 apex(leftcand, upperleft);
9701 if (
b->verbose > 2) {
9702 printf(
" Connecting ");
9725#ifdef ANSI_DECLARATORS
9727 int vertices,
int axis,
9728 struct otri *farleft,
struct otri *farright)
9736struct otri *farleft;
9737struct otri *farright;
9741 struct otri midtri, tri1, tri2, tri3;
9742 struct otri innerleft, innerright;
9746 if (
b->verbose > 2) {
9747 printf(
" Triangulating %d vertices.\n", vertices);
9749 if (vertices == 2) {
9753 setorg(*farleft, sortarray[0]);
9754 setdest(*farleft, sortarray[1]);
9757 setorg(*farright, sortarray[1]);
9758 setdest(*farright, sortarray[0]);
9760 bond(*farleft, *farright);
9763 bond(*farleft, *farright);
9766 bond(*farleft, *farright);
9767 if (
b->verbose > 2) {
9768 printf(
" Creating ");
9770 printf(
" Creating ");
9774 lprev(*farright, *farleft);
9776 }
else if (vertices == 3) {
9787 setorg(midtri, sortarray[0]);
9788 setdest(midtri, sortarray[1]);
9789 setorg(tri1, sortarray[1]);
9791 setorg(tri2, sortarray[2]);
9793 setorg(tri3, sortarray[1]);
9817 setorg(midtri, sortarray[0]);
9819 setorg(tri3, sortarray[0]);
9823 setdest(midtri, sortarray[1]);
9824 setorg(tri1, sortarray[1]);
9826 setapex(midtri, sortarray[2]);
9827 setorg(tri2, sortarray[2]);
9831 setdest(midtri, sortarray[2]);
9832 setorg(tri1, sortarray[2]);
9834 setapex(midtri, sortarray[1]);
9835 setorg(tri2, sortarray[1]);
9859 lnext(*farleft, *farright);
9862 if (
b->verbose > 2) {
9863 printf(
" Creating ");
9865 printf(
" Creating ");
9867 printf(
" Creating ");
9869 printf(
" Creating ");
9875 divider = vertices >> 1;
9879 &innerright, farright);
9880 if (
b->verbose > 1) {
9881 printf(
" Joining triangulations with %d and %d vertices.\n", divider,
9882 vertices - divider);
9885 mergehulls(
m,
b, farleft, &innerleft, &innerright, farright, axis);
9889#ifdef ANSI_DECLARATORS
9895struct otri *startghost;
9899 struct otri searchedge;
9900 struct otri dissolveedge;
9901 struct otri deadtriangle;
9907 printf(
" Removing ghost triangles.\n");
9910 lprev(*startghost, searchedge);
9912 m->dummytri[0] =
encode(searchedge);
9914 otricopy(*startghost, dissolveedge);
9918 lnext(dissolveedge, deadtriangle);
9925 if (dissolveedge.tri !=
m->dummytri) {
9926 org(dissolveedge, markorg);
9935 sym(deadtriangle, dissolveedge);
9938 }
while (!
otriequal(dissolveedge, *startghost));
9952#ifdef ANSI_DECLARATORS
9962 struct otri hullleft, hullright;
9967 printf(
" Sorting vertices.\n");
9973 for (i = 0; i <
m->invertices; i++) {
9980 for (j = 1; j <
m->invertices; j++) {
9981 if ((sortarray[i][0] == sortarray[j][0])
9982 && (sortarray[i][1] == sortarray[j][1])) {
9985"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
9986 sortarray[j][0], sortarray[j][1]);
9992 sortarray[i] = sortarray[j];
9999 if (i - divider >= 2) {
10000 if (divider >= 2) {
10008 printf(
" Forming triangulation.\n");
10039#ifdef ANSI_DECLARATORS
10040void boundingbox(
struct mesh *
m,
struct behavior *
b)
10042void boundingbox(
m,
b)
10048 struct otri inftri;
10052 printf(
" Creating triangular bounding box.\n");
10056 if (
m->ymax -
m->ymin >
width) {
10059 if (
width == 0.0) {
10066 m->infvertex1[0] =
m->xmin - 50.0 *
width;
10067 m->infvertex1[1] =
m->ymin - 40.0 *
width;
10068 m->infvertex2[0] =
m->xmax + 50.0 *
width;
10069 m->infvertex2[1] =
m->ymin - 40.0 *
width;
10070 m->infvertex3[0] = 0.5 * (
m->xmin +
m->xmax);
10071 m->infvertex3[1] =
m->ymax + 60.0 *
width;
10075 setorg(inftri,
m->infvertex1);
10080 m->dummytri[0] = (
triangle) inftri.tri;
10081 if (
b->verbose > 2) {
10082 printf(
" Creating ");
10105#ifdef ANSI_DECLARATORS
10106long removebox(
struct mesh *
m,
struct behavior *
b)
10108long removebox(
m,
b)
10114 struct otri deadtriangle;
10115 struct otri searchedge;
10116 struct otri checkedge;
10117 struct otri nextedge, finaledge, dissolveedge;
10123 printf(
" Removing triangular bounding box.\n");
10126 nextedge.tri =
m->dummytri;
10127 nextedge.orient = 0;
10130 lprev(nextedge, finaledge);
10135 lprev(nextedge, searchedge);
10139 lnext(nextedge, checkedge);
10141 if (checkedge.tri ==
m->dummytri) {
10150 m->dummytri[0] =
encode(searchedge);
10152 while (!
otriequal(nextedge, finaledge)) {
10154 lprev(nextedge, dissolveedge);
10163 if (dissolveedge.tri !=
m->dummytri) {
10164 org(dissolveedge, markorg);
10172 lnext(nextedge, deadtriangle);
10173 sym(deadtriangle, nextedge);
10177 if (nextedge.tri ==
m->dummytri) {
10204#ifdef ANSI_DECLARATORS
10205long incrementaldelaunay(
struct mesh *
m,
struct behavior *
b)
10207long incrementaldelaunay(
m,
b)
10213 struct otri starttri;
10219 printf(
" Incrementally inserting vertices.\n");
10223 while (vertexloop != (
vertex) NULL) {
10224 starttri.tri =
m->dummytri;
10225 if (
insertvertex(
m,
b, vertexloop, &starttri, (
struct osub *) NULL, 0, 0)
10229"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10230 vertexloop[0], vertexloop[1]);
10238 return removebox(
m,
b);
10253#ifdef ANSI_DECLARATORS
10254void eventheapinsert(
struct event **heap,
int heapsize,
struct event *newevent)
10256void eventheapinsert(heap, heapsize, newevent)
10257struct event **heap;
10259struct event *newevent;
10263 REAL eventx, eventy;
10268 eventx = newevent->xkey;
10269 eventy = newevent->ykey;
10270 eventnum = heapsize;
10271 notdone = eventnum > 0;
10273 parent = (eventnum - 1) >> 1;
10274 if ((heap[parent]->ykey < eventy) ||
10275 ((heap[parent]->ykey == eventy)
10276 && (heap[parent]->xkey <= eventx))) {
10279 heap[eventnum] = heap[parent];
10280 heap[eventnum]->heapposition = eventnum;
10283 notdone = eventnum > 0;
10286 heap[eventnum] = newevent;
10287 newevent->heapposition = eventnum;
10294#ifdef ANSI_DECLARATORS
10295void eventheapify(
struct event **heap,
int heapsize,
int eventnum)
10297void eventheapify(heap, heapsize, eventnum)
10298struct event **heap;
10304 struct event *thisevent;
10305 REAL eventx, eventy;
10306 int leftchild, rightchild;
10310 thisevent = heap[eventnum];
10311 eventx = thisevent->xkey;
10312 eventy = thisevent->ykey;
10313 leftchild = 2 * eventnum + 1;
10314 notdone = leftchild < heapsize;
10316 if ((heap[leftchild]->ykey < eventy) ||
10317 ((heap[leftchild]->ykey == eventy)
10318 && (heap[leftchild]->xkey < eventx))) {
10319 smallest = leftchild;
10321 smallest = eventnum;
10323 rightchild = leftchild + 1;
10324 if (rightchild < heapsize) {
10325 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10326 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10327 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10328 smallest = rightchild;
10331 if (smallest == eventnum) {
10334 heap[eventnum] = heap[smallest];
10335 heap[eventnum]->heapposition = eventnum;
10336 heap[smallest] = thisevent;
10337 thisevent->heapposition = smallest;
10339 eventnum = smallest;
10340 leftchild = 2 * eventnum + 1;
10341 notdone = leftchild < heapsize;
10350#ifdef ANSI_DECLARATORS
10351void eventheapdelete(
struct event **heap,
int heapsize,
int eventnum)
10353void eventheapdelete(heap, heapsize, eventnum)
10354struct event **heap;
10360 struct event *moveevent;
10361 REAL eventx, eventy;
10365 moveevent = heap[heapsize - 1];
10366 if (eventnum > 0) {
10367 eventx = moveevent->xkey;
10368 eventy = moveevent->ykey;
10370 parent = (eventnum - 1) >> 1;
10371 if ((heap[parent]->ykey < eventy) ||
10372 ((heap[parent]->ykey == eventy)
10373 && (heap[parent]->xkey <= eventx))) {
10376 heap[eventnum] = heap[parent];
10377 heap[eventnum]->heapposition = eventnum;
10380 notdone = eventnum > 0;
10384 heap[eventnum] = moveevent;
10385 moveevent->heapposition = eventnum;
10386 eventheapify(heap, heapsize - 1, eventnum);
10393#ifdef ANSI_DECLARATORS
10394void createeventheap(
struct mesh *
m,
struct event ***eventheap,
10395 struct event **events,
struct event **freeevents)
10397void createeventheap(
m, eventheap, events, freeevents)
10399struct event ***eventheap;
10400struct event **events;
10401struct event **freeevents;
10409 maxevents = (3 *
m->invertices) / 2;
10410 *eventheap = (
struct event **)
trimalloc(maxevents *
10411 (
int)
sizeof(
struct event *));
10412 *events = (
struct event *)
trimalloc(maxevents * (
int)
sizeof(
struct event));
10414 for (i = 0; i <
m->invertices; i++) {
10416 (*events)[i].eventptr = (
VOID *) thisvertex;
10417 (*events)[i].xkey = thisvertex[0];
10418 (*events)[i].ykey = thisvertex[1];
10419 eventheapinsert(*eventheap, i, *events + i);
10421 *freeevents = (
struct event *) NULL;
10422 for (i = maxevents - 1; i >=
m->invertices; i--) {
10423 (*events)[i].eventptr = (
VOID *) *freeevents;
10424 *freeevents = *events + i;
10432#ifdef ANSI_DECLARATORS
10433int rightofhyperbola(
struct mesh *
m,
struct otri *fronttri,
vertex newsite)
10435int rightofhyperbola(
m, fronttri, newsite)
10437struct otri *fronttri;
10442 vertex leftvertex, rightvertex;
10443 REAL dxa, dya, dxb, dyb;
10445 m->hyperbolacount++;
10447 dest(*fronttri, leftvertex);
10448 apex(*fronttri, rightvertex);
10449 if ((leftvertex[1] < rightvertex[1]) ||
10450 ((leftvertex[1] == rightvertex[1]) &&
10451 (leftvertex[0] < rightvertex[0]))) {
10452 if (newsite[0] >= rightvertex[0]) {
10456 if (newsite[0] <= leftvertex[0]) {
10460 dxa = leftvertex[0] - newsite[0];
10461 dya = leftvertex[1] - newsite[1];
10462 dxb = rightvertex[0] - newsite[0];
10463 dyb = rightvertex[1] - newsite[1];
10464 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10471#ifdef ANSI_DECLARATORS
10474REAL circletop(
m, pa, pb, pc, ccwabc)
10483 REAL xac, yac, xbc, ybc, xab, yab;
10484 REAL aclen2, bclen2, ablen2;
10486 m->circletopcount++;
10488 xac = pa[0] - pc[0];
10489 yac = pa[1] - pc[1];
10490 xbc = pb[0] - pc[0];
10491 ybc = pb[1] - pc[1];
10492 xab = pa[0] - pb[0];
10493 yab = pa[1] - pb[1];
10494 aclen2 = xac * xac + yac * yac;
10495 bclen2 = xbc * xbc + ybc * ybc;
10496 ablen2 = xab * xab + yab * yab;
10497 return pc[1] + (xac * bclen2 - xbc * aclen2 +
sqrt(aclen2 * bclen2 * ablen2))
10505#ifdef ANSI_DECLARATORS
10506void check4deadevent(
struct otri *checktri,
struct event **freeevents,
10507 struct event **eventheap,
int *heapsize)
10509void check4deadevent(checktri, freeevents, eventheap, heapsize)
10510struct otri *checktri;
10511struct event **freeevents;
10512struct event **eventheap;
10517 struct event *deadevent;
10521 org(*checktri, eventvertex);
10522 if (eventvertex != (
vertex) NULL) {
10523 deadevent = (
struct event *) eventvertex;
10524 eventnum = deadevent->heapposition;
10525 deadevent->eventptr = (
VOID *) *freeevents;
10526 *freeevents = deadevent;
10527 eventheapdelete(eventheap, *heapsize, eventnum);
10529 setorg(*checktri, NULL);
10537#ifdef ANSI_DECLARATORS
10538struct splaynode *splay(
struct mesh *
m,
struct splaynode *splaytree,
10539 vertex searchpoint,
struct otri *searchtri)
10541struct splaynode *splay(
m, splaytree, searchpoint, searchtri)
10543struct splaynode *splaytree;
10545struct otri *searchtri;
10549 struct splaynode *child, *grandchild;
10550 struct splaynode *lefttree, *righttree;
10551 struct splaynode *leftright;
10553 int rightofroot, rightofchild;
10555 if (splaytree == (
struct splaynode *) NULL) {
10556 return (
struct splaynode *) NULL;
10558 dest(splaytree->keyedge, checkvertex);
10559 if (checkvertex == splaytree->keydest) {
10560 rightofroot = rightofhyperbola(
m, &splaytree->keyedge, searchpoint);
10562 otricopy(splaytree->keyedge, *searchtri);
10563 child = splaytree->rchild;
10565 child = splaytree->lchild;
10567 if (child == (
struct splaynode *) NULL) {
10570 dest(child->keyedge, checkvertex);
10571 if (checkvertex != child->keydest) {
10572 child = splay(
m, child, searchpoint, searchtri);
10573 if (child == (
struct splaynode *) NULL) {
10575 splaytree->rchild = (
struct splaynode *) NULL;
10577 splaytree->lchild = (
struct splaynode *) NULL;
10582 rightofchild = rightofhyperbola(
m, &child->keyedge, searchpoint);
10583 if (rightofchild) {
10584 otricopy(child->keyedge, *searchtri);
10585 grandchild = splay(
m, child->rchild, searchpoint, searchtri);
10586 child->rchild = grandchild;
10588 grandchild = splay(
m, child->lchild, searchpoint, searchtri);
10589 child->lchild = grandchild;
10591 if (grandchild == (
struct splaynode *) NULL) {
10593 splaytree->rchild = child->lchild;
10594 child->lchild = splaytree;
10596 splaytree->lchild = child->rchild;
10597 child->rchild = splaytree;
10601 if (rightofchild) {
10603 splaytree->rchild = child->lchild;
10604 child->lchild = splaytree;
10606 splaytree->lchild = grandchild->rchild;
10607 grandchild->rchild = splaytree;
10609 child->rchild = grandchild->lchild;
10610 grandchild->lchild = child;
10613 splaytree->rchild = grandchild->lchild;
10614 grandchild->lchild = splaytree;
10616 splaytree->lchild = child->rchild;
10617 child->rchild = splaytree;
10619 child->lchild = grandchild->rchild;
10620 grandchild->rchild = child;
10624 lefttree = splay(
m, splaytree->lchild, searchpoint, searchtri);
10625 righttree = splay(
m, splaytree->rchild, searchpoint, searchtri);
10628 if (lefttree == (
struct splaynode *) NULL) {
10630 }
else if (righttree == (
struct splaynode *) NULL) {
10632 }
else if (lefttree->rchild == (
struct splaynode *) NULL) {
10633 lefttree->rchild = righttree->lchild;
10634 righttree->lchild = lefttree;
10636 }
else if (righttree->lchild == (
struct splaynode *) NULL) {
10637 righttree->lchild = lefttree->rchild;
10638 lefttree->rchild = righttree;
10642 leftright = lefttree->rchild;
10643 while (leftright->rchild != (
struct splaynode *) NULL) {
10644 leftright = leftright->rchild;
10646 leftright->rchild = righttree;
10656#ifdef ANSI_DECLARATORS
10657struct splaynode *splayinsert(
struct mesh *
m,
struct splaynode *splayroot,
10658 struct otri *newkey,
vertex searchpoint)
10660struct splaynode *splayinsert(
m, splayroot, newkey, searchpoint)
10662struct splaynode *splayroot;
10663struct otri *newkey;
10668 struct splaynode *newsplaynode;
10670 newsplaynode = (
struct splaynode *)
poolalloc(&
m->splaynodes);
10671 otricopy(*newkey, newsplaynode->keyedge);
10672 dest(*newkey, newsplaynode->keydest);
10673 if (splayroot == (
struct splaynode *) NULL) {
10674 newsplaynode->lchild = (
struct splaynode *) NULL;
10675 newsplaynode->rchild = (
struct splaynode *) NULL;
10676 }
else if (rightofhyperbola(
m, &splayroot->keyedge, searchpoint)) {
10677 newsplaynode->lchild = splayroot;
10678 newsplaynode->rchild = splayroot->rchild;
10679 splayroot->rchild = (
struct splaynode *) NULL;
10681 newsplaynode->lchild = splayroot->lchild;
10682 newsplaynode->rchild = splayroot;
10683 splayroot->lchild = (
struct splaynode *) NULL;
10685 return newsplaynode;
10692#ifdef ANSI_DECLARATORS
10693struct splaynode *circletopinsert(
struct mesh *
m,
struct behavior *
b,
10694 struct splaynode *splayroot,
10695 struct otri *newkey,
10698struct splaynode *circletopinsert(
m,
b, splayroot, newkey, pa, pb, pc, topy)
10701struct splaynode *splayroot;
10702struct otri *newkey;
10711 REAL xac, yac, xbc, ybc;
10712 REAL aclen2, bclen2;
10713 REAL searchpoint[2];
10714 struct otri dummytri;
10717 xac = pa[0] - pc[0];
10718 yac = pa[1] - pc[1];
10719 xbc = pb[0] - pc[0];
10720 ybc = pb[1] - pc[1];
10721 aclen2 = xac * xac + yac * yac;
10722 bclen2 = xbc * xbc + ybc * ybc;
10723 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10724 searchpoint[1] = topy;
10725 return splayinsert(
m, splay(
m, splayroot, (
vertex) searchpoint, &dummytri),
10726 newkey, (
vertex) searchpoint);
10733#ifdef ANSI_DECLARATORS
10734struct splaynode *frontlocate(
struct mesh *
m,
struct splaynode *splayroot,
10735 struct otri *bottommost,
vertex searchvertex,
10736 struct otri *searchtri,
int *farright)
10738struct splaynode *frontlocate(
m, splayroot, bottommost, searchvertex,
10739 searchtri, farright)
10741struct splaynode *splayroot;
10742struct otri *bottommost;
10744struct otri *searchtri;
10752 otricopy(*bottommost, *searchtri);
10753 splayroot = splay(
m, splayroot, searchvertex, searchtri);
10756 while (!farrightflag && rightofhyperbola(
m, searchtri, searchvertex)) {
10758 farrightflag =
otriequal(*searchtri, *bottommost);
10760 *farright = farrightflag;
10768#ifdef ANSI_DECLARATORS
10769long sweeplinedelaunay(
struct mesh *
m,
struct behavior *
b)
10771long sweeplinedelaunay(
m,
b)
10777 struct event **eventheap;
10778 struct event *events;
10779 struct event *freeevents;
10780 struct event *nextevent;
10781 struct event *newevent;
10782 struct splaynode *splayroot;
10783 struct otri bottommost;
10784 struct otri searchtri;
10785 struct otri fliptri;
10786 struct otri lefttri, righttri, farlefttri, farrighttri;
10787 struct otri inserttri;
10788 vertex firstvertex, secondvertex;
10789 vertex nextvertex, lastvertex;
10791 vertex leftvertex, midvertex, rightvertex;
10792 REAL lefttest, righttest;
10794 int check4events, farrightflag;
10799 splayroot = (
struct splaynode *) NULL;
10802 printf(
" Placing vertices in event heap.\n");
10804 createeventheap(
m, &eventheap, &events, &freeevents);
10805 heapsize =
m->invertices;
10808 printf(
" Forming triangulation.\n");
10812 bond(lefttri, righttri);
10815 bond(lefttri, righttri);
10818 bond(lefttri, righttri);
10819 firstvertex = (
vertex) eventheap[0]->eventptr;
10820 eventheap[0]->eventptr = (
VOID *) freeevents;
10821 freeevents = eventheap[0];
10822 eventheapdelete(eventheap, heapsize, 0);
10825 if (heapsize == 0) {
10826 printf(
"Error: Input vertices are all identical.\n");
10829 secondvertex = (
vertex) eventheap[0]->eventptr;
10830 eventheap[0]->eventptr = (
VOID *) freeevents;
10831 freeevents = eventheap[0];
10832 eventheapdelete(eventheap, heapsize, 0);
10834 if ((firstvertex[0] == secondvertex[0]) &&
10835 (firstvertex[1] == secondvertex[1])) {
10838"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10839 secondvertex[0], secondvertex[1]);
10844 }
while ((firstvertex[0] == secondvertex[0]) &&
10845 (firstvertex[1] == secondvertex[1]));
10846 setorg(lefttri, firstvertex);
10847 setdest(lefttri, secondvertex);
10848 setorg(righttri, secondvertex);
10849 setdest(righttri, firstvertex);
10850 lprev(lefttri, bottommost);
10851 lastvertex = secondvertex;
10852 while (heapsize > 0) {
10853 nextevent = eventheap[0];
10854 eventheapdelete(eventheap, heapsize, 0);
10857 if (nextevent->xkey <
m->xmin) {
10858 decode(nextevent->eventptr, fliptri);
10859 oprev(fliptri, farlefttri);
10860 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10861 onext(fliptri, farrighttri);
10862 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10864 if (
otriequal(farlefttri, bottommost)) {
10865 lprev(fliptri, bottommost);
10869 lprev(fliptri, lefttri);
10870 lnext(fliptri, righttri);
10871 sym(lefttri, farlefttri);
10875 dest(fliptri, leftvertex);
10876 apex(fliptri, midvertex);
10877 org(fliptri, rightvertex);
10878 splayroot = circletopinsert(
m,
b, splayroot, &lefttri, leftvertex,
10879 midvertex, rightvertex, nextevent->ykey);
10882 nextvertex = (
vertex) nextevent->eventptr;
10883 if ((nextvertex[0] == lastvertex[0]) &&
10884 (nextvertex[1] == lastvertex[1])) {
10887"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10888 nextvertex[0], nextvertex[1]);
10894 lastvertex = nextvertex;
10896 splayroot = frontlocate(
m, splayroot, &bottommost, nextvertex,
10897 &searchtri, &farrightflag);
10907 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10910 sym(searchtri, farlefttri);
10913 dest(farrighttri, connectvertex);
10914 setorg(lefttri, connectvertex);
10915 setdest(lefttri, nextvertex);
10916 setorg(righttri, nextvertex);
10917 setdest(righttri, connectvertex);
10918 bond(lefttri, righttri);
10921 bond(lefttri, righttri);
10924 bond(lefttri, farlefttri);
10925 bond(righttri, farrighttri);
10926 if (!farrightflag &&
otriequal(farrighttri, bottommost)) {
10931 splayroot = splayinsert(
m, splayroot, &lefttri, nextvertex);
10933 lnext(righttri, inserttri);
10934 splayroot = splayinsert(
m, splayroot, &inserttri, nextvertex);
10938 nextevent->eventptr = (
VOID *) freeevents;
10939 freeevents = nextevent;
10941 if (check4events) {
10942 apex(farlefttri, leftvertex);
10943 dest(lefttri, midvertex);
10944 apex(lefttri, rightvertex);
10946 if (lefttest > 0.0) {
10947 newevent = freeevents;
10948 freeevents = (
struct event *) freeevents->eventptr;
10949 newevent->xkey =
m->xminextreme;
10950 newevent->ykey = circletop(
m, leftvertex, midvertex, rightvertex,
10952 newevent->eventptr = (
VOID *)
encode(lefttri);
10953 eventheapinsert(eventheap, heapsize, newevent);
10955 setorg(lefttri, newevent);
10957 apex(righttri, leftvertex);
10958 org(righttri, midvertex);
10959 apex(farrighttri, rightvertex);
10961 if (righttest > 0.0) {
10962 newevent = freeevents;
10963 freeevents = (
struct event *) freeevents->eventptr;
10964 newevent->xkey =
m->xminextreme;
10965 newevent->ykey = circletop(
m, leftvertex, midvertex, rightvertex,
10967 newevent->eventptr = (
VOID *)
encode(farrighttri);
10968 eventheapinsert(eventheap, heapsize, newevent);
10970 setorg(farrighttri, newevent);
10996#ifdef ANSI_DECLARATORS
11013 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11018 printf(
"Constructing Delaunay triangulation ");
11019 if (
b->incremental) {
11020 printf(
"by incremental method.\n");
11021 }
else if (
b->sweepline) {
11022 printf(
"by sweepline method.\n");
11024 printf(
"by divide-and-conquer method.\n");
11027 if (
b->incremental) {
11028 hulledges = incrementaldelaunay(
m,
b);
11029 }
else if (
b->sweepline) {
11030 hulledges = sweeplinedelaunay(
m,
b);
11036 if (
m->triangles.items == 0) {
11073#ifdef ANSI_DECLARATORS
11074int reconstruct(
struct mesh *
m,
struct behavior *
b,
int *trianglelist,
11075 REAL *triangleattriblist,
REAL *trianglearealist,
11076 int elements,
int corners,
int attribs,
11077 int *segmentlist,
int *segmentmarkerlist,
int numberofsegments)
11079int reconstruct(
m,
b, trianglelist, triangleattriblist, trianglearealist,
11080 elements, corners, attribs, segmentlist, segmentmarkerlist,
11085REAL *triangleattriblist;
11086REAL *trianglearealist;
11091int *segmentmarkerlist;
11092int numberofsegments;
11097#ifdef ANSI_DECLARATORS
11098long reconstruct(
struct mesh *
m,
struct behavior *
b,
char *elefilename,
11099 char *areafilename,
char *polyfilename, FILE *polyfile)
11101long reconstruct(
m,
b, elefilename, areafilename, polyfilename, polyfile)
11123 struct otri triangleloop;
11124 struct otri triangleleft;
11125 struct otri checktri;
11126 struct otri checkleft;
11127 struct otri checkneighbor;
11128 struct osub subsegloop;
11133 vertex checkdest, checkapex;
11136 vertex segmentorg, segmentdest;
11140 int killvertexindex;
11142 int segmentmarkers;
11147 long elementnumber, segmentnumber;
11152 m->inelements = elements;
11153 incorners = corners;
11154 if (incorners < 3) {
11155 printf(
"Error: Triangles must have at least 3 vertices.\n");
11158 m->eextras = attribs;
11162 printf(
"Opening %s.\n", elefilename);
11164 elefile = fopen(elefilename,
"r");
11165 if (elefile == (FILE *) NULL) {
11166 printf(
" Error: Cannot access file %s.\n", elefilename);
11171 stringptr = readline(inputline, elefile, elefilename);
11172 m->inelements = (
int) strtol(stringptr, &stringptr, 0);
11173 stringptr = findfield(stringptr);
11174 if (*stringptr ==
'\0') {
11177 incorners = (
int) strtol(stringptr, &stringptr, 0);
11178 if (incorners < 3) {
11179 printf(
"Error: Triangles in %s must have at least 3 vertices.\n",
11184 stringptr = findfield(stringptr);
11185 if (*stringptr ==
'\0') {
11188 m->eextras = (
int) strtol(stringptr, &stringptr, 0);
11195 for (elementnumber = 1; elementnumber <=
m->inelements; elementnumber++) {
11198 triangleloop.tri[3] = (
triangle) triangleloop.tri;
11201 segmentmarkers = 0;
11204 m->insegments = numberofsegments;
11205 segmentmarkers = segmentmarkerlist != (
int *) NULL;
11209 stringptr = readline(inputline, polyfile,
b->inpolyfilename);
11210 m->insegments = (
int) strtol(stringptr, &stringptr, 0);
11211 stringptr = findfield(stringptr);
11212 if (*stringptr !=
'\0') {
11213 segmentmarkers = (
int) strtol(stringptr, &stringptr, 0);
11218 for (segmentnumber = 1; segmentnumber <=
m->insegments; segmentnumber++) {
11221 subsegloop.ss[2] = (
subseg) subsegloop.ss;
11232 printf(
"Opening %s.\n", areafilename);
11234 areafile = fopen(areafilename,
"r");
11235 if (areafile == (FILE *) NULL) {
11236 printf(
" Error: Cannot access file %s.\n", areafilename);
11239 stringptr = readline(inputline, areafile, areafilename);
11240 areaelements = (
int) strtol(stringptr, &stringptr, 0);
11241 if (areaelements !=
m->inelements) {
11242 printf(
"Error: %s and %s disagree on number of triangles.\n",
11243 elefilename, areafilename);
11250 printf(
"Reconstructing mesh.\n");
11258 for (i = 0; i <
m->vertices.items; i++) {
11259 vertexarray[i] = (
triangle)
m->dummytri;
11263 printf(
" Assembling triangles.\n");
11269 elementnumber =
b->firstnumber;
11270 while (triangleloop.tri != (
triangle *) NULL) {
11273 for (j = 0; j < 3; j++) {
11274 corner[j] = trianglelist[vertexindex++];
11275 if ((corner[j] <
b->firstnumber) ||
11276 (corner[j] >=
b->firstnumber +
m->invertices)) {
11277 printf(
"Error: Triangle %ld has an invalid vertex index.\n",
11284 stringptr = readline(inputline, elefile, elefilename);
11285 for (j = 0; j < 3; j++) {
11286 stringptr = findfield(stringptr);
11287 if (*stringptr ==
'\0') {
11288 printf(
"Error: Triangle %ld is missing vertex %d in %s.\n",
11289 elementnumber, j + 1, elefilename);
11292 corner[j] = (
int) strtol(stringptr, &stringptr, 0);
11293 if ((corner[j] <
b->firstnumber) ||
11294 (corner[j] >=
b->firstnumber +
m->invertices)) {
11295 printf(
"Error: Triangle %ld has an invalid vertex index.\n",
11304 for (j = 3; j < incorners; j++) {
11306 killvertexindex = trianglelist[vertexindex++];
11308 stringptr = findfield(stringptr);
11309 if (*stringptr !=
'\0') {
11310 killvertexindex = (
int) strtol(stringptr, &stringptr, 0);
11312 if ((killvertexindex >=
b->firstnumber) &&
11313 (killvertexindex <
b->firstnumber +
m->invertices)) {
11326 for (j = 0; j <
m->eextras; j++) {
11330 stringptr = findfield(stringptr);
11331 if (*stringptr ==
'\0') {
11335 (
REAL) strtod(stringptr, &stringptr));
11342 area = trianglearealist[elementnumber -
b->firstnumber];
11345 stringptr = readline(inputline, areafile, areafilename);
11346 stringptr = findfield(stringptr);
11347 if (*stringptr ==
'\0') {
11350 area = (
REAL) strtod(stringptr, &stringptr);
11357 triangleloop.orient = 0;
11362 for (triangleloop.orient = 0; triangleloop.orient < 3;
11363 triangleloop.orient++) {
11365 aroundvertex = corner[triangleloop.orient];
11367 nexttri = vertexarray[aroundvertex -
b->firstnumber];
11369 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11371 vertexarray[aroundvertex -
b->firstnumber] =
encode(triangleloop);
11372 decode(nexttri, checktri);
11373 if (checktri.tri !=
m->dummytri) {
11374 dest(triangleloop, tdest);
11375 apex(triangleloop, tapex);
11378 dest(checktri, checkdest);
11379 apex(checktri, checkapex);
11380 if (tapex == checkdest) {
11382 lprev(triangleloop, triangleleft);
11383 bond(triangleleft, checktri);
11385 if (tdest == checkapex) {
11387 lprev(checktri, checkleft);
11388 bond(triangleloop, checkleft);
11391 nexttri = checktri.tri[6 + checktri.orient];
11392 decode(nexttri, checktri);
11393 }
while (checktri.tri !=
m->dummytri);
11412 printf(
" Marking segments in triangulation.\n");
11419 segmentnumber =
b->firstnumber;
11420 while (subsegloop.ss != (
subseg *) NULL) {
11422 end[0] = segmentlist[vertexindex++];
11423 end[1] = segmentlist[vertexindex++];
11424 if (segmentmarkers) {
11425 boundmarker = segmentmarkerlist[segmentnumber -
b->firstnumber];
11429 stringptr = readline(inputline, polyfile,
b->inpolyfilename);
11431 stringptr = findfield(stringptr);
11432 if (*stringptr ==
'\0') {
11433 printf(
"Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11437 end[0] = (
int) strtol(stringptr, &stringptr, 0);
11439 stringptr = findfield(stringptr);
11440 if (*stringptr ==
'\0') {
11441 printf(
"Error: Segment %ld is missing its second endpoint in %s.\n",
11442 segmentnumber, polyfilename);
11445 end[1] = (
int) strtol(stringptr, &stringptr, 0);
11447 if (segmentmarkers) {
11448 stringptr = findfield(stringptr);
11449 if (*stringptr ==
'\0') {
11452 boundmarker = (
int) strtol(stringptr, &stringptr, 0);
11456 for (j = 0; j < 2; j++) {
11457 if ((end[j] <
b->firstnumber) ||
11458 (end[j] >=
b->firstnumber +
m->invertices)) {
11459 printf(
"Error: Segment %ld has an invalid vertex index.\n",
11466 subsegloop.ssorient = 0;
11469 setsorg(subsegloop, segmentorg);
11470 setsdest(subsegloop, segmentdest);
11473 setmark(subsegloop, boundmarker);
11475 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11476 subsegloop.ssorient++) {
11478 aroundvertex = end[1 - subsegloop.ssorient];
11480 prevlink = &vertexarray[aroundvertex -
b->firstnumber];
11481 nexttri = vertexarray[aroundvertex -
b->firstnumber];
11482 decode(nexttri, checktri);
11483 sorg(subsegloop, shorg);
11492 while (notfound && (checktri.tri !=
m->dummytri)) {
11493 dest(checktri, checkdest);
11494 if (shorg == checkdest) {
11496 *prevlink = checktri.tri[6 + checktri.orient];
11498 tsbond(checktri, subsegloop);
11500 sym(checktri, checkneighbor);
11501 if (checkneighbor.tri ==
m->dummytri) {
11511 prevlink = &checktri.tri[6 + checktri.orient];
11512 nexttri = checktri.tri[6 + checktri.orient];
11513 decode(nexttri, checktri);
11523 for (i = 0; i <
m->vertices.items; i++) {
11525 nexttri = vertexarray[i];
11526 decode(nexttri, checktri);
11527 while (checktri.tri !=
m->dummytri) {
11530 nexttri = checktri.tri[6 + checktri.orient];
11533 sym(checktri, checkneighbor);
11534 if (checkneighbor.tri ==
m->dummytri) {
11538 decode(nexttri, checktri);
11573#ifdef ANSI_DECLARATORS
11575 struct otri *searchtri,
11581struct otri *searchtri;
11586 struct otri checktri;
11588 vertex leftvertex, rightvertex;
11589 REAL leftccw, rightccw;
11590 int leftflag, rightflag;
11593 org(*searchtri, startvertex);
11594 dest(*searchtri, rightvertex);
11595 apex(*searchtri, leftvertex);
11598 leftflag = leftccw > 0.0;
11601 rightflag = rightccw > 0.0;
11602 if (leftflag && rightflag) {
11605 onext(*searchtri, checktri);
11606 if (checktri.tri ==
m->dummytri) {
11615 if (searchtri->tri ==
m->dummytri) {
11616 printf(
"Internal error in finddirection(): Unable to find a\n");
11617 printf(
" triangle leading from (%.12g, %.12g) to", startvertex[0],
11619 printf(
" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11622 apex(*searchtri, leftvertex);
11623 rightccw = leftccw;
11625 leftflag = leftccw > 0.0;
11627 while (rightflag) {
11630 if (searchtri->tri ==
m->dummytri) {
11631 printf(
"Internal error in finddirection(): Unable to find a\n");
11632 printf(
" triangle leading from (%.12g, %.12g) to", startvertex[0],
11634 printf(
" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11637 dest(*searchtri, rightvertex);
11638 leftccw = rightccw;
11640 rightflag = rightccw > 0.0;
11642 if (leftccw == 0.0) {
11644 }
else if (rightccw == 0.0) {
11668#ifdef ANSI_DECLARATORS
11670 struct otri *splittri,
struct osub *splitsubseg,
11676struct otri *splittri;
11677struct osub *splitsubseg;
11682 struct osub opposubseg;
11685 vertex leftvertex, rightvertex;
11698 apex(*splittri, endpoint1);
11699 org(*splittri, torg);
11700 dest(*splittri, tdest);
11702 tx = tdest[0] - torg[0];
11703 ty = tdest[1] - torg[1];
11704 ex = endpoint2[0] - endpoint1[0];
11705 ey = endpoint2[1] - endpoint1[1];
11706 etx = torg[0] - endpoint2[0];
11707 ety = torg[1] - endpoint2[1];
11708 denom = ty *
ex - tx *
ey;
11709 if (denom == 0.0) {
11710 printf(
"Internal error in segmentintersection():");
11711 printf(
" Attempt to find intersection of parallel segments.\n");
11714 split = (
ey * etx -
ex * ety) / denom;
11718 for (i = 0; i < 2 +
m->nextras; i++) {
11719 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11723 if (
b->verbose > 1) {
11725 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11726 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11729 success =
insertvertex(
m,
b, newvertex, splittri, splitsubseg, 0, 0);
11731 printf(
"Internal error in segmentintersection():\n");
11732 printf(
" Failure to split a segment.\n");
11737 if (
m->steinerleft > 0) {
11743 spivot(*splitsubseg, opposubseg);
11749 }
while (splitsubseg->ss !=
m->dummysub);
11753 }
while (opposubseg.ss !=
m->dummysub);
11759 dest(*splittri, rightvertex);
11760 apex(*splittri, leftvertex);
11761 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11763 }
else if ((rightvertex[0] != endpoint1[0]) ||
11764 (rightvertex[1] != endpoint1[1])) {
11765 printf(
"Internal error in segmentintersection():\n");
11766 printf(
" Topological inconsistency after splitting a segment.\n");
11796#ifdef ANSI_DECLARATORS
11798 vertex endpoint2,
int newmark)
11803struct otri *searchtri;
11809 struct otri crosstri;
11810 struct osub crosssubseg;
11811 vertex leftvertex, rightvertex;
11816 dest(*searchtri, rightvertex);
11817 apex(*searchtri, leftvertex);
11818 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11819 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11821 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11842 lnext(*searchtri, crosstri);
11843 tspivot(crosstri, crosssubseg);
11845 if (crosssubseg.ss ==
m->dummysub) {
11880#ifdef ANSI_DECLARATORS
11881void conformingedge(
struct mesh *
m,
struct behavior *
b,
11884void conformingedge(
m,
b, endpoint1, endpoint2, newmark)
11893 struct otri searchtri1, searchtri2;
11894 struct osub brokensubseg;
11896 vertex midvertex1, midvertex2;
11901 if (
b->verbose > 2) {
11902 printf(
"Forcing segment into triangulation by recursive splitting:\n");
11903 printf(
" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11904 endpoint2[0], endpoint2[1]);
11909 for (i = 0; i < 2 +
m->nextras; i++) {
11910 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11915 searchtri1.tri =
m->dummytri;
11917 success =
insertvertex(
m,
b, newvertex, &searchtri1, (
struct osub *) NULL,
11920 if (
b->verbose > 2) {
11921 printf(
" Segment intersects existing vertex (%.12g, %.12g).\n",
11922 newvertex[0], newvertex[1]);
11926 org(searchtri1, newvertex);
11929 if (
b->verbose > 2) {
11930 printf(
" Two segments intersect at (%.12g, %.12g).\n",
11931 newvertex[0], newvertex[1]);
11934 tspivot(searchtri1, brokensubseg);
11935 success =
insertvertex(
m,
b, newvertex, &searchtri1, &brokensubseg,
11938 printf(
"Internal error in conformingedge():\n");
11939 printf(
" Failure to split a segment.\n");
11944 if (
m->steinerleft > 0) {
11958 org(searchtri1, midvertex1);
11959 conformingedge(
m,
b, midvertex1, endpoint1, newmark);
11964 org(searchtri2, midvertex2);
11965 conformingedge(
m,
b, midvertex2, endpoint2, newmark);
12010#ifdef ANSI_DECLARATORS
12012 struct otri *fixuptri,
int leftside)
12017struct otri *fixuptri;
12022 struct otri neartri;
12023 struct otri fartri;
12024 struct osub faredge;
12025 vertex nearvertex, leftvertex, rightvertex, farvertex;
12029 lnext(*fixuptri, neartri);
12030 sym(neartri, fartri);
12032 if (fartri.tri ==
m->dummytri) {
12036 if (faredge.ss !=
m->dummysub) {
12040 apex(neartri, nearvertex);
12041 org(neartri, leftvertex);
12042 dest(neartri, rightvertex);
12043 apex(fartri, farvertex);
12063 if (
incircle(
m,
b, leftvertex, farvertex, rightvertex, nearvertex) <=
12130#ifdef ANSI_DECLARATORS
12132 struct otri *starttri,
vertex endpoint2,
int newmark)
12137struct otri *starttri;
12143 struct otri fixuptri, fixuptri2;
12144 struct osub crosssubseg;
12153 org(*starttri, endpoint1);
12154 lnext(*starttri, fixuptri);
12161 org(fixuptri, farvertex);
12164 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12165 oprev(fixuptri, fixuptri2);
12178 oprev(fixuptri, fixuptri2);
12185 oprev(fixuptri, fixuptri2);
12201 tspivot(fixuptri, crosssubseg);
12202 if (crosssubseg.ss ==
m->dummysub) {
12232#ifdef ANSI_DECLARATORS
12245 struct otri searchtri1, searchtri2;
12250 if (
b->verbose > 1) {
12251 printf(
" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12252 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12256 checkvertex = (
vertex) NULL;
12258 if (encodedtri != (
triangle) NULL) {
12259 decode(encodedtri, searchtri1);
12260 org(searchtri1, checkvertex);
12262 if (checkvertex != endpoint1) {
12264 searchtri1.tri =
m->dummytri;
12265 searchtri1.orient = 0;
12270 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12271 printf(
" (%.12g, %.12g) in triangulation.\n",
12272 endpoint1[0], endpoint1[1]);
12286 org(searchtri1, endpoint1);
12289 checkvertex = (
vertex) NULL;
12291 if (encodedtri != (
triangle) NULL) {
12292 decode(encodedtri, searchtri2);
12293 org(searchtri2, checkvertex);
12295 if (checkvertex != endpoint2) {
12297 searchtri2.tri =
m->dummytri;
12298 searchtri2.orient = 0;
12303 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12304 printf(
" (%.12g, %.12g) in triangulation.\n",
12305 endpoint2[0], endpoint2[1]);
12319 org(searchtri2, endpoint2);
12325 conformingedge(
m,
b, endpoint1, endpoint2, newmark);
12344#ifdef ANSI_DECLARATORS
12353 struct otri hulltri;
12354 struct otri nexttri;
12355 struct otri starttri;
12359 hulltri.tri =
m->dummytri;
12360 hulltri.orient = 0;
12370 oprev(hulltri, nexttri);
12371 while (nexttri.tri !=
m->dummytri) {
12373 oprev(hulltri, nexttri);
12375 }
while (!
otriequal(hulltri, starttri));
12390#ifdef ANSI_DECLARATORS
12392 int *segmentmarkerlist,
int numberofsegments)
12394void formskeleton(
m,
b, segmentlist, segmentmarkerlist, numberofsegments)
12398int *segmentmarkerlist;
12399int numberofsegments;
12404#ifdef ANSI_DECLARATORS
12406 FILE *polyfile,
char *polyfilename)
12419 char polyfilename[6];
12425 vertex endpoint1, endpoint2;
12426 int segmentmarkers;
12433 printf(
"Recovering segments in Delaunay triangulation.\n");
12436 strcpy(polyfilename,
"input");
12437 m->insegments = numberofsegments;
12438 segmentmarkers = segmentmarkerlist != (
int *) NULL;
12443 stringptr = readline(inputline, polyfile, polyfilename);
12444 m->insegments = (
int) strtol(stringptr, &stringptr, 0);
12445 stringptr = findfield(stringptr);
12446 if (*stringptr ==
'\0') {
12447 segmentmarkers = 0;
12449 segmentmarkers = (
int) strtol(stringptr, &stringptr, 0);
12454 if (
m->triangles.items == 0) {
12460 if (
m->insegments > 0) {
12463 printf(
" Recovering PSLG segments.\n");
12469 for (i = 0; i <
m->insegments; i++) {
12471 end1 = segmentlist[index++];
12472 end2 = segmentlist[index++];
12473 if (segmentmarkers) {
12474 boundmarker = segmentmarkerlist[i];
12477 stringptr = readline(inputline, polyfile,
b->inpolyfilename);
12478 stringptr = findfield(stringptr);
12479 if (*stringptr ==
'\0') {
12480 printf(
"Error: Segment %d has no endpoints in %s.\n",
12481 b->firstnumber + i, polyfilename);
12484 end1 = (
int) strtol(stringptr, &stringptr, 0);
12486 stringptr = findfield(stringptr);
12487 if (*stringptr ==
'\0') {
12488 printf(
"Error: Segment %d is missing its second endpoint in %s.\n",
12489 b->firstnumber + i, polyfilename);
12492 end2 = (
int) strtol(stringptr, &stringptr, 0);
12494 if (segmentmarkers) {
12495 stringptr = findfield(stringptr);
12496 if (*stringptr ==
'\0') {
12499 boundmarker = (
int) strtol(stringptr, &stringptr, 0);
12503 if ((end1 < b->firstnumber) ||
12504 (end1 >=
b->firstnumber +
m->invertices)) {
12506 printf(
"Warning: Invalid first endpoint of segment %d in %s.\n",
12507 b->firstnumber + i, polyfilename);
12509 }
else if ((end2 < b->firstnumber) ||
12510 (end2 >=
b->firstnumber +
m->invertices)) {
12512 printf(
"Warning: Invalid second endpoint of segment %d in %s.\n",
12513 b->firstnumber + i, polyfilename);
12519 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12521 printf(
"Warning: Endpoints of segment %d are coincident in %s.\n",
12522 b->firstnumber + i, polyfilename);
12532 if (
b->convex || !
b->poly) {
12535 printf(
" Enclosing convex hull with segments.\n");
12557#ifdef ANSI_DECLARATORS
12566 struct otri hulltri;
12567 struct otri nexttri;
12568 struct otri starttri;
12569 struct osub hullsubseg;
12576 printf(
" Marking concavities (external triangles) for elimination.\n");
12579 hulltri.tri =
m->dummytri;
12580 hulltri.orient = 0;
12589 tspivot(hulltri, hullsubseg);
12590 if (hullsubseg.ss ==
m->dummysub) {
12595 *deadtriangle = hulltri.tri;
12599 if (
mark(hullsubseg) == 0) {
12601 org(hulltri, horg);
12602 dest(hulltri, hdest);
12614 oprev(hulltri, nexttri);
12615 while (nexttri.tri !=
m->dummytri) {
12617 oprev(hulltri, nexttri);
12619 }
while (!
otriequal(hulltri, starttri));
12639#ifdef ANSI_DECLARATORS
12648 struct otri testtri;
12649 struct otri neighbor;
12652 struct osub neighborsubseg;
12655 vertex deadorg, deaddest, deadapex;
12661 printf(
" Marking neighbors of marked triangles.\n");
12667 while (virusloop != (
triangle **) NULL) {
12668 testtri.tri = *virusloop;
12674 if (
b->verbose > 2) {
12677 testtri.orient = 0;
12678 org(testtri, deadorg);
12679 dest(testtri, deaddest);
12680 apex(testtri, deadapex);
12681 printf(
" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12682 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12683 deadapex[0], deadapex[1]);
12686 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12688 sym(testtri, neighbor);
12690 tspivot(testtri, neighborsubseg);
12692 if ((neighbor.tri ==
m->dummytri) ||
infected(neighbor)) {
12693 if (neighborsubseg.ss !=
m->dummysub) {
12698 if (neighbor.tri !=
m->dummytri) {
12707 if (neighborsubseg.ss ==
m->dummysub) {
12710 if (
b->verbose > 2) {
12711 org(neighbor, deadorg);
12712 dest(neighbor, deaddest);
12713 apex(neighbor, deadapex);
12715 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12716 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12717 deadapex[0], deadapex[1]);
12722 *deadtriangle = neighbor.tri;
12727 if (
mark(neighborsubseg) == 0) {
12730 org(neighbor, norg);
12731 dest(neighbor, ndest);
12748 printf(
" Deleting marked triangles.\n");
12753 while (virusloop != (
triangle **) NULL) {
12754 testtri.tri = *virusloop;
12759 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12760 org(testtri, testvertex);
12762 if (testvertex != (
vertex) NULL) {
12767 onext(testtri, neighbor);
12769 while ((neighbor.tri !=
m->dummytri) &&
12782 if (neighbor.tri ==
m->dummytri) {
12784 oprev(testtri, neighbor);
12786 while (neighbor.tri !=
m->dummytri) {
12799 if (
b->verbose > 1) {
12800 printf(
" Deleting vertex (%.12g, %.12g)\n",
12801 testvertex[0], testvertex[1]);
12811 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12812 sym(testtri, neighbor);
12813 if (neighbor.tri ==
m->dummytri) {
12849#ifdef ANSI_DECLARATORS
12861 struct otri testtri;
12862 struct otri neighbor;
12865 struct osub neighborsubseg;
12866 vertex regionorg, regiondest, regionapex;
12870 if (
b->verbose > 1) {
12871 printf(
" Marking neighbors of marked triangles.\n");
12878 while (virusloop != (
triangle **) NULL) {
12879 testtri.tri = *virusloop;
12885 if (
b->regionattrib) {
12893 if (
b->verbose > 2) {
12896 testtri.orient = 0;
12897 org(testtri, regionorg);
12898 dest(testtri, regiondest);
12899 apex(testtri, regionapex);
12900 printf(
" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12901 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12902 regionapex[0], regionapex[1]);
12905 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12907 sym(testtri, neighbor);
12909 tspivot(testtri, neighborsubseg);
12912 if ((neighbor.tri !=
m->dummytri) && !
infected(neighbor)
12913 && (neighborsubseg.ss ==
m->dummysub)) {
12914 if (
b->verbose > 2) {
12915 org(neighbor, regionorg);
12916 dest(neighbor, regiondest);
12917 apex(neighbor, regionapex);
12918 printf(
" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12919 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12920 regionapex[0], regionapex[1]);
12926 *regiontri = neighbor.tri;
12936 if (
b->verbose > 1) {
12937 printf(
" Unmarking marked triangles.\n");
12941 while (virusloop != (
triangle **) NULL) {
12942 testtri.tri = *virusloop;
12962#ifdef ANSI_DECLARATORS
12964 REAL *regionlist,
int regions)
12966void carveholes(
m,
b, holelist, holes, regionlist, regions)
12976 struct otri searchtri;
12977 struct otri triangleloop;
12978 struct otri *regiontris;
12981 vertex searchorg, searchdest;
12986 if (!(
b->quiet || (
b->noholes &&
b->convex))) {
12987 printf(
"Removing unwanted triangles.\n");
12988 if (
b->verbose && (holes > 0)) {
12989 printf(
" Marking holes for elimination.\n");
12995 regiontris = (
struct otri *)
trimalloc(regions *
12996 (
int)
sizeof(
struct otri));
12998 regiontris = (
struct otri *) NULL;
13001 if (((holes > 0) && !
b->noholes) || !
b->convex || (regions > 0)) {
13013 if ((holes > 0) && !
b->noholes) {
13015 for (i = 0; i < 2 * holes; i += 2) {
13017 if ((holelist[i] >=
m->xmin) && (holelist[i] <=
m->xmax)
13018 && (holelist[i + 1] >=
m->ymin) && (holelist[i + 1] <=
m->ymax)) {
13020 searchtri.tri =
m->dummytri;
13021 searchtri.orient = 0;
13026 org(searchtri, searchorg);
13027 dest(searchtri, searchdest);
13031 intersect =
locate(
m,
b, &holelist[i], &searchtri);
13037 *holetri = searchtri.tri;
13052 for (i = 0; i < regions; i++) {
13053 regiontris[i].tri =
m->dummytri;
13055 if ((regionlist[4 * i] >=
m->xmin) && (regionlist[4 * i] <=
m->xmax) &&
13056 (regionlist[4 * i + 1] >=
m->ymin) &&
13057 (regionlist[4 * i + 1] <=
m->ymax)) {
13059 searchtri.tri =
m->dummytri;
13060 searchtri.orient = 0;
13065 org(searchtri, searchorg);
13066 dest(searchtri, searchdest);
13070 intersect =
locate(
m,
b, ®ionlist[4 * i], &searchtri);
13074 otricopy(searchtri, regiontris[i]);
13081 if (
m->viri.items > 0) {
13089 if (
b->regionattrib) {
13091 printf(
"Spreading regional attributes and area constraints.\n");
13093 printf(
"Spreading regional attributes.\n");
13096 printf(
"Spreading regional area constraints.\n");
13099 if (
b->regionattrib && !
b->refine) {
13102 triangleloop.orient = 0;
13104 while (triangleloop.tri != (
triangle *) NULL) {
13109 for (i = 0; i < regions; i++) {
13110 if (regiontris[i].tri !=
m->dummytri) {
13113 if (!
deadtri(regiontris[i].tri)) {
13117 *regiontri = regiontris[i].tri;
13119 regionplague(
m,
b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13124 if (
b->regionattrib && !
b->refine) {
13131 if (((holes > 0) && !
b->noholes) || !
b->convex || (regions > 0)) {
13156#ifdef ANSI_DECLARATORS
13157void tallyencs(
struct mesh *
m,
struct behavior *
b)
13159void tallyencs(
m,
b)
13165 struct osub subsegloop;
13169 subsegloop.ssorient = 0;
13171 while (subsegloop.ss != (
subseg *) NULL) {
13173 dummy = checkseg4encroach(
m,
b, &subsegloop);
13188void precisionerror()
13190 printf(
"Try increasing the area criterion and/or reducing the minimum\n");
13191 printf(
" allowable angle so that tiny triangles are not created.\n");
13193 printf(
"Alternatively, try recompiling me with double precision\n");
13194 printf(
" arithmetic (by removing \"#define SINGLE\" from the\n");
13195 printf(
" source file or \"-DSINGLE\" from the makefile).\n");
13217#ifdef ANSI_DECLARATORS
13218void splitencsegs(
struct mesh *
m,
struct behavior *
b,
int triflaws)
13220void splitencsegs(
m,
b, triflaws)
13227 struct otri enctri;
13228 struct otri testtri;
13229 struct osub testsh;
13230 struct osub currentenc;
13231 struct badsubseg *encloop;
13232 vertex eorg, edest, eapex;
13235 REAL segmentlength, nearestpoweroftwo;
13237 REAL multiplier, divisor;
13238 int acuteorg, acuteorg2, acutedest, acutedest2;
13246 while ((
m->badsubsegs.items > 0) && (
m->steinerleft != 0)) {
13248 encloop = badsubsegtraverse(
m);
13249 while ((encloop != (
struct badsubseg *) NULL) && (
m->steinerleft != 0)) {
13250 sdecode(encloop->encsubseg, currentenc);
13251 sorg(currentenc, eorg);
13252 sdest(currentenc, edest);
13258 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13276 lnext(enctri, testtri);
13278 acuteorg = testsh.ss !=
m->dummysub;
13282 acutedest = testsh.ss !=
m->dummysub;
13287 if (!
b->conformdel && !acuteorg && !acutedest) {
13288 apex(enctri, eapex);
13290 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13291 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13292 deletevertex(
m,
b, &testtri);
13294 apex(enctri, eapex);
13295 lprev(enctri, testtri);
13301 sym(enctri, testtri);
13302 if (testtri.tri !=
m->dummytri) {
13306 acutedest2 = testsh.ss !=
m->dummysub;
13307 acutedest = acutedest || acutedest2;
13311 acuteorg2 = testsh.ss !=
m->dummysub;
13312 acuteorg = acuteorg || acuteorg2;
13315 if (!
b->conformdel && !acuteorg2 && !acutedest2) {
13316 org(testtri, eapex);
13318 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13319 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13320 deletevertex(
m,
b, &testtri);
13321 sym(enctri, testtri);
13322 apex(testtri, eapex);
13330 if (acuteorg || acutedest) {
13331 segmentlength =
sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13332 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13335 nearestpoweroftwo = 1.0;
13336 while (segmentlength > 3.0 * nearestpoweroftwo) {
13337 nearestpoweroftwo *= 2.0;
13339 while (segmentlength < 1.5 * nearestpoweroftwo) {
13340 nearestpoweroftwo *= 0.5;
13343 split = nearestpoweroftwo / segmentlength;
13345 split = 1.0 - split;
13356 for (i = 0; i < 2 +
m->nextras; i++) {
13357 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13365 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13366 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13367 if ((multiplier != 0.0) && (divisor != 0.0)) {
13368 multiplier = multiplier / divisor;
13370 if (multiplier == multiplier) {
13371 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13372 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13379 if (
b->verbose > 1) {
13381 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13382 eorg[0], eorg[1], edest[0], edest[1],
13383 newvertex[0], newvertex[1]);
13386 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13387 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13388 printf(
"Error: Ran out of precision at (%.12g, %.12g).\n",
13389 newvertex[0], newvertex[1]);
13390 printf(
"I attempted to split a segment to a smaller size than\n");
13391 printf(
" can be accommodated by the finite precision of\n");
13392 printf(
" floating point arithmetic.\n");
13400 printf(
"Internal error in splitencsegs():\n");
13401 printf(
" Failure to split a segment.\n");
13404 if (
m->steinerleft > 0) {
13408 dummy = checkseg4encroach(
m,
b, ¤tenc);
13410 dummy = checkseg4encroach(
m,
b, ¤tenc);
13413 badsubsegdealloc(
m, encloop);
13414 encloop = badsubsegtraverse(
m);
13429#ifdef ANSI_DECLARATORS
13430void tallyfaces(
struct mesh *
m,
struct behavior *
b)
13432void tallyfaces(
m,
b)
13438 struct otri triangleloop;
13441 printf(
" Making a list of bad triangles.\n");
13444 triangleloop.orient = 0;
13446 while (triangleloop.tri != (
triangle *) NULL) {
13448 testtriangle(
m,
b, &triangleloop);
13465#ifdef ANSI_DECLARATORS
13466void splittriangle(
struct mesh *
m,
struct behavior *
b,
13467 struct badtriang *badtri)
13469void splittriangle(
m,
b, badtri)
13472struct badtriang *badtri;
13476 struct otri badotri;
13477 vertex borg, bdest, bapex;
13484 decode(badtri->poortri, badotri);
13485 org(badotri, borg);
13486 dest(badotri, bdest);
13487 apex(badotri, bapex);
13491 if (!
deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13492 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13493 if (
b->verbose > 1) {
13494 printf(
" Splitting this triangle at its circumcenter:\n");
13495 printf(
" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13496 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13505 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13506 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13507 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13510 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13511 newvertex[0], newvertex[1]);
13516 for (i = 2; i < 2 +
m->nextras; i++) {
13518 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13519 + eta * (bapex[i] - borg[i]);
13539 success =
insertvertex(
m,
b, newvertex, &badotri, (
struct osub *) NULL,
13542 if (
m->steinerleft > 0) {
13549 if (
b->verbose > 1) {
13550 printf(
" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13561 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13562 newvertex[0], newvertex[1]);
13570 printf(
" The new vertex is at the circumcenter of triangle\n");
13571 printf(
" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13572 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13574 printf(
"This probably means that I am trying to refine triangles\n");
13575 printf(
" to a smaller size than can be accommodated by the finite\n");
13576 printf(
" precision of floating point arithmetic. (You can be\n");
13577 printf(
" sure of this if I fail to terminate.)\n");
13594#ifdef ANSI_DECLARATORS
13595void enforcequality(
struct mesh *
m,
struct behavior *
b)
13597void enforcequality(
m,
b)
13603 struct badtriang *badtri;
13607 printf(
"Adding Steiner points to enforce quality.\n");
13613 printf(
" Looking for encroached subsegments.\n");
13617 if (
b->verbose && (
m->badsubsegs.items > 0)) {
13618 printf(
" Splitting encroached subsegments.\n");
13621 splitencsegs(
m,
b, 0);
13626 if ((
b->minangle > 0.0) ||
b->vararea ||
b->fixedarea ||
b->usertest) {
13631 for (i = 0; i < 4096; i++) {
13632 m->queuefront[i] = (
struct badtriang *) NULL;
13634 m->firstnonemptyq = -1;
13640 m->checkquality = 1;
13642 printf(
" Splitting bad triangles.\n");
13644 while ((
m->badtriangles.items > 0) && (
m->steinerleft != 0)) {
13646 badtri = dequeuebadtriang(
m);
13647 splittriangle(
m,
b, badtri);
13648 if (
m->badsubsegs.items > 0) {
13650 enqueuebadtriang(
m,
b, badtri);
13653 splitencsegs(
m,
b, 1);
13665 if (!
b->quiet &&
b->conformdel && (
m->badsubsegs.items > 0) &&
13666 (
m->steinerleft == 0)) {
13667 printf(
"\nWarning: I ran out of Steiner points, but the mesh has\n");
13668 if (
m->badsubsegs.items == 1) {
13669 printf(
" one encroached subsegment, and therefore might not be truly\n"
13672 printf(
" %ld encroached subsegments, and therefore might not be truly\n"
13673 ,
m->badsubsegs.items);
13675 printf(
" Delaunay. If the Delaunay property is important to you,\n");
13676 printf(
" try increasing the number of Steiner points (controlled by\n");
13677 printf(
" the -S switch) slightly and try again.\n\n");
13693#ifdef ANSI_DECLARATORS
13702 struct otri triangleloop, trisym;
13703 struct osub checkmark;
13711 printf(
"Adding vertices for second-order triangles.\n");
13718 m->vertices.deaditemstack = (
VOID *) NULL;
13728 while (triangleloop.tri != (
triangle *) NULL) {
13729 for (triangleloop.orient = 0; triangleloop.orient < 3;
13730 triangleloop.orient++) {
13731 sym(triangleloop, trisym);
13732 if ((triangleloop.tri < trisym.tri) || (trisym.tri ==
m->dummytri)) {
13733 org(triangleloop, torg);
13734 dest(triangleloop, tdest);
13738 for (i = 0; i < 2 +
m->nextras; i++) {
13739 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13746 if (
b->usesegments) {
13747 tspivot(triangleloop, checkmark);
13749 if (checkmark.ss !=
m->dummysub) {
13754 if (
b->verbose > 1) {
13755 printf(
" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13758 triangleloop.tri[
m->highorderindex + triangleloop.orient] =
13760 if (trisym.tri !=
m->dummytri) {
13761 trisym.tri[
m->highorderindex + trisym.orient] = (
triangle) newvertex;
13784#ifdef ANSI_DECLARATORS
13785char *readline(
char *
string, FILE *infile,
char *infilename)
13787char *readline(
string, infile, infilename)
13799 if (result == (
char *) NULL) {
13800 printf(
" Error: Unexpected end of file in %s.\n", infilename);
13805 while ((*result !=
'\0') && (*result !=
'#')
13806 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
13807 && ((*result <
'0') || (*result >
'9'))) {
13811 }
while ((*result ==
'#') || (*result ==
'\0'));
13828#ifdef ANSI_DECLARATORS
13829char *findfield(
char *
string)
13831char *findfield(
string)
13840 while ((*result !=
'\0') && (*result !=
'#')
13841 && (*result !=
' ') && (*result !=
'\t')) {
13846 while ((*result !=
'\0') && (*result !=
'#')
13847 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
13848 && ((*result <
'0') || (*result >
'9'))) {
13852 if (*result ==
'#') {
13869#ifdef ANSI_DECLARATORS
13870void readnodes(
struct mesh *
m,
struct behavior *
b,
char *nodefilename,
13871 char *polyfilename, FILE **polyfile)
13873void readnodes(
m,
b, nodefilename, polyfilename, polyfile)
13896 printf(
"Opening %s.\n", polyfilename);
13898 *polyfile = fopen(polyfilename,
"r");
13899 if (*polyfile == (FILE *) NULL) {
13900 printf(
" Error: Cannot access file %s.\n", polyfilename);
13905 stringptr = readline(inputline, *polyfile, polyfilename);
13906 m->invertices = (
int) strtol(stringptr, &stringptr, 0);
13907 stringptr = findfield(stringptr);
13908 if (*stringptr ==
'\0') {
13911 m->mesh_dim = (
int) strtol(stringptr, &stringptr, 0);
13913 stringptr = findfield(stringptr);
13914 if (*stringptr ==
'\0') {
13917 m->nextras = (
int) strtol(stringptr, &stringptr, 0);
13919 stringptr = findfield(stringptr);
13920 if (*stringptr ==
'\0') {
13923 nodemarkers = (
int) strtol(stringptr, &stringptr, 0);
13925 if (
m->invertices > 0) {
13926 infile = *polyfile;
13927 infilename = polyfilename;
13928 m->readnodefile = 0;
13932 m->readnodefile = 1;
13933 infilename = nodefilename;
13936 m->readnodefile = 1;
13937 infilename = nodefilename;
13938 *polyfile = (FILE *) NULL;
13941 if (
m->readnodefile) {
13944 printf(
"Opening %s.\n", nodefilename);
13946 infile = fopen(nodefilename,
"r");
13947 if (infile == (FILE *) NULL) {
13948 printf(
" Error: Cannot access file %s.\n", nodefilename);
13953 stringptr = readline(inputline, infile, nodefilename);
13954 m->invertices = (
int) strtol(stringptr, &stringptr, 0);
13955 stringptr = findfield(stringptr);
13956 if (*stringptr ==
'\0') {
13959 m->mesh_dim = (
int) strtol(stringptr, &stringptr, 0);
13961 stringptr = findfield(stringptr);
13962 if (*stringptr ==
'\0') {
13965 m->nextras = (
int) strtol(stringptr, &stringptr, 0);
13967 stringptr = findfield(stringptr);
13968 if (*stringptr ==
'\0') {
13971 nodemarkers = (
int) strtol(stringptr, &stringptr, 0);
13975 if (
m->invertices < 3) {
13976 printf(
"Error: Input must have at least three input vertices.\n");
13979 if (
m->mesh_dim != 2) {
13980 printf(
"Error: Triangle only works with two-dimensional meshes.\n");
13983 if (
m->nextras == 0) {
13990 for (i = 0; i <
m->invertices; i++) {
13992 stringptr = readline(inputline, infile, infilename);
13994 firstnode = (
int) strtol(stringptr, &stringptr, 0);
13995 if ((firstnode == 0) || (firstnode == 1)) {
13996 b->firstnumber = firstnode;
13999 stringptr = findfield(stringptr);
14000 if (*stringptr ==
'\0') {
14001 printf(
"Error: Vertex %d has no x coordinate.\n",
b->firstnumber + i);
14004 x = (
REAL) strtod(stringptr, &stringptr);
14005 stringptr = findfield(stringptr);
14006 if (*stringptr ==
'\0') {
14007 printf(
"Error: Vertex %d has no y coordinate.\n",
b->firstnumber + i);
14010 y = (
REAL) strtod(stringptr, &stringptr);
14014 for (j = 2; j < 2 +
m->nextras; j++) {
14015 stringptr = findfield(stringptr);
14016 if (*stringptr ==
'\0') {
14017 vertexloop[j] = 0.0;
14019 vertexloop[j] = (
REAL) strtod(stringptr, &stringptr);
14024 stringptr = findfield(stringptr);
14025 if (*stringptr ==
'\0') {
14028 currentmarker = (
int) strtol(stringptr, &stringptr, 0);
14038 m->xmin =
m->xmax =
x;
14039 m->ymin =
m->ymax =
y;
14047 if (
m->readnodefile) {
14053 m->xminextreme = 10 *
m->xmin - 9 *
m->xmax;
14066#ifdef ANSI_DECLARATORS
14068 REAL *pointattriblist,
int *pointmarkerlist,
14069 int numberofpoints,
int numberofpointattribs)
14072 numberofpoints, numberofpointattribs)
14076REAL *pointattriblist;
14077int *pointmarkerlist;
14079int numberofpointattribs;
14089 m->invertices = numberofpoints;
14091 m->nextras = numberofpointattribs;
14092 m->readnodefile = 0;
14093 if (
m->invertices < 3) {
14094 printf(
"Error: Input must have at least three input vertices.\n");
14097 if (
m->nextras == 0) {
14106 for (i = 0; i <
m->invertices; i++) {
14109 x = vertexloop[0] = pointlist[coordindex++];
14110 y = vertexloop[1] = pointlist[coordindex++];
14112 for (j = 0; j < numberofpointattribs; j++) {
14113 vertexloop[2 + j] = pointattriblist[attribindex++];
14115 if (pointmarkerlist != (
int *) NULL) {
14125 m->xmin =
m->xmax =
x;
14126 m->ymin =
m->ymax =
y;
14128 m->xmin = (
x <
m->xmin) ?
x :
m->xmin;
14129 m->xmax = (
x >
m->xmax) ?
x :
m->xmax;
14130 m->ymin = (
y <
m->ymin) ?
y :
m->ymin;
14131 m->ymax = (
y >
m->ymax) ?
y :
m->ymax;
14137 m->xminextreme = 10 *
m->xmin - 9 *
m->xmax;
14151#ifdef ANSI_DECLARATORS
14152void readholes(
struct mesh *
m,
struct behavior *
b,
14153 FILE *polyfile,
char *polyfilename,
REAL **hlist,
int *holes,
14154 REAL **rlist,
int *regions)
14156void readholes(
m,
b, polyfile, polyfilename, hlist, holes, rlist, regions)
14176 stringptr = readline(inputline, polyfile, polyfilename);
14177 *holes = (
int) strtol(stringptr, &stringptr, 0);
14181 for (i = 0; i < 2 * *holes; i += 2) {
14182 stringptr = readline(inputline, polyfile, polyfilename);
14183 stringptr = findfield(stringptr);
14184 if (*stringptr ==
'\0') {
14185 printf(
"Error: Hole %d has no x coordinate.\n",
14186 b->firstnumber + (i >> 1));
14189 holelist[i] = (
REAL) strtod(stringptr, &stringptr);
14191 stringptr = findfield(stringptr);
14192 if (*stringptr ==
'\0') {
14193 printf(
"Error: Hole %d has no y coordinate.\n",
14194 b->firstnumber + (i >> 1));
14197 holelist[i + 1] = (
REAL) strtod(stringptr, &stringptr);
14201 *hlist = (
REAL *) NULL;
14205 if ((
b->regionattrib ||
b->vararea) && !
b->refine) {
14207 stringptr = readline(inputline, polyfile, polyfilename);
14208 *regions = (
int) strtol(stringptr, &stringptr, 0);
14209 if (*regions > 0) {
14211 *rlist = regionlist;
14213 for (i = 0; i < *regions; i++) {
14214 stringptr = readline(inputline, polyfile, polyfilename);
14215 stringptr = findfield(stringptr);
14216 if (*stringptr ==
'\0') {
14217 printf(
"Error: Region %d has no x coordinate.\n",
14218 b->firstnumber + i);
14221 regionlist[index++] = (
REAL) strtod(stringptr, &stringptr);
14223 stringptr = findfield(stringptr);
14224 if (*stringptr ==
'\0') {
14225 printf(
"Error: Region %d has no y coordinate.\n",
14226 b->firstnumber + i);
14229 regionlist[index++] = (
REAL) strtod(stringptr, &stringptr);
14231 stringptr = findfield(stringptr);
14232 if (*stringptr ==
'\0') {
14234 "Error: Region %d has no region attribute or area constraint.\n",
14235 b->firstnumber + i);
14238 regionlist[index++] = (
REAL) strtod(stringptr, &stringptr);
14240 stringptr = findfield(stringptr);
14241 if (*stringptr ==
'\0') {
14242 regionlist[index] = regionlist[index - 1];
14244 regionlist[index] = (
REAL) strtod(stringptr, &stringptr);
14252 *rlist = (
REAL *) NULL;
14270#ifdef ANSI_DECLARATORS
14271void finishfile(FILE *outfile,
int argc,
char **argv)
14273void finishfile(outfile, argc, argv)
14282 fprintf(outfile,
"# Generated by");
14283 for (i = 0; i < argc; i++) {
14284 fprintf(outfile,
" ");
14285 fputs(argv[i], outfile);
14287 fprintf(outfile,
"\n");
14304#ifdef ANSI_DECLARATORS
14306 REAL **pointattriblist,
int **pointmarkerlist)
14308void writenodes(
m,
b, pointlist, pointattriblist, pointmarkerlist)
14312REAL **pointattriblist;
14313int **pointmarkerlist;
14318#ifdef ANSI_DECLARATORS
14319void writenodes(
struct mesh *
m,
struct behavior *
b,
char *nodefilename,
14320 int argc,
char **argv)
14348 outvertices =
m->vertices.items -
m->undeads;
14350 outvertices =
m->vertices.items;
14355 printf(
"Writing vertices.\n");
14358 if (*pointlist == (
REAL *) NULL) {
14362 if ((
m->nextras > 0) && (*pointattriblist == (
REAL *) NULL)) {
14363 *pointattriblist = (
REAL *)
trimalloc((
int) (outvertices *
m->nextras *
14367 if (!
b->nobound && (*pointmarkerlist == (
int *) NULL)) {
14368 *pointmarkerlist = (
int *)
trimalloc((
int) (outvertices *
sizeof(
int)));
14370 plist = *pointlist;
14371 palist = *pointattriblist;
14372 pmlist = *pointmarkerlist;
14377 printf(
"Writing %s.\n", nodefilename);
14379 outfile = fopen(nodefilename,
"w");
14380 if (outfile == (FILE *) NULL) {
14381 printf(
" Error: Cannot create file %s.\n", nodefilename);
14386 fprintf(outfile,
"%ld %d %d %d\n", outvertices,
m->mesh_dim,
14387 m->nextras, 1 -
b->nobound);
14391 vertexnumber =
b->firstnumber;
14393 while (vertexloop != (
vertex) NULL) {
14397 plist[coordindex++] = vertexloop[0];
14398 plist[coordindex++] = vertexloop[1];
14400 for (i = 0; i <
m->nextras; i++) {
14401 palist[attribindex++] = vertexloop[2 + i];
14405 pmlist[vertexnumber -
b->firstnumber] =
vertexmark(vertexloop);
14409 fprintf(outfile,
"%4d %.17g %.17g", vertexnumber, vertexloop[0],
14411 for (i = 0; i <
m->nextras; i++) {
14413 fprintf(outfile,
" %.17g", vertexloop[i + 2]);
14416 fprintf(outfile,
"\n");
14419 fprintf(outfile,
" %d\n",
vertexmark(vertexloop));
14430 finishfile(outfile, argc, argv);
14444#ifdef ANSI_DECLARATORS
14457 vertexnumber =
b->firstnumber;
14459 while (vertexloop != (
vertex) NULL) {
14476#ifdef ANSI_DECLARATORS
14478 int **trianglelist,
REAL **triangleattriblist)
14484REAL **triangleattriblist;
14489#ifdef ANSI_DECLARATORS
14490void writeelements(
struct mesh *
m,
struct behavior *
b,
char *elefilename,
14491 int argc,
char **argv)
14512 struct otri triangleloop;
14514 vertex mid1, mid2, mid3;
14515 long elementnumber;
14520 printf(
"Writing triangles.\n");
14523 if (*trianglelist == (
int *) NULL) {
14524 *trianglelist = (
int *)
trimalloc((
int) (
m->triangles.items *
14525 ((
b->order + 1) * (
b->order + 2) /
14526 2) *
sizeof(
int)));
14529 if ((
m->eextras > 0) && (*triangleattriblist == (
REAL *) NULL)) {
14530 *triangleattriblist = (
REAL *)
trimalloc((
int) (
m->triangles.items *
14534 tlist = *trianglelist;
14535 talist = *triangleattriblist;
14540 printf(
"Writing %s.\n", elefilename);
14542 outfile = fopen(elefilename,
"w");
14543 if (outfile == (FILE *) NULL) {
14544 printf(
" Error: Cannot create file %s.\n", elefilename);
14548 fprintf(outfile,
"%ld %d %d\n",
m->triangles.items,
14549 (
b->order + 1) * (
b->order + 2) / 2,
m->eextras);
14554 triangleloop.orient = 0;
14555 elementnumber =
b->firstnumber;
14556 while (triangleloop.tri != (
triangle *) NULL) {
14557 org(triangleloop, p1);
14558 dest(triangleloop, p2);
14559 apex(triangleloop, p3);
14560 if (
b->order == 1) {
14567 fprintf(outfile,
"%4ld %4d %4d %4d", elementnumber,
14571 mid1 = (
vertex) triangleloop.tri[
m->highorderindex + 1];
14572 mid2 = (
vertex) triangleloop.tri[
m->highorderindex + 2];
14573 mid3 = (
vertex) triangleloop.tri[
m->highorderindex];
14583 fprintf(outfile,
"%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14590 for (i = 0; i <
m->eextras; i++) {
14594 for (i = 0; i <
m->eextras; i++) {
14595 fprintf(outfile,
" %.17g",
elemattribute(triangleloop, i));
14597 fprintf(outfile,
"\n");
14605 finishfile(outfile, argc, argv);
14617#ifdef ANSI_DECLARATORS
14619 int **segmentlist,
int **segmentmarkerlist)
14621void writepoly(
m,
b, segmentlist, segmentmarkerlist)
14625int **segmentmarkerlist;
14630#ifdef ANSI_DECLARATORS
14631void writepoly(
struct mesh *
m,
struct behavior *
b,
char *polyfilename,
14632 REAL *holelist,
int holes,
REAL *regionlist,
int regions,
14633 int argc,
char **argv)
14635void writepoly(
m,
b, polyfilename, holelist, holes, regionlist, regions,
14657 long holenumber, regionnumber;
14659 struct osub subsegloop;
14660 vertex endpoint1, endpoint2;
14665 printf(
"Writing segments.\n");
14668 if (*segmentlist == (
int *) NULL) {
14669 *segmentlist = (
int *)
trimalloc((
int) (
m->subsegs.items * 2 *
14673 if (!
b->nobound && (*segmentmarkerlist == (
int *) NULL)) {
14674 *segmentmarkerlist = (
int *)
trimalloc((
int) (
m->subsegs.items *
14677 slist = *segmentlist;
14678 smlist = *segmentmarkerlist;
14682 printf(
"Writing %s.\n", polyfilename);
14684 outfile = fopen(polyfilename,
"w");
14685 if (outfile == (FILE *) NULL) {
14686 printf(
" Error: Cannot create file %s.\n", polyfilename);
14692 fprintf(outfile,
"%d %d %d %d\n", 0,
m->mesh_dim,
m->nextras,
14695 fprintf(outfile,
"%ld %d\n",
m->subsegs.items, 1 -
b->nobound);
14700 subsegloop.ssorient = 0;
14701 subsegnumber =
b->firstnumber;
14702 while (subsegloop.ss != (
subseg *) NULL) {
14703 sorg(subsegloop, endpoint1);
14704 sdest(subsegloop, endpoint2);
14711 smlist[subsegnumber -
b->firstnumber] =
mark(subsegloop);
14716 fprintf(outfile,
"%4ld %4d %4d\n", subsegnumber,
14719 fprintf(outfile,
"%4ld %4d %4d %4d\n", subsegnumber,
14730 fprintf(outfile,
"%d\n", holes);
14732 for (holenumber = 0; holenumber < holes; holenumber++) {
14734 fprintf(outfile,
"%4ld %.17g %.17g\n",
b->firstnumber + holenumber,
14735 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14739 fprintf(outfile,
"%d\n", regions);
14740 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14742 fprintf(outfile,
"%4ld %.17g %.17g %.17g %.17g\n",
14743 b->firstnumber + regionnumber,
14744 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14745 regionlist[4 * regionnumber + 2],
14746 regionlist[4 * regionnumber + 3]);
14751 finishfile(outfile, argc, argv);
14763#ifdef ANSI_DECLARATORS
14765 int **edgelist,
int **edgemarkerlist)
14771int **edgemarkerlist;
14776#ifdef ANSI_DECLARATORS
14777void writeedges(
struct mesh *
m,
struct behavior *
b,
char *edgefilename,
14778 int argc,
char **argv)
14798 struct otri triangleloop, trisym;
14799 struct osub checkmark;
14807 printf(
"Writing edges.\n");
14810 if (*edgelist == (
int *) NULL) {
14811 *edgelist = (
int *)
trimalloc((
int) (
m->edges * 2 *
sizeof(
int)));
14814 if (!
b->nobound && (*edgemarkerlist == (
int *) NULL)) {
14815 *edgemarkerlist = (
int *)
trimalloc((
int) (
m->edges *
sizeof(
int)));
14818 emlist = *edgemarkerlist;
14822 printf(
"Writing %s.\n", edgefilename);
14824 outfile = fopen(edgefilename,
"w");
14825 if (outfile == (FILE *) NULL) {
14826 printf(
" Error: Cannot create file %s.\n", edgefilename);
14830 fprintf(outfile,
"%ld %d\n",
m->edges, 1 -
b->nobound);
14835 edgenumber =
b->firstnumber;
14842 while (triangleloop.tri != (
triangle *) NULL) {
14843 for (triangleloop.orient = 0; triangleloop.orient < 3;
14844 triangleloop.orient++) {
14845 sym(triangleloop, trisym);
14846 if ((triangleloop.tri < trisym.tri) || (trisym.tri ==
m->dummytri)) {
14847 org(triangleloop, p1);
14848 dest(triangleloop, p2);
14856 fprintf(outfile,
"%4ld %d %d\n", edgenumber,
14862 if (
b->usesegments) {
14863 tspivot(triangleloop, checkmark);
14864 if (checkmark.ss ==
m->dummysub) {
14866 emlist[edgenumber -
b->firstnumber] = 0;
14868 fprintf(outfile,
"%4ld %d %d %d\n", edgenumber,
14873 emlist[edgenumber -
b->firstnumber] =
mark(checkmark);
14875 fprintf(outfile,
"%4ld %d %d %d\n", edgenumber,
14881 emlist[edgenumber -
b->firstnumber] = trisym.tri ==
m->dummytri;
14883 fprintf(outfile,
"%4ld %d %d %d\n", edgenumber,
14895 finishfile(outfile, argc, argv);
14917#ifdef ANSI_DECLARATORS
14919 REAL **vpointattriblist,
int **vpointmarkerlist,
14920 int **vedgelist,
int **vedgemarkerlist,
REAL **vnormlist)
14922void writevoronoi(
m,
b, vpointlist, vpointattriblist, vpointmarkerlist,
14923 vedgelist, vedgemarkerlist, vnormlist)
14927REAL **vpointattriblist;
14928int **vpointmarkerlist;
14930int **vedgemarkerlist;
14936#ifdef ANSI_DECLARATORS
14937void writevoronoi(
struct mesh *
m,
struct behavior *
b,
char *vnodefilename,
14938 char *vedgefilename,
int argc,
char **argv)
14940void writevoronoi(
m,
b, vnodefilename, vedgefilename, argc, argv)
14943char *vnodefilename;
14944char *vedgefilename;
14962 struct otri triangleloop, trisym;
14963 vertex torg, tdest, tapex;
14964 REAL circumcenter[2];
14966 long vnodenumber, vedgenumber;
14973 printf(
"Writing Voronoi vertices.\n");
14976 if (*vpointlist == (
REAL *) NULL) {
14977 *vpointlist = (
REAL *)
trimalloc((
int) (
m->triangles.items * 2 *
14981 if (*vpointattriblist == (
REAL *) NULL) {
14982 *vpointattriblist = (
REAL *)
trimalloc((
int) (
m->triangles.items *
14983 m->nextras *
sizeof(
REAL)));
14985 *vpointmarkerlist = (
int *) NULL;
14986 plist = *vpointlist;
14987 palist = *vpointattriblist;
14992 printf(
"Writing %s.\n", vnodefilename);
14994 outfile = fopen(vnodefilename,
"w");
14995 if (outfile == (FILE *) NULL) {
14996 printf(
" Error: Cannot create file %s.\n", vnodefilename);
15001 fprintf(outfile,
"%ld %d %d %d\n",
m->triangles.items, 2,
m->nextras, 0);
15006 triangleloop.orient = 0;
15007 vnodenumber =
b->firstnumber;
15008 while (triangleloop.tri != (
triangle *) NULL) {
15009 org(triangleloop, torg);
15010 dest(triangleloop, tdest);
15011 apex(triangleloop, tapex);
15015 plist[coordindex++] = circumcenter[0];
15016 plist[coordindex++] = circumcenter[1];
15017 for (i = 2; i < 2 +
m->nextras; i++) {
15019 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15020 + eta * (tapex[i] - torg[i]);
15024 fprintf(outfile,
"%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15026 for (i = 2; i < 2 +
m->nextras; i++) {
15028 fprintf(outfile,
" %.17g", torg[i] + xi * (tdest[i] - torg[i])
15029 + eta * (tapex[i] - torg[i]));
15031 fprintf(outfile,
"\n");
15034 * (
int *) (triangleloop.tri + 6) = (
int) vnodenumber;
15040 finishfile(outfile, argc, argv);
15045 printf(
"Writing Voronoi edges.\n");
15048 if (*vedgelist == (
int *) NULL) {
15049 *vedgelist = (
int *)
trimalloc((
int) (
m->edges * 2 *
sizeof(
int)));
15051 *vedgemarkerlist = (
int *) NULL;
15053 if (*vnormlist == (
REAL *) NULL) {
15056 elist = *vedgelist;
15057 normlist = *vnormlist;
15061 printf(
"Writing %s.\n", vedgefilename);
15063 outfile = fopen(vedgefilename,
"w");
15064 if (outfile == (FILE *) NULL) {
15065 printf(
" Error: Cannot create file %s.\n", vedgefilename);
15069 fprintf(outfile,
"%ld %d\n",
m->edges, 0);
15074 vedgenumber =
b->firstnumber;
15081 while (triangleloop.tri != (
triangle *) NULL) {
15082 for (triangleloop.orient = 0; triangleloop.orient < 3;
15083 triangleloop.orient++) {
15084 sym(triangleloop, trisym);
15085 if ((triangleloop.tri < trisym.tri) || (trisym.tri ==
m->dummytri)) {
15087 p1 = * (
int *) (triangleloop.tri + 6);
15088 if (trisym.tri ==
m->dummytri) {
15089 org(triangleloop, torg);
15090 dest(triangleloop, tdest);
15093 elist[coordindex] = p1;
15094 normlist[coordindex++] = tdest[1] - torg[1];
15095 elist[coordindex] = -1;
15096 normlist[coordindex++] = torg[0] - tdest[0];
15101 fprintf(outfile,
"%4ld %d %d %.17g %.17g\n", vedgenumber,
15102 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15106 p2 = * (
int *) (trisym.tri + 6);
15109 elist[coordindex] = p1;
15110 normlist[coordindex++] = 0.0;
15111 elist[coordindex] = p2;
15112 normlist[coordindex++] = 0.0;
15114 fprintf(outfile,
"%4ld %d %d\n", vedgenumber, p1, p2);
15124 finishfile(outfile, argc, argv);
15130#ifdef ANSI_DECLARATORS
15141#ifdef ANSI_DECLARATORS
15142void writeneighbors(
struct mesh *
m,
struct behavior *
b,
char *neighborfilename,
15143 int argc,
char **argv)
15148char *neighborfilename;
15162 struct otri triangleloop, trisym;
15163 long elementnumber;
15164 int neighbor1, neighbor2, neighbor3;
15169 printf(
"Writing neighbors.\n");
15172 if (*neighborlist == (
int *) NULL) {
15173 *neighborlist = (
int *)
trimalloc((
int) (
m->triangles.items * 3 *
15176 nlist = *neighborlist;
15180 printf(
"Writing %s.\n", neighborfilename);
15182 outfile = fopen(neighborfilename,
"w");
15183 if (outfile == (FILE *) NULL) {
15184 printf(
" Error: Cannot create file %s.\n", neighborfilename);
15188 fprintf(outfile,
"%ld %d\n",
m->triangles.items, 3);
15193 triangleloop.orient = 0;
15194 elementnumber =
b->firstnumber;
15195 while (triangleloop.tri != (
triangle *) NULL) {
15196 * (
int *) (triangleloop.tri + 6) = (
int) elementnumber;
15200 * (
int *) (
m->dummytri + 6) = -1;
15204 elementnumber =
b->firstnumber;
15205 while (triangleloop.tri != (
triangle *) NULL) {
15206 triangleloop.orient = 1;
15207 sym(triangleloop, trisym);
15208 neighbor1 = * (
int *) (trisym.tri + 6);
15209 triangleloop.orient = 2;
15210 sym(triangleloop, trisym);
15211 neighbor2 = * (
int *) (trisym.tri + 6);
15212 triangleloop.orient = 0;
15213 sym(triangleloop, trisym);
15214 neighbor3 = * (
int *) (trisym.tri + 6);
15216 nlist[index++] = neighbor1;
15217 nlist[index++] = neighbor2;
15218 nlist[index++] = neighbor3;
15221 fprintf(outfile,
"%4ld %d %d %d\n", elementnumber,
15222 neighbor1, neighbor2, neighbor3);
15230 finishfile(outfile, argc, argv);
15245#ifdef ANSI_DECLARATORS
15246void writeoff(
struct mesh *
m,
struct behavior *
b,
char *offfilename,
15247 int argc,
char **argv)
15249void writeoff(
m,
b, offfilename, argc, argv)
15259 struct otri triangleloop;
15265 printf(
"Writing %s.\n", offfilename);
15269 outvertices =
m->vertices.items -
m->undeads;
15271 outvertices =
m->vertices.items;
15274 outfile = fopen(offfilename,
"w");
15275 if (outfile == (FILE *) NULL) {
15276 printf(
" Error: Cannot create file %s.\n", offfilename);
15280 fprintf(outfile,
"OFF\n%ld %ld %ld\n", outvertices,
m->triangles.items,
15286 while (vertexloop != (
vertex) NULL) {
15289 fprintf(outfile,
" %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15298 triangleloop.orient = 0;
15299 while (triangleloop.tri != (
triangle *) NULL) {
15300 org(triangleloop, p1);
15301 dest(triangleloop, p2);
15302 apex(triangleloop, p3);
15304 fprintf(outfile,
" 3 %4d %4d %4d\n",
vertexmark(p1) -
b->firstnumber,
15308 finishfile(outfile, argc, argv);
15323#ifdef ANSI_DECLARATORS
15332 struct otri triangleloop;
15334 REAL cossquaretable[8];
15335 REAL ratiotable[16];
15337 REAL edgelength[3];
15341 REAL shortest, longest;
15343 REAL smallestarea, biggestarea;
15344 REAL triminaltitude2;
15348 REAL smallestangle, biggestangle;
15349 REAL radconst, degconst;
15350 int angletable[18];
15351 int aspecttable[16];
15357 printf(
"Mesh quality statistics:\n\n");
15358 radconst =
PI / 18.0;
15359 degconst = 180.0 /
PI;
15360 for (i = 0; i < 8; i++) {
15361 cossquaretable[i] =
cos(radconst * (
REAL) (i + 1));
15362 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15364 for (i = 0; i < 18; i++) {
15368 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15369 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15370 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15371 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15372 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15373 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15374 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15375 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15376 for (i = 0; i < 16; i++) {
15377 aspecttable[i] = 0;
15381 minaltitude =
m->xmax -
m->xmin +
m->ymax -
m->ymin;
15382 minaltitude = minaltitude * minaltitude;
15383 shortest = minaltitude;
15385 smallestarea = minaltitude;
15388 smallestangle = 0.0;
15389 biggestangle = 2.0;
15394 triangleloop.orient = 0;
15395 while (triangleloop.tri != (
triangle *) NULL) {
15396 org(triangleloop, p[0]);
15397 dest(triangleloop, p[1]);
15398 apex(triangleloop, p[2]);
15401 for (i = 0; i < 3; i++) {
15404 dx[i] = p[j][0] - p[k][0];
15405 dy[i] = p[j][1] - p[k][1];
15406 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15407 if (edgelength[i] > trilongest2) {
15408 trilongest2 = edgelength[i];
15410 if (edgelength[i] > longest) {
15411 longest = edgelength[i];
15413 if (edgelength[i] < shortest) {
15414 shortest = edgelength[i];
15419 if (triarea < smallestarea) {
15420 smallestarea = triarea;
15422 if (triarea > biggestarea) {
15423 biggestarea = triarea;
15425 triminaltitude2 = triarea * triarea / trilongest2;
15426 if (triminaltitude2 < minaltitude) {
15427 minaltitude = triminaltitude2;
15429 triaspect2 = trilongest2 / triminaltitude2;
15430 if (triaspect2 > worstaspect) {
15431 worstaspect = triaspect2;
15434 while ((aspectindex < 15) &&
15435 (triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15439 aspecttable[aspectindex]++;
15441 for (i = 0; i < 3; i++) {
15444 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15445 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15447 for (ii = 7; ii >= 0; ii--) {
15448 if (cossquare > cossquaretable[ii]) {
15452 if (dotproduct <= 0.0) {
15453 angletable[tendegree]++;
15454 if (cossquare > smallestangle) {
15455 smallestangle = cossquare;
15457 if (acutebiggest && (cossquare < biggestangle)) {
15458 biggestangle = cossquare;
15461 angletable[17 - tendegree]++;
15462 if (acutebiggest || (cossquare > biggestangle)) {
15463 biggestangle = cossquare;
15471 shortest =
sqrt(shortest);
15472 longest =
sqrt(longest);
15473 minaltitude =
sqrt(minaltitude);
15474 worstaspect =
sqrt(worstaspect);
15475 smallestarea *= 0.5;
15476 biggestarea *= 0.5;
15477 if (smallestangle >= 1.0) {
15478 smallestangle = 0.0;
15480 smallestangle = degconst *
acos(
sqrt(smallestangle));
15482 if (biggestangle >= 1.0) {
15483 biggestangle = 180.0;
15485 if (acutebiggest) {
15486 biggestangle = degconst *
acos(
sqrt(biggestangle));
15488 biggestangle = 180.0 - degconst *
acos(
sqrt(biggestangle));
15492 printf(
" Smallest area: %16.5g | Largest area: %16.5g\n",
15493 smallestarea, biggestarea);
15494 printf(
" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15495 shortest, longest);
15496 printf(
" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15497 minaltitude, worstaspect);
15499 printf(
" Triangle aspect ratio histogram:\n");
15500 printf(
" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15501 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15503 for (i = 1; i < 7; i++) {
15504 printf(
" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15505 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15506 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15508 printf(
" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15509 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15511 printf(
" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15513 printf(
" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15514 smallestangle, biggestangle);
15516 printf(
" Angle histogram:\n");
15517 for (i = 0; i < 9; i++) {
15518 printf(
" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15519 i * 10, i * 10 + 10, angletable[i],
15520 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15531#ifdef ANSI_DECLARATORS
15540 printf(
"\nStatistics:\n\n");
15541 printf(
" Input vertices: %d\n",
m->invertices);
15543 printf(
" Input triangles: %d\n",
m->inelements);
15546 printf(
" Input segments: %d\n",
m->insegments);
15548 printf(
" Input holes: %d\n",
m->holes);
15552 printf(
"\n Mesh vertices: %ld\n",
m->vertices.items -
m->undeads);
15553 printf(
" Mesh triangles: %ld\n",
m->triangles.items);
15554 printf(
" Mesh edges: %ld\n",
m->edges);
15555 printf(
" Mesh exterior boundary edges: %ld\n",
m->hullsize);
15556 if (
b->poly ||
b->refine) {
15557 printf(
" Mesh interior boundary edges: %ld\n",
15558 m->subsegs.items -
m->hullsize);
15559 printf(
" Mesh subsegments (constrained edges): %ld\n",
15566 printf(
"Memory allocation statistics:\n\n");
15567 printf(
" Maximum number of vertices: %ld\n",
m->vertices.maxitems);
15568 printf(
" Maximum number of triangles: %ld\n",
m->triangles.maxitems);
15569 if (
m->subsegs.maxitems > 0) {
15570 printf(
" Maximum number of subsegments: %ld\n",
m->subsegs.maxitems);
15572 if (
m->viri.maxitems > 0) {
15573 printf(
" Maximum number of viri: %ld\n",
m->viri.maxitems);
15575 if (
m->badsubsegs.maxitems > 0) {
15576 printf(
" Maximum number of encroached subsegments: %ld\n",
15577 m->badsubsegs.maxitems);
15579 if (
m->badtriangles.maxitems > 0) {
15580 printf(
" Maximum number of bad triangles: %ld\n",
15581 m->badtriangles.maxitems);
15583 if (
m->flipstackers.maxitems > 0) {
15584 printf(
" Maximum number of stacked triangle flips: %ld\n",
15585 m->flipstackers.maxitems);
15587 if (
m->splaynodes.maxitems > 0) {
15588 printf(
" Maximum number of splay tree nodes: %ld\n",
15589 m->splaynodes.maxitems);
15591 printf(
" Approximate heap memory use (bytes): %ld\n\n",
15592 m->vertices.maxitems *
m->vertices.itembytes +
15593 m->triangles.maxitems *
m->triangles.itembytes +
15594 m->subsegs.maxitems *
m->subsegs.itembytes +
15595 m->viri.maxitems *
m->viri.itembytes +
15596 m->badsubsegs.maxitems *
m->badsubsegs.itembytes +
15597 m->badtriangles.maxitems *
m->badtriangles.itembytes +
15598 m->flipstackers.maxitems *
m->flipstackers.itembytes +
15599 m->splaynodes.maxitems *
m->splaynodes.itembytes);
15601 printf(
"Algorithmic statistics:\n\n");
15602 if (!
b->weighted) {
15603 printf(
" Number of incircle tests: %ld\n",
m->incirclecount);
15605 printf(
" Number of 3D orientation tests: %ld\n",
m->orient3dcount);
15607 printf(
" Number of 2D orientation tests: %ld\n",
m->counterclockcount);
15608 if (
m->hyperbolacount > 0) {
15609 printf(
" Number of right-of-hyperbola tests: %ld\n",
15610 m->hyperbolacount);
15612 if (
m->circletopcount > 0) {
15613 printf(
" Number of circle top computations: %ld\n",
15614 m->circletopcount);
15616 if (
m->circumcentercount > 0) {
15617 printf(
" Number of triangle circumcenter computations: %ld\n",
15618 m->circumcentercount);
15651#ifdef ANSI_DECLARATORS
15664#ifdef ANSI_DECLARATORS
15665int main(
int argc,
char **argv)
15667int main(argc, argv)
15685 struct timeval tv0,
tv1,
tv2,
tv3, tv4, tv5, tv6;
15686 struct timezone tz;
15690 gettimeofday(&tv0, &tz);
15699 m.steinerleft =
b.steiner;
15706 readnodes(&
m, &
b,
b.innodefilename,
b.inpolyfilename, &polyfile);
15711 gettimeofday(&
tv1, &tz);
15728 m.hullsize = reconstruct(&
m, &
b,
b.inelefilename,
b.areafilename,
15729 b.inpolyfilename, polyfile);
15738 gettimeofday(&
tv2, &tz);
15740 printf(
"Mesh reconstruction");
15742 printf(
"Delaunay");
15744 printf(
" milliseconds: %ld\n", 1000l * (
tv2.tv_sec -
tv1.tv_sec) +
15745 (
tv2.tv_usec -
tv1.tv_usec) / 1000l);
15751 m.infvertex1 = (
vertex) NULL;
15752 m.infvertex2 = (
vertex) NULL;
15753 m.infvertex3 = (
vertex) NULL;
15755 if (
b.usesegments) {
15756 m.checksegments = 1;
15770 gettimeofday(&
tv3, &tz);
15771 if (
b.usesegments && !
b.refine) {
15772 printf(
"Segment milliseconds: %ld\n",
15773 1000l * (
tv3.tv_sec -
tv2.tv_sec) +
15774 (
tv3.tv_usec -
tv2.tv_usec) / 1000l);
15779 if (
b.poly && (
m.triangles.items > 0)) {
15786 readholes(&
m, &
b, polyfile,
b.inpolyfilename, &holearray, &
m.holes,
15787 ®ionarray, &
m.regions);
15803 gettimeofday(&tv4, &tz);
15804 if (
b.poly && !
b.refine) {
15805 printf(
"Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec -
tv3.tv_sec) +
15806 (tv4.tv_usec -
tv3.tv_usec) / 1000l);
15812 if (
b.quality && (
m.triangles.items > 0)) {
15813 enforcequality(&
m, &
b);
15819 gettimeofday(&tv5, &tz);
15822 printf(
"Quality milliseconds: %ld\n",
15823 1000l * (tv5.tv_sec - tv4.tv_sec) +
15824 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15831 m.edges = (3l *
m.triangles.items +
m.hullsize) / 2l;
15851 if (
b.usesegments) {
15864 if (
b.nonodewritten || (
b.noiterationnum &&
m.readnodefile)) {
15867 printf(
"NOT writing vertices.\n");
15869 printf(
"NOT writing a .node file.\n");
15882 if (
b.noelewritten) {
15885 printf(
"NOT writing triangles.\n");
15887 printf(
"NOT writing an .ele file.\n");
15899 if (
b.poly ||
b.convex) {
15901 if (
b.nopolywritten ||
b.noiterationnum) {
15904 printf(
"NOT writing segments.\n");
15906 printf(
"NOT writing a .poly file.\n");
15922 writepoly(&
m, &
b,
b.outpolyfilename, holearray,
m.holes, regionarray,
15923 m.regions, argc, argv);
15929 if (
m.regions > 0) {
15937 writeoff(&
m, &
b,
b.offfilename, argc, argv);
15966 gettimeofday(&tv6, &tz);
15967 printf(
"\nOutput milliseconds: %ld\n",
15968 1000l * (tv6.tv_sec - tv5.tv_sec) +
15969 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15970 printf(
"Total running milliseconds: %ld\n",
15971 1000l * (tv6.tv_sec - tv0.tv_sec) +
15972 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15981 checkdelaunay(&
m, &
b);
include TDocParser_001 C image html pict1_TDocParser_001 png width
typedef void((*Func_t)())
REAL * pointattributelist
int numberoftriangleattributes
int numberofpointattributes
REAL * triangleattributelist
static uint64_t sum(uint64_t i)
#define sdest(osub, vertexptr)
#define sorg(osub, vertexptr)
VOID * traverse(struct memorypool *pool)
void highorder(struct mesh *m, struct behavior *b)
#define apex(otri, vertexptr)
void makevertexmap(struct mesh *m, struct behavior *b)
#define dnext(otri1, otri2)
void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, REAL **pointattriblist, int **pointmarkerlist)
void numbernodes(struct mesh *m, struct behavior *b)
void writepoly(struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist)
vertex getvertex(struct mesh *m, struct behavior *b, int number)
#define setelemattribute(otri, attnum, value)
#define setsorg(osub, vertexptr)
#define segdest(osub, vertexptr)
void poolrestart(struct memorypool *pool)
#define segorg(osub, vertexptr)
#define Two_Product(a, b, x, y)
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
#define sdecode(sptr, osub)
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
#define setorg(otri, vertexptr)
REAL estimate(int elen, REAL *e)
enum locateresult preciselocate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment)
#define elemattribute(otri, attnum)
int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
void makesubseg(struct mesh *m, struct osub *newsubseg)
#define bond(otri1, otri2)
void trifree(VOID *memptr)
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
void pooldealloc(struct memorypool *pool, VOID *dyingitem)
#define setsegorg(osub, vertexptr)
void alternateaxes(vertex *sortarray, int arraysize, int axis)
#define lnext(otri1, otri2)
int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight, REAL permanent)
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
long divconqdelaunay(struct mesh *m, struct behavior *b)
#define Two_Product_Presplit(a, b, bhi, blo, x, y)
void regionplague(struct mesh *m, struct behavior *b, REAL attribute, REAL area)
#define onext(otri1, otri2)
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
void triangledeinit(struct mesh *m, struct behavior *b)
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
vertex vertextraverse(struct mesh *m)
#define lprev(otri1, otri2)
triangle * triangletraverse(struct mesh *m)
#define tspivot(otri, osub)
VOID * poolalloc(struct memorypool *pool)
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
#define Two_Diff_Tail(a, b, x, y)
void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, REAL **vpointattriblist, int **vpointmarkerlist, int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
void poolzero(struct memorypool *pool)
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
#define dprev(otri1, otri2)
void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments)
#define setvertexmark(vx, value)
#define SPLAYNODEPERBLOCK
void triangulate(char *triswitches, struct triangulateio *in, struct triangulateio *out, struct triangulateio *vorout)
#define setvertex2tri(vx, value)
void initializevertexpool(struct mesh *m, struct behavior *b)
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, struct otri *innerleft, struct otri *innerright, struct otri *farright, int axis)
void parsecommandline(int argc, char **argv, struct behavior *b)
VOID * trimalloc(int size)
#define oprev(otri1, otri2)
#define BADSUBSEGPERBLOCK
void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
void vertexdealloc(struct mesh *m, vertex dyingvertex)
void infecthull(struct mesh *m, struct behavior *b)
void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, REAL *regionlist, int regions)
#define setapex(otri, vertexptr)
#define dest(otri, vertexptr)
void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist, REAL *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs)
#define otricopy(otri1, otri2)
#define Two_Sum(a, b, x, y)
#define tsbond(otri, osub)
#define setmark(osub, value)
void initializetrisubpools(struct mesh *m, struct behavior *b)
void writeedges(struct mesh *m, struct behavior *b, int **edgelist, int **edgemarkerlist)
#define Two_One_Product(a1, a0, b, x3, x2, x1, x0)
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
long delaunay(struct mesh *m, struct behavior *b)
#define setdest(otri, vertexptr)
void markhull(struct mesh *m, struct behavior *b)
void vertexsort(vertex *sortarray, int arraysize)
unsigned long randomnation(unsigned int choices)
REAL incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
#define stpivot(osub, otri)
REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
#define decode(ptr, otri)
#define otriequal(otri1, otri2)
#define org(otri, vertexptr)
void traversalinit(struct memorypool *pool)
REAL nonregular(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
void plague(struct mesh *m, struct behavior *b)
#define setsegdest(osub, vertexptr)
#define FLIPSTACKERPERBLOCK
void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
#define setvertextype(vx, value)
void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes)
#define sym(otri1, otri2)
void quality_statistics(struct mesh *m, struct behavior *b)
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
REAL counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
void pooldeinit(struct memorypool *pool)
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
#define setsdest(osub, vertexptr)
#define spivot(osub1, osub2)
#define ssym(osub1, osub2)
void writeelements(struct mesh *m, struct behavior *b, int **trianglelist, REAL **triangleattriblist)
void insertsegment(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0)
void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
#define Fast_Two_Sum(a, b, x, y)
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
void findcircumcenter(struct mesh *m, struct behavior *b, vertex torg, vertex tdest, vertex tapex, vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
#define Split(a, ahi, alo)
subseg * subsegtraverse(struct mesh *m)
REAL orient3d(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight)
void statistics(struct mesh *m, struct behavior *b)
#define sbond(osub1, osub2)
#define setareabound(otri, value)
void triangleinit(struct mesh *m)