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 283 #define INPUTVERTEX 0 284 #define SEGMENTVERTEX 1 286 #define DEADVERTEX -32768 287 #define UNDEADVERTEX -32767 295 #define SAMPLEFACTOR 11 301 #define SAMPLERATE 10 305 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308 309 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732 313 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333 320 #include <sys/time.h> 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 1329 #ifdef EXTERNAL_TEST 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);
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 3267 #define STARTINDEX 0 3269 #define STARTINDEX 1 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");
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);
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);
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 3833 struct memorypool *pool;
3840 pool->deaditemstack = (
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 3867 struct 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 3910 void poolinit(
struct memorypool *pool,
int bytecount,
int itemcount,
3913 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
3914 struct memorypool *pool;
3926 if (alignment > (
int)
sizeof(
VOID *)) {
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 3961 struct memorypool *pool;
3965 while (pool->firstblock != (
VOID **)
NULL) {
3966 pool->nowblock = (
VOID **) *(pool->firstblock);
3968 pool->firstblock = pool->nowblock;
3978 #ifdef ANSI_DECLARATORS 3982 struct 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 4045 struct memorypool *pool;
4051 *((
VOID **) dyingitem) = pool->deaditemstack;
4052 pool->deaditemstack = dyingitem;
4064 #ifdef ANSI_DECLARATORS 4068 struct 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 4104 struct memorypool *pool;
4109 unsigned long alignptr;
4112 if (pool->pathitem == pool->nextitem) {
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 4166 void dummyinit(
struct mesh *m,
struct behavior *b,
int trianglebytes,
4169 void dummyinit(m, b, trianglebytes, subsegbytes)
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));
4191 m->dummytri[0] = (
triangle) m->dummytri;
4192 m->dummytri[1] = (
triangle) m->dummytri;
4193 m->dummytri[2] = (
triangle) m->dummytri;
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;
4222 m->dummysub[6] = (
subseg) m->dummytri;
4223 m->dummysub[7] = (
subseg) m->dummytri;
4225 * (
int *) (m->dummysub + 8) = 0;
4229 m->dummytri[6] = (
triangle) m->dummysub;
4230 m->dummytri[7] = (
triangle) m->dummysub;
4231 m->dummytri[8] = (
triangle) m->dummysub;
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) &&
4326 (trisize < (int) ( 6 *
sizeof(
triangle) +
sizeof(int)))) {
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);
4345 dummyinit(m, b, m->triangles.itembytes, 0);
4355 #ifdef ANSI_DECLARATORS 4376 #ifdef ANSI_DECLARATORS 4391 }
while (
deadtri(newtriangle));
4401 #ifdef ANSI_DECLARATORS 4422 #ifdef ANSI_DECLARATORS 4447 #ifdef ANSI_DECLARATORS 4468 #ifdef ANSI_DECLARATORS 4496 #ifdef ANSI_DECLARATORS 4497 void badsubsegdealloc(
struct mesh *m,
struct badsubseg *dyingseg)
4499 void badsubsegdealloc(m, dyingseg)
4501 struct badsubseg *dyingseg;
4521 #ifdef ANSI_DECLARATORS 4522 struct badsubseg *badsubsegtraverse(
struct mesh *m)
4524 struct 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 4637 void maketriangle(
struct mesh *m,
struct behavior *b,
struct otri *newotri)
4642 struct 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 4685 struct osub *newsubseg;
4692 newsubseg->ss[0] = (
subseg) m->dummysub;
4693 newsubseg->ss[1] = (
subseg) m->dummysub;
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++) {
5063 Two_Sum(Q, product0, sum, hh);
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]);
5578 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[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]);
5675 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[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]);
5772 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[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]);