255#define FILENAMESIZE 2048
260#define INPUTLINESIZE 1024
266#define TRIPERBLOCK 4092
267#define SUBSEGPERBLOCK 508
268#define VERTEXPERBLOCK 4092
269#define VIRUSPERBLOCK 1020
271#define BADSUBSEGPERBLOCK 252
273#define BADTRIPERBLOCK 4092
275#define FLIPSTACKERPERBLOCK 252
277#define SPLAYNODEPERBLOCK 508
284#define SEGMENTVERTEX 1
286#define DEADVERTEX -32768
287#define UNDEADVERTEX -32767
295#define SAMPLEFACTOR 11
305#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
309#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
313#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
913#define decode(ptr, otri) \
914 (otri).orient = (int) ((uintptr_t) (ptr) & (uintptr_t) 3l); \
915 (otri).tri = (triangle *) \
916 ((uintptr_t) (ptr) ^ (uintptr_t) (otri).orient)
922#define encode(otri) \
923 (triangle) ((uintptr_t) (otri).tri | (uintptr_t) (otri).orient)
933#define sym(otri1, otri2) \
934 ptr = (otri1).tri[(otri1).orient]; \
937#define symself(otri) \
938 ptr = (otri).tri[(otri).orient]; \
943#define lnext(otri1, otri2) \
944 (otri2).tri = (otri1).tri; \
945 (otri2).orient = plus1mod3[(otri1).orient]
947#define lnextself(otri) \
948 (otri).orient = plus1mod3[(otri).orient]
952#define lprev(otri1, otri2) \
953 (otri2).tri = (otri1).tri; \
954 (otri2).orient = minus1mod3[(otri1).orient]
956#define lprevself(otri) \
957 (otri).orient = minus1mod3[(otri).orient]
963#define onext(otri1, otri2) \
964 lprev(otri1, otri2); \
967#define onextself(otri) \
975#define oprev(otri1, otri2) \
979#define oprevself(otri) \
987#define dnext(otri1, otri2) \
991#define dnextself(otri) \
999#define dprev(otri1, otri2) \
1000 lnext(otri1, otri2); \
1003#define dprevself(otri) \
1011#define rnext(otri1, otri2) \
1012 sym(otri1, otri2); \
1016#define rnextself(otri) \
1025#define rprev(otri1, otri2) \
1026 sym(otri1, otri2); \
1030#define rprevself(otri) \
1038#define org(otri, vertexptr) \
1039 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
1041#define dest(otri, vertexptr) \
1042 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
1044#define apex(otri, vertexptr) \
1045 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
1047#define setorg(otri, vertexptr) \
1048 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1050#define setdest(otri, vertexptr) \
1051 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
1053#define setapex(otri, vertexptr) \
1054 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
1058#define bond(otri1, otri2) \
1059 (otri1).tri[(otri1).orient] = encode(otri2); \
1060 (otri2).tri[(otri2).orient] = encode(otri1)
1067#define dissolve(otri) \
1068 (otri).tri[(otri).orient] = (triangle) m->dummytri
1072#define otricopy(otri1, otri2) \
1073 (otri2).tri = (otri1).tri; \
1074 (otri2).orient = (otri1).orient
1078#define otriequal(otri1, otri2) \
1079 (((otri1).tri == (otri2).tri) && \
1080 ((otri1).orient == (otri2).orient))
1085#define infect(otri) \
1086 (otri).tri[6] = (triangle) \
1087 ((uintptr_t) (otri).tri[6] | (uintptr_t) 2l)
1089#define uninfect(otri) \
1090 (otri).tri[6] = (triangle) \
1091 ((uintptr_t) (otri).tri[6] & ~ (uintptr_t) 2l)
1095#define infected(otri) \
1096 (((uintptr_t) (otri).tri[6] & (uintptr_t) 2l) != 0l)
1100#define elemattribute(otri, attnum) \
1101 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
1103#define setelemattribute(otri, attnum, value) \
1104 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
1108#define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
1110#define setareabound(otri, value) \
1111 ((REAL *) (otri).tri)[m->areaboundindex] = value
1118#define deadtri(tria) ((tria)[1] == (triangle) NULL)
1120#define killtri(tria) \
1121 (tria)[1] = (triangle) NULL; \
1122 (tria)[3] = (triangle) NULL
1133#define sdecode(sptr, osub) \
1134 (osub).ssorient = (int) ((uintptr_t) (sptr) & (uintptr_t) 1l); \
1135 (osub).ss = (subseg *) \
1136 ((uintptr_t) (sptr) & ~ (uintptr_t) 3l)
1142#define sencode(osub) \
1143 (subseg) ((uintptr_t) (osub).ss | (uintptr_t) (osub).ssorient)
1147#define ssym(osub1, osub2) \
1148 (osub2).ss = (osub1).ss; \
1149 (osub2).ssorient = 1 - (osub1).ssorient
1151#define ssymself(osub) \
1152 (osub).ssorient = 1 - (osub).ssorient
1157#define spivot(osub1, osub2) \
1158 sptr = (osub1).ss[(osub1).ssorient]; \
1159 sdecode(sptr, osub2)
1161#define spivotself(osub) \
1162 sptr = (osub).ss[(osub).ssorient]; \
1168#define snext(osub1, osub2) \
1169 sptr = (osub1).ss[1 - (osub1).ssorient]; \
1170 sdecode(sptr, osub2)
1172#define snextself(osub) \
1173 sptr = (osub).ss[1 - (osub).ssorient]; \
1179#define sorg(osub, vertexptr) \
1180 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
1182#define sdest(osub, vertexptr) \
1183 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
1185#define setsorg(osub, vertexptr) \
1186 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
1188#define setsdest(osub, vertexptr) \
1189 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
1191#define segorg(osub, vertexptr) \
1192 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
1194#define segdest(osub, vertexptr) \
1195 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
1197#define setsegorg(osub, vertexptr) \
1198 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
1200#define setsegdest(osub, vertexptr) \
1201 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
1207#define mark(osub) (* (int *) ((osub).ss + 8))
1209#define setmark(osub, value) \
1210 * (int *) ((osub).ss + 8) = value
1214#define sbond(osub1, osub2) \
1215 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
1216 (osub2).ss[(osub2).ssorient] = sencode(osub1)
1221#define sdissolve(osub) \
1222 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
1226#define subsegcopy(osub1, osub2) \
1227 (osub2).ss = (osub1).ss; \
1228 (osub2).ssorient = (osub1).ssorient
1232#define subsegequal(osub1, osub2) \
1233 (((osub1).ss == (osub2).ss) && \
1234 ((osub1).ssorient == (osub2).ssorient))
1241#define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
1243#define killsubseg(sub) \
1244 (sub)[1] = (subseg) NULL; \
1245 (sub)[2] = (subseg) NULL
1253#define tspivot(otri, osub) \
1254 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
1260#define stpivot(osub, otri) \
1261 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
1266#define tsbond(otri, osub) \
1267 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
1268 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
1272#define tsdissolve(otri) \
1273 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
1277#define stdissolve(osub) \
1278 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
1284#define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
1286#define setvertexmark(vx, value) \
1287 ((int *) (vx))[m->vertexmarkindex] = value
1289#define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
1291#define setvertextype(vx, value) \
1292 ((int *) (vx))[m->vertexmarkindex + 1] = value
1294#define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
1296#define setvertex2tri(vx, value) \
1297 ((triangle *) (vx))[m->vertex2triindex] = value
1336#ifdef ANSI_DECLARATORS
1347 REAL dxoa, dxda, dxod;
1348 REAL dyoa, dyda, dyod;
1349 REAL oalen, dalen, odlen;
1354 dxoa = triorg[0] - triapex[0];
1355 dyoa = triorg[1] - triapex[1];
1356 dxda = tridest[0] - triapex[0];
1357 dyda = tridest[1] - triapex[1];
1358 dxod = triorg[0] - tridest[0];
1359 dyod = triorg[1] - tridest[1];
1361 oalen = dxoa * dxoa + dyoa * dyoa;
1362 dalen = dxda * dxda + dyda * dyda;
1363 odlen = dxod * dxod + dyod * dyod;
1365 maxlen = (dalen > oalen) ? dalen : oalen;
1366 maxlen = (odlen > maxlen) ? odlen : maxlen;
1368 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
1385#ifdef ANSI_DECLARATORS
1396#ifdef ANSI_DECLARATORS
1407 if (memptr == (
VOID *) NULL) {
1408 printf(
"Error: Out of memory.\n");
1414#ifdef ANSI_DECLARATORS
1445 printf(
"triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
1447 printf(
"triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
1451 printf(
"triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
1453 printf(
"triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
1457 printf(
" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
1459 printf(
" -r Refines a previously generated mesh.\n");
1461 " -q Quality mesh generation. A minimum angle may be specified.\n");
1462 printf(
" -a Applies a maximum triangle area constraint.\n");
1463 printf(
" -u Applies a user-defined triangle constraint.\n");
1466 " -A Applies attributes to identify triangles in certain regions.\n");
1467 printf(
" -c Encloses the convex hull with segments.\n");
1469 printf(
" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
1475 printf(
" -j Jettison unused vertices from output .node file.\n");
1476 printf(
" -e Generates an edge list.\n");
1477 printf(
" -v Generates a Voronoi diagram.\n");
1478 printf(
" -n Generates a list of triangle neighbors.\n");
1479 printf(
" -g Generates an .off file for Geomview.\n");
1480 printf(
" -B Suppresses output of boundary information.\n");
1481 printf(
" -P Suppresses output of .poly file.\n");
1482 printf(
" -N Suppresses output of .node file.\n");
1483 printf(
" -E Suppresses output of .ele file.\n");
1484 printf(
" -I Suppresses mesh iteration numbers.\n");
1485 printf(
" -O Ignores holes in .poly file.\n");
1486 printf(
" -X Suppresses use of exact arithmetic.\n");
1487 printf(
" -z Numbers all items starting from zero (rather than one).\n");
1488 printf(
" -o2 Generates second-order subparametric elements.\n");
1490 printf(
" -Y Suppresses boundary segment splitting.\n");
1491 printf(
" -S Specifies maximum number of added Steiner points.\n");
1494 printf(
" -i Uses incremental method, rather than divide-and-conquer.\n");
1495 printf(
" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
1497 printf(
" -l Uses vertical cuts only, rather than alternating cuts.\n");
1501 " -s Force segments into mesh by splitting (instead of using CDT).\n");
1503 printf(
" -C Check consistency of final mesh.\n");
1505 printf(
" -Q Quiet: No terminal output except errors.\n");
1506 printf(
" -V Verbose: Detailed information on what I'm doing.\n");
1507 printf(
" -h Help: Detailed instructions for Triangle.\n");
1523 printf(
"Triangle\n");
1525"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
1526 printf(
"Version 1.6\n\n");
1528"Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
1529 printf(
"2360 Woolsey #H / Berkeley, California 94705-1927\n");
1530 printf(
"Bugs/comments to jrs@cs.berkeley.edu\n");
1532"Created as part of the Quake project (tools for earthquake simulation).\n");
1534"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
1535 printf(
"There is no warranty whatsoever. Use at your own risk.\n");
1537 printf(
"This executable is compiled for single precision arithmetic.\n\n\n");
1539 printf(
"This executable is compiled for double precision arithmetic.\n\n\n");
1542"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
1544"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
1546"high-quality triangular meshes. The latter can be generated with no small\n"
1549"or large angles, and are thus suitable for finite element analysis. If no\n"
1552"command line switch is specified, your .node input file is read, and the\n");
1554"Delaunay triangulation is returned in .node and .ele output files. The\n");
1555 printf(
"command syntax is:\n\n");
1556 printf(
"triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
1558"Underscores indicate that numbers may optionally follow certain switches.\n");
1560"Do not leave any space between a switch and its numeric parameter.\n");
1562"input_file must be a file with extension .node, or extension .poly if the\n");
1564"-p switch is used. If -r is used, you must supply .node and .ele files,\n");
1566"and possibly a .poly file and an .area file as well. The formats of these\n"
1568 printf(
"files are described below.\n\n");
1569 printf(
"Command Line Switches:\n\n");
1571" -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
1574" vertices, segments, holes, regional attributes, and regional area\n");
1576" constraints. Generates a constrained Delaunay triangulation (CDT)\n"
1579" fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
1581" constrained Delaunay triangulation (CCDT). If you want a truly\n");
1583" Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
1585" well. When -p is not used, Triangle reads a .node file by default.\n"
1588" -r Refines a previously generated mesh. The mesh is read from a .node\n"
1591" file and an .ele file. If -p is also used, a .poly file is read\n");
1593" and used to constrain segments in the mesh. If -a is also used\n");
1595" (with no number following), an .area file is read and used to\n");
1597" impose area constraints on the mesh. Further details on refinement\n"
1599 printf(
" appear below.\n");
1601" -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
1603" Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
1606" ensure that all angles are between 20 and 140 degrees. An\n");
1608" alternative bound on the minimum angle, replacing 20 degrees, may\n");
1610" be specified after the `q'. The specified angle may include a\n");
1612" decimal point, but not exponential notation. Note that a bound of\n"
1615" theta degrees on the smallest angle also implies a bound of\n");
1617" (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
1620" degrees or smaller, Triangle is mathematically guaranteed to\n");
1622" terminate (assuming infinite precision arithmetic--Triangle may\n");
1624" fail to terminate if you run out of precision). In practice,\n");
1626" Triangle often succeeds for minimum angles up to 34 degrees. For\n");
1628" some meshes, however, you might need to reduce the minimum angle to\n"
1631" avoid problems associated with insufficient floating-point\n");
1632 printf(
" precision.\n");
1634" -a Imposes a maximum triangle area. If a number follows the `a', no\n");
1636" triangle is generated whose area is larger than that number. If no\n"
1639" number is specified, an .area file (if -r is used) or .poly file\n");
1641" (if -r is not used) specifies a set of maximum area constraints.\n");
1643" An .area file contains a separate area constraint for each\n");
1645" triangle, and is useful for refining a finite element mesh based on\n"
1648" a posteriori error estimates. A .poly file can optionally contain\n"
1651" an area constraint for each segment-bounded region, thereby\n");
1653" controlling triangle densities in a first triangulation of a PSLG.\n"
1656" You can impose both a fixed area constraint and a varying area\n");
1658" constraint by invoking the -a switch twice, once with and once\n");
1660" without a number following. Each area specified may include a\n");
1661 printf(
" decimal point.\n");
1663" -u Imposes a user-defined constraint on triangle size. There are two\n"
1666" ways to use this feature. One is to edit the triunsuitable()\n");
1668" procedure in triangle.c to encode any constraint you like, then\n");
1670" recompile Triangle. The other is to compile triangle.c with the\n");
1672" EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
1674" link Triangle with a separate object file that implements\n");
1676" triunsuitable(). In either case, the -u switch causes the user-\n");
1677 printf(
" defined test to be applied to every triangle.\n");
1679" -A Assigns an additional floating-point attribute to each triangle\n");
1681" that identifies what segment-bounded region each triangle belongs\n");
1683" to. Attributes are assigned to regions by the .poly file. If a\n");
1685" region is not explicitly marked by the .poly file, triangles in\n");
1687" that region are assigned an attribute of zero. The -A switch has\n");
1689" an effect only when the -p switch is used and the -r switch is not.\n"
1692" -c Creates segments on the convex hull of the triangulation. If you\n");
1694" are triangulating a vertex set, this switch causes a .poly file to\n"
1697" be written, containing all edges of the convex hull. If you are\n");
1699" triangulating a PSLG, this switch specifies that the whole convex\n");
1701" hull of the PSLG should be triangulated, regardless of what\n");
1703" segments the PSLG has. If you do not use this switch when\n");
1705" triangulating a PSLG, Triangle assumes that you have identified the\n"
1708" region to be triangulated by surrounding it with segments of the\n");
1710" input PSLG. Beware: if you are not careful, this switch can cause\n"
1713" the introduction of an extremely thin angle between a PSLG segment\n"
1716" and a convex hull segment, which can cause overrefinement (and\n");
1718" possibly failure if Triangle runs out of precision). If you are\n");
1720" refining a mesh, the -c switch works differently: it causes a\n");
1722" .poly file to be written containing the boundary edges of the mesh\n"
1724 printf(
" (useful if no .poly file was read).\n");
1726" -D Conforming Delaunay triangulation: use this switch if you want to\n"
1729" ensure that all the triangles in the mesh are Delaunay, and not\n");
1731" merely constrained Delaunay; or if you want to ensure that all the\n"
1734" Voronoi vertices lie within the triangulation. (Some finite volume\n"
1737" methods have this requirement.) This switch invokes Ruppert's\n");
1739" original algorithm, which splits every subsegment whose diametral\n");
1741" circle is encroached. It usually increases the number of vertices\n"
1743 printf(
" and triangles.\n");
1745" -j Jettisons vertices that are not part of the final triangulation\n");
1747" from the output .node file. By default, Triangle copies all\n");
1749" vertices in the input .node file to the output .node file, in the\n");
1751" same order, so their indices do not change. The -j switch prevents\n"
1754" duplicated input vertices, or vertices `eaten' by holes, from\n");
1756" appearing in the output .node file. Thus, if two input vertices\n");
1758" have exactly the same coordinates, only the first appears in the\n");
1760" output. If any vertices are jettisoned, the vertex numbering in\n");
1762" the output .node file differs from that of the input .node file.\n");
1764" -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
1766" -v Outputs the Voronoi diagram associated with the triangulation.\n");
1768" Does not attempt to detect degeneracies, so some Voronoi vertices\n");
1770" may be duplicated. See the discussion of Voronoi diagrams below.\n");
1772" -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
1773 printf(
" triangle.\n");
1775" -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
1777 printf(
" viewing with the Geometry Center's Geomview package.\n");
1779" -B No boundary markers in the output .node, .poly, and .edge output\n");
1781" files. See the detailed discussion of boundary markers below.\n");
1783" -P No output .poly file. Saves disk space, but you lose the ability\n");
1785" to maintain constraining segments on later refinements of the mesh.\n"
1787 printf(
" -N No output .node file.\n");
1788 printf(
" -E No output .ele file.\n");
1790" -I No iteration numbers. Suppresses the output of .node and .poly\n");
1792" files, so your input files won't be overwritten. (If your input is\n"
1795" a .poly file only, a .node file is written.) Cannot be used with\n");
1797" the -r switch, because that would overwrite your input .ele file.\n");
1799" Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
1801" using a .node file for input, because no .node file is written, so\n"
1803 printf(
" there is no record of any added Steiner points.\n");
1804 printf(
" -O No holes. Ignores the holes in the .poly file.\n");
1806" -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
1809" arithmetic for certain tests if it thinks the inexact tests are not\n"
1812" accurate enough. Exact arithmetic ensures the robustness of the\n");
1814" triangulation algorithms, despite floating-point roundoff error.\n");
1816" Disabling exact arithmetic with the -X switch causes a small\n");
1818" improvement in speed and creates the possibility that Triangle will\n"
1820 printf(
" fail to produce a valid mesh. Not recommended.\n");
1822" -z Numbers all items starting from zero (rather than one). Note that\n"
1825" this switch is normally overridden by the value used to number the\n"
1828" first vertex of the input .node or .poly file. However, this\n");
1830" switch is useful when calling Triangle from another program.\n");
1832" -o2 Generates second-order subparametric elements with six nodes each.\n"
1835" -Y No new vertices on the boundary. This switch is useful when the\n");
1837" mesh boundary must be preserved so that it conforms to some\n");
1839" adjacent mesh. Be forewarned that you will probably sacrifice much\n"
1842" of the quality of the mesh; Triangle will try, but the resulting\n");
1844" mesh may contain poorly shaped triangles. Works well if all the\n");
1846" boundary vertices are closely spaced. Specify this switch twice\n");
1848" (`-YY') to prevent all segment splitting, including internal\n");
1849 printf(
" boundaries.\n");
1851" -S Specifies the maximum number of Steiner points (vertices that are\n");
1853" not in the input, but are added to meet the constraints on minimum\n"
1856" angle and maximum area). The default is to allow an unlimited\n");
1858" number. If you specify this switch with no number after it,\n");
1860" the limit is set to zero. Triangle always adds vertices at segment\n"
1863" intersections, even if it needs to use more vertices than the limit\n"
1866" you set. When Triangle inserts segments by splitting (-s), it\n");
1868" always adds enough vertices to ensure that all the segments of the\n"
1870 printf(
" PLSG are recovered, ignoring the limit if necessary.\n");
1872" -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
1874" construct a Delaunay triangulation. Try it if the divide-and-\n");
1875 printf(
" conquer algorithm fails.\n");
1877" -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
1879" triangulation. Warning: does not use exact arithmetic for all\n");
1880 printf(
" calculations. An exact result is not guaranteed.\n");
1882" -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
1884" default, Triangle alternates between vertical and horizontal cuts,\n"
1887" which usually improve the speed except with vertex sets that are\n");
1889" small or short and wide. This switch is primarily of theoretical\n");
1890 printf(
" interest.\n");
1892" -s Specifies that segments should be forced into the triangulation by\n"
1895" recursively splitting them at their midpoints, rather than by\n");
1897" generating a constrained Delaunay triangulation. Segment splitting\n"
1900" is true to Ruppert's original algorithm, but can create needlessly\n"
1903" small triangles. This switch is primarily of theoretical interest.\n"
1906" -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
1909" checking, even if the -X switch is used. Useful if you suspect\n");
1910 printf(
" Triangle is buggy.\n");
1912" -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
1913 printf(
" unless an error occurs.\n");
1915" -V Verbose: Gives detailed information about what Triangle is doing.\n"
1918" Add more `V's for increasing amount of detail. `-V' is most\n");
1920" useful; itgives information on algorithmic progress and much more\n");
1922" detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
1924" prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
1926 printf(
" information only a debugger could love.\n");
1927 printf(
" -h Help: Displays these instructions.\n");
1929 printf(
"Definitions:\n");
1932" A Delaunay triangulation of a vertex set is a triangulation whose\n");
1934" vertices are the vertex set, that covers the convex hull of the vertex\n");
1936" set. A Delaunay triangulation has the property that no vertex lies\n");
1938" inside the circumscribing circle (circle that passes through all three\n");
1939 printf(
" vertices) of any triangle in the triangulation.\n\n");
1941" A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
1943" polygonal cells (some of which may be unbounded, meaning infinitely\n");
1945" large), where each cell is the set of points in the plane that are closer\n"
1948" to some input vertex than to any other input vertex. The Voronoi diagram\n"
1950 printf(
" is a geometric dual of the Delaunay triangulation.\n\n");
1952" A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
1954" Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
1957" Segments may intersect each other only at their endpoints. The file\n");
1958 printf(
" format for PSLGs (.poly files) is described below.\n\n");
1960" A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
1962" Delaunay triangulation, but each PSLG segment is present as a single edge\n"
1965" of the CDT. (A constrained Delaunay triangulation is not truly a\n");
1967" Delaunay triangulation, because some of its triangles might not be\n");
1969" Delaunay.) By definition, a CDT does not have any vertices other than\n");
1971" those specified in the input PSLG. Depending on context, a CDT might\n");
1973" cover the convex hull of the PSLG, or it might cover only a segment-\n");
1974 printf(
" bounded region (e.g. a polygon).\n\n");
1976" A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
1979" each triangle is truly Delaunay, and each PSLG segment is represented by\n"
1982" a linear contiguous sequence of edges of the triangulation. New vertices\n"
1985" (not part of the PSLG) may appear, and each input segment may have been\n");
1987" subdivided into shorter edges (subsegments) by these additional vertices.\n"
1990" The new vertices are frequently necessary to maintain the Delaunay\n");
1991 printf(
" property while ensuring that every segment is represented.\n\n");
1993" A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
1995" triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
1996 printf(
" vertices may appear, and input segments may be subdivided into\n");
1998" subsegments, but not to guarantee that segments are respected; rather, to\n"
2001" improve the quality of the triangles. The high-quality meshes produced\n");
2003" by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
2004 printf(
" with the -D switch.\n\n");
2005 printf(
"File Formats:\n\n");
2007" All files may contain comments prefixed by the character '#'. Vertices,\n"
2010" triangles, edges, holes, and maximum area constraints must be numbered\n");
2012" consecutively, starting from either 1 or 0. Whichever you choose, all\n");
2014" input files must be consistent; if the vertices are numbered from 1, so\n");
2016" must be all other objects. Triangle automatically detects your choice\n");
2018" while reading the .node (or .poly) file. (When calling Triangle from\n");
2020" another program, use the -z switch if you wish to number objects from\n");
2021 printf(
" zero.) Examples of these file formats are given below.\n\n");
2022 printf(
" .node files:\n");
2024" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2027" <# of boundary markers (0 or 1)>\n"
2030" Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2033" The attributes, which are typically floating-point values of physical\n");
2035" quantities (such as mass or conductivity) associated with the nodes of\n"
2038" a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
2041" -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
2043 printf(
" has attributes assigned to it by linear interpolation.\n\n");
2045" If the fourth entry of the first line is `1', the last column of the\n");
2047" remainder of the file is assumed to contain boundary markers. Boundary\n"
2050" markers are used to identify boundary vertices and vertices resting on\n"
2053" PSLG segments; a complete description appears in a section below. The\n"
2056" .node file produced by Triangle contains boundary markers in the last\n");
2057 printf(
" column unless they are suppressed by the -B switch.\n\n");
2058 printf(
" .ele files:\n");
2060" First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
2062" Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
2065" Nodes are indices into the corresponding .node file. The first three\n");
2067" nodes are the corner vertices, and are listed in counterclockwise order\n"
2070" around each triangle. (The remaining nodes, if any, depend on the type\n"
2072 printf(
" of finite element used.)\n\n");
2074" The attributes are just like those of .node files. Because there is no\n"
2077" simple mapping from input to output triangles, Triangle attempts to\n");
2079" interpolate attributes, and may cause a lot of diffusion of attributes\n"
2082" among nearby triangles as the triangulation is refined. Attributes do\n"
2084 printf(
" not diffuse across segments, so attributes used to identify\n");
2085 printf(
" segment-bounded regions remain intact.\n\n");
2087" In .ele files produced by Triangle, each triangular element has three\n");
2089" nodes (vertices) unless the -o2 switch is used, in which case\n");
2091" subparametric quadratic elements with six nodes each are generated.\n");
2093" The first three nodes are the corners in counterclockwise order, and\n");
2095" the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
2097" opposite the first, second, and third vertices, respectively.\n");
2099 printf(
" .poly files:\n");
2101" First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
2104" <# of boundary markers (0 or 1)>\n"
2107" Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
2108 printf(
" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
2110" Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
2111 printf(
" One line: <# of holes>\n");
2112 printf(
" Following lines: <hole #> <x> <y>\n");
2114" Optional line: <# of regional attributes and/or area constraints>\n");
2116" Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
2119" A .poly file represents a PSLG, as well as some additional information.\n"
2122" The first section lists all the vertices, and is identical to the\n");
2124" format of .node files. <# of vertices> may be set to zero to indicate\n"
2127" that the vertices are listed in a separate .node file; .poly files\n");
2129" produced by Triangle always have this format. A vertex set represented\n"
2132" this way has the advantage that it may easily be triangulated with or\n");
2134" without segments (depending on whether the -p switch is invoked).\n");
2137" The second section lists the segments. Segments are edges whose\n");
2139" presence in the triangulation is enforced. (Depending on the choice of\n"
2142" switches, segment might be subdivided into smaller edges). Each\n");
2144" segment is specified by listing the indices of its two endpoints. This\n"
2147" means that you must include its endpoints in the vertex list. Each\n");
2148 printf(
" segment, like each point, may have a boundary marker.\n\n");
2150" If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
2153" Delaunay triangulation (CDT), in which each segment appears as a single\n"
2156" edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
2159" produces a conforming constrained Delaunay triangulation (CCDT), in\n");
2161" which segments may be subdivided into smaller edges. If -D is\n");
2163" selected, Triangle produces a conforming Delaunay triangulation, so\n");
2165" that every triangle is Delaunay, and not just constrained Delaunay.\n");
2168" The third section lists holes (and concavities, if -c is selected) in\n");
2170" the triangulation. Holes are specified by identifying a point inside\n");
2172" each hole. After the triangulation is formed, Triangle creates holes\n");
2174" by eating triangles, spreading out from each hole point until its\n");
2176" progress is blocked by segments in the PSLG. You must be careful to\n");
2178" enclose each hole in segments, or your whole triangulation might be\n");
2180" eaten away. If the two triangles abutting a segment are eaten, the\n");
2182" segment itself is also eaten. Do not place a hole directly on a\n");
2183 printf(
" segment; if you do, Triangle chooses one side of the segment\n");
2184 printf(
" arbitrarily.\n\n");
2186" The optional fourth section lists regional attributes (to be assigned\n");
2188" to all triangles in a region) and regional constraints on the maximum\n");
2190" triangle area. Triangle reads this section only if the -A switch is\n");
2192" used or the -a switch is used without a number following it, and the -r\n"
2195" switch is not used. Regional attributes and area constraints are\n");
2197" propagated in the same manner as holes: you specify a point for each\n");
2199" attribute and/or constraint, and the attribute and/or constraint\n");
2201" affects the whole region (bounded by segments) containing the point.\n");
2203" If two values are written on a line after the x and y coordinate, the\n");
2205" first such value is assumed to be a regional attribute (but is only\n");
2207" applied if the -A switch is selected), and the second value is assumed\n"
2210" to be a regional area constraint (but is only applied if the -a switch\n"
2213" is selected). You may specify just one value after the coordinates,\n");
2215" which can serve as both an attribute and an area constraint, depending\n"
2218" on the choice of switches. If you are using the -A and -a switches\n");
2220" simultaneously and wish to assign an attribute to some region without\n");
2221 printf(
" imposing an area constraint, use a negative maximum area.\n\n");
2223" When a triangulation is created from a .poly file, you must either\n");
2225" enclose the entire region to be triangulated in PSLG segments, or\n");
2227" use the -c switch, which automatically creates extra segments that\n");
2229" enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
2232" Triangle eats all triangles that are not enclosed by segments; if you\n");
2234" are not careful, your whole triangulation may be eaten away. If you do\n"
2237" use the -c switch, you can still produce concavities by the appropriate\n"
2240" placement of holes just inside the boundary of the convex hull.\n");
2243" An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
2245" upon segments (except, of course, the endpoints of each segment). You\n"
2248" aren't required to make your .poly files ideal, but you should be aware\n"
2251" of what can go wrong. Segment intersections are relatively safe--\n");
2253" Triangle calculates the intersection points for you and adds them to\n");
2255" the triangulation--as long as your machine's floating-point precision\n");
2257" doesn't become a problem. You are tempting the fates if you have three\n"
2260" segments that cross at the same location, and expect Triangle to figure\n"
2263" out where the intersection point is. Thanks to floating-point roundoff\n"
2266" error, Triangle will probably decide that the three segments intersect\n"
2269" at three different points, and you will find a minuscule triangle in\n");
2271" your output--unless Triangle tries to refine the tiny triangle, uses\n");
2273" up the last bit of machine precision, and fails to terminate at all.\n");
2275" You're better off putting the intersection point in the input files,\n");
2277" and manually breaking up each segment into two. Similarly, if you\n");
2279" place a vertex at the middle of a segment, and hope that Triangle will\n"
2282" break up the segment at that vertex, you might get lucky. On the other\n"
2285" hand, Triangle might decide that the vertex doesn't lie precisely on\n");
2287" the segment, and you'll have a needle-sharp triangle in your output--or\n"
2289 printf(
" a lot of tiny triangles if you're generating a quality mesh.\n");
2292" When Triangle reads a .poly file, it also writes a .poly file, which\n");
2294" includes all the subsegments--the edges that are parts of input\n");
2296" segments. If the -c switch is used, the output .poly file also\n");
2298" includes all of the edges on the convex hull. Hence, the output .poly\n"
2301" file is useful for finding edges associated with input segments and for\n"
2304" setting boundary conditions in finite element simulations. Moreover,\n");
2306" you will need the output .poly file if you plan to refine the output\n");
2308" mesh, and don't want segments to be missing in later triangulations.\n");
2310 printf(
" .area files:\n");
2311 printf(
" First line: <# of triangles>\n");
2312 printf(
" Following lines: <triangle #> <maximum area>\n");
2315" An .area file associates with each triangle a maximum area that is used\n"
2318" for mesh refinement. As with other file formats, every triangle must\n");
2320" be represented, and the triangles must be numbered consecutively. A\n");
2322" triangle may be left unconstrained by assigning it a negative maximum\n");
2323 printf(
" area.\n\n");
2324 printf(
" .edge files:\n");
2325 printf(
" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
2327" Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
2330" Endpoints are indices into the corresponding .node file. Triangle can\n"
2333" produce .edge files (use the -e switch), but cannot read them. The\n");
2335" optional column of boundary markers is suppressed by the -B switch.\n");
2338" In Voronoi diagrams, one also finds a special kind of edge that is an\n");
2340" infinite ray with only one endpoint. For these edges, a different\n");
2341 printf(
" format is used:\n\n");
2342 printf(
" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
2344" The `direction' is a floating-point vector that indicates the direction\n"
2346 printf(
" of the infinite ray.\n\n");
2347 printf(
" .neigh files:\n");
2349" First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
2352" Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
2355" Neighbors are indices into the corresponding .ele file. An index of -1\n"
2358" indicates no neighbor (because the triangle is on an exterior\n");
2360" boundary). The first neighbor of triangle i is opposite the first\n");
2361 printf(
" corner of triangle i, and so on.\n\n");
2363" Triangle can produce .neigh files (use the -n switch), but cannot read\n"
2365 printf(
" them.\n\n");
2366 printf(
"Boundary Markers:\n\n");
2368" Boundary markers are tags used mainly to identify which output vertices\n");
2370" and edges are associated with which PSLG segment, and to identify which\n");
2372" vertices and edges occur on a boundary of the triangulation. A common\n");
2374" use is to determine where boundary conditions should be applied to a\n");
2376" finite element mesh. You can prevent boundary markers from being written\n"
2378 printf(
" into files produced by Triangle by using the -B switch.\n\n");
2380" The boundary marker associated with each segment in an output .poly file\n"
2382 printf(
" and each edge in an output .edge file is chosen as follows:\n");
2384" - If an output edge is part or all of a PSLG segment with a nonzero\n");
2386" boundary marker, then the edge is assigned the same marker.\n");
2388" - Otherwise, if the edge lies on a boundary of the triangulation\n");
2390" (even the boundary of a hole), then the edge is assigned the marker\n");
2391 printf(
" one (1).\n");
2392 printf(
" - Otherwise, the edge is assigned the marker zero (0).\n");
2394" The boundary marker associated with each vertex in an output .node file\n");
2395 printf(
" is chosen as follows:\n");
2397" - If a vertex is assigned a nonzero boundary marker in the input file,\n"
2400" then it is assigned the same marker in the output .node file.\n");
2402" - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
2404" endpoint of the segment) with a nonzero boundary marker, then the\n");
2406" vertex is assigned the same marker. If the vertex lies on several\n");
2407 printf(
" such segments, one of the markers is chosen arbitrarily.\n");
2409" - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
2410 printf(
" then the vertex is assigned the marker one (1).\n");
2411 printf(
" - Otherwise, the vertex is assigned the marker zero (0).\n");
2414" If you want Triangle to determine for you which vertices and edges are on\n"
2417" the boundary, assign them the boundary marker zero (or use no markers at\n"
2420" all) in your input files. In the output files, all boundary vertices,\n");
2421 printf(
" edges, and segments will be assigned the value one.\n\n");
2422 printf(
"Triangulation Iteration Numbers:\n\n");
2424" Because Triangle can read and refine its own triangulations, input\n");
2426" and output files have iteration numbers. For instance, Triangle might\n");
2428" read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
2430" triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
2431 printf(
" mesh.4.poly. Files with no iteration number are treated as if\n");
2433" their iteration number is zero; hence, Triangle might read the file\n");
2435" points.node, triangulate it, and produce the files points.1.node and\n");
2436 printf(
" points.1.ele.\n\n");
2438" Iteration numbers allow you to create a sequence of successively finer\n");
2440" meshes suitable for multigrid methods. They also allow you to produce a\n"
2443" sequence of meshes using error estimate-driven mesh refinement.\n");
2446" If you're not using refinement or quality meshing, and you don't like\n");
2448" iteration numbers, use the -I switch to disable them. This switch also\n");
2450" disables output of .node and .poly files to prevent your input files from\n"
2453" being overwritten. (If the input is a .poly file that contains its own\n");
2455" points, a .node file is written. This can be quite convenient for\n");
2456 printf(
" computing CDTs or quality meshes.)\n\n");
2457 printf(
"Examples of How to Use Triangle:\n\n");
2459" `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
2462" triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
2464" to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
2466" instead. (No additional .node file is needed, so none is written.)\n");
2469" `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
2471" object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
2474" its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
2477" The segments are copied to object.2.poly, and all edges are written to\n");
2478 printf(
" object.2.edge.\n\n");
2480" `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
2483" object.node), generates a mesh whose angles are all between 31.5 and 117\n"
2486" degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
2489" mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
2490 printf(
" into multiple subsegments; these are written to object.1.poly.\n");
2493" Here is a sample file `box.poly' describing a square with a square hole:\n"
2497" # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
2499 printf(
" 8 2 0 1\n");
2500 printf(
" # Outer box has these vertices:\n");
2501 printf(
" 1 0 0 0\n");
2502 printf(
" 2 0 3 0\n");
2503 printf(
" 3 3 0 0\n");
2504 printf(
" 4 3 3 33 # A special marker for this vertex.\n");
2505 printf(
" # Inner square has these vertices:\n");
2506 printf(
" 5 1 1 0\n");
2507 printf(
" 6 1 2 0\n");
2508 printf(
" 7 2 1 0\n");
2509 printf(
" 8 2 2 0\n");
2510 printf(
" # Five segments with boundary markers.\n");
2512 printf(
" 1 1 2 5 # Left side of outer box.\n");
2513 printf(
" # Square hole has these segments:\n");
2514 printf(
" 2 5 7 0\n");
2515 printf(
" 3 7 8 0\n");
2516 printf(
" 4 8 6 10\n");
2517 printf(
" 5 6 5 0\n");
2518 printf(
" # One hole in the middle of the inner square.\n");
2520 printf(
" 1 1.5 1.5\n");
2523" Note that some segments are missing from the outer square, so you must\n");
2525" use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
2528" file `box.1.node', with twelve vertices. The last four vertices were\n");
2530" added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
2532" from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
2534" other vertices but 4 have been marked to indicate that they lie on a\n");
2535 printf(
" boundary.\n\n");
2536 printf(
" 12 2 0 1\n");
2537 printf(
" 1 0 0 5\n");
2538 printf(
" 2 0 3 5\n");
2539 printf(
" 3 3 0 1\n");
2540 printf(
" 4 3 3 33\n");
2541 printf(
" 5 1 1 1\n");
2542 printf(
" 6 1 2 10\n");
2543 printf(
" 7 2 1 1\n");
2544 printf(
" 8 2 2 10\n");
2545 printf(
" 9 0 1.5 5\n");
2546 printf(
" 10 1.5 0 1\n");
2547 printf(
" 11 3 1.5 1\n");
2548 printf(
" 12 1.5 3 1\n");
2549 printf(
" # Generated by triangle -pqc box.poly\n");
2551 printf(
" Here is the output file `box.1.ele', with twelve triangles.\n");
2553 printf(
" 12 3 0\n");
2554 printf(
" 1 5 6 9\n");
2555 printf(
" 2 10 3 7\n");
2556 printf(
" 3 6 8 12\n");
2557 printf(
" 4 9 1 5\n");
2558 printf(
" 5 6 2 9\n");
2559 printf(
" 6 7 3 11\n");
2560 printf(
" 7 11 4 8\n");
2561 printf(
" 8 7 5 10\n");
2562 printf(
" 9 12 2 6\n");
2563 printf(
" 10 8 7 11\n");
2564 printf(
" 11 5 1 10\n");
2565 printf(
" 12 8 4 12\n");
2566 printf(
" # Generated by triangle -pqc box.poly\n\n");
2568" Here is the output file `box.1.poly'. Note that segments have been added\n"
2571" to represent the convex hull, and some segments have been subdivided by\n");
2573" newly added vertices. Note also that <# of vertices> is set to zero to\n");
2574 printf(
" indicate that the vertices should be read from the .node file.\n");
2576 printf(
" 0 2 0 1\n");
2578 printf(
" 1 1 9 5\n");
2579 printf(
" 2 5 7 1\n");
2580 printf(
" 3 8 7 1\n");
2581 printf(
" 4 6 8 10\n");
2582 printf(
" 5 5 6 1\n");
2583 printf(
" 6 3 10 1\n");
2584 printf(
" 7 4 11 1\n");
2585 printf(
" 8 2 12 1\n");
2586 printf(
" 9 9 2 5\n");
2587 printf(
" 10 10 1 1\n");
2588 printf(
" 11 11 3 1\n");
2589 printf(
" 12 12 4 1\n");
2591 printf(
" 1 1.5 1.5\n");
2592 printf(
" # Generated by triangle -pqc box.poly\n");
2594 printf(
"Refinement and Area Constraints:\n");
2597" The -r switch causes a mesh (.node and .ele files) to be read and\n");
2599" refined. If the -p switch is also used, a .poly file is read and used to\n"
2602" specify edges that are constrained and cannot be eliminated (although\n");
2604" they can be subdivided into smaller edges) by the refinement process.\n");
2607" When you refine a mesh, you generally want to impose tighter constraints.\n"
2610" One way to accomplish this is to use -q with a larger angle, or -a\n");
2612" followed by a smaller area than you used to generate the mesh you are\n");
2614" refining. Another way to do this is to create an .area file, which\n");
2616" specifies a maximum area for each triangle, and use the -a switch\n");
2618" (without a number following). Each triangle's area constraint is applied\n"
2621" to that triangle. Area constraints tend to diffuse as the mesh is\n");
2623" refined, so if there are large variations in area constraint between\n");
2625" adjacent triangles, you may not get the results you want. In that case,\n"
2628" consider instead using the -u switch and writing a C procedure that\n");
2629 printf(
" determines which triangles are too large.\n\n");
2631" If you are refining a mesh composed of linear (three-node) elements, the\n"
2634" output mesh contains all the nodes present in the input mesh, in the same\n"
2637" order, with new nodes added at the end of the .node file. However, the\n");
2639" refinement is not hierarchical: there is no guarantee that each output\n");
2641" element is contained in a single input element. Often, an output element\n"
2644" can overlap two or three input elements, and some input edges are not\n");
2646" present in the output mesh. Hence, a sequence of refined meshes forms a\n"
2649" hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
2651" mesh of higher-order elements, the hierarchical property applies only to\n"
2654" the nodes at the corners of an element; the midpoint nodes on each edge\n");
2655 printf(
" are discarded before the mesh is refined.\n\n");
2657" Maximum area constraints in .poly files operate differently from those in\n"
2660" .area files. A maximum area in a .poly file applies to the whole\n");
2662" (segment-bounded) region in which a point falls, whereas a maximum area\n");
2664" in an .area file applies to only one triangle. Area constraints in .poly\n"
2667" files are used only when a mesh is first generated, whereas area\n");
2669" constraints in .area files are used only to refine an existing mesh, and\n"
2672" are typically based on a posteriori error estimates resulting from a\n");
2673 printf(
" finite element simulation on that mesh.\n\n");
2675" `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
2677" refines the triangulation to enforce a 25 degree minimum angle, and then\n"
2680" writes the refined triangulation to object.2.node and object.2.ele.\n");
2683" `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
2686" After reconstructing the mesh and its subsegments, Triangle refines the\n");
2688" mesh so that no triangle has area greater than 6.2, and furthermore the\n");
2690" triangles satisfy the maximum area constraints in z.3.area. No angle\n");
2692" bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
2694 printf(
" z.4.poly.\n\n");
2696" The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
2698" x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
2699 printf(
" suitable for multigrid.\n\n");
2700 printf(
"Convex Hulls and Mesh Boundaries:\n\n");
2702" If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
2704" hull as a by-product in the output .poly file if you use the -c switch.\n");
2706" There are faster algorithms for finding a two-dimensional convex hull\n");
2707 printf(
" than triangulation, of course, but this one comes for free.\n\n");
2709" If the input is an unconstrained mesh (you are using the -r switch but\n");
2711" not the -p switch), Triangle produces a list of its boundary edges\n");
2713" (including hole boundaries) as a by-product when you use the -c switch.\n");
2715" If you also use the -p switch, the output .poly file contains all the\n");
2716 printf(
" segments from the input .poly file as well.\n\n");
2717 printf(
"Voronoi Diagrams:\n\n");
2719" The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
2721" .v.edge. For example, `triangle -v points' reads points.node, produces\n");
2723" its Delaunay triangulation in points.1.node and points.1.ele, and\n");
2725" produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
2728" .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
2730" file contains a list of all Voronoi edges, some of which may be infinite\n"
2733" rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
2734 printf(
" vertices through Triangle, if so desired.)\n\n");
2736" This implementation does not use exact arithmetic to compute the Voronoi\n"
2739" vertices, and does not check whether neighboring vertices are identical.\n"
2742" Be forewarned that if the Delaunay triangulation is degenerate or\n");
2744" near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
2745 printf(
" crossing edges.\n\n");
2747" The result is a valid Voronoi diagram only if Triangle's output is a true\n"
2750" Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
2752" may contain crossing edges and other pathology) if the output is a CDT or\n"
2755" CCDT, or if it has holes or concavities. If the triangulated domain is\n");
2757" convex and has no holes, you can use -D switch to force Triangle to\n");
2759" construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
2760 printf(
" Voronoi diagram will be valid.\n\n");
2761 printf(
"Mesh Topology:\n\n");
2763" You may wish to know which triangles are adjacent to a certain Delaunay\n");
2765" edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
2767" Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
2769" each other. All of this information can be found by cross-referencing\n");
2771" output files with the recollection that the Delaunay triangulation and\n");
2772 printf(
" the Voronoi diagram are planar duals.\n\n");
2774" Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
2776" the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
2778" wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
2780" vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
2781 printf(
" of vertex k of the corresponding .node file.\n\n");
2783" Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
2785" vertices of the corresponding Voronoi edge. If the endpoints of a\n");
2787" Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
2790" and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
2793" respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
2796" at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
2799" a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
2802" adjoin the right and left sides of the corresponding Voronoi edge,\n");
2804" respectively. To find which Voronoi cells are adjacent to each other,\n");
2805 printf(
" just read the list of Delaunay edges.\n\n");
2807" Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
2810" but you can reconstructed it straightforwardly. For instance, to find\n");
2812" all the edges of Voronoi cell 1, search the output .edge file for every\n");
2814" edge that has input vertex 1 as an endpoint. The corresponding dual\n");
2816" edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
2819" For each Voronoi vertex, the .neigh file gives a list of the three\n");
2821" Voronoi vertices attached to it. You might find this more convenient\n");
2822 printf(
" than the .v.edge file.\n\n");
2823 printf(
"Quadratic Elements:\n\n");
2825" Triangle generates meshes with subparametric quadratic elements if the\n");
2827" -o2 switch is specified. Quadratic elements have six nodes per element,\n"
2830" rather than three. `Subparametric' means that the edges of the triangles\n"
2833" are always straight, so that subparametric quadratic elements are\n");
2835" geometrically identical to linear elements, even though they can be used\n"
2838" with quadratic interpolating functions. The three extra nodes of an\n");
2840" element fall at the midpoints of the three edges, with the fourth, fifth,\n"
2843" and sixth nodes appearing opposite the first, second, and third corners\n");
2844 printf(
" respectively.\n\n");
2845 printf(
"Domains with Small Angles:\n\n");
2847" If two input segments adjoin each other at a small angle, clearly the -q\n"
2850" switch cannot remove the small angle. Moreover, Triangle may have no\n");
2852" choice but to generate additional triangles whose smallest angles are\n");
2854" smaller than the specified bound. However, these triangles only appear\n");
2856" between input segments separated by small angles. Moreover, if you\n");
2858" request a minimum angle of theta degrees, Triangle will generally produce\n"
2861" no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
2863 printf(
" the minimum angle.\n\n");
2864 printf(
"Statistics:\n\n");
2866" After generating a mesh, Triangle prints a count of entities in the\n");
2868" output mesh, including the number of vertices, triangles, edges, exterior\n"
2871" boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
2873" including hole boundaries), interior boundary edges (i.e. subsegments of\n"
2876" input segments not on the boundary), and total subsegments. If you've\n");
2878" forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
2881" with the -rNEP switches to read the mesh and print the statistics without\n"
2884" writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
2887" The -V switch produces extended statistics, including a rough estimate\n");
2889" of memory use, the number of calls to geometric predicates, and\n");
2891" histograms of the angles and the aspect ratios of the triangles in the\n");
2892 printf(
" mesh.\n\n");
2893 printf(
"Exact Arithmetic:\n\n");
2895" Triangle uses adaptive exact arithmetic to perform what computational\n");
2897" geometers call the `orientation' and `incircle' tests. If the floating-\n"
2900" point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
2902" most workstations do), and does not use extended precision internal\n");
2904" floating-point registers, then your output is guaranteed to be an\n");
2906" absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
2909" error notwithstanding. The word `adaptive' implies that these arithmetic\n"
2912" routines compute the result only to the precision necessary to guarantee\n"
2915" correctness, so they are usually nearly as fast as their approximate\n");
2916 printf(
" counterparts.\n\n");
2918" May CPUs, including Intel x86 processors, have extended precision\n");
2920" floating-point registers. These must be reconfigured so their precision\n"
2923" is reduced to memory precision. Triangle does this if it is compiled\n");
2924 printf(
" correctly. See the makefile for details.\n\n");
2926" The exact tests can be disabled with the -X switch. On most inputs, this\n"
2929" switch reduces the computation time by about eight percent--it's not\n");
2931" worth the risk. There are rare difficult inputs (having many collinear\n");
2933" and cocircular vertices), however, for which the difference in speed\n");
2935" could be a factor of two. Be forewarned that these are precisely the\n");
2937" inputs most likely to cause errors if you use the -X switch. Hence, the\n"
2939 printf(
" -X switch is not recommended.\n\n");
2941" Unfortunately, the exact tests don't solve every numerical problem.\n");
2943" Exact arithmetic is not used to compute the positions of new vertices,\n");
2945" because the bit complexity of vertex coordinates would grow without\n");
2947" bound. Hence, segment intersections aren't computed exactly; in very\n");
2949" unusual cases, roundoff error in computing an intersection point might\n");
2951" actually lead to an inverted triangle and an invalid triangulation.\n");
2953" (This is one reason to specify your own intersection points in your .poly\n"
2956" files.) Similarly, exact arithmetic is not used to compute the vertices\n"
2958 printf(
" of the Voronoi diagram.\n\n");
2960" Another pair of problems not solved by the exact arithmetic routines is\n");
2962" underflow and overflow. If Triangle is compiled for double precision\n");
2964" arithmetic, I believe that Triangle's geometric predicates work correctly\n"
2967" if the exponent of every input coordinate falls in the range [-148, 201].\n"
2970" Underflow can silently prevent the orientation and incircle tests from\n");
2972" being performed exactly, while overflow typically causes a floating\n");
2973 printf(
" exception.\n\n");
2974 printf(
"Calling Triangle from Another Program:\n\n");
2975 printf(
" Read the file triangle.h for details.\n\n");
2976 printf(
"Troubleshooting:\n\n");
2977 printf(
" Please read this section before mailing me bugs.\n\n");
2978 printf(
" `My output mesh has no triangles!'\n\n");
2980" If you're using a PSLG, you've probably failed to specify a proper set\n"
2983" of bounding segments, or forgotten to use the -c switch. Or you may\n");
2985" have placed a hole badly, thereby eating all your triangles. To test\n");
2986 printf(
" these possibilities, try again with the -c and -O switches.\n");
2988" Alternatively, all your input vertices may be collinear, in which case\n"
2990 printf(
" you can hardly expect to triangulate them.\n\n");
2991 printf(
" `Triangle doesn't terminate, or just crashes.'\n\n");
2993" Bad things can happen when triangles get so small that the distance\n");
2995" between their vertices isn't much larger than the precision of your\n");
2997" machine's arithmetic. If you've compiled Triangle for single-precision\n"
3000" arithmetic, you might do better by recompiling it for double-precision.\n"
3003" Then again, you might just have to settle for more lenient constraints\n"
3006" on the minimum angle and the maximum area than you had planned.\n");
3009" You can minimize precision problems by ensuring that the origin lies\n");
3011" inside your vertex set, or even inside the densest part of your\n");
3013" mesh. If you're triangulating an object whose x-coordinates all fall\n");
3015" between 6247133 and 6247134, you're not leaving much floating-point\n");
3016 printf(
" precision for Triangle to work with.\n\n");
3018" Precision problems can occur covertly if the input PSLG contains two\n");
3020" segments that meet (or intersect) at an extremely small angle, or if\n");
3022" such an angle is introduced by the -c switch. If you don't realize\n");
3024" that a tiny angle is being formed, you might never discover why\n");
3026" Triangle is crashing. To check for this possibility, use the -S switch\n"
3029" (with an appropriate limit on the number of Steiner points, found by\n");
3031" trial-and-error) to stop Triangle early, and view the output .poly file\n"
3034" with Show Me (described below). Look carefully for regions where dense\n"
3037" clusters of vertices are forming and for small angles between segments.\n"
3040" Zoom in closely, as such segments might look like a single segment from\n"
3042 printf(
" a distance.\n\n");
3044" If some of the input values are too large, Triangle may suffer a\n");
3046" floating exception due to overflow when attempting to perform an\n");
3048" orientation or incircle test. (Read the section on exact arithmetic\n");
3050" above.) Again, I recommend compiling Triangle for double (rather\n");
3051 printf(
" than single) precision arithmetic.\n\n");
3053" Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
3055" -u) with an input that is not segment-bounded--that is, if your input\n");
3057" is a vertex set, or you're using the -c switch. If the convex hull of\n"
3060" your input vertices has collinear vertices on its boundary, an input\n");
3062" vertex that you think lies on the convex hull might actually lie just\n");
3064" inside the convex hull. If so, the vertex and the nearby convex hull\n");
3066" edge form an extremely thin triangle. When Triangle tries to refine\n");
3068" the mesh to enforce angle and area constraints, Triangle might generate\n"
3071" extremely tiny triangles, or it might fail because of insufficient\n");
3072 printf(
" floating-point precision.\n\n");
3074" `The numbering of the output vertices doesn't match the input vertices.'\n"
3078" You may have had duplicate input vertices, or you may have eaten some\n");
3080" of your input vertices with a hole, or by placing them outside the area\n"
3083" enclosed by segments. In any case, you can solve the problem by not\n");
3084 printf(
" using the -j switch.\n\n");
3086" `Triangle executes without incident, but when I look at the resulting\n");
3088" mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
3091" If you select the -X switch, Triangle occasionally makes mistakes due\n");
3093" to floating-point roundoff error. Although these errors are rare,\n");
3095" don't use the -X switch. If you still have problems, please report the\n"
3097 printf(
" bug.\n\n");
3099" `Triangle executes without incident, but when I look at the resulting\n");
3100 printf(
" Voronoi diagram, it has overlapping edges or other geometric\n");
3101 printf(
" inconsistencies.'\n");
3104" If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
3107" diagram if the domain you are triangulating is convex and free of\n");
3109" holes, and you use the -D switch to construct a conforming Delaunay\n");
3110 printf(
" triangulation (instead of a CDT or CCDT).\n\n");
3112" Strange things can happen if you've taken liberties with your PSLG. Do\n");
3114" you have a vertex lying in the middle of a segment? Triangle sometimes\n");
3116" copes poorly with that sort of thing. Do you want to lay out a collinear\n"
3119" row of evenly spaced, segment-connected vertices? Have you simply\n");
3121" defined one long segment connecting the leftmost vertex to the rightmost\n"
3124" vertex, and a bunch of vertices lying along it? This method occasionally\n"
3127" works, especially with horizontal and vertical lines, but often it\n");
3129" doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
3131 printf(
" separate segment. If you don't like it, tough.\n\n");
3133" Furthermore, if you have segments that intersect other than at their\n");
3135" endpoints, try not to let the intersections fall extremely close to PSLG\n"
3137 printf(
" vertices or each other.\n\n");
3139" If you have problems refining a triangulation not produced by Triangle:\n");
3141" Are you sure the triangulation is geometrically valid? Is it formatted\n");
3143" correctly for Triangle? Are the triangles all listed so the first three\n"
3146" vertices are their corners in counterclockwise order? Are all of the\n");
3148" triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
3150 printf(
" assumes that it starts with a CDT.\n\n");
3151 printf(
"Show Me:\n\n");
3153" Triangle comes with a separate program named `Show Me', whose primary\n");
3155" purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
3158" purpose is to check the validity of your input files, and do so more\n");
3160" thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
3162" you have the X Windows system. Sorry, Microsoft Windows users.\n");
3164 printf(
"Triangle on the Web:\n");
3166 printf(
" To see an illustrated version of these instructions, check out\n");
3168 printf(
" http://www.cs.cmu.edu/~quake/triangle.html\n");
3170 printf(
"A Brief Plea:\n");
3173" If you use Triangle, and especially if you use it to accomplish real\n");
3175" work, I would like very much to hear from you. A short letter or email\n");
3177" (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
3180" to me. The more people I know are using this program, the more easily I\n"
3183" can justify spending time on improvements, which in turn will benefit\n");
3185" you. Also, I can put you on a list to receive email whenever a new\n");
3186 printf(
" version of Triangle is available.\n\n");
3188" If you use a mesh generated by Triangle in a publication, please include\n"
3191" an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
3194" If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
3196" ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
3198" Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
3200" Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
3202" Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
3204" Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
3206 printf(
" Geometry.)'\n\n");
3207 printf(
"Research credit:\n\n");
3209" Of course, I can take credit for only a fraction of the ideas that made\n");
3211" this mesh generator possible. Triangle owes its existence to the efforts\n"
3214" of many fine computational geometers and other researchers, including\n");
3216" Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
3219" Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
3221" Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
3223" Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
3225" Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
3227 printf(
" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
3229" Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
3230 printf(
" source code for references.\n\n");
3244 printf(
" Please report this bug to jrs@cs.berkeley.edu\n");
3245 printf(
" Include the message above, your input data set, and the exact\n");
3246 printf(
" command line you used to run Triangle.\n");
3257#ifdef ANSI_DECLARATORS
3278 b->
poly =
b->refine =
b->quality = 0;
3279 b->vararea =
b->fixedarea =
b->usertest = 0;
3280 b->regionattrib =
b->convex =
b->weighted =
b->jettison = 0;
3282 b->edgesout =
b->voronoi =
b->neighbors =
b->geomview = 0;
3283 b->nobound =
b->nopolywritten =
b->nonodewritten =
b->noelewritten = 0;
3284 b->noiterationnum = 0;
3285 b->noholes =
b->noexact = 0;
3286 b->incremental =
b->sweepline = 0;
3296 b->quiet =
b->verbose = 0;
3298 b->innodefilename[0] =
'\0';
3303 if (argv[i][0] ==
'-') {
3305 for (j =
STARTINDEX; argv[i][j] !=
'\0'; j++) {
3306 if (argv[i][j] ==
'p') {
3310 if (argv[i][j] ==
'r') {
3313 if (argv[i][j] ==
'q') {
3315 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3316 (argv[i][j + 1] ==
'.')) {
3318 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3319 (argv[i][j + 1] ==
'.')) {
3321 workstring[k] = argv[i][j];
3324 workstring[k] =
'\0';
3325 b->minangle = (
REAL) strtod(workstring, (
char **) NULL);
3330 if (argv[i][j] ==
'a') {
3332 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3333 (argv[i][j + 1] ==
'.')) {
3336 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3337 (argv[i][j + 1] ==
'.')) {
3339 workstring[k] = argv[i][j];
3342 workstring[k] =
'\0';
3343 b->maxarea = (
REAL) strtod(workstring, (
char **) NULL);
3344 if (
b->maxarea <= 0.0) {
3345 printf(
"Error: Maximum area must be greater than zero.\n");
3352 if (argv[i][j] ==
'u') {
3357 if (argv[i][j] ==
'A') {
3358 b->regionattrib = 1;
3360 if (argv[i][j] ==
'c') {
3363 if (argv[i][j] ==
'w') {
3366 if (argv[i][j] ==
'W') {
3369 if (argv[i][j] ==
'j') {
3372 if (argv[i][j] ==
'z') {
3375 if (argv[i][j] ==
'e') {
3378 if (argv[i][j] ==
'v') {
3381 if (argv[i][j] ==
'n') {
3384 if (argv[i][j] ==
'g') {
3387 if (argv[i][j] ==
'B') {
3390 if (argv[i][j] ==
'P') {
3391 b->nopolywritten = 1;
3393 if (argv[i][j] ==
'N') {
3394 b->nonodewritten = 1;
3396 if (argv[i][j] ==
'E') {
3397 b->noelewritten = 1;
3400 if (argv[i][j] ==
'I') {
3401 b->noiterationnum = 1;
3404 if (argv[i][j] ==
'O') {
3407 if (argv[i][j] ==
'X') {
3410 if (argv[i][j] ==
'o') {
3411 if (argv[i][j + 1] ==
'2') {
3417 if (argv[i][j] ==
'Y') {
3420 if (argv[i][j] ==
'S') {
3422 while ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3424 b->steiner =
b->steiner * 10 + (
int) (argv[i][j] -
'0');
3429 if (argv[i][j] ==
'i') {
3432 if (argv[i][j] ==
'F') {
3436 if (argv[i][j] ==
'l') {
3441 if (argv[i][j] ==
's') {
3444 if ((argv[i][j] ==
'D') || (argv[i][j] ==
'L')) {
3449 if (argv[i][j] ==
'C') {
3453 if (argv[i][j] ==
'Q') {
3456 if (argv[i][j] ==
'V') {
3460 if ((argv[i][j] ==
'h') || (argv[i][j] ==
'H') ||
3461 (argv[i][j] ==
'?')) {
3474 if (
b->innodefilename[0] ==
'\0') {
3477 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 5],
".node")) {
3478 b->innodefilename[strlen(
b->innodefilename) - 5] =
'\0';
3480 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 5],
".poly")) {
3481 b->innodefilename[strlen(
b->innodefilename) - 5] =
'\0';
3485 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 4],
".ele")) {
3486 b->innodefilename[strlen(
b->innodefilename) - 4] =
'\0';
3489 if (!strcmp(&
b->innodefilename[strlen(
b->innodefilename) - 5],
".area")) {
3490 b->innodefilename[strlen(
b->innodefilename) - 5] =
'\0';
3497 b->usesegments =
b->poly ||
b->refine ||
b->quality ||
b->convex;
3498 b->goodangle = cos(
b->minangle *
PI / 180.0);
3499 if (
b->goodangle == 1.0) {
3500 b->offconstant = 0.0;
3502 b->offconstant = 0.475 * sqrt((1.0 +
b->goodangle) / (1.0 -
b->goodangle));
3504 b->goodangle *=
b->goodangle;
3505 if (
b->refine &&
b->noiterationnum) {
3507 "Error: You cannot use the -I switch when refining a triangulation.\n");
3512 if (!
b->refine && !
b->poly) {
3517 if (
b->refine || !
b->poly) {
3518 b->regionattrib = 0;
3522 if (
b->weighted && (
b->poly ||
b->quality)) {
3525 printf(
"Warning: weighted triangulations (-w, -W) are incompatible\n");
3526 printf(
" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
3530 if (
b->jettison &&
b->nonodewritten && !
b->quiet) {
3531 printf(
"Warning: -j and -N switches are somewhat incompatible.\n");
3532 printf(
" If any vertices are jettisoned, you will need the output\n");
3533 printf(
" .node file to reconstruct the new node indices.");
3537 strcpy(
b->inpolyfilename,
b->innodefilename);
3538 strcpy(
b->inelefilename,
b->innodefilename);
3539 strcpy(
b->areafilename,
b->innodefilename);
3541 strcpy(workstring,
b->innodefilename);
3543 while (workstring[j] !=
'\0') {
3544 if ((workstring[j] ==
'.') && (workstring[j + 1] !=
'\0')) {
3550 if (increment > 0) {
3553 if ((workstring[j] >=
'0') && (workstring[j] <=
'9')) {
3554 meshnumber = meshnumber * 10 + (
int) (workstring[j] -
'0');
3559 }
while (workstring[j] !=
'\0');
3561 if (
b->noiterationnum) {
3562 strcpy(
b->outnodefilename,
b->innodefilename);
3563 strcpy(
b->outelefilename,
b->innodefilename);
3564 strcpy(
b->edgefilename,
b->innodefilename);
3565 strcpy(
b->vnodefilename,
b->innodefilename);
3566 strcpy(
b->vedgefilename,
b->innodefilename);
3567 strcpy(
b->neighborfilename,
b->innodefilename);
3568 strcpy(
b->offfilename,
b->innodefilename);
3569 strcat(
b->outnodefilename,
".node");
3570 strcat(
b->outelefilename,
".ele");
3571 strcat(
b->edgefilename,
".edge");
3572 strcat(
b->vnodefilename,
".v.node");
3573 strcat(
b->vedgefilename,
".v.edge");
3574 strcat(
b->neighborfilename,
".neigh");
3575 strcat(
b->offfilename,
".off");
3576 }
else if (increment == 0) {
3577 strcpy(
b->outnodefilename,
b->innodefilename);
3578 strcpy(
b->outpolyfilename,
b->innodefilename);
3579 strcpy(
b->outelefilename,
b->innodefilename);
3580 strcpy(
b->edgefilename,
b->innodefilename);
3581 strcpy(
b->vnodefilename,
b->innodefilename);
3582 strcpy(
b->vedgefilename,
b->innodefilename);
3583 strcpy(
b->neighborfilename,
b->innodefilename);
3584 strcpy(
b->offfilename,
b->innodefilename);
3585 strcat(
b->outnodefilename,
".1.node");
3586 strcat(
b->outpolyfilename,
".1.poly");
3587 strcat(
b->outelefilename,
".1.ele");
3588 strcat(
b->edgefilename,
".1.edge");
3589 strcat(
b->vnodefilename,
".1.v.node");
3590 strcat(
b->vedgefilename,
".1.v.edge");
3591 strcat(
b->neighborfilename,
".1.neigh");
3592 strcat(
b->offfilename,
".1.off");
3594 workstring[increment] =
'%';
3595 workstring[increment + 1] =
'd';
3596 workstring[increment + 2] =
'\0';
3597 sprintf(
b->outnodefilename, workstring, meshnumber + 1);
3598 strcpy(
b->outpolyfilename,
b->outnodefilename);
3599 strcpy(
b->outelefilename,
b->outnodefilename);
3600 strcpy(
b->edgefilename,
b->outnodefilename);
3601 strcpy(
b->vnodefilename,
b->outnodefilename);
3602 strcpy(
b->vedgefilename,
b->outnodefilename);
3603 strcpy(
b->neighborfilename,
b->outnodefilename);
3604 strcpy(
b->offfilename,
b->outnodefilename);
3605 strcat(
b->outnodefilename,
".node");
3606 strcat(
b->outpolyfilename,
".poly");
3607 strcat(
b->outelefilename,
".ele");
3608 strcat(
b->edgefilename,
".edge");
3609 strcat(
b->vnodefilename,
".v.node");
3610 strcat(
b->vedgefilename,
".v.edge");
3611 strcat(
b->neighborfilename,
".neigh");
3612 strcat(
b->offfilename,
".off");
3614 strcat(
b->innodefilename,
".node");
3615 strcat(
b->inpolyfilename,
".poly");
3616 strcat(
b->inelefilename,
".ele");
3617 strcat(
b->areafilename,
".area");
3640#ifdef ANSI_DECLARATORS
3650 struct otri printtri;
3651 struct osub printsh;
3654 printf(
"triangle x%zx with orientation %d:\n", (
size_t) t->
tri,
3657 if (printtri.
tri ==
m->dummytri) {
3658 printf(
" [0] = Outer space\n");
3660 printf(
" [0] = x%zx %d\n", (
size_t) printtri.
tri,
3664 if (printtri.
tri ==
m->dummytri) {
3665 printf(
" [1] = Outer space\n");
3667 printf(
" [1] = x%zx %d\n", (
size_t) printtri.
tri,
3671 if (printtri.
tri ==
m->dummytri) {
3672 printf(
" [2] = Outer space\n");
3674 printf(
" [2] = x%zx %d\n", (
size_t) printtri.
tri,
3678 org(*t, printvertex);
3679 if (printvertex == (
vertex) NULL)
3680 printf(
" Origin[%d] = NULL\n", (t->
orient + 1) % 3 + 3);
3682 printf(
" Origin[%d] = x%zx (%.12g, %.12g)\n",
3683 (t->
orient + 1) % 3 + 3, (
size_t) printvertex,
3684 printvertex[0], printvertex[1]);
3685 dest(*t, printvertex);
3686 if (printvertex == (
vertex) NULL)
3687 printf(
" Dest [%d] = NULL\n", (t->
orient + 2) % 3 + 3);
3689 printf(
" Dest [%d] = x%zx (%.12g, %.12g)\n",
3690 (t->
orient + 2) % 3 + 3, (
size_t) printvertex,
3691 printvertex[0], printvertex[1]);
3692 apex(*t, printvertex);
3693 if (printvertex == (
vertex) NULL)
3694 printf(
" Apex [%d] = NULL\n", t->
orient + 3);
3696 printf(
" Apex [%d] = x%zx (%.12g, %.12g)\n",
3697 t->
orient + 3, (
size_t) printvertex,
3698 printvertex[0], printvertex[1]);
3700 if (
b->usesegments) {
3702 if (printsh.
ss !=
m->dummysub) {
3703 printf(
" [6] = x%zx %d\n", (
size_t) printsh.
ss,
3707 if (printsh.
ss !=
m->dummysub) {
3708 printf(
" [7] = x%zx %d\n", (
size_t) printsh.
ss,
3712 if (printsh.
ss !=
m->dummysub) {
3713 printf(
" [8] = x%zx %d\n", (
size_t) printsh.
ss,
3719 printf(
" Area constraint: %.4g\n",
areabound(*t));
3734#ifdef ANSI_DECLARATORS
3744 struct osub printsh;
3745 struct otri printtri;
3750 printf(
"subsegment x%zx with orientation %d and mark %d:\n",
3753 if (printsh.
ss ==
m->dummysub) {
3754 printf(
" [0] = No subsegment\n");
3756 printf(
" [0] = x%zx %d\n", (
size_t) printsh.
ss,
3760 if (printsh.
ss ==
m->dummysub) {
3761 printf(
" [1] = No subsegment\n");
3763 printf(
" [1] = x%zx %d\n", (
size_t) printsh.
ss,
3767 sorg(*s, printvertex);
3768 if (printvertex == (
vertex) NULL)
3769 printf(
" Origin[%d] = NULL\n", 2 + s->
ssorient);
3771 printf(
" Origin[%d] = x%zx (%.12g, %.12g)\n",
3772 2 + s->
ssorient, (
size_t) printvertex,
3773 printvertex[0], printvertex[1]);
3774 sdest(*s, printvertex);
3775 if (printvertex == (
vertex) NULL)
3776 printf(
" Dest [%d] = NULL\n", 3 - s->
ssorient);
3778 printf(
" Dest [%d] = x%zx (%.12g, %.12g)\n",
3779 3 - s->
ssorient, (
size_t) printvertex,
3780 printvertex[0], printvertex[1]);
3783 if (printtri.
tri ==
m->dummytri) {
3784 printf(
" [6] = Outer space\n");
3786 printf(
" [6] = x%zx %d\n", (
size_t) printtri.
tri,
3790 if (printtri.
tri ==
m->dummytri) {
3791 printf(
" [7] = Outer space\n");
3793 printf(
" [7] = x%zx %d\n", (
size_t) printtri.
tri,
3798 if (printvertex == (
vertex) NULL)
3799 printf(
" Segment origin[%d] = NULL\n", 4 + s->
ssorient);
3801 printf(
" Segment origin[%d] = x%zx (%.12g, %.12g)\n",
3802 4 + s->
ssorient, (
size_t) printvertex,
3803 printvertex[0], printvertex[1]);
3805 if (printvertex == (
vertex) NULL)
3806 printf(
" Segment dest [%d] = NULL\n", 5 - s->
ssorient);
3808 printf(
" Segment dest [%d] = x%zx (%.12g, %.12g)\n",
3809 5 - s->
ssorient, (
size_t) printvertex,
3810 printvertex[0], printvertex[1]);
3830#ifdef ANSI_DECLARATORS
3864#ifdef ANSI_DECLARATORS
3880 alignptr = (uintptr_t) (pool->
nowblock + 1);
3910#ifdef ANSI_DECLARATORS
3935 if (firstitemcount == 0) {
3958#ifdef ANSI_DECLARATORS
3979#ifdef ANSI_DECLARATORS
4003 (
int)
sizeof(
VOID *) +
4007 *newblock = (
VOID *) NULL;
4014 alignptr = (uintptr_t) (pool->
nowblock + 1);
4042#ifdef ANSI_DECLARATORS
4065#ifdef ANSI_DECLARATORS
4078 alignptr = (uintptr_t) (pool->
pathblock + 1);
4101#ifdef ANSI_DECLARATORS
4114 return (
VOID *) NULL;
4122 alignptr = (uintptr_t) (pool->
pathblock + 1);
4166#ifdef ANSI_DECLARATORS
4182 m->triangles.alignbytes);
4184 alignptr = (uintptr_t)
m->dummytribase;
4186 (alignptr + (uintptr_t)
m->triangles.alignbytes -
4187 (alignptr % (uintptr_t)
m->triangles.alignbytes));
4200 if (
b->usesegments) {
4205 m->subsegs.alignbytes);
4207 alignptr = (uintptr_t)
m->dummysubbase;
4209 (alignptr + (uintptr_t)
m->subsegs.alignbytes -
4210 (alignptr % (uintptr_t)
m->subsegs.alignbytes));
4215 m->dummysub[0] = (
subseg)
m->dummysub;
4216 m->dummysub[1] = (
subseg)
m->dummysub;
4218 m->dummysub[2] = (
subseg) NULL;
4219 m->dummysub[3] = (
subseg) NULL;
4220 m->dummysub[4] = (
subseg) NULL;
4221 m->dummysub[5] = (
subseg) NULL;
4223 m->dummysub[6] = (
subseg)
m->dummytri;
4224 m->dummysub[7] = (
subseg)
m->dummytri;
4226 * (
int *) (
m->dummysub + 8) = 0;
4246#ifdef ANSI_DECLARATORS
4260 m->vertexmarkindex = ((
m->mesh_dim +
m->nextras) *
sizeof(
REAL) +
4263 vertexsize = (
m->vertexmarkindex + 2) *
sizeof(
int);
4267 m->vertex2triindex = (vertexsize +
sizeof(
triangle) - 1) /
4269 vertexsize = (
m->vertex2triindex + 1) *
sizeof(
triangle);
4289#ifdef ANSI_DECLARATORS
4304 m->highorderindex = 6 + (
b->usesegments * 3);
4306 trisize = ((
b->order + 1) * (
b->order + 2) / 2 + (
m->highorderindex - 3)) *
4310 m->elemattribindex = (trisize +
sizeof(
REAL) - 1) /
sizeof(
REAL);
4314 m->areaboundindex =
m->elemattribindex +
m->eextras +
b->regionattrib;
4318 trisize = (
m->areaboundindex + 1) *
sizeof(
REAL);
4319 }
else if (
m->eextras +
b->regionattrib > 0) {
4320 trisize =
m->areaboundindex *
sizeof(
REAL);
4326 if ((
b->voronoi ||
b->neighbors) &&
4328 trisize = 6 *
sizeof(
triangle) +
sizeof(
int);
4333 (2 *
m->invertices - 2) >
TRIPERBLOCK ? (2 *
m->invertices - 2) :
4336 if (
b->usesegments) {
4343 dummyinit(
m,
b,
m->triangles.itembytes,
m->subsegs.itembytes);
4356#ifdef ANSI_DECLARATORS
4377#ifdef ANSI_DECLARATORS
4389 if (newtriangle == (
triangle *) NULL) {
4392 }
while (
deadtri(newtriangle));
4402#ifdef ANSI_DECLARATORS
4423#ifdef ANSI_DECLARATORS
4435 if (newsubseg == (
subseg *) NULL) {
4448#ifdef ANSI_DECLARATORS
4469#ifdef ANSI_DECLARATORS
4481 if (newvertex == (
vertex) NULL) {
4497#ifdef ANSI_DECLARATORS
4500void badsubsegdealloc(
m, dyingseg)
4522#ifdef ANSI_DECLARATORS
4534 if (newseg == (
struct badsubseg *) NULL) {
4555#ifdef ANSI_DECLARATORS
4570 getblock =
m->vertices.firstblock;
4571 current =
b->firstnumber;
4574 if (current +
m->vertices.itemsfirstblock <= number) {
4575 getblock = (
VOID **) *getblock;
4576 current +=
m->vertices.itemsfirstblock;
4577 while (current +
m->vertices.itemsperblock <= number) {
4578 getblock = (
VOID **) *getblock;
4579 current +=
m->vertices.itemsperblock;
4584 alignptr = (uintptr_t) (getblock + 1);
4585 foundvertex = (
char *) (alignptr + (uintptr_t)
m->vertices.alignbytes -
4586 (alignptr % (uintptr_t)
m->vertices.alignbytes));
4587 return (
vertex) (foundvertex +
m->vertices.itembytes * (number - current));
4596#ifdef ANSI_DECLARATORS
4607 if (
b->usesegments) {
4615 if ((
b->minangle > 0.0) ||
b->vararea ||
b->fixedarea ||
b->usertest) {
4637#ifdef ANSI_DECLARATORS
4643struct otri *newotri;
4658 if (
b->usesegments) {
4665 for (i = 0; i <
m->eextras; i++) {
4681#ifdef ANSI_DECLARATORS
4686struct osub *newsubseg;
4693 newsubseg->
ss[0] = (
subseg)
m->dummysub;
4694 newsubseg->
ss[1] = (
subseg)
m->dummysub;
4701 newsubseg->
ss[6] = (
subseg)
m->dummytri;
4702 newsubseg->
ss[7] = (
subseg)
m->dummytri;
4730#define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
4746#define Fast_Two_Sum_Tail(a, b, x, y) \
4750#define Fast_Two_Sum(a, b, x, y) \
4751 x = (REAL) (a + b); \
4752 Fast_Two_Sum_Tail(a, b, x, y)
4754#define Two_Sum_Tail(a, b, x, y) \
4755 bvirt = (REAL) (x - a); \
4756 avirt = x - bvirt; \
4757 bround = b - bvirt; \
4758 around = a - avirt; \
4761#define Two_Sum(a, b, x, y) \
4762 x = (REAL) (a + b); \
4763 Two_Sum_Tail(a, b, x, y)
4765#define Two_Diff_Tail(a, b, x, y) \
4766 bvirt = (REAL) (a - x); \
4767 avirt = x + bvirt; \
4768 bround = bvirt - b; \
4769 around = a - avirt; \
4772#define Two_Diff(a, b, x, y) \
4773 x = (REAL) (a - b); \
4774 Two_Diff_Tail(a, b, x, y)
4776#define Split(a, ahi, alo) \
4777 c = (REAL) (splitter * a); \
4778 abig = (REAL) (c - a); \
4782#define Two_Product_Tail(a, b, x, y) \
4783 Split(a, ahi, alo); \
4784 Split(b, bhi, blo); \
4785 err1 = x - (ahi * bhi); \
4786 err2 = err1 - (alo * bhi); \
4787 err3 = err2 - (ahi * blo); \
4788 y = (alo * blo) - err3
4790#define Two_Product(a, b, x, y) \
4791 x = (REAL) (a * b); \
4792 Two_Product_Tail(a, b, x, y)
4797#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
4798 x = (REAL) (a * b); \
4799 Split(a, ahi, alo); \
4800 err1 = x - (ahi * bhi); \
4801 err2 = err1 - (alo * bhi); \
4802 err3 = err2 - (ahi * blo); \
4803 y = (alo * blo) - err3
4807#define Square_Tail(a, x, y) \
4808 Split(a, ahi, alo); \
4809 err1 = x - (ahi * ahi); \
4810 err3 = err1 - ((ahi + ahi) * alo); \
4811 y = (alo * alo) - err3
4813#define Square(a, x, y) \
4814 x = (REAL) (a * a); \
4815 Square_Tail(a, x, y)
4820#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
4821 Two_Sum(a0, b , _i, x0); \
4822 Two_Sum(a1, _i, x2, x1)
4824#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
4825 Two_Diff(a0, b , _i, x0); \
4826 Two_Sum( a1, _i, x2, x1)
4828#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
4829 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
4830 Two_One_Sum(_j, _0, b1, x3, x2, x1)
4832#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
4833 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
4834 Two_One_Diff(_j, _0, b1, x3, x2, x1)
4838#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
4839 Split(b, bhi, blo); \
4840 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
4841 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
4842 Two_Sum(_i, _0, _k, x1); \
4843 Fast_Two_Sum(_j, _k, x3, x2)
4867 REAL check, lastcheck;
4875 _control87(_PC_24, _MCW_PC);
4877 _control87(_PC_53, _MCW_PC);
4883 fenv.__control_word = 4210;
4886 fenv.__control_word = 4722;
4906 every_other = !every_other;
4908 }
while ((check != 1.0) && (check != lastcheck));
4937#ifdef ANSI_DECLARATORS
4953 REAL avirt, bround, around;
4954 int eindex, findex, hindex;
4959 eindex = findex = 0;
4960 if ((fnow > enow) == (fnow > -enow)) {
4968 if ((eindex < elen) && (findex < flen)) {
4969 if ((fnow > enow) == (fnow > -enow)) {
4980 while ((eindex < elen) && (findex < flen)) {
4981 if ((fnow > enow) == (fnow > -enow)) {
4994 while (eindex < elen) {
5002 while (findex < flen) {
5010 if ((Q != 0.0) || (hindex == 0)) {
5031#ifdef ANSI_DECLARATORS
5049 REAL avirt, bround, around;
5052 REAL ahi, alo, bhi, blo;
5053 REAL err1, err2, err3;
5061 for (eindex = 1; eindex < elen; eindex++) {
5073 if ((Q != 0.0) || (hindex == 0)) {
5087#ifdef ANSI_DECLARATORS
5100 for (eindex = 1; eindex < elen; eindex++) {
5126#ifdef ANSI_DECLARATORS
5138 REAL acxtail, acytail, bcxtail, bcytail;
5140 REAL detlefttail, detrighttail;
5142 REAL B[4], C1[8], C2[12], D[16];
5144 int C1length, C2length, Dlength;
5151 REAL avirt, bround, around;
5154 REAL ahi, alo, bhi, blo;
5155 REAL err1, err2, err3;
5159 acx = (
REAL) (pa[0] - pc[0]);
5160 bcx = (
REAL) (pb[0] - pc[0]);
5161 acy = (
REAL) (pa[1] - pc[1]);
5162 bcy = (
REAL) (pb[1] - pc[1]);
5167 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
5168 B3, B[2], B[1], B[0]);
5173 if ((det >= errbound) || (-det >= errbound)) {
5182 if ((acxtail == 0.0) && (acytail == 0.0)
5183 && (bcxtail == 0.0) && (bcytail == 0.0)) {
5188 det += (acx * bcytail + bcy * acxtail)
5189 - (acy * bcxtail + bcx * acytail);
5190 if ((det >= errbound) || (-det >= errbound)) {
5212 return(D[Dlength - 1]);
5215#ifdef ANSI_DECLARATORS
5228 REAL detleft, detright, det;
5229 REAL detsum, errbound;
5231 m->counterclockcount++;
5233 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
5234 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
5235 det = detleft - detright;
5241 if (detleft > 0.0) {
5242 if (detright <= 0.0) {
5245 detsum = detleft + detright;
5247 }
else if (detleft < 0.0) {
5248 if (detright >= 0.0) {
5251 detsum = -detleft - detright;
5258 if ((det >= errbound) || (-det >= errbound)) {
5284#ifdef ANSI_DECLARATORS
5299 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5300 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5301 REAL bc[4], ca[4], ab[4];
5303 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
5304 int axbclen, axxbclen, aybclen, ayybclen, alen;
5305 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
5306 int bxcalen, bxxcalen, bycalen, byycalen, blen;
5307 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
5308 int cxablen, cxxablen, cyablen, cyyablen, clen;
5311 REAL fin1[1152], fin2[1152];
5312 REAL *finnow, *finother, *finswap;
5315 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
5316 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
5317 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
5318 REAL aa[4], bb[4], cc[4];
5324 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
5325 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
5326 int temp8len, temp16alen, temp16blen, temp16clen;
5327 int temp32alen, temp32blen, temp48len, temp64len;
5328 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
5329 int axtbblen, axtcclen, aytbblen, aytcclen;
5330 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
5331 int bxtaalen, bxtcclen, bytaalen, bytcclen;
5332 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
5333 int cxtaalen, cxtbblen, cytaalen, cytbblen;
5334 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
5335 int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
5336 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
5337 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
5338 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
5339 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
5340 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
5341 REAL abt[8], bct[8], cat[8];
5342 int abtlen, bctlen, catlen;
5343 REAL abtt[4], bctt[4], catt[4];
5344 int abttlen, bcttlen, cattlen;
5349 REAL avirt, bround, around;
5352 REAL ahi, alo, bhi, blo;
5353 REAL err1, err2, err3;
5357 adx = (
REAL) (pa[0] - pd[0]);
5358 bdx = (
REAL) (pb[0] - pd[0]);
5359 cdx = (
REAL) (pc[0] - pd[0]);
5360 ady = (
REAL) (pa[1] - pd[1]);
5361 bdy = (
REAL) (pb[1] - pd[1]);
5362 cdy = (
REAL) (pc[1] - pd[1]);
5366 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
5376 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
5386 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
5399 if ((det >= errbound) || (-det >= errbound)) {
5409 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
5410 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
5415 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
5416 - (bdy * cdxtail + cdx * bdytail))
5417 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
5418 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
5419 - (cdy * adxtail + adx * cdytail))
5420 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
5421 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
5422 - (ady * bdxtail + bdx * adytail))
5423 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
5424 if ((det >= errbound) || (-det >= errbound)) {
5431 if ((bdxtail != 0.0) || (bdytail != 0.0)
5432 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5433 Square(adx, adxadx1, adxadx0);
5434 Square(ady, adyady1, adyady0);
5435 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
5438 if ((cdxtail != 0.0) || (cdytail != 0.0)
5439 || (adxtail != 0.0) || (adytail != 0.0)) {
5440 Square(bdx, bdxbdx1, bdxbdx0);
5441 Square(bdy, bdybdy1, bdybdy0);
5442 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
5445 if ((adxtail != 0.0) || (adytail != 0.0)
5446 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5447 Square(cdx, cdxcdx1, cdxcdx0);
5448 Square(cdy, cdycdy1, cdycdy0);
5449 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
5453 if (adxtail != 0.0) {
5465 temp16blen, temp16b, temp32a);
5467 temp32alen, temp32a, temp48);
5470 finswap = finnow; finnow = finother; finother = finswap;
5472 if (adytail != 0.0) {
5484 temp16blen, temp16b, temp32a);
5486 temp32alen, temp32a, temp48);
5489 finswap = finnow; finnow = finother; finother = finswap;
5491 if (bdxtail != 0.0) {
5503 temp16blen, temp16b, temp32a);
5505 temp32alen, temp32a, temp48);
5508 finswap = finnow; finnow = finother; finother = finswap;
5510 if (bdytail != 0.0) {
5522 temp16blen, temp16b, temp32a);
5524 temp32alen, temp32a, temp48);
5527 finswap = finnow; finnow = finother; finother = finswap;
5529 if (cdxtail != 0.0) {
5541 temp16blen, temp16b, temp32a);
5543 temp32alen, temp32a, temp48);
5546 finswap = finnow; finnow = finother; finother = finswap;
5548 if (cdytail != 0.0) {
5560 temp16blen, temp16b, temp32a);
5562 temp32alen, temp32a, temp48);
5565 finswap = finnow; finnow = finother; finother = finswap;
5568 if ((adxtail != 0.0) || (adytail != 0.0)) {
5569 if ((bdxtail != 0.0) || (bdytail != 0.0)
5570 || (cdxtail != 0.0) || (cdytail != 0.0)) {
5573 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5585 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
5595 if (adxtail != 0.0) {
5601 temp32alen, temp32a, temp48);
5604 finswap = finnow; finnow = finother; finother = finswap;
5605 if (bdytail != 0.0) {
5611 finswap = finnow; finnow = finother; finother = finswap;
5613 if (cdytail != 0.0) {
5619 finswap = finnow; finnow = finother; finother = finswap;
5630 temp16blen, temp16b, temp32b);
5632 temp32blen, temp32b, temp64);
5635 finswap = finnow; finnow = finother; finother = finswap;
5637 if (adytail != 0.0) {
5643 temp32alen, temp32a, temp48);
5646 finswap = finnow; finnow = finother; finother = finswap;
5657 temp16blen, temp16b, temp32b);
5659 temp32blen, temp32b, temp64);
5662 finswap = finnow; finnow = finother; finother = finswap;
5665 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
5666 if ((cdxtail != 0.0) || (cdytail != 0.0)
5667 || (adxtail != 0.0) || (adytail != 0.0)) {
5670 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5682 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
5692 if (bdxtail != 0.0) {
5698 temp32alen, temp32a, temp48);
5701 finswap = finnow; finnow = finother; finother = finswap;
5702 if (cdytail != 0.0) {
5708 finswap = finnow; finnow = finother; finother = finswap;
5710 if (adytail != 0.0) {
5716 finswap = finnow; finnow = finother; finother = finswap;
5727 temp16blen, temp16b, temp32b);
5729 temp32blen, temp32b, temp64);
5732 finswap = finnow; finnow = finother; finother = finswap;
5734 if (bdytail != 0.0) {
5740 temp32alen, temp32a, temp48);
5743 finswap = finnow; finnow = finother; finother = finswap;
5754 temp16blen, temp16b, temp32b);
5756 temp32blen, temp32b, temp64);
5759 finswap = finnow; finnow = finother; finother = finswap;
5762 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
5763 if ((adxtail != 0.0) || (adytail != 0.0)
5764 || (bdxtail != 0.0) || (bdytail != 0.0)) {
5767 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
5779 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
5789 if (cdxtail != 0.0) {
5795 temp32alen, temp32a, temp48);
5798 finswap = finnow; finnow = finother; finother = finswap;
5799 if (adytail != 0.0) {
5805 finswap = finnow; finnow = finother; finother = finswap;
5807 if (bdytail != 0.0) {
5813 finswap = finnow; finnow = finother; finother = finswap;
5824 temp16blen, temp16b, temp32b);
5826 temp32blen, temp32b, temp64);
5829 finswap = finnow; finnow = finother; finother = finswap;
5831 if (cdytail != 0.0) {
5837 temp32alen, temp32a, temp48);
5840 finswap = finnow; finnow = finother; finother = finswap;
5851 temp16blen, temp16b, temp32b);
5853 temp32blen, temp32b, temp64);
5856 finswap = finnow; finnow = finother; finother = finswap;
5860 return finnow[finlength - 1];
5863#ifdef ANSI_DECLARATORS
5877 REAL adx, bdx, cdx, ady, bdy, cdy;
5878 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
5879 REAL alift, blift, clift;
5881 REAL permanent, errbound;
5885 adx = pa[0] - pd[0];
5886 bdx = pb[0] - pd[0];
5887 cdx = pc[0] - pd[0];
5888 ady = pa[1] - pd[1];
5889 bdy = pb[1] - pd[1];
5890 cdy = pc[1] - pd[1];
5894 alift = adx * adx + ady * ady;
5898 blift = bdx * bdx + bdy * bdy;
5902 clift = cdx * cdx + cdy * cdy;
5904 det = alift * (bdxcdy - cdxbdy)
5905 + blift * (cdxady - adxcdy)
5906 + clift * (adxbdy - bdxady);
5916 if ((det > errbound) || (-det > errbound)) {
5945#ifdef ANSI_DECLARATORS
5951 aheight, bheight, cheight, dheight, permanent)
5964 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
5967 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
5968 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
5969 REAL bc[4], ca[4], ab[4];
5971 REAL adet[8], bdet[8], cdet[8];
5972 int alen, blen, clen;
5975 REAL *finnow, *finother, *finswap;
5976 REAL fin1[192], fin2[192];
5979 REAL adxtail, bdxtail, cdxtail;
5980 REAL adytail, bdytail, cdytail;
5981 REAL adheighttail, bdheighttail, cdheighttail;
5985 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
5986 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
5989 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
5990 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
5993 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
5994 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
5995 REAL bct[8], cat[8], abt[8];
5996 int bctlen, catlen, abtlen;
5999 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
6000 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
6001 REAL u[4],
v[12], w[16];
6003 int vlength, wlength;
6007 REAL avirt, bround, around;
6010 REAL ahi, alo, bhi, blo;
6011 REAL err1, err2, err3;
6015 adx = (
REAL) (pa[0] - pd[0]);
6016 bdx = (
REAL) (pb[0] - pd[0]);
6017 cdx = (
REAL) (pc[0] - pd[0]);
6018 ady = (
REAL) (pa[1] - pd[1]);
6019 bdy = (
REAL) (pb[1] - pd[1]);
6020 cdy = (
REAL) (pc[1] - pd[1]);
6021 adheight = (
REAL) (aheight - dheight);
6022 bdheight = (
REAL) (bheight - dheight);
6023 cdheight = (
REAL) (cheight - dheight);
6027 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
6033 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
6039 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
6048 if ((det >= errbound) || (-det >= errbound)) {
6062 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
6063 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
6064 (adheighttail == 0.0) &&
6065 (bdheighttail == 0.0) &&
6066 (cdheighttail == 0.0)) {
6071 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
6072 (bdy * cdxtail + cdx * bdytail)) +
6073 adheighttail * (bdx * cdy - bdy * cdx)) +
6074 (bdheight * ((cdx * adytail + ady * cdxtail) -
6075 (cdy * adxtail + adx * cdytail)) +
6076 bdheighttail * (cdx * ady - cdy * adx)) +
6077 (cdheight * ((adx * bdytail + bdy * adxtail) -
6078 (ady * bdxtail + bdx * adytail)) +
6079 cdheighttail * (adx * bdy - ady * bdx));
6080 if ((det >= errbound) || (-det >= errbound)) {
6087 if (adxtail == 0.0) {
6088 if (adytail == 0.0) {
6096 at_b[1] = at_blarge;
6099 at_c[1] = at_clarge;
6103 if (adytail == 0.0) {
6105 at_b[1] = at_blarge;
6109 at_c[1] = at_clarge;
6114 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
6115 at_blarge, at_b[2], at_b[1], at_b[0]);
6116 at_b[3] = at_blarge;
6120 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
6121 at_clarge, at_c[2], at_c[1], at_c[0]);
6122 at_c[3] = at_clarge;
6126 if (bdxtail == 0.0) {
6127 if (bdytail == 0.0) {
6135 bt_c[1] = bt_clarge;
6138 bt_a[1] = bt_alarge;
6142 if (bdytail == 0.0) {
6144 bt_c[1] = bt_clarge;
6148 bt_a[1] = bt_alarge;
6153 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
6154 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
6155 bt_c[3] = bt_clarge;
6159 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
6160 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
6161 bt_a[3] = bt_alarge;
6165 if (cdxtail == 0.0) {
6166 if (cdytail == 0.0) {
6174 ct_a[1] = ct_alarge;
6177 ct_b[1] = ct_blarge;
6181 if (cdytail == 0.0) {
6183 ct_a[1] = ct_alarge;
6187 ct_b[1] = ct_blarge;
6192 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
6193 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
6194 ct_a[3] = ct_alarge;
6198 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
6199 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
6200 ct_b[3] = ct_blarge;
6209 finswap = finnow; finnow = finother; finother = finswap;
6215 finswap = finnow; finnow = finother; finother = finswap;
6221 finswap = finnow; finnow = finother; finother = finswap;
6223 if (adheighttail != 0.0) {
6227 finswap = finnow; finnow = finother; finother = finswap;
6229 if (bdheighttail != 0.0) {
6233 finswap = finnow; finnow = finother; finother = finswap;
6235 if (cdheighttail != 0.0) {
6239 finswap = finnow; finnow = finother; finother = finswap;
6242 if (adxtail != 0.0) {
6243 if (bdytail != 0.0) {
6244 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
6245 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
6249 finswap = finnow; finnow = finother; finother = finswap;
6250 if (cdheighttail != 0.0) {
6252 u3, u[2], u[1], u[0]);
6256 finswap = finnow; finnow = finother; finother = finswap;
6259 if (cdytail != 0.0) {
6261 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
6262 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
6266 finswap = finnow; finnow = finother; finother = finswap;
6267 if (bdheighttail != 0.0) {
6269 u3, u[2], u[1], u[0]);
6273 finswap = finnow; finnow = finother; finother = finswap;
6277 if (bdxtail != 0.0) {
6278 if (cdytail != 0.0) {
6279 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
6280 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
6284 finswap = finnow; finnow = finother; finother = finswap;
6285 if (adheighttail != 0.0) {
6287 u3, u[2], u[1], u[0]);
6291 finswap = finnow; finnow = finother; finother = finswap;
6294 if (adytail != 0.0) {
6296 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
6297 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
6301 finswap = finnow; finnow = finother; finother = finswap;
6302 if (cdheighttail != 0.0) {
6304 u3, u[2], u[1], u[0]);
6308 finswap = finnow; finnow = finother; finother = finswap;
6312 if (cdxtail != 0.0) {
6313 if (adytail != 0.0) {
6314 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
6315 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
6319 finswap = finnow; finnow = finother; finother = finswap;
6320 if (bdheighttail != 0.0) {
6322 u3, u[2], u[1], u[0]);
6326 finswap = finnow; finnow = finother; finother = finswap;
6329 if (bdytail != 0.0) {
6331 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
6332 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
6336 finswap = finnow; finnow = finother; finother = finswap;
6337 if (adheighttail != 0.0) {
6339 u3, u[2], u[1], u[0]);
6343 finswap = finnow; finnow = finother; finother = finswap;
6348 if (adheighttail != 0.0) {
6352 finswap = finnow; finnow = finother; finother = finswap;
6354 if (bdheighttail != 0.0) {
6358 finswap = finnow; finnow = finother; finother = finswap;
6360 if (cdheighttail != 0.0) {
6364 finswap = finnow; finnow = finother; finother = finswap;
6367 return finnow[finlength - 1];
6370#ifdef ANSI_DECLARATORS
6375REAL orient3d(
m,
b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
6389 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
6390 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
6392 REAL permanent, errbound;
6396 adx = pa[0] - pd[0];
6397 bdx = pb[0] - pd[0];
6398 cdx = pc[0] - pd[0];
6399 ady = pa[1] - pd[1];
6400 bdy = pb[1] - pd[1];
6401 cdy = pc[1] - pd[1];
6402 adheight = aheight - dheight;
6403 bdheight = bheight - dheight;
6404 cdheight = cheight - dheight;
6415 det = adheight * (bdxcdy - cdxbdy)
6416 + bdheight * (cdxady - adxcdy)
6417 + cdheight * (adxbdy - bdxady);
6427 if ((det > errbound) || (-det > errbound)) {
6431 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
6453#ifdef ANSI_DECLARATORS
6467 if (
b->weighted == 0) {
6469 }
else if (
b->weighted == 1) {
6471 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
6472 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
6473 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
6474 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
6476 return orient3d(
m,
b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
6494#ifdef ANSI_DECLARATORS
6513 REAL xdo, ydo, xao, yao;
6514 REAL dodist, aodist, dadist;
6516 REAL dx, dy, dxoff, dyoff;
6518 m->circumcentercount++;
6521 xdo = tdest[0] - torg[0];
6522 ydo = tdest[1] - torg[1];
6523 xao = tapex[0] - torg[0];
6524 yao = tapex[1] - torg[1];
6525 dodist = xdo * xdo + ydo * ydo;
6526 aodist = xao * xao + yao * yao;
6527 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
6528 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
6530 denominator = 0.5 / (xdo * yao - xao * ydo);
6537 m->counterclockcount--;
6539 dx = (yao * dodist - ydo * aodist) * denominator;
6540 dy = (xdo * aodist - xao * dodist) * denominator;
6547 if ((dodist < aodist) && (dodist < dadist)) {
6548 if (offcenter && (
b->offconstant > 0.0)) {
6550 dxoff = 0.5 * xdo -
b->offconstant * ydo;
6551 dyoff = 0.5 * ydo +
b->offconstant * xdo;
6554 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6559 }
else if (aodist < dadist) {
6560 if (offcenter && (
b->offconstant > 0.0)) {
6561 dxoff = 0.5 * xao +
b->offconstant * yao;
6562 dyoff = 0.5 * yao -
b->offconstant * xao;
6565 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
6571 if (offcenter && (
b->offconstant > 0.0)) {
6572 dxoff = 0.5 * (tapex[0] - tdest[0]) -
6573 b->offconstant * (tapex[1] - tdest[1]);
6574 dyoff = 0.5 * (tapex[1] - tdest[1]) +
6575 b->offconstant * (tapex[0] - tdest[0]);
6578 if (dxoff * dxoff + dyoff * dyoff <
6579 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
6586 circumcenter[0] = torg[0] + dx;
6587 circumcenter[1] = torg[1] + dy;
6594 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
6595 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
6608#ifdef ANSI_DECLARATORS
6628 m->checksegments = 0;
6629 m->checkquality = 0;
6630 m->incirclecount =
m->counterclockcount =
m->orient3dcount = 0;
6631 m->hyperbolacount =
m->circletopcount =
m->circumcentercount = 0;
6647#ifdef ANSI_DECLARATORS
6651unsigned int choices;
6671#ifdef ANSI_DECLARATORS
6680 struct otri triangleloop;
6681 struct otri oppotri, oppooppotri;
6682 vertex triorg, tridest, triapex;
6683 vertex oppoorg, oppodest;
6689 saveexact =
b->noexact;
6692 printf(
" Checking consistency of mesh...\n");
6698 while (triangleloop.tri != (
triangle *) NULL) {
6700 for (triangleloop.orient = 0; triangleloop.orient < 3;
6701 triangleloop.orient++) {
6702 org(triangleloop, triorg);
6703 dest(triangleloop, tridest);
6704 if (triangleloop.orient == 0) {
6706 apex(triangleloop, triapex);
6708 printf(
" !! !! Inverted ");
6714 sym(triangleloop, oppotri);
6715 if (oppotri.tri !=
m->dummytri) {
6717 sym(oppotri, oppooppotri);
6718 if ((triangleloop.tri != oppooppotri.tri)
6719 || (triangleloop.orient != oppooppotri.orient)) {
6720 printf(
" !! !! Asymmetric triangle-triangle bond:\n");
6721 if (triangleloop.tri == oppooppotri.tri) {
6722 printf(
" (Right triangle, wrong orientation)\n");
6726 printf(
" Second (nonreciprocating) ");
6732 org(oppotri, oppoorg);
6733 dest(oppotri, oppodest);
6734 if ((triorg != oppodest) || (tridest != oppoorg)) {
6735 printf(
" !! !! Mismatched edge coordinates between two triangles:\n"
6737 printf(
" First mismatched ");
6739 printf(
" Second mismatched ");
6749 printf(
" In my studied opinion, the mesh appears to be consistent.\n");
6751 }
else if (horrors == 1) {
6752 printf(
" !! !! !! !! Precisely one festering wound discovered.\n");
6754 printf(
" !! !! !! !! %d abominations witnessed.\n", horrors);
6757 b->noexact = saveexact;
6770#ifdef ANSI_DECLARATORS
6773void checkdelaunay(
m,
b)
6779 struct otri triangleloop;
6780 struct otri oppotri;
6781 struct osub opposubseg;
6782 vertex triorg, tridest, triapex;
6784 int shouldbedelaunay;
6791 saveexact =
b->noexact;
6794 printf(
" Checking Delaunay property of mesh...\n");
6800 while (triangleloop.tri != (
triangle *) NULL) {
6802 for (triangleloop.orient = 0; triangleloop.orient < 3;
6803 triangleloop.orient++) {
6804 org(triangleloop, triorg);
6805 dest(triangleloop, tridest);
6806 apex(triangleloop, triapex);
6807 sym(triangleloop, oppotri);
6808 apex(oppotri, oppoapex);
6812 shouldbedelaunay = (oppotri.tri !=
m->dummytri) &&
6813 !
deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
6814 (triorg !=
m->infvertex1) && (triorg !=
m->infvertex2) &&
6815 (triorg !=
m->infvertex3) &&
6816 (tridest !=
m->infvertex1) && (tridest !=
m->infvertex2) &&
6817 (tridest !=
m->infvertex3) &&
6818 (triapex !=
m->infvertex1) && (triapex !=
m->infvertex2) &&
6819 (triapex !=
m->infvertex3) &&
6820 (oppoapex !=
m->infvertex1) && (oppoapex !=
m->infvertex2) &&
6821 (oppoapex !=
m->infvertex3);
6822 if (
m->checksegments && shouldbedelaunay) {
6825 tspivot(triangleloop, opposubseg);
6826 if (opposubseg.ss !=
m->dummysub){
6827 shouldbedelaunay = 0;
6830 if (shouldbedelaunay) {
6831 if (
nonregular(
m,
b, triorg, tridest, triapex, oppoapex) > 0.0) {
6833 printf(
" !! !! Non-Delaunay pair of triangles:\n");
6834 printf(
" First non-Delaunay ");
6836 printf(
" Second non-Delaunay ");
6838 printf(
" !! !! Non-regular pair of triangles:\n");
6839 printf(
" First non-regular ");
6841 printf(
" Second non-regular ");
6853 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
6855 }
else if (horrors == 1) {
6857 " !! !! !! !! Precisely one terrifying transgression identified.\n");
6859 printf(
" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
6862 b->noexact = saveexact;
6880#ifdef ANSI_DECLARATORS
6884void enqueuebadtriang(
m,
b, badtri)
6891 REAL length, multiplier;
6892 int exponent, expincrement;
6897 if (
b->verbose > 2) {
6898 printf(
" Queueing bad triangle:\n");
6899 printf(
" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
6907 if (badtri->
key >= 1.0) {
6908 length = badtri->
key;
6913 length = 1.0 / badtri->
key;
6919 while (length > 2.0) {
6923 while (length * multiplier * multiplier > 1.0) {
6925 multiplier *= multiplier;
6928 exponent += expincrement;
6929 length *= multiplier;
6937 queuenumber = 2047 - exponent;
6939 queuenumber = 2048 + exponent;
6943 if (
m->queuefront[queuenumber] == (
struct badtriang *) NULL) {
6946 if (queuenumber >
m->firstnonemptyq) {
6948 m->nextnonemptyq[queuenumber] =
m->firstnonemptyq;
6949 m->firstnonemptyq = queuenumber;
6953 i = queuenumber + 1;
6954 while (
m->queuefront[i] == (
struct badtriang *) NULL) {
6958 m->nextnonemptyq[queuenumber] =
m->nextnonemptyq[i];
6959 m->nextnonemptyq[i] = queuenumber;
6962 m->queuefront[queuenumber] = badtri;
6968 m->queuetail[queuenumber] = badtri;
6986#ifdef ANSI_DECLARATORS
6990void enqueuebadtri(
m,
b, enqtri, minedge, enqapex, enqorg, enqdest)
7006 newbad->
key = minedge;
7010 enqueuebadtriang(
m,
b, newbad);
7023#ifdef ANSI_DECLARATORS
7034 if (
m->firstnonemptyq < 0) {
7038 result =
m->queuefront[
m->firstnonemptyq];
7043 if (result ==
m->queuetail[
m->firstnonemptyq]) {
7044 m->firstnonemptyq =
m->nextnonemptyq[
m->firstnonemptyq];
7076#ifdef ANSI_DECLARATORS
7078 struct osub *testsubseg)
7080int checkseg4encroach(
m,
b, testsubseg)
7083struct osub *testsubseg;
7087 struct otri neighbortri;
7088 struct osub testsym;
7093 vertex eorg, edest, eapex;
7099 sorg(*testsubseg, eorg);
7100 sdest(*testsubseg, edest);
7102 stpivot(*testsubseg, neighbortri);
7104 if (neighbortri.tri !=
m->dummytri) {
7107 apex(neighbortri, eapex);
7113 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7114 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7115 if (dotproduct < 0.0) {
7116 if (
b->conformdel ||
7117 (dotproduct * dotproduct >=
7118 (2.0 *
b->goodangle - 1.0) * (2.0 *
b->goodangle - 1.0) *
7119 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7120 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7121 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7122 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7128 ssym(*testsubseg, testsym);
7129 stpivot(testsym, neighbortri);
7131 if (neighbortri.tri !=
m->dummytri) {
7134 apex(neighbortri, eapex);
7137 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
7138 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
7139 if (dotproduct < 0.0) {
7140 if (
b->conformdel ||
7141 (dotproduct * dotproduct >=
7142 (2.0 *
b->goodangle - 1.0) * (2.0 *
b->goodangle - 1.0) *
7143 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
7144 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
7145 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
7146 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
7152 if (encroached && (!
b->nobisect || ((
b->nobisect == 1) && (sides == 2)))) {
7153 if (
b->verbose > 2) {
7155 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
7156 eorg[0], eorg[1], edest[0], edest[1]);
7161 if (encroached == 1) {
7189#ifdef ANSI_DECLARATORS
7192void testtriangle(
m,
b, testtri)
7195struct otri *testtri;
7199 struct otri tri1, tri2;
7200 struct osub testsub;
7201 vertex torg, tdest, tapex;
7203 vertex org1, dest1, org2, dest2;
7205 REAL dxod, dyod, dxda, dyda, dxao, dyao;
7206 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
7207 REAL apexlen, orglen, destlen, minedge;
7214 org(*testtri, torg);
7215 dest(*testtri, tdest);
7216 apex(*testtri, tapex);
7217 dxod = torg[0] - tdest[0];
7218 dyod = torg[1] - tdest[1];
7219 dxda = tdest[0] - tapex[0];
7220 dyda = tdest[1] - tapex[1];
7221 dxao = tapex[0] - torg[0];
7222 dyao = tapex[1] - torg[1];
7223 dxod2 = dxod * dxod;
7224 dyod2 = dyod * dyod;
7225 dxda2 = dxda * dxda;
7226 dyda2 = dyda * dyda;
7227 dxao2 = dxao * dxao;
7228 dyao2 = dyao * dyao;
7230 apexlen = dxod2 + dyod2;
7231 orglen = dxda2 + dyda2;
7232 destlen = dxao2 + dyao2;
7234 if ((apexlen < orglen) && (apexlen < destlen)) {
7238 angle = dxda * dxao + dyda * dyao;
7239 angle = angle * angle / (orglen * destlen);
7243 }
else if (orglen < destlen) {
7247 angle = dxod * dxao + dyod * dyao;
7248 angle = angle * angle / (apexlen * destlen);
7251 lnext(*testtri, tri1);
7256 angle = dxod * dxda + dyod * dyda;
7257 angle = angle * angle / (apexlen * orglen);
7260 lprev(*testtri, tri1);
7263 if (
b->vararea ||
b->fixedarea ||
b->usertest) {
7265 area = 0.5 * (dxod * dyda - dyod * dxda);
7266 if (
b->fixedarea && (area >
b->maxarea)) {
7268 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7273 if ((
b->vararea) && (area >
areabound(*testtri)) &&
7276 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7283 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7290 if (angle >
b->goodangle) {
7305 if (testsub.ss ==
m->dummysub) {
7311 }
while (testsub.ss ==
m->dummysub);
7319 }
while (testsub.ss ==
m->dummysub);
7324 joinvertex = (
vertex) NULL;
7325 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
7327 }
else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
7330 if (joinvertex != (
vertex) NULL) {
7333 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
7334 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
7335 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
7336 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
7338 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
7347 enqueuebadtri(
m,
b, testtri, minedge, tapex, torg, tdest);
7375#ifdef ANSI_DECLARATORS
7384 struct otri triangleloop;
7388 printf(
" Constructing mapping from vertices to triangles.\n");
7396 org(triangleloop, triorg);
7470#ifdef ANSI_DECLARATORS
7473 int stopatsubsegment)
7479struct otri *searchtri;
7480int stopatsubsegment;
7484 struct otri backtracktri;
7485 struct osub checkedge;
7486 vertex forg, fdest, fapex;
7487 REAL orgorient, destorient;
7492 if (
b->verbose > 2) {
7493 printf(
" Searching for point (%.12g, %.12g).\n",
7494 searchpoint[0], searchpoint[1]);
7497 org(*searchtri, forg);
7498 dest(*searchtri, fdest);
7499 apex(*searchtri, fapex);
7501 if (
b->verbose > 2) {
7502 printf(
" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
7503 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
7506 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
7516 if (destorient > 0.0) {
7517 if (orgorient > 0.0) {
7523 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
7524 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
7529 if (orgorient > 0.0) {
7534 if (destorient == 0.0) {
7538 if (orgorient == 0.0) {
7550 lprev(*searchtri, backtracktri);
7553 lnext(*searchtri, backtracktri);
7556 sym(backtracktri, *searchtri);
7558 if (
m->checksegments && stopatsubsegment) {
7560 tspivot(backtracktri, checkedge);
7561 if (checkedge.
ss !=
m->dummysub) {
7563 otricopy(backtracktri, *searchtri);
7568 if (searchtri->
tri ==
m->dummytri) {
7570 otricopy(backtracktri, *searchtri);
7574 apex(*searchtri, fapex);
7614#ifdef ANSI_DECLARATORS
7622struct otri *searchtri;
7628 struct otri sampletri;
7631 REAL searchdist, dist;
7633 long samplesperblock, totalsamplesleft, samplesleft;
7634 long population, totalpopulation;
7637 if (
b->verbose > 2) {
7638 printf(
" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
7639 searchpoint[0], searchpoint[1]);
7643 org(*searchtri, torg);
7644 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7645 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7646 if (
b->verbose > 2) {
7647 printf(
" Boundary triangle has origin (%.12g, %.12g).\n",
7653 if (
m->recenttri.tri != (
triangle *) NULL) {
7655 org(
m->recenttri, torg);
7656 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7660 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7661 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7662 if (dist < searchdist) {
7665 if (
b->verbose > 2) {
7666 printf(
" Choosing recent triangle with origin (%.12g, %.12g).\n",
7678 m->triangles.items) {
7686 samplesperblock = (
m->samples *
TRIPERBLOCK - 1) /
m->triangles.maxitems + 1;
7689 samplesleft = (
m->samples *
m->triangles.itemsfirstblock - 1) /
7690 m->triangles.maxitems + 1;
7691 totalsamplesleft =
m->samples;
7692 population =
m->triangles.itemsfirstblock;
7693 totalpopulation =
m->triangles.maxitems;
7694 sampleblock =
m->triangles.firstblock;
7696 while (totalsamplesleft > 0) {
7698 if (population > totalpopulation) {
7699 population = totalpopulation;
7702 alignptr = (uintptr_t) (sampleblock + 1);
7703 firsttri = (
char *) (alignptr +
7704 (uintptr_t)
m->triangles.alignbytes -
7706 (uintptr_t)
m->triangles.alignbytes));
7712 m->triangles.itembytes));
7714 org(sampletri, torg);
7715 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
7716 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
7717 if (dist < searchdist) {
7720 if (
b->verbose > 2) {
7721 printf(
" Choosing triangle with origin (%.12g, %.12g).\n",
7729 }
while ((samplesleft > 0) && (totalsamplesleft > 0));
7731 if (totalsamplesleft > 0) {
7732 sampleblock = (
VOID **) *sampleblock;
7733 samplesleft = samplesperblock;
7734 totalpopulation -= population;
7740 org(*searchtri, torg);
7741 dest(*searchtri, tdest);
7743 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
7746 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
7756 }
else if (ahead == 0.0) {
7758 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
7759 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
7785#ifdef ANSI_DECLARATORS
7797 struct otri oppotri;
7798 struct osub newsubseg;
7804 dest(*tri, tridest);
7814 if (newsubseg.
ss ==
m->dummysub) {
7828 tsbond(oppotri, newsubseg);
7829 setmark(newsubseg, subsegmark);
7830 if (
b->verbose > 2) {
7831 printf(
" Inserting new ");
7835 if (
mark(newsubseg) == 0) {
7836 setmark(newsubseg, subsegmark);
7889#ifdef ANSI_DECLARATORS
7895struct otri *flipedge;
7899 struct otri botleft, botright;
7900 struct otri topleft, topright;
7902 struct otri botlcasing, botrcasing;
7903 struct otri toplcasing, toprcasing;
7904 struct osub botlsubseg, botrsubseg;
7905 struct osub toplsubseg, toprsubseg;
7906 vertex leftvertex, rightvertex, botvertex;
7912 org(*flipedge, rightvertex);
7913 dest(*flipedge, leftvertex);
7914 apex(*flipedge, botvertex);
7915 sym(*flipedge, top);
7917 if (top.
tri ==
m->dummytri) {
7918 printf(
"Internal error in flip(): Attempt to flip on boundary.\n");
7922 if (
m->checksegments) {
7923 tspivot(*flipedge, toplsubseg);
7924 if (toplsubseg.
ss !=
m->dummysub) {
7925 printf(
"Internal error in flip(): Attempt to flip a segment.\n");
7931 apex(top, farvertex);
7934 lprev(top, topleft);
7935 sym(topleft, toplcasing);
7936 lnext(top, topright);
7937 sym(topright, toprcasing);
7938 lnext(*flipedge, botleft);
7939 sym(botleft, botlcasing);
7940 lprev(*flipedge, botright);
7941 sym(botright, botrcasing);
7943 bond(topleft, botlcasing);
7944 bond(botleft, botrcasing);
7945 bond(botright, toprcasing);
7946 bond(topright, toplcasing);
7948 if (
m->checksegments) {
7952 tspivot(botright, botrsubseg);
7953 tspivot(topright, toprsubseg);
7954 if (toplsubseg.
ss ==
m->dummysub) {
7957 tsbond(topright, toplsubseg);
7959 if (botlsubseg.
ss ==
m->dummysub) {
7962 tsbond(topleft, botlsubseg);
7964 if (botrsubseg.
ss ==
m->dummysub) {
7967 tsbond(botleft, botrsubseg);
7969 if (toprsubseg.
ss ==
m->dummysub) {
7972 tsbond(botright, toprsubseg);
7977 setorg(*flipedge, farvertex);
7978 setdest(*flipedge, botvertex);
7979 setapex(*flipedge, rightvertex);
7983 if (
b->verbose > 2) {
7984 printf(
" Edge flip results in left ");
7986 printf(
" and right ");
8024#ifdef ANSI_DECLARATORS
8030struct otri *flipedge;
8034 struct otri botleft, botright;
8035 struct otri topleft, topright;
8037 struct otri botlcasing, botrcasing;
8038 struct otri toplcasing, toprcasing;
8039 struct osub botlsubseg, botrsubseg;
8040 struct osub toplsubseg, toprsubseg;
8041 vertex leftvertex, rightvertex, botvertex;
8047 org(*flipedge, rightvertex);
8048 dest(*flipedge, leftvertex);
8049 apex(*flipedge, botvertex);
8050 sym(*flipedge, top);
8052 if (top.
tri ==
m->dummytri) {
8053 printf(
"Internal error in unflip(): Attempt to flip on boundary.\n");
8057 if (
m->checksegments) {
8058 tspivot(*flipedge, toplsubseg);
8059 if (toplsubseg.
ss !=
m->dummysub) {
8060 printf(
"Internal error in unflip(): Attempt to flip a subsegment.\n");
8066 apex(top, farvertex);
8069 lprev(top, topleft);
8070 sym(topleft, toplcasing);
8071 lnext(top, topright);
8072 sym(topright, toprcasing);
8073 lnext(*flipedge, botleft);
8074 sym(botleft, botlcasing);
8075 lprev(*flipedge, botright);
8076 sym(botright, botrcasing);
8078 bond(topleft, toprcasing);
8079 bond(botleft, toplcasing);
8080 bond(botright, botlcasing);
8081 bond(topright, botrcasing);
8083 if (
m->checksegments) {
8087 tspivot(botright, botrsubseg);
8088 tspivot(topright, toprsubseg);
8089 if (toplsubseg.
ss ==
m->dummysub) {
8092 tsbond(botleft, toplsubseg);
8094 if (botlsubseg.
ss ==
m->dummysub) {
8097 tsbond(botright, botlsubseg);
8099 if (botrsubseg.
ss ==
m->dummysub) {
8102 tsbond(topright, botrsubseg);
8104 if (toprsubseg.
ss ==
m->dummysub) {
8107 tsbond(topleft, toprsubseg);
8112 setorg(*flipedge, botvertex);
8113 setdest(*flipedge, farvertex);
8114 setapex(*flipedge, leftvertex);
8118 if (
b->verbose > 2) {
8119 printf(
" Edge unflip results in left ");
8121 printf(
" and right ");
8173#ifdef ANSI_DECLARATORS
8176 struct osub *splitseg,
8177 int segmentflaws,
int triflaws )
8180 segmentflaws, triflaws)
8184struct otri *searchtri;
8185struct osub *splitseg;
8194 struct otri botleft, botright;
8195 struct otri topleft, topright;
8196 struct otri newbotleft, newbotright;
8197 struct otri newtopright;
8198 struct otri botlcasing, botrcasing;
8199 struct otri toplcasing, toprcasing;
8200 struct otri testtri;
8201 struct osub botlsubseg, botrsubseg;
8202 struct osub toplsubseg, toprsubseg;
8203 struct osub brokensubseg;
8204 struct osub checksubseg;
8205 struct osub rightsubseg;
8206 struct osub newsubseg;
8210 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
8211 vertex segmentorg, segmentdest;
8226 if (
b->verbose > 1) {
8227 printf(
" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
8230 if (splitseg == (
struct osub *) NULL) {
8233 if (searchtri->
tri ==
m->dummytri) {
8235 horiz.
tri =
m->dummytri;
8239 intersect =
locate(
m,
b, newvertex, &horiz);
8261 if (
m->checksegments && (splitseg == (
struct osub *) NULL)) {
8264 if (brokensubseg.
ss !=
m->dummysub) {
8267 enq =
b->nobisect != 2;
8268 if (enq && (
b->nobisect == 1)) {
8271 sym(horiz, testtri);
8272 enq = testtri.
tri !=
m->dummytri;
8280 if (
b->verbose > 2) {
8282 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
8298 lprev(horiz, botright);
8299 sym(botright, botrcasing);
8300 sym(horiz, topright);
8302 mirrorflag = topright.
tri !=
m->dummytri;
8305 sym(topright, toprcasing);
8314 org(horiz, rightvertex);
8315 dest(horiz, leftvertex);
8316 apex(horiz, botvertex);
8317 setorg(newbotright, botvertex);
8318 setdest(newbotright, rightvertex);
8319 setapex(newbotright, newvertex);
8320 setorg(horiz, newvertex);
8321 for (i = 0; i <
m->eextras; i++) {
8330 dest(topright, topvertex);
8331 setorg(newtopright, rightvertex);
8332 setdest(newtopright, topvertex);
8333 setapex(newtopright, newvertex);
8334 setorg(topright, newvertex);
8335 for (i = 0; i <
m->eextras; i++) {
8347 if (
m->checksegments) {
8348 tspivot(botright, botrsubseg);
8349 if (botrsubseg.
ss !=
m->dummysub) {
8351 tsbond(newbotright, botrsubseg);
8354 tspivot(topright, toprsubseg);
8355 if (toprsubseg.
ss !=
m->dummysub) {
8357 tsbond(newtopright, toprsubseg);
8363 bond(newbotright, botrcasing);
8365 bond(newbotright, botright);
8368 bond(newtopright, toprcasing);
8370 bond(newtopright, topright);
8372 bond(newtopright, newbotright);
8375 if (splitseg != (
struct osub *) NULL) {
8378 segorg(*splitseg, segmentorg);
8379 segdest(*splitseg, segmentdest);
8381 spivot(*splitseg, rightsubseg);
8383 tspivot(newbotright, newsubseg);
8386 sbond(*splitseg, newsubseg);
8388 sbond(newsubseg, rightsubseg);
8397 if (
m->checkquality) {
8400 m->lastflip->flippedtri =
encode(horiz);
8406 printf(
"Internal error in insertvertex():\n");
8408 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
8412 printf(
"Internal error in insertvertex():\n");
8413 printf(
" Clockwise triangle prior to edge vertex insertion (top).\n");
8416 printf(
"Internal error in insertvertex():\n");
8418 " Clockwise triangle after edge vertex insertion (top right).\n");
8421 printf(
"Internal error in insertvertex():\n");
8423 " Clockwise triangle after edge vertex insertion (top left).\n");
8427 printf(
"Internal error in insertvertex():\n");
8429 " Clockwise triangle after edge vertex insertion (bottom left).\n");
8432 printf(
"Internal error in insertvertex():\n");
8434 " Clockwise triangle after edge vertex insertion (bottom right).\n");
8437 if (
b->verbose > 2) {
8438 printf(
" Updating bottom left ");
8441 printf(
" Updating top left ");
8443 printf(
" Creating top right ");
8446 printf(
" Creating bottom right ");
8455 lnext(horiz, botleft);
8456 lprev(horiz, botright);
8457 sym(botleft, botlcasing);
8458 sym(botright, botrcasing);
8463 org(horiz, rightvertex);
8464 dest(horiz, leftvertex);
8465 apex(horiz, botvertex);
8466 setorg(newbotleft, leftvertex);
8467 setdest(newbotleft, botvertex);
8468 setapex(newbotleft, newvertex);
8469 setorg(newbotright, botvertex);
8470 setdest(newbotright, rightvertex);
8471 setapex(newbotright, newvertex);
8473 for (i = 0; i <
m->eextras; i++) {
8488 if (
m->checksegments) {
8490 if (botlsubseg.
ss !=
m->dummysub) {
8492 tsbond(newbotleft, botlsubseg);
8494 tspivot(botright, botrsubseg);
8495 if (botrsubseg.
ss !=
m->dummysub) {
8497 tsbond(newbotright, botrsubseg);
8502 bond(newbotleft, botlcasing);
8503 bond(newbotright, botrcasing);
8506 bond(newbotleft, newbotright);
8508 bond(botleft, newbotleft);
8510 bond(botright, newbotright);
8512 if (
m->checkquality) {
8515 m->lastflip->flippedtri =
encode(horiz);
8521 printf(
"Internal error in insertvertex():\n");
8522 printf(
" Clockwise triangle prior to vertex insertion.\n");
8525 printf(
"Internal error in insertvertex():\n");
8526 printf(
" Clockwise triangle after vertex insertion (top).\n");
8529 printf(
"Internal error in insertvertex():\n");
8530 printf(
" Clockwise triangle after vertex insertion (left).\n");
8533 printf(
"Internal error in insertvertex():\n");
8534 printf(
" Clockwise triangle after vertex insertion (right).\n");
8537 if (
b->verbose > 2) {
8538 printf(
" Updating top ");
8540 printf(
" Creating left ");
8542 printf(
" Creating right ");
8555 rightvertex =
first;
8556 dest(horiz, leftvertex);
8562 if (
m->checksegments) {
8565 if (checksubseg.
ss !=
m->dummysub) {
8571 if (checkseg4encroach(
m,
b, &checksubseg)) {
8582 if (top.
tri ==
m->dummytri) {
8587 apex(top, farvertex);
8593 if ((leftvertex ==
m->infvertex1) || (leftvertex ==
m->infvertex2) ||
8594 (leftvertex ==
m->infvertex3)) {
8601 }
else if ((rightvertex ==
m->infvertex1) ||
8602 (rightvertex ==
m->infvertex2) ||
8603 (rightvertex ==
m->infvertex3)) {
8610 }
else if ((farvertex ==
m->infvertex1) ||
8611 (farvertex ==
m->infvertex2) ||
8612 (farvertex ==
m->infvertex3)) {
8618 doflip =
incircle(
m,
b, leftvertex, newvertex, rightvertex,
8625 lprev(top, topleft);
8626 sym(topleft, toplcasing);
8627 lnext(top, topright);
8628 sym(topright, toprcasing);
8629 lnext(horiz, botleft);
8630 sym(botleft, botlcasing);
8631 lprev(horiz, botright);
8632 sym(botright, botrcasing);
8634 bond(topleft, botlcasing);
8635 bond(botleft, botrcasing);
8636 bond(botright, toprcasing);
8637 bond(topright, toplcasing);
8638 if (
m->checksegments) {
8642 tspivot(botright, botrsubseg);
8643 tspivot(topright, toprsubseg);
8644 if (toplsubseg.
ss ==
m->dummysub) {
8647 tsbond(topright, toplsubseg);
8649 if (botlsubseg.
ss ==
m->dummysub) {
8652 tsbond(topleft, botlsubseg);
8654 if (botrsubseg.
ss ==
m->dummysub) {
8657 tsbond(botleft, botrsubseg);
8659 if (toprsubseg.
ss ==
m->dummysub) {
8662 tsbond(botright, toprsubseg);
8666 setorg(horiz, farvertex);
8672 for (i = 0; i <
m->eextras; i++) {
8691 if (
m->checkquality) {
8695 m->lastflip = newflip;
8699 if (newvertex != (
vertex) NULL) {
8702 printf(
"Internal error in insertvertex():\n");
8703 printf(
" Clockwise triangle prior to edge flip (bottom).\n");
8717 printf(
"Internal error in insertvertex():\n");
8718 printf(
" Clockwise triangle after edge flip (left).\n");
8722 printf(
"Internal error in insertvertex():\n");
8723 printf(
" Clockwise triangle after edge flip (right).\n");
8727 if (
b->verbose > 2) {
8728 printf(
" Edge flip results in left ");
8731 printf(
" and right ");
8738 leftvertex = farvertex;
8747 testtriangle(
m,
b, &horiz);
8752 sym(horiz, testtri);
8756 if ((leftvertex ==
first) || (testtri.
tri ==
m->dummytri)) {
8758 lnext(horiz, *searchtri);
8759 lnext(horiz,
m->recenttri);
8763 lnext(testtri, horiz);
8764 rightvertex = leftvertex;
8765 dest(horiz, leftvertex);
8834#ifdef ANSI_DECLARATORS
8836 struct otri *firstedge,
struct otri *lastedge,
8837 int edgecount,
int doflip,
int triflaws)
8842struct otri *firstedge;
8843struct otri *lastedge;
8850 struct otri testtri;
8851 struct otri besttri;
8852 struct otri tempedge;
8853 vertex leftbasevertex, rightbasevertex;
8861 apex(*lastedge, leftbasevertex);
8862 dest(*firstedge, rightbasevertex);
8863 if (
b->verbose > 2) {
8864 printf(
" Triangulating interior polygon at edge\n");
8865 printf(
" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
8866 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
8869 onext(*firstedge, besttri);
8870 dest(besttri, bestvertex);
8873 for (i = 2; i <= edgecount - 2; i++) {
8875 dest(testtri, testvertex);
8877 if (
incircle(
m,
b, leftbasevertex, rightbasevertex, bestvertex,
8878 testvertex) > 0.0) {
8880 bestvertex = testvertex;
8884 if (
b->verbose > 2) {
8885 printf(
" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
8888 if (bestnumber > 1) {
8890 oprev(besttri, tempedge);
8894 if (bestnumber < edgecount - 2) {
8896 sym(besttri, tempedge);
8900 sym(tempedge, besttri);
8908 sym(besttri, testtri);
8909 testtriangle(
m,
b, &testtri);
8933#ifdef ANSI_DECLARATORS
8936void deletevertex(
m,
b, deltri)
8943 struct otri countingtri;
8944 struct otri firstedge, lastedge;
8945 struct otri deltriright;
8946 struct otri lefttri, righttri;
8947 struct otri leftcasing, rightcasing;
8948 struct osub leftsubseg, rightsubseg;
8955 org(*deltri, delvertex);
8956 if (
b->verbose > 1) {
8957 printf(
" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
8962 onext(*deltri, countingtri);
8964 while (!
otriequal(*deltri, countingtri)) {
8966 if (countingtri.tri ==
m->dummytri) {
8967 printf(
"Internal error in deletevertex():\n");
8968 printf(
" Attempt to delete boundary vertex.\n");
8977 if (edgecount < 3) {
8978 printf(
"Internal error in deletevertex():\n Vertex has degree %d.\n",
8983 if (edgecount > 3) {
8987 onext(*deltri, firstedge);
8988 oprev(*deltri, lastedge);
8993 lprev(*deltri, deltriright);
8994 dnext(*deltri, lefttri);
8995 sym(lefttri, leftcasing);
8996 oprev(deltriright, righttri);
8997 sym(righttri, rightcasing);
8998 bond(*deltri, leftcasing);
8999 bond(deltriright, rightcasing);
9001 if (leftsubseg.ss !=
m->dummysub) {
9002 tsbond(*deltri, leftsubseg);
9004 tspivot(righttri, rightsubseg);
9005 if (rightsubseg.ss !=
m->dummysub) {
9006 tsbond(deltriright, rightsubseg);
9010 org(lefttri, neworg);
9013 testtriangle(
m,
b, deltri);
9036#ifdef ANSI_DECLARATORS
9039void undovertex(
m,
b)
9045 struct otri fliptri;
9046 struct otri botleft, botright, topright;
9047 struct otri botlcasing, botrcasing, toprcasing;
9048 struct otri gluetri;
9049 struct osub botlsubseg, botrsubseg, toprsubseg;
9050 vertex botvertex, rightvertex;
9058 decode(
m->lastflip->flippedtri, fliptri);
9064 if (
m->lastflip->prevflip == (
struct flipstacker *) NULL) {
9067 dprev(fliptri, botleft);
9069 onext(fliptri, botright);
9071 sym(botleft, botlcasing);
9072 sym(botright, botrcasing);
9073 dest(botleft, botvertex);
9077 bond(fliptri, botlcasing);
9079 tsbond(fliptri, botlsubseg);
9081 bond(fliptri, botrcasing);
9082 tspivot(botright, botrsubseg);
9083 tsbond(fliptri, botrsubseg);
9091 lprev(fliptri, gluetri);
9092 sym(gluetri, botright);
9094 sym(botright, botrcasing);
9095 dest(botright, rightvertex);
9097 setorg(fliptri, rightvertex);
9098 bond(gluetri, botrcasing);
9099 tspivot(botright, botrsubseg);
9100 tsbond(gluetri, botrsubseg);
9105 sym(fliptri, gluetri);
9106 if (gluetri.tri !=
m->dummytri) {
9108 dnext(gluetri, topright);
9109 sym(topright, toprcasing);
9111 setorg(gluetri, rightvertex);
9112 bond(gluetri, toprcasing);
9113 tspivot(topright, toprsubseg);
9114 tsbond(gluetri, toprsubseg);
9128 m->lastflip =
m->lastflip->prevflip;
9183#ifdef ANSI_DECLARATORS
9194 REAL pivotx, pivoty;
9197 if (arraysize == 2) {
9199 if ((sortarray[0][0] > sortarray[1][0]) ||
9200 ((sortarray[0][0] == sortarray[1][0]) &&
9201 (sortarray[0][1] > sortarray[1][1]))) {
9202 temp = sortarray[1];
9203 sortarray[1] = sortarray[0];
9204 sortarray[0] = temp;
9210 pivotx = sortarray[pivot][0];
9211 pivoty = sortarray[pivot][1];
9215 while (left < right) {
9219 }
while ((left <= right) && ((sortarray[left][0] < pivotx) ||
9220 ((sortarray[left][0] == pivotx) &&
9221 (sortarray[left][1] < pivoty))));
9225 }
while ((left <= right) && ((sortarray[right][0] > pivotx) ||
9226 ((sortarray[right][0] == pivotx) &&
9227 (sortarray[right][1] > pivoty))));
9230 temp = sortarray[left];
9231 sortarray[left] = sortarray[right];
9232 sortarray[right] = temp;
9239 if (right < arraysize - 2) {
9241 vertexsort(&sortarray[right + 1], arraysize - right - 1);
9257#ifdef ANSI_DECLARATORS
9270 REAL pivot1, pivot2;
9273 if (arraysize == 2) {
9275 if ((sortarray[0][axis] > sortarray[1][axis]) ||
9276 ((sortarray[0][axis] == sortarray[1][axis]) &&
9277 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
9278 temp = sortarray[1];
9279 sortarray[1] = sortarray[0];
9280 sortarray[0] = temp;
9286 pivot1 = sortarray[pivot][axis];
9287 pivot2 = sortarray[pivot][1 - axis];
9291 while (left < right) {
9295 }
while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
9296 ((sortarray[left][axis] == pivot1) &&
9297 (sortarray[left][1 - axis] < pivot2))));
9301 }
while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
9302 ((sortarray[right][axis] == pivot1) &&
9303 (sortarray[right][1 - axis] > pivot2))));
9306 temp = sortarray[left];
9307 sortarray[left] = sortarray[right];
9308 sortarray[right] = temp;
9313 if (left > median) {
9317 if (right < median - 1) {
9319 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
9320 median - right - 1, axis);
9335#ifdef ANSI_DECLARATORS
9347 divider = arraysize >> 1;
9348 if (arraysize <= 3) {
9356 if (arraysize - divider >= 2) {
9360 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
9399#ifdef ANSI_DECLARATORS
9401 struct otri *innerleft,
struct otri *innerright,
9402 struct otri *farright,
int axis)
9404void mergehulls(
m,
b, farleft, innerleft, innerright, farright, axis)
9407struct otri *farleft;
9408struct otri *innerleft;
9409struct otri *innerright;
9410struct otri *farright;
9415 struct otri leftcand, rightcand;
9416 struct otri baseedge;
9417 struct otri nextedge;
9418 struct otri sidecasing, topcasing, outercasing;
9419 struct otri checkedge;
9422 vertex innerleftapex, innerrightapex;
9423 vertex farleftpt, farrightpt;
9424 vertex farleftapex, farrightapex;
9425 vertex lowerleft, lowerright;
9426 vertex upperleft, upperright;
9431 int leftfinished, rightfinished;
9434 dest(*innerleft, innerleftdest);
9435 apex(*innerleft, innerleftapex);
9436 org(*innerright, innerrightorg);
9437 apex(*innerright, innerrightapex);
9439 if (
b->dwyer && (axis == 1)) {
9440 org(*farleft, farleftpt);
9441 apex(*farleft, farleftapex);
9442 dest(*farright, farrightpt);
9443 apex(*farright, farrightapex);
9447 while (farleftapex[1] < farleftpt[1]) {
9450 farleftpt = farleftapex;
9451 apex(*farleft, farleftapex);
9453 sym(*innerleft, checkedge);
9454 apex(checkedge, checkvertex);
9455 while (checkvertex[1] > innerleftdest[1]) {
9456 lnext(checkedge, *innerleft);
9457 innerleftapex = innerleftdest;
9458 innerleftdest = checkvertex;
9459 sym(*innerleft, checkedge);
9460 apex(checkedge, checkvertex);
9462 while (innerrightapex[1] < innerrightorg[1]) {
9465 innerrightorg = innerrightapex;
9466 apex(*innerright, innerrightapex);
9468 sym(*farright, checkedge);
9469 apex(checkedge, checkvertex);
9470 while (checkvertex[1] > farrightpt[1]) {
9471 lnext(checkedge, *farright);
9472 farrightapex = farrightpt;
9473 farrightpt = checkvertex;
9474 sym(*farright, checkedge);
9475 apex(checkedge, checkvertex);
9486 innerleftdest = innerleftapex;
9487 apex(*innerleft, innerleftapex);
9495 innerrightorg = innerrightapex;
9496 apex(*innerright, innerrightapex);
9499 }
while (changemade);
9501 sym(*innerleft, leftcand);
9502 sym(*innerright, rightcand);
9506 bond(baseedge, *innerleft);
9508 bond(baseedge, *innerright);
9510 setorg(baseedge, innerrightorg);
9511 setdest(baseedge, innerleftdest);
9513 if (
b->verbose > 2) {
9514 printf(
" Creating base bounding ");
9518 org(*farleft, farleftpt);
9519 if (innerleftdest == farleftpt) {
9520 lnext(baseedge, *farleft);
9522 dest(*farright, farrightpt);
9523 if (innerrightorg == farrightpt) {
9524 lprev(baseedge, *farright);
9527 lowerleft = innerleftdest;
9528 lowerright = innerrightorg;
9530 apex(leftcand, upperleft);
9531 apex(rightcand, upperright);
9542 if (leftfinished && rightfinished) {
9545 setorg(nextedge, lowerleft);
9546 setdest(nextedge, lowerright);
9549 bond(nextedge, baseedge);
9551 bond(nextedge, rightcand);
9553 bond(nextedge, leftcand);
9554 if (
b->verbose > 2) {
9555 printf(
" Creating top bounding ");
9559 if (
b->dwyer && (axis == 1)) {
9560 org(*farleft, farleftpt);
9561 apex(*farleft, farleftapex);
9562 dest(*farright, farrightpt);
9563 apex(*farright, farrightapex);
9564 sym(*farleft, checkedge);
9565 apex(checkedge, checkvertex);
9569 while (checkvertex[0] < farleftpt[0]) {
9570 lprev(checkedge, *farleft);
9571 farleftapex = farleftpt;
9572 farleftpt = checkvertex;
9573 sym(*farleft, checkedge);
9574 apex(checkedge, checkvertex);
9576 while (farrightapex[0] > farrightpt[0]) {
9579 farrightpt = farrightapex;
9580 apex(*farright, farrightapex);
9586 if (!leftfinished) {
9588 lprev(leftcand, nextedge);
9590 apex(nextedge, nextapex);
9593 if (nextapex != (
vertex) NULL) {
9595 badedge =
incircle(
m,
b, lowerleft, lowerright, upperleft, nextapex) >
9601 sym(nextedge, topcasing);
9603 sym(nextedge, sidecasing);
9604 bond(nextedge, topcasing);
9605 bond(leftcand, sidecasing);
9607 sym(leftcand, outercasing);
9609 bond(nextedge, outercasing);
9611 setorg(leftcand, lowerleft);
9618 upperleft = nextapex;
9621 apex(nextedge, nextapex);
9622 if (nextapex != (
vertex) NULL) {
9624 badedge =
incircle(
m,
b, lowerleft, lowerright, upperleft,
9634 if (!rightfinished) {
9636 lnext(rightcand, nextedge);
9638 apex(nextedge, nextapex);
9641 if (nextapex != (
vertex) NULL) {
9643 badedge =
incircle(
m,
b, lowerleft, lowerright, upperright, nextapex) >
9649 sym(nextedge, topcasing);
9651 sym(nextedge, sidecasing);
9652 bond(nextedge, topcasing);
9653 bond(rightcand, sidecasing);
9655 sym(rightcand, outercasing);
9657 bond(nextedge, outercasing);
9660 setdest(rightcand, lowerright);
9662 setorg(nextedge, upperright);
9666 upperright = nextapex;
9669 apex(nextedge, nextapex);
9670 if (nextapex != (
vertex) NULL) {
9672 badedge =
incircle(
m,
b, lowerleft, lowerright, upperright,
9681 if (leftfinished || (!rightfinished &&
9682 (
incircle(
m,
b, upperleft, lowerleft, lowerright, upperright) >
9686 bond(baseedge, rightcand);
9687 lprev(rightcand, baseedge);
9689 lowerright = upperright;
9690 sym(baseedge, rightcand);
9691 apex(rightcand, upperright);
9695 bond(baseedge, leftcand);
9696 lnext(leftcand, baseedge);
9697 setorg(baseedge, lowerright);
9698 lowerleft = upperleft;
9699 sym(baseedge, leftcand);
9700 apex(leftcand, upperleft);
9702 if (
b->verbose > 2) {
9703 printf(
" Connecting ");
9726#ifdef ANSI_DECLARATORS
9728 int vertices,
int axis,
9729 struct otri *farleft,
struct otri *farright)
9737struct otri *farleft;
9738struct otri *farright;
9742 struct otri midtri, tri1, tri2, tri3;
9743 struct otri innerleft, innerright;
9747 if (
b->verbose > 2) {
9748 printf(
" Triangulating %d vertices.\n", vertices);
9750 if (vertices == 2) {
9754 setorg(*farleft, sortarray[0]);
9755 setdest(*farleft, sortarray[1]);
9758 setorg(*farright, sortarray[1]);
9759 setdest(*farright, sortarray[0]);
9761 bond(*farleft, *farright);
9764 bond(*farleft, *farright);
9767 bond(*farleft, *farright);
9768 if (
b->verbose > 2) {
9769 printf(
" Creating ");
9771 printf(
" Creating ");
9775 lprev(*farright, *farleft);
9777 }
else if (vertices == 3) {
9788 setorg(midtri, sortarray[0]);
9789 setdest(midtri, sortarray[1]);
9790 setorg(tri1, sortarray[1]);
9792 setorg(tri2, sortarray[2]);
9794 setorg(tri3, sortarray[1]);
9818 setorg(midtri, sortarray[0]);
9820 setorg(tri3, sortarray[0]);
9824 setdest(midtri, sortarray[1]);
9825 setorg(tri1, sortarray[1]);
9827 setapex(midtri, sortarray[2]);
9828 setorg(tri2, sortarray[2]);
9832 setdest(midtri, sortarray[2]);
9833 setorg(tri1, sortarray[2]);
9835 setapex(midtri, sortarray[1]);
9836 setorg(tri2, sortarray[1]);
9860 lnext(*farleft, *farright);
9863 if (
b->verbose > 2) {
9864 printf(
" Creating ");
9866 printf(
" Creating ");
9868 printf(
" Creating ");
9870 printf(
" Creating ");
9876 divider = vertices >> 1;
9880 &innerright, farright);
9881 if (
b->verbose > 1) {
9882 printf(
" Joining triangulations with %d and %d vertices.\n", divider,
9883 vertices - divider);
9886 mergehulls(
m,
b, farleft, &innerleft, &innerright, farright, axis);
9890#ifdef ANSI_DECLARATORS
9896struct otri *startghost;
9900 struct otri searchedge;
9901 struct otri dissolveedge;
9902 struct otri deadtriangle;
9908 printf(
" Removing ghost triangles.\n");
9911 lprev(*startghost, searchedge);
9913 m->dummytri[0] =
encode(searchedge);
9915 otricopy(*startghost, dissolveedge);
9919 lnext(dissolveedge, deadtriangle);
9926 if (dissolveedge.
tri !=
m->dummytri) {
9927 org(dissolveedge, markorg);
9936 sym(deadtriangle, dissolveedge);
9939 }
while (!
otriequal(dissolveedge, *startghost));
9953#ifdef ANSI_DECLARATORS
9963 struct otri hullleft, hullright;
9968 printf(
" Sorting vertices.\n");
9974 for (i = 0; i <
m->invertices; i++) {
9981 for (j = 1; j <
m->invertices; j++) {
9982 if ((sortarray[i][0] == sortarray[j][0])
9983 && (sortarray[i][1] == sortarray[j][1])) {
9986"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
9987 sortarray[j][0], sortarray[j][1]);
9993 sortarray[i] = sortarray[j];
10000 if (i - divider >= 2) {
10001 if (divider >= 2) {
10009 printf(
" Forming triangulation.\n");
10040#ifdef ANSI_DECLARATORS
10043void boundingbox(
m,
b)
10049 struct otri inftri;
10053 printf(
" Creating triangular bounding box.\n");
10057 if (
m->ymax -
m->ymin >
width) {
10060 if (
width == 0.0) {
10067 m->infvertex1[0] =
m->xmin - 50.0 *
width;
10068 m->infvertex1[1] =
m->ymin - 40.0 *
width;
10069 m->infvertex2[0] =
m->xmax + 50.0 *
width;
10070 m->infvertex2[1] =
m->ymin - 40.0 *
width;
10071 m->infvertex3[0] = 0.5 * (
m->xmin +
m->xmax);
10072 m->infvertex3[1] =
m->ymax + 60.0 *
width;
10076 setorg(inftri,
m->infvertex1);
10081 m->dummytri[0] = (
triangle) inftri.tri;
10082 if (
b->verbose > 2) {
10083 printf(
" Creating ");
10106#ifdef ANSI_DECLARATORS
10109long removebox(
m,
b)
10115 struct otri deadtriangle;
10116 struct otri searchedge;
10117 struct otri checkedge;
10118 struct otri nextedge, finaledge, dissolveedge;
10124 printf(
" Removing triangular bounding box.\n");
10127 nextedge.tri =
m->dummytri;
10128 nextedge.orient = 0;
10131 lprev(nextedge, finaledge);
10136 lprev(nextedge, searchedge);
10140 lnext(nextedge, checkedge);
10142 if (checkedge.tri ==
m->dummytri) {
10151 m->dummytri[0] =
encode(searchedge);
10153 while (!
otriequal(nextedge, finaledge)) {
10155 lprev(nextedge, dissolveedge);
10164 if (dissolveedge.tri !=
m->dummytri) {
10165 org(dissolveedge, markorg);
10173 lnext(nextedge, deadtriangle);
10174 sym(deadtriangle, nextedge);
10178 if (nextedge.tri ==
m->dummytri) {
10205#ifdef ANSI_DECLARATORS
10208long incrementaldelaunay(
m,
b)
10214 struct otri starttri;
10220 printf(
" Incrementally inserting vertices.\n");
10224 while (vertexloop != (
vertex) NULL) {
10225 starttri.tri =
m->dummytri;
10230"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10231 vertexloop[0], vertexloop[1]);
10239 return removebox(
m,
b);
10254#ifdef ANSI_DECLARATORS
10255void eventheapinsert(
struct event **heap,
int heapsize,
struct event *newevent)
10257void eventheapinsert(heap, heapsize, newevent)
10258struct event **heap;
10260struct event *newevent;
10264 REAL eventx, eventy;
10269 eventx = newevent->
xkey;
10270 eventy = newevent->
ykey;
10271 eventnum = heapsize;
10272 notdone = eventnum > 0;
10274 parent = (eventnum - 1) >> 1;
10275 if ((heap[parent]->
ykey < eventy) ||
10276 ((heap[parent]->
ykey == eventy)
10277 && (heap[parent]->
xkey <= eventx))) {
10280 heap[eventnum] = heap[parent];
10284 notdone = eventnum > 0;
10287 heap[eventnum] = newevent;
10295#ifdef ANSI_DECLARATORS
10296void eventheapify(
struct event **heap,
int heapsize,
int eventnum)
10298void eventheapify(heap, heapsize, eventnum)
10299struct event **heap;
10305 struct event *thisevent;
10306 REAL eventx, eventy;
10307 int leftchild, rightchild;
10311 thisevent = heap[eventnum];
10312 eventx = thisevent->
xkey;
10313 eventy = thisevent->
ykey;
10314 leftchild = 2 * eventnum + 1;
10315 notdone = leftchild < heapsize;
10317 if ((heap[leftchild]->
ykey < eventy) ||
10318 ((heap[leftchild]->
ykey == eventy)
10319 && (heap[leftchild]->
xkey < eventx))) {
10320 smallest = leftchild;
10322 smallest = eventnum;
10324 rightchild = leftchild + 1;
10325 if (rightchild < heapsize) {
10326 if ((heap[rightchild]->
ykey < heap[smallest]->
ykey) ||
10327 ((heap[rightchild]->
ykey == heap[smallest]->
ykey)
10328 && (heap[rightchild]->
xkey < heap[smallest]->
xkey))) {
10329 smallest = rightchild;
10332 if (smallest == eventnum) {
10335 heap[eventnum] = heap[smallest];
10337 heap[smallest] = thisevent;
10340 eventnum = smallest;
10341 leftchild = 2 * eventnum + 1;
10342 notdone = leftchild < heapsize;
10351#ifdef ANSI_DECLARATORS
10352void eventheapdelete(
struct event **heap,
int heapsize,
int eventnum)
10354void eventheapdelete(heap, heapsize, eventnum)
10355struct event **heap;
10361 struct event *moveevent;
10362 REAL eventx, eventy;
10366 moveevent = heap[heapsize - 1];
10367 if (eventnum > 0) {
10368 eventx = moveevent->
xkey;
10369 eventy = moveevent->
ykey;
10371 parent = (eventnum - 1) >> 1;
10372 if ((heap[parent]->
ykey < eventy) ||
10373 ((heap[parent]->
ykey == eventy)
10374 && (heap[parent]->
xkey <= eventx))) {
10377 heap[eventnum] = heap[parent];
10381 notdone = eventnum > 0;
10385 heap[eventnum] = moveevent;
10387 eventheapify(heap, heapsize - 1, eventnum);
10394#ifdef ANSI_DECLARATORS
10395void createeventheap(
struct mesh *
m,
struct event ***eventheap,
10396 struct event **events,
struct event **freeevents)
10398void createeventheap(
m, eventheap, events, freeevents)
10400struct event ***eventheap;
10401struct event **events;
10402struct event **freeevents;
10410 maxevents = (3 *
m->invertices) / 2;
10412 (
int)
sizeof(
struct event *));
10415 for (i = 0; i <
m->invertices; i++) {
10417 (*events)[i].eventptr = (
VOID *) thisvertex;
10418 (*events)[i].xkey = thisvertex[0];
10419 (*events)[i].ykey = thisvertex[1];
10420 eventheapinsert(*eventheap, i, *events + i);
10422 *freeevents = (
struct event *) NULL;
10423 for (i = maxevents - 1; i >=
m->invertices; i--) {
10425 *freeevents = *events + i;
10433#ifdef ANSI_DECLARATORS
10434int rightofhyperbola(
struct mesh *
m,
struct otri *fronttri,
vertex newsite)
10436int rightofhyperbola(
m, fronttri, newsite)
10438struct otri *fronttri;
10443 vertex leftvertex, rightvertex;
10444 REAL dxa, dya, dxb, dyb;
10446 m->hyperbolacount++;
10448 dest(*fronttri, leftvertex);
10449 apex(*fronttri, rightvertex);
10450 if ((leftvertex[1] < rightvertex[1]) ||
10451 ((leftvertex[1] == rightvertex[1]) &&
10452 (leftvertex[0] < rightvertex[0]))) {
10453 if (newsite[0] >= rightvertex[0]) {
10457 if (newsite[0] <= leftvertex[0]) {
10461 dxa = leftvertex[0] - newsite[0];
10462 dya = leftvertex[1] - newsite[1];
10463 dxb = rightvertex[0] - newsite[0];
10464 dyb = rightvertex[1] - newsite[1];
10465 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10472#ifdef ANSI_DECLARATORS
10475REAL circletop(
m, pa, pb, pc, ccwabc)
10484 REAL xac, yac, xbc, ybc, xab, yab;
10485 REAL aclen2, bclen2, ablen2;
10489 xac = pa[0] - pc[0];
10490 yac = pa[1] - pc[1];
10491 xbc = pb[0] - pc[0];
10492 ybc = pb[1] - pc[1];
10493 xab = pa[0] - pb[0];
10494 yab = pa[1] - pb[1];
10495 aclen2 = xac * xac + yac * yac;
10496 bclen2 = xbc * xbc + ybc * ybc;
10497 ablen2 = xab * xab + yab * yab;
10498 return pc[1] + (xac * bclen2 - xbc * aclen2 +
sqrt(aclen2 * bclen2 * ablen2))
10506#ifdef ANSI_DECLARATORS
10507void check4deadevent(
struct otri *checktri,
struct event **freeevents,
10508 struct event **eventheap,
int *heapsize)
10510void check4deadevent(checktri, freeevents, eventheap, heapsize)
10511struct otri *checktri;
10512struct event **freeevents;
10513struct event **eventheap;
10518 struct event *deadevent;
10522 org(*checktri, eventvertex);
10523 if (eventvertex != (
vertex) NULL) {
10524 deadevent = (
struct event *) eventvertex;
10527 *freeevents = deadevent;
10528 eventheapdelete(eventheap, *heapsize, eventnum);
10530 setorg(*checktri, NULL);
10538#ifdef ANSI_DECLARATORS
10542struct splaynode *splay(
m, splaytree, searchpoint, searchtri)
10546struct otri *searchtri;
10551 struct splaynode *lefttree, *righttree;
10554 int rightofroot, rightofchild;
10556 if (splaytree == (
struct splaynode *) NULL) {
10560 if (checkvertex == splaytree->
keydest) {
10561 rightofroot = rightofhyperbola(
m, &splaytree->
keyedge, searchpoint);
10564 child = splaytree->
rchild;
10566 child = splaytree->
lchild;
10568 if (child == (
struct splaynode *) NULL) {
10572 if (checkvertex != child->
keydest) {
10573 child = splay(
m, child, searchpoint, searchtri);
10574 if (child == (
struct splaynode *) NULL) {
10583 rightofchild = rightofhyperbola(
m, &child->
keyedge, searchpoint);
10584 if (rightofchild) {
10586 grandchild = splay(
m, child->
rchild, searchpoint, searchtri);
10587 child->
rchild = grandchild;
10589 grandchild = splay(
m, child->
lchild, searchpoint, searchtri);
10590 child->
lchild = grandchild;
10592 if (grandchild == (
struct splaynode *) NULL) {
10595 child->
lchild = splaytree;
10598 child->
rchild = splaytree;
10602 if (rightofchild) {
10605 child->
lchild = splaytree;
10608 grandchild->
rchild = splaytree;
10611 grandchild->
lchild = child;
10615 grandchild->
lchild = splaytree;
10618 child->
rchild = splaytree;
10621 grandchild->
rchild = child;
10625 lefttree = splay(
m, splaytree->
lchild, searchpoint, searchtri);
10626 righttree = splay(
m, splaytree->
rchild, searchpoint, searchtri);
10629 if (lefttree == (
struct splaynode *) NULL) {
10631 }
else if (righttree == (
struct splaynode *) NULL) {
10635 righttree->
lchild = lefttree;
10639 lefttree->
rchild = righttree;
10643 leftright = lefttree->
rchild;
10645 leftright = leftright->
rchild;
10647 leftright->
rchild = righttree;
10657#ifdef ANSI_DECLARATORS
10661struct splaynode *splayinsert(
m, splayroot, newkey, searchpoint)
10664struct otri *newkey;
10674 if (splayroot == (
struct splaynode *) NULL) {
10677 }
else if (rightofhyperbola(
m, &splayroot->
keyedge, searchpoint)) {
10678 newsplaynode->
lchild = splayroot;
10683 newsplaynode->
rchild = splayroot;
10686 return newsplaynode;
10693#ifdef ANSI_DECLARATORS
10696 struct otri *newkey,
10699struct splaynode *circletopinsert(
m,
b, splayroot, newkey, pa, pb, pc, topy)
10703struct otri *newkey;
10712 REAL xac, yac, xbc, ybc;
10713 REAL aclen2, bclen2;
10714 REAL searchpoint[2];
10715 struct otri dummytri;
10718 xac = pa[0] - pc[0];
10719 yac = pa[1] - pc[1];
10720 xbc = pb[0] - pc[0];
10721 ybc = pb[1] - pc[1];
10722 aclen2 = xac * xac + yac * yac;
10723 bclen2 = xbc * xbc + ybc * ybc;
10724 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10725 searchpoint[1] = topy;
10726 return splayinsert(
m, splay(
m, splayroot, (
vertex) searchpoint, &dummytri),
10727 newkey, (
vertex) searchpoint);
10734#ifdef ANSI_DECLARATORS
10736 struct otri *bottommost,
vertex searchvertex,
10737 struct otri *searchtri,
int *farright)
10739struct splaynode *frontlocate(
m, splayroot, bottommost, searchvertex,
10740 searchtri, farright)
10743struct otri *bottommost;
10745struct otri *searchtri;
10753 otricopy(*bottommost, *searchtri);
10754 splayroot = splay(
m, splayroot, searchvertex, searchtri);
10757 while (!farrightflag && rightofhyperbola(
m, searchtri, searchvertex)) {
10759 farrightflag =
otriequal(*searchtri, *bottommost);
10761 *farright = farrightflag;
10769#ifdef ANSI_DECLARATORS
10772long sweeplinedelaunay(
m,
b)
10778 struct event **eventheap;
10779 struct event *events;
10780 struct event *freeevents;
10781 struct event *nextevent;
10782 struct event *newevent;
10784 struct otri bottommost;
10785 struct otri searchtri;
10786 struct otri fliptri;
10787 struct otri lefttri, righttri, farlefttri, farrighttri;
10788 struct otri inserttri;
10789 vertex firstvertex, secondvertex;
10790 vertex nextvertex, lastvertex;
10792 vertex leftvertex, midvertex, rightvertex;
10793 REAL lefttest, righttest;
10795 int check4events, farrightflag;
10803 printf(
" Placing vertices in event heap.\n");
10805 createeventheap(
m, &eventheap, &events, &freeevents);
10806 heapsize =
m->invertices;
10809 printf(
" Forming triangulation.\n");
10813 bond(lefttri, righttri);
10816 bond(lefttri, righttri);
10819 bond(lefttri, righttri);
10820 firstvertex = (
vertex) eventheap[0]->eventptr;
10822 freeevents = eventheap[0];
10823 eventheapdelete(eventheap, heapsize, 0);
10826 if (heapsize == 0) {
10827 printf(
"Error: Input vertices are all identical.\n");
10830 secondvertex = (
vertex) eventheap[0]->eventptr;
10832 freeevents = eventheap[0];
10833 eventheapdelete(eventheap, heapsize, 0);
10835 if ((firstvertex[0] == secondvertex[0]) &&
10836 (firstvertex[1] == secondvertex[1])) {
10839"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10840 secondvertex[0], secondvertex[1]);
10845 }
while ((firstvertex[0] == secondvertex[0]) &&
10846 (firstvertex[1] == secondvertex[1]));
10847 setorg(lefttri, firstvertex);
10848 setdest(lefttri, secondvertex);
10849 setorg(righttri, secondvertex);
10850 setdest(righttri, firstvertex);
10851 lprev(lefttri, bottommost);
10852 lastvertex = secondvertex;
10853 while (heapsize > 0) {
10854 nextevent = eventheap[0];
10855 eventheapdelete(eventheap, heapsize, 0);
10858 if (nextevent->
xkey <
m->xmin) {
10860 oprev(fliptri, farlefttri);
10861 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10862 onext(fliptri, farrighttri);
10863 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10865 if (
otriequal(farlefttri, bottommost)) {
10866 lprev(fliptri, bottommost);
10870 lprev(fliptri, lefttri);
10871 lnext(fliptri, righttri);
10872 sym(lefttri, farlefttri);
10876 dest(fliptri, leftvertex);
10877 apex(fliptri, midvertex);
10878 org(fliptri, rightvertex);
10879 splayroot = circletopinsert(
m,
b, splayroot, &lefttri, leftvertex,
10880 midvertex, rightvertex, nextevent->
ykey);
10884 if ((nextvertex[0] == lastvertex[0]) &&
10885 (nextvertex[1] == lastvertex[1])) {
10888"Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10889 nextvertex[0], nextvertex[1]);
10895 lastvertex = nextvertex;
10897 splayroot = frontlocate(
m, splayroot, &bottommost, nextvertex,
10898 &searchtri, &farrightflag);
10908 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10911 sym(searchtri, farlefttri);
10914 dest(farrighttri, connectvertex);
10915 setorg(lefttri, connectvertex);
10916 setdest(lefttri, nextvertex);
10917 setorg(righttri, nextvertex);
10918 setdest(righttri, connectvertex);
10919 bond(lefttri, righttri);
10922 bond(lefttri, righttri);
10925 bond(lefttri, farlefttri);
10926 bond(righttri, farrighttri);
10927 if (!farrightflag &&
otriequal(farrighttri, bottommost)) {
10932 splayroot = splayinsert(
m, splayroot, &lefttri, nextvertex);
10934 lnext(righttri, inserttri);
10935 splayroot = splayinsert(
m, splayroot, &inserttri, nextvertex);
10940 freeevents = nextevent;
10942 if (check4events) {
10943 apex(farlefttri, leftvertex);
10944 dest(lefttri, midvertex);
10945 apex(lefttri, rightvertex);
10947 if (lefttest > 0.0) {
10948 newevent = freeevents;
10950 newevent->
xkey =
m->xminextreme;
10951 newevent->
ykey = circletop(
m, leftvertex, midvertex, rightvertex,
10954 eventheapinsert(eventheap, heapsize, newevent);
10956 setorg(lefttri, newevent);
10958 apex(righttri, leftvertex);
10959 org(righttri, midvertex);
10960 apex(farrighttri, rightvertex);
10962 if (righttest > 0.0) {
10963 newevent = freeevents;
10965 newevent->
xkey =
m->xminextreme;
10966 newevent->
ykey = circletop(
m, leftvertex, midvertex, rightvertex,
10969 eventheapinsert(eventheap, heapsize, newevent);
10971 setorg(farrighttri, newevent);
10997#ifdef ANSI_DECLARATORS
11014 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11019 printf(
"Constructing Delaunay triangulation ");
11020 if (
b->incremental) {
11021 printf(
"by incremental method.\n");
11022 }
else if (
b->sweepline) {
11023 printf(
"by sweepline method.\n");
11025 printf(
"by divide-and-conquer method.\n");
11028 if (
b->incremental) {
11029 hulledges = incrementaldelaunay(
m,
b);
11030 }
else if (
b->sweepline) {
11031 hulledges = sweeplinedelaunay(
m,
b);
11037 if (
m->triangles.items == 0) {
11074#ifdef ANSI_DECLARATORS
11075int reconstruct(
struct mesh *
m,
struct behavior *
b,
int *trianglelist,
11076 REAL *triangleattriblist,
REAL *trianglearealist,
11077 int elements,
int corners,
int attribs,
11078 int *segmentlist,
int *segmentmarkerlist,
int numberofsegments)
11080int reconstruct(
m,
b, trianglelist, triangleattriblist, trianglearealist,
11081 elements, corners, attribs, segmentlist, segmentmarkerlist,
11086REAL *triangleattriblist;
11087REAL *trianglearealist;
11092int *segmentmarkerlist;
11093int numberofsegments;
11098#ifdef ANSI_DECLARATORS
11099long reconstruct(
struct mesh *
m,
struct behavior *
b,
char *elefilename,
11100 char *areafilename,
char *polyfilename, FILE *polyfile)
11102long reconstruct(
m,
b, elefilename, areafilename, polyfilename, polyfile)
11124 struct otri triangleloop;
11125 struct otri triangleleft;
11126 struct otri checktri;
11127 struct otri checkleft;
11128 struct otri checkneighbor;
11129 struct osub subsegloop;
11134 vertex checkdest, checkapex;
11137 vertex segmentorg, segmentdest;
11141 int killvertexindex;
11143 int segmentmarkers;
11148 long elementnumber, segmentnumber;
11153 m->inelements = elements;
11154 incorners = corners;
11155 if (incorners < 3) {
11156 printf(
"Error: Triangles must have at least 3 vertices.\n");
11159 m->eextras = attribs;
11163 printf(
"Opening %s.\n", elefilename);
11165 elefile = fopen(elefilename,
"r");
11166 if (elefile == (FILE *) NULL) {
11167 printf(
" Error: Cannot access file %s.\n", elefilename);
11172 stringptr = readline(inputline, elefile, elefilename);
11173 m->inelements = (
int) strtol(stringptr, &stringptr, 0);
11174 stringptr = findfield(stringptr);
11175 if (*stringptr ==
'\0') {
11178 incorners = (
int) strtol(stringptr, &stringptr, 0);
11179 if (incorners < 3) {
11180 printf(
"Error: Triangles in %s must have at least 3 vertices.\n",
11185 stringptr = findfield(stringptr);
11186 if (*stringptr ==
'\0') {
11189 m->eextras = (
int) strtol(stringptr, &stringptr, 0);
11196 for (elementnumber = 1; elementnumber <=
m->inelements; elementnumber++) {
11199 triangleloop.tri[3] = (
triangle) triangleloop.tri;
11202 segmentmarkers = 0;
11205 m->insegments = numberofsegments;
11206 segmentmarkers = segmentmarkerlist != (
int *) NULL;
11210 stringptr = readline(inputline, polyfile,
b->inpolyfilename);
11211 m->insegments = (
int) strtol(stringptr, &stringptr, 0);
11212 stringptr = findfield(stringptr);
11213 if (*stringptr !=
'\0') {
11214 segmentmarkers = (
int) strtol(stringptr, &stringptr, 0);
11219 for (segmentnumber = 1; segmentnumber <=
m->insegments; segmentnumber++) {
11222 subsegloop.ss[2] = (
subseg) subsegloop.ss;
11233 printf(
"Opening %s.\n", areafilename);
11235 areafile = fopen(areafilename,
"r");
11236 if (areafile == (FILE *) NULL) {
11237 printf(
" Error: Cannot access file %s.\n", areafilename);
11240 stringptr = readline(inputline, areafile, areafilename);
11241 areaelements = (
int) strtol(stringptr, &stringptr, 0);
11242 if (areaelements !=
m->inelements) {
11243 printf(
"Error: %s and %s disagree on number of triangles.\n",
11244 elefilename, areafilename);
11251 printf(
"Reconstructing mesh.\n");
11259 for (i = 0; i <
m->vertices.items; i++) {
11260 vertexarray[i] = (
triangle)
m->dummytri;
11264 printf(
" Assembling triangles.\n");
11270 elementnumber =
b->firstnumber;
11271 while (triangleloop.tri != (
triangle *) NULL) {
11274 for (j = 0; j < 3; j++) {
11275 corner[j] = trianglelist[vertexindex++];
11276 if ((corner[j] <
b->firstnumber) ||
11277 (corner[j] >=
b->firstnumber +
m->invertices)) {
11278 printf(
"Error: Triangle %ld has an invalid vertex index.\n",
11285 stringptr = readline(inputline, elefile, elefilename);
11286 for (j = 0; j < 3; j++) {
11287 stringptr = findfield(stringptr);
11288 if (*stringptr ==
'\0') {
11289 printf(
"Error: Triangle %ld is missing vertex %d in %s.\n",
11290 elementnumber, j + 1, elefilename);
11293 corner[j] = (
int) strtol(stringptr, &stringptr, 0);
11294 if ((corner[j] <
b->firstnumber) ||
11295 (corner[j] >=
b->firstnumber +
m->invertices)) {
11296 printf(
"Error: Triangle %ld has an invalid vertex index.\n",
11305 for (j = 3; j < incorners; j++) {
11307 killvertexindex = trianglelist[vertexindex++];
11309 stringptr = findfield(stringptr);
11310 if (*stringptr !=
'\0') {
11311 killvertexindex = (
int) strtol(stringptr, &stringptr, 0);
11313 if ((killvertexindex >=
b->firstnumber) &&
11314 (killvertexindex <
b->firstnumber +
m->invertices)) {
11327 for (j = 0; j <
m->eextras; j++) {
11331 stringptr = findfield(stringptr);
11332 if (*stringptr ==
'\0') {
11336 (
REAL) strtod(stringptr, &stringptr));
11343 area = trianglearealist[elementnumber -
b->firstnumber];
11346 stringptr = readline(inputline, areafile, areafilename);
11347 stringptr = findfield(stringptr);
11348 if (*stringptr ==
'\0') {
11351 area = (
REAL) strtod(stringptr, &stringptr);
11358 triangleloop.orient = 0;
11363 for (triangleloop.orient = 0; triangleloop.orient < 3;
11364 triangleloop.orient++) {
11366 aroundvertex = corner[triangleloop.orient];
11368 nexttri = vertexarray[aroundvertex -
b->firstnumber];
11370 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11372 vertexarray[aroundvertex -
b->firstnumber] =
encode(triangleloop);
11373 decode(nexttri, checktri);
11374 if (checktri.
tri !=
m->dummytri) {
11375 dest(triangleloop, tdest);
11376 apex(triangleloop, tapex);
11379 dest(checktri, checkdest);
11380 apex(checktri, checkapex);
11381 if (tapex == checkdest) {
11383 lprev(triangleloop, triangleleft);
11384 bond(triangleleft, checktri);
11386 if (tdest == checkapex) {
11388 lprev(checktri, checkleft);
11389 bond(triangleloop, checkleft);
11392 nexttri = checktri.
tri[6 + checktri.
orient];
11393 decode(nexttri, checktri);
11394 }
while (checktri.
tri !=
m->dummytri);
11413 printf(
" Marking segments in triangulation.\n");
11420 segmentnumber =
b->firstnumber;
11421 while (subsegloop.ss != (
subseg *) NULL) {
11423 end[0] = segmentlist[vertexindex++];
11424 end[1] = segmentlist[vertexindex++];
11425 if (segmentmarkers) {
11426 boundmarker = segmentmarkerlist[segmentnumber -
b->firstnumber];
11430 stringptr = readline(inputline, polyfile,
b->inpolyfilename);
11432 stringptr = findfield(stringptr);
11433 if (*stringptr ==
'\0') {
11434 printf(
"Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11438 end[0] = (
int) strtol(stringptr, &stringptr, 0);
11440 stringptr = findfield(stringptr);
11441 if (*stringptr ==
'\0') {
11442 printf(
"Error: Segment %ld is missing its second endpoint in %s.\n",
11443 segmentnumber, polyfilename);
11446 end[1] = (
int) strtol(stringptr, &stringptr, 0);
11448 if (segmentmarkers) {
11449 stringptr = findfield(stringptr);
11450 if (*stringptr ==
'\0') {
11453 boundmarker = (
int) strtol(stringptr, &stringptr, 0);
11457 for (j = 0; j < 2; j++) {
11458 if ((end[j] <
b->firstnumber) ||
11459 (end[j] >=
b->firstnumber +
m->invertices)) {
11460 printf(
"Error: Segment %ld has an invalid vertex index.\n",
11467 subsegloop.ssorient = 0;
11470 setsorg(subsegloop, segmentorg);
11471 setsdest(subsegloop, segmentdest);
11474 setmark(subsegloop, boundmarker);
11476 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11477 subsegloop.ssorient++) {
11479 aroundvertex = end[1 - subsegloop.ssorient];
11481 prevlink = &vertexarray[aroundvertex -
b->firstnumber];
11482 nexttri = vertexarray[aroundvertex -
b->firstnumber];
11483 decode(nexttri, checktri);
11484 sorg(subsegloop, shorg);
11493 while (notfound && (checktri.
tri !=
m->dummytri)) {
11494 dest(checktri, checkdest);
11495 if (shorg == checkdest) {
11497 *prevlink = checktri.
tri[6 + checktri.
orient];
11499 tsbond(checktri, subsegloop);
11501 sym(checktri, checkneighbor);
11502 if (checkneighbor.tri ==
m->dummytri) {
11512 prevlink = &checktri.
tri[6 + checktri.
orient];
11513 nexttri = checktri.
tri[6 + checktri.
orient];
11514 decode(nexttri, checktri);
11524 for (i = 0; i <
m->vertices.items; i++) {
11526 nexttri = vertexarray[i];
11527 decode(nexttri, checktri);
11528 while (checktri.
tri !=
m->dummytri) {
11531 nexttri = checktri.
tri[6 + checktri.
orient];
11534 sym(checktri, checkneighbor);
11535 if (checkneighbor.tri ==
m->dummytri) {
11539 decode(nexttri, checktri);
11574#ifdef ANSI_DECLARATORS
11576 struct otri *searchtri,
11582struct otri *searchtri;
11587 struct otri checktri;
11589 vertex leftvertex, rightvertex;
11590 REAL leftccw, rightccw;
11591 int leftflag, rightflag;
11594 org(*searchtri, startvertex);
11595 dest(*searchtri, rightvertex);
11596 apex(*searchtri, leftvertex);
11599 leftflag = leftccw > 0.0;
11602 rightflag = rightccw > 0.0;
11603 if (leftflag && rightflag) {
11606 onext(*searchtri, checktri);
11607 if (checktri.
tri ==
m->dummytri) {
11616 if (searchtri->
tri ==
m->dummytri) {
11617 printf(
"Internal error in finddirection(): Unable to find a\n");
11618 printf(
" triangle leading from (%.12g, %.12g) to", startvertex[0],
11620 printf(
" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11623 apex(*searchtri, leftvertex);
11624 rightccw = leftccw;
11626 leftflag = leftccw > 0.0;
11628 while (rightflag) {
11631 if (searchtri->
tri ==
m->dummytri) {
11632 printf(
"Internal error in finddirection(): Unable to find a\n");
11633 printf(
" triangle leading from (%.12g, %.12g) to", startvertex[0],
11635 printf(
" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11638 dest(*searchtri, rightvertex);
11639 leftccw = rightccw;
11641 rightflag = rightccw > 0.0;
11643 if (leftccw == 0.0) {
11645 }
else if (rightccw == 0.0) {
11669#ifdef ANSI_DECLARATORS
11671 struct otri *splittri,
struct osub *splitsubseg,
11677struct otri *splittri;
11678struct osub *splitsubseg;
11683 struct osub opposubseg;
11686 vertex leftvertex, rightvertex;
11699 apex(*splittri, endpoint1);
11700 org(*splittri, torg);
11701 dest(*splittri, tdest);
11703 tx = tdest[0] - torg[0];
11704 ty = tdest[1] - torg[1];
11705 ex = endpoint2[0] - endpoint1[0];
11706 ey = endpoint2[1] - endpoint1[1];
11707 etx = torg[0] - endpoint2[0];
11708 ety = torg[1] - endpoint2[1];
11709 denom = ty *
ex - tx *
ey;
11710 if (denom == 0.0) {
11711 printf(
"Internal error in segmentintersection():");
11712 printf(
" Attempt to find intersection of parallel segments.\n");
11715 split = (
ey * etx -
ex * ety) / denom;
11719 for (i = 0; i < 2 +
m->nextras; i++) {
11720 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11724 if (
b->verbose > 1) {
11726 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11727 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11730 success =
insertvertex(
m,
b, newvertex, splittri, splitsubseg, 0, 0);
11732 printf(
"Internal error in segmentintersection():\n");
11733 printf(
" Failure to split a segment.\n");
11738 if (
m->steinerleft > 0) {
11744 spivot(*splitsubseg, opposubseg);
11750 }
while (splitsubseg->
ss !=
m->dummysub);
11754 }
while (opposubseg.
ss !=
m->dummysub);
11760 dest(*splittri, rightvertex);
11761 apex(*splittri, leftvertex);
11762 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11764 }
else if ((rightvertex[0] != endpoint1[0]) ||
11765 (rightvertex[1] != endpoint1[1])) {
11766 printf(
"Internal error in segmentintersection():\n");
11767 printf(
" Topological inconsistency after splitting a segment.\n");
11797#ifdef ANSI_DECLARATORS
11799 vertex endpoint2,
int newmark)
11804struct otri *searchtri;
11810 struct otri crosstri;
11811 struct osub crosssubseg;
11812 vertex leftvertex, rightvertex;
11817 dest(*searchtri, rightvertex);
11818 apex(*searchtri, leftvertex);
11819 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11820 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11822 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11843 lnext(*searchtri, crosstri);
11844 tspivot(crosstri, crosssubseg);
11846 if (crosssubseg.
ss ==
m->dummysub) {
11881#ifdef ANSI_DECLARATORS
11885void conformingedge(
m,
b, endpoint1, endpoint2, newmark)
11894 struct otri searchtri1, searchtri2;
11895 struct osub brokensubseg;
11897 vertex midvertex1, midvertex2;
11902 if (
b->verbose > 2) {
11903 printf(
"Forcing segment into triangulation by recursive splitting:\n");
11904 printf(
" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11905 endpoint2[0], endpoint2[1]);
11910 for (i = 0; i < 2 +
m->nextras; i++) {
11911 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11916 searchtri1.tri =
m->dummytri;
11921 if (
b->verbose > 2) {
11922 printf(
" Segment intersects existing vertex (%.12g, %.12g).\n",
11923 newvertex[0], newvertex[1]);
11927 org(searchtri1, newvertex);
11930 if (
b->verbose > 2) {
11931 printf(
" Two segments intersect at (%.12g, %.12g).\n",
11932 newvertex[0], newvertex[1]);
11935 tspivot(searchtri1, brokensubseg);
11936 success =
insertvertex(
m,
b, newvertex, &searchtri1, &brokensubseg,
11939 printf(
"Internal error in conformingedge():\n");
11940 printf(
" Failure to split a segment.\n");
11945 if (
m->steinerleft > 0) {
11959 org(searchtri1, midvertex1);
11960 conformingedge(
m,
b, midvertex1, endpoint1, newmark);
11965 org(searchtri2, midvertex2);
11966 conformingedge(
m,
b, midvertex2, endpoint2, newmark);
12011#ifdef ANSI_DECLARATORS
12013 struct otri *fixuptri,
int leftside)
12018struct otri *fixuptri;
12023 struct otri neartri;
12024 struct otri fartri;
12025 struct osub faredge;
12026 vertex nearvertex, leftvertex, rightvertex, farvertex;
12030 lnext(*fixuptri, neartri);
12031 sym(neartri, fartri);
12033 if (fartri.
tri ==
m->dummytri) {
12037 if (faredge.
ss !=
m->dummysub) {
12041 apex(neartri, nearvertex);
12042 org(neartri, leftvertex);
12043 dest(neartri, rightvertex);
12044 apex(fartri, farvertex);
12064 if (
incircle(
m,
b, leftvertex, farvertex, rightvertex, nearvertex) <=
12131#ifdef ANSI_DECLARATORS
12133 struct otri *starttri,
vertex endpoint2,
int newmark)
12138struct otri *starttri;
12144 struct otri fixuptri, fixuptri2;
12145 struct osub crosssubseg;
12154 org(*starttri, endpoint1);
12155 lnext(*starttri, fixuptri);
12162 org(fixuptri, farvertex);
12165 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12166 oprev(fixuptri, fixuptri2);
12179 oprev(fixuptri, fixuptri2);
12186 oprev(fixuptri, fixuptri2);
12202 tspivot(fixuptri, crosssubseg);
12203 if (crosssubseg.
ss ==
m->dummysub) {
12233#ifdef ANSI_DECLARATORS
12246 struct otri searchtri1, searchtri2;
12251 if (
b->verbose > 1) {
12252 printf(
" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12253 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12257 checkvertex = (
vertex) NULL;
12259 if (encodedtri != (
triangle) NULL) {
12260 decode(encodedtri, searchtri1);
12261 org(searchtri1, checkvertex);
12263 if (checkvertex != endpoint1) {
12265 searchtri1.
tri =
m->dummytri;
12271 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12272 printf(
" (%.12g, %.12g) in triangulation.\n",
12273 endpoint1[0], endpoint1[1]);
12287 org(searchtri1, endpoint1);
12290 checkvertex = (
vertex) NULL;
12292 if (encodedtri != (
triangle) NULL) {
12293 decode(encodedtri, searchtri2);
12294 org(searchtri2, checkvertex);
12296 if (checkvertex != endpoint2) {
12298 searchtri2.
tri =
m->dummytri;
12304 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12305 printf(
" (%.12g, %.12g) in triangulation.\n",
12306 endpoint2[0], endpoint2[1]);
12320 org(searchtri2, endpoint2);
12326 conformingedge(
m,
b, endpoint1, endpoint2, newmark);
12345#ifdef ANSI_DECLARATORS
12354 struct otri hulltri;
12355 struct otri nexttri;
12356 struct otri starttri;
12360 hulltri.
tri =
m->dummytri;
12371 oprev(hulltri, nexttri);
12372 while (nexttri.
tri !=
m->dummytri) {
12374 oprev(hulltri, nexttri);
12376 }
while (!
otriequal(hulltri, starttri));
12391#ifdef ANSI_DECLARATORS
12393 int *segmentmarkerlist,
int numberofsegments)
12395void formskeleton(
m,
b, segmentlist, segmentmarkerlist, numberofsegments)
12399int *segmentmarkerlist;
12400int numberofsegments;
12405#ifdef ANSI_DECLARATORS
12407 FILE *polyfile,
char *polyfilename)
12420 char polyfilename[6];
12426 vertex endpoint1, endpoint2;
12427 int segmentmarkers;
12434 printf(
"Recovering segments in Delaunay triangulation.\n");
12437 strcpy(polyfilename,
"input");
12438 m->insegments = numberofsegments;
12439 segmentmarkers = segmentmarkerlist != (
int *) NULL;
12444 stringptr = readline(inputline, polyfile, polyfilename);
12445 m->insegments = (
int) strtol(stringptr, &stringptr, 0);
12446 stringptr = findfield(stringptr);
12447 if (*stringptr ==
'\0') {
12448 segmentmarkers = 0;
12450 segmentmarkers = (
int) strtol(stringptr, &stringptr, 0);
12455 if (
m->triangles.items == 0) {
12461 if (
m->insegments > 0) {
12464 printf(
" Recovering PSLG segments.\n");
12470 for (i = 0; i <
m->insegments; i++) {
12472 end1 = segmentlist[index++];
12473 end2 = segmentlist[index++];
12474 if (segmentmarkers) {
12475 boundmarker = segmentmarkerlist[i];
12478 stringptr = readline(inputline, polyfile,
b->inpolyfilename);
12479 stringptr = findfield(stringptr);
12480 if (*stringptr ==
'\0') {
12481 printf(
"Error: Segment %d has no endpoints in %s.\n",
12482 b->firstnumber + i, polyfilename);
12485 end1 = (
int) strtol(stringptr, &stringptr, 0);
12487 stringptr = findfield(stringptr);
12488 if (*stringptr ==
'\0') {
12489 printf(
"Error: Segment %d is missing its second endpoint in %s.\n",
12490 b->firstnumber + i, polyfilename);
12493 end2 = (
int) strtol(stringptr, &stringptr, 0);
12495 if (segmentmarkers) {
12496 stringptr = findfield(stringptr);
12497 if (*stringptr ==
'\0') {
12500 boundmarker = (
int) strtol(stringptr, &stringptr, 0);
12505 (end1 >=
b->firstnumber +
m->invertices)) {
12507 printf(
"Warning: Invalid first endpoint of segment %d in %s.\n",
12508 b->firstnumber + i, polyfilename);
12511 (end2 >=
b->firstnumber +
m->invertices)) {
12513 printf(
"Warning: Invalid second endpoint of segment %d in %s.\n",
12514 b->firstnumber + i, polyfilename);
12520 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12522 printf(
"Warning: Endpoints of segment %d are coincident in %s.\n",
12523 b->firstnumber + i, polyfilename);
12533 if (
b->convex || !
b->poly) {
12536 printf(
" Enclosing convex hull with segments.\n");
12558#ifdef ANSI_DECLARATORS
12567 struct otri hulltri;
12568 struct otri nexttri;
12569 struct otri starttri;
12570 struct osub hullsubseg;
12577 printf(
" Marking concavities (external triangles) for elimination.\n");
12580 hulltri.
tri =
m->dummytri;
12590 tspivot(hulltri, hullsubseg);
12591 if (hullsubseg.
ss ==
m->dummysub) {
12596 *deadtriangle = hulltri.
tri;
12600 if (
mark(hullsubseg) == 0) {
12602 org(hulltri, horg);
12603 dest(hulltri, hdest);
12615 oprev(hulltri, nexttri);
12616 while (nexttri.
tri !=
m->dummytri) {
12618 oprev(hulltri, nexttri);
12620 }
while (!
otriequal(hulltri, starttri));
12640#ifdef ANSI_DECLARATORS
12649 struct otri testtri;
12650 struct otri neighbor;
12653 struct osub neighborsubseg;
12656 vertex deadorg, deaddest, deadapex;
12662 printf(
" Marking neighbors of marked triangles.\n");
12668 while (virusloop != (
triangle **) NULL) {
12669 testtri.
tri = *virusloop;
12675 if (
b->verbose > 2) {
12679 org(testtri, deadorg);
12680 dest(testtri, deaddest);
12681 apex(testtri, deadapex);
12682 printf(
" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12683 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12684 deadapex[0], deadapex[1]);
12689 sym(testtri, neighbor);
12691 tspivot(testtri, neighborsubseg);
12693 if ((neighbor.
tri ==
m->dummytri) ||
infected(neighbor)) {
12694 if (neighborsubseg.
ss !=
m->dummysub) {
12699 if (neighbor.
tri !=
m->dummytri) {
12708 if (neighborsubseg.
ss ==
m->dummysub) {
12711 if (
b->verbose > 2) {
12712 org(neighbor, deadorg);
12713 dest(neighbor, deaddest);
12714 apex(neighbor, deadapex);
12716 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12717 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12718 deadapex[0], deadapex[1]);
12723 *deadtriangle = neighbor.
tri;
12728 if (
mark(neighborsubseg) == 0) {
12731 org(neighbor, norg);
12732 dest(neighbor, ndest);
12749 printf(
" Deleting marked triangles.\n");
12754 while (virusloop != (
triangle **) NULL) {
12755 testtri.
tri = *virusloop;
12761 org(testtri, testvertex);
12763 if (testvertex != (
vertex) NULL) {
12768 onext(testtri, neighbor);
12770 while ((neighbor.
tri !=
m->dummytri) &&
12783 if (neighbor.
tri ==
m->dummytri) {
12785 oprev(testtri, neighbor);
12787 while (neighbor.
tri !=
m->dummytri) {
12800 if (
b->verbose > 1) {
12801 printf(
" Deleting vertex (%.12g, %.12g)\n",
12802 testvertex[0], testvertex[1]);
12813 sym(testtri, neighbor);
12814 if (neighbor.
tri ==
m->dummytri) {
12850#ifdef ANSI_DECLARATORS
12862 struct otri testtri;
12863 struct otri neighbor;
12866 struct osub neighborsubseg;
12867 vertex regionorg, regiondest, regionapex;
12871 if (
b->verbose > 1) {
12872 printf(
" Marking neighbors of marked triangles.\n");
12879 while (virusloop != (
triangle **) NULL) {
12880 testtri.
tri = *virusloop;
12886 if (
b->regionattrib) {
12894 if (
b->verbose > 2) {
12898 org(testtri, regionorg);
12899 dest(testtri, regiondest);
12900 apex(testtri, regionapex);
12901 printf(
" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12902 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12903 regionapex[0], regionapex[1]);
12908 sym(testtri, neighbor);
12910 tspivot(testtri, neighborsubseg);
12913 if ((neighbor.
tri !=
m->dummytri) && !
infected(neighbor)
12914 && (neighborsubseg.
ss ==
m->dummysub)) {
12915 if (
b->verbose > 2) {
12916 org(neighbor, regionorg);
12917 dest(neighbor, regiondest);
12918 apex(neighbor, regionapex);
12919 printf(
" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12920 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12921 regionapex[0], regionapex[1]);
12927 *regiontri = neighbor.
tri;
12937 if (
b->verbose > 1) {
12938 printf(
" Unmarking marked triangles.\n");
12942 while (virusloop != (
triangle **) NULL) {
12943 testtri.
tri = *virusloop;
12963#ifdef ANSI_DECLARATORS
12965 REAL *regionlist,
int regions)
12967void carveholes(
m,
b, holelist, holes, regionlist, regions)
12977 struct otri searchtri;
12978 struct otri triangleloop;
12979 struct otri *regiontris;
12982 vertex searchorg, searchdest;
12987 if (!(
b->quiet || (
b->noholes &&
b->convex))) {
12988 printf(
"Removing unwanted triangles.\n");
12989 if (
b->verbose && (holes > 0)) {
12990 printf(
" Marking holes for elimination.\n");
12997 (
int)
sizeof(
struct otri));
12999 regiontris = (
struct otri *) NULL;
13002 if (((holes > 0) && !
b->noholes) || !
b->convex || (regions > 0)) {
13014 if ((holes > 0) && !
b->noholes) {
13016 for (i = 0; i < 2 * holes; i += 2) {
13018 if ((holelist[i] >=
m->xmin) && (holelist[i] <=
m->xmax)
13019 && (holelist[i + 1] >=
m->ymin) && (holelist[i + 1] <=
m->ymax)) {
13021 searchtri.
tri =
m->dummytri;
13027 org(searchtri, searchorg);
13028 dest(searchtri, searchdest);
13032 intersect =
locate(
m,
b, &holelist[i], &searchtri);
13038 *holetri = searchtri.
tri;
13053 for (i = 0; i < regions; i++) {
13054 regiontris[i].
tri =
m->dummytri;
13056 if ((regionlist[4 * i] >=
m->xmin) && (regionlist[4 * i] <=
m->xmax) &&
13057 (regionlist[4 * i + 1] >=
m->ymin) &&
13058 (regionlist[4 * i + 1] <=
m->ymax)) {
13060 searchtri.
tri =
m->dummytri;
13066 org(searchtri, searchorg);
13067 dest(searchtri, searchdest);
13071 intersect =
locate(
m,
b, ®ionlist[4 * i], &searchtri);
13075 otricopy(searchtri, regiontris[i]);
13082 if (
m->viri.items > 0) {
13090 if (
b->regionattrib) {
13092 printf(
"Spreading regional attributes and area constraints.\n");
13094 printf(
"Spreading regional attributes.\n");
13097 printf(
"Spreading regional area constraints.\n");
13100 if (
b->regionattrib && !
b->refine) {
13103 triangleloop.
orient = 0;
13110 for (i = 0; i < regions; i++) {
13111 if (regiontris[i].
tri !=
m->dummytri) {
13118 *regiontri = regiontris[i].
tri;
13120 regionplague(
m,
b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13125 if (
b->regionattrib && !
b->refine) {
13132 if (((holes > 0) && !
b->noholes) || !
b->convex || (regions > 0)) {
13157#ifdef ANSI_DECLARATORS
13160void tallyencs(
m,
b)
13166 struct osub subsegloop;
13170 subsegloop.ssorient = 0;
13172 while (subsegloop.ss != (
subseg *) NULL) {
13174 dummy = checkseg4encroach(
m,
b, &subsegloop);
13189void precisionerror()
13191 printf(
"Try increasing the area criterion and/or reducing the minimum\n");
13192 printf(
" allowable angle so that tiny triangles are not created.\n");
13194 printf(
"Alternatively, try recompiling me with double precision\n");
13195 printf(
" arithmetic (by removing \"#define SINGLE\" from the\n");
13196 printf(
" source file or \"-DSINGLE\" from the makefile).\n");
13218#ifdef ANSI_DECLARATORS
13219void splitencsegs(
struct mesh *
m,
struct behavior *
b,
int triflaws)
13221void splitencsegs(
m,
b, triflaws)
13228 struct otri enctri;
13229 struct otri testtri;
13230 struct osub testsh;
13231 struct osub currentenc;
13233 vertex eorg, edest, eapex;
13236 REAL segmentlength, nearestpoweroftwo;
13238 REAL multiplier, divisor;
13239 int acuteorg, acuteorg2, acutedest, acutedest2;
13247 while ((
m->badsubsegs.items > 0) && (
m->steinerleft != 0)) {
13249 encloop = badsubsegtraverse(
m);
13250 while ((encloop != (
struct badsubseg *) NULL) && (
m->steinerleft != 0)) {
13252 sorg(currentenc, eorg);
13253 sdest(currentenc, edest);
13277 lnext(enctri, testtri);
13279 acuteorg = testsh.ss !=
m->dummysub;
13283 acutedest = testsh.ss !=
m->dummysub;
13288 if (!
b->conformdel && !acuteorg && !acutedest) {
13289 apex(enctri, eapex);
13291 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13292 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13293 deletevertex(
m,
b, &testtri);
13295 apex(enctri, eapex);
13296 lprev(enctri, testtri);
13302 sym(enctri, testtri);
13303 if (testtri.
tri !=
m->dummytri) {
13307 acutedest2 = testsh.ss !=
m->dummysub;
13308 acutedest = acutedest || acutedest2;
13312 acuteorg2 = testsh.ss !=
m->dummysub;
13313 acuteorg = acuteorg || acuteorg2;
13316 if (!
b->conformdel && !acuteorg2 && !acutedest2) {
13317 org(testtri, eapex);
13319 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13320 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13321 deletevertex(
m,
b, &testtri);
13322 sym(enctri, testtri);
13323 apex(testtri, eapex);
13331 if (acuteorg || acutedest) {
13332 segmentlength =
sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13333 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13336 nearestpoweroftwo = 1.0;
13337 while (segmentlength > 3.0 * nearestpoweroftwo) {
13338 nearestpoweroftwo *= 2.0;
13340 while (segmentlength < 1.5 * nearestpoweroftwo) {
13341 nearestpoweroftwo *= 0.5;
13344 split = nearestpoweroftwo / segmentlength;
13346 split = 1.0 - split;
13357 for (i = 0; i < 2 +
m->nextras; i++) {
13358 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13366 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13367 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13368 if ((multiplier != 0.0) && (divisor != 0.0)) {
13369 multiplier = multiplier / divisor;
13371 if (multiplier == multiplier) {
13372 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13373 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13380 if (
b->verbose > 1) {
13382 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13383 eorg[0], eorg[1], edest[0], edest[1],
13384 newvertex[0], newvertex[1]);
13387 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13388 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13389 printf(
"Error: Ran out of precision at (%.12g, %.12g).\n",
13390 newvertex[0], newvertex[1]);
13391 printf(
"I attempted to split a segment to a smaller size than\n");
13392 printf(
" can be accommodated by the finite precision of\n");
13393 printf(
" floating point arithmetic.\n");
13401 printf(
"Internal error in splitencsegs():\n");
13402 printf(
" Failure to split a segment.\n");
13405 if (
m->steinerleft > 0) {
13409 dummy = checkseg4encroach(
m,
b, ¤tenc);
13411 dummy = checkseg4encroach(
m,
b, ¤tenc);
13414 badsubsegdealloc(
m, encloop);
13415 encloop = badsubsegtraverse(
m);
13430#ifdef ANSI_DECLARATORS
13433void tallyfaces(
m,
b)
13439 struct otri triangleloop;
13442 printf(
" Making a list of bad triangles.\n");
13445 triangleloop.orient = 0;
13447 while (triangleloop.tri != (
triangle *) NULL) {
13449 testtriangle(
m,
b, &triangleloop);
13466#ifdef ANSI_DECLARATORS
13470void splittriangle(
m,
b, badtri)
13477 struct otri badotri;
13478 vertex borg, bdest, bapex;
13486 org(badotri, borg);
13487 dest(badotri, bdest);
13488 apex(badotri, bapex);
13494 if (
b->verbose > 1) {
13495 printf(
" Splitting this triangle at its circumcenter:\n");
13496 printf(
" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13497 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13506 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13507 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13508 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13511 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13512 newvertex[0], newvertex[1]);
13517 for (i = 2; i < 2 +
m->nextras; i++) {
13519 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13520 + eta * (bapex[i] - borg[i]);
13543 if (
m->steinerleft > 0) {
13550 if (
b->verbose > 1) {
13551 printf(
" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13562 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13563 newvertex[0], newvertex[1]);
13571 printf(
" The new vertex is at the circumcenter of triangle\n");
13572 printf(
" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13573 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13575 printf(
"This probably means that I am trying to refine triangles\n");
13576 printf(
" to a smaller size than can be accommodated by the finite\n");
13577 printf(
" precision of floating point arithmetic. (You can be\n");
13578 printf(
" sure of this if I fail to terminate.)\n");
13595#ifdef ANSI_DECLARATORS
13598void enforcequality(
m,
b)
13608 printf(
"Adding Steiner points to enforce quality.\n");
13614 printf(
" Looking for encroached subsegments.\n");
13618 if (
b->verbose && (
m->badsubsegs.items > 0)) {
13619 printf(
" Splitting encroached subsegments.\n");
13622 splitencsegs(
m,
b, 0);
13627 if ((
b->minangle > 0.0) ||
b->vararea ||
b->fixedarea ||
b->usertest) {
13632 for (i = 0; i < 4096; i++) {
13633 m->queuefront[i] = (
struct badtriang *) NULL;
13635 m->firstnonemptyq = -1;
13641 m->checkquality = 1;
13643 printf(
" Splitting bad triangles.\n");
13645 while ((
m->badtriangles.items > 0) && (
m->steinerleft != 0)) {
13647 badtri = dequeuebadtriang(
m);
13648 splittriangle(
m,
b, badtri);
13649 if (
m->badsubsegs.items > 0) {
13651 enqueuebadtriang(
m,
b, badtri);
13654 splitencsegs(
m,
b, 1);
13666 if (!
b->quiet &&
b->conformdel && (
m->badsubsegs.items > 0) &&
13667 (
m->steinerleft == 0)) {
13668 printf(
"\nWarning: I ran out of Steiner points, but the mesh has\n");
13669 if (
m->badsubsegs.items == 1) {
13670 printf(
" one encroached subsegment, and therefore might not be truly\n"
13673 printf(
" %ld encroached subsegments, and therefore might not be truly\n"
13674 ,
m->badsubsegs.items);
13676 printf(
" Delaunay. If the Delaunay property is important to you,\n");
13677 printf(
" try increasing the number of Steiner points (controlled by\n");
13678 printf(
" the -S switch) slightly and try again.\n\n");
13694#ifdef ANSI_DECLARATORS
13703 struct otri triangleloop, trisym;
13704 struct osub checkmark;
13712 printf(
"Adding vertices for second-order triangles.\n");
13719 m->vertices.deaditemstack = (
VOID *) NULL;
13730 for (triangleloop.
orient = 0; triangleloop.
orient < 3;
13731 triangleloop.
orient++) {
13732 sym(triangleloop, trisym);
13733 if ((triangleloop.
tri < trisym.
tri) || (trisym.
tri ==
m->dummytri)) {
13734 org(triangleloop, torg);
13735 dest(triangleloop, tdest);
13739 for (i = 0; i < 2 +
m->nextras; i++) {
13740 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13747 if (
b->usesegments) {
13748 tspivot(triangleloop, checkmark);
13750 if (checkmark.
ss !=
m->dummysub) {
13755 if (
b->verbose > 1) {
13756 printf(
" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13759 triangleloop.
tri[
m->highorderindex + triangleloop.
orient] =
13761 if (trisym.
tri !=
m->dummytri) {
13785#ifdef ANSI_DECLARATORS
13786char *readline(
char *
string, FILE *infile,
char *infilename)
13788char *readline(
string, infile, infilename)
13800 if (result == (
char *) NULL) {
13801 printf(
" Error: Unexpected end of file in %s.\n", infilename);
13806 while ((*result !=
'\0') && (*result !=
'#')
13807 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
13808 && ((*result <
'0') || (*result >
'9'))) {
13812 }
while ((*result ==
'#') || (*result ==
'\0'));
13829#ifdef ANSI_DECLARATORS
13830char *findfield(
char *
string)
13832char *findfield(
string)
13841 while ((*result !=
'\0') && (*result !=
'#')
13842 && (*result !=
' ') && (*result !=
'\t')) {
13847 while ((*result !=
'\0') && (*result !=
'#')
13848 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
13849 && ((*result <
'0') || (*result >
'9'))) {
13853 if (*result ==
'#') {
13870#ifdef ANSI_DECLARATORS
13871void readnodes(
struct mesh *
m,
struct behavior *
b,
char *nodefilename,
13872 char *polyfilename, FILE **polyfile)
13874void readnodes(
m,
b, nodefilename, polyfilename, polyfile)
13897 printf(
"Opening %s.\n", polyfilename);
13899 *polyfile = fopen(polyfilename,
"r");
13900 if (*polyfile == (FILE *) NULL) {
13901 printf(
" Error: Cannot access file %s.\n", polyfilename);
13906 stringptr = readline(inputline, *polyfile, polyfilename);
13907 m->invertices = (
int) strtol(stringptr, &stringptr, 0);
13908 stringptr = findfield(stringptr);
13909 if (*stringptr ==
'\0') {
13912 m->mesh_dim = (
int) strtol(stringptr, &stringptr, 0);
13914 stringptr = findfield(stringptr);
13915 if (*stringptr ==
'\0') {
13918 m->nextras = (
int) strtol(stringptr, &stringptr, 0);
13920 stringptr = findfield(stringptr);
13921 if (*stringptr ==
'\0') {
13924 nodemarkers = (
int) strtol(stringptr, &stringptr, 0);
13926 if (
m->invertices > 0) {
13927 infile = *polyfile;
13928 infilename = polyfilename;
13929 m->readnodefile = 0;
13933 m->readnodefile = 1;
13934 infilename = nodefilename;
13937 m->readnodefile = 1;
13938 infilename = nodefilename;
13939 *polyfile = (FILE *) NULL;
13942 if (
m->readnodefile) {
13945 printf(
"Opening %s.\n", nodefilename);
13947 infile = fopen(nodefilename,
"r");
13948 if (infile == (FILE *) NULL) {
13949 printf(
" Error: Cannot access file %s.\n", nodefilename);
13954 stringptr = readline(inputline, infile, nodefilename);
13955 m->invertices = (
int) strtol(stringptr, &stringptr, 0);
13956 stringptr = findfield(stringptr);
13957 if (*stringptr ==
'\0') {
13960 m->mesh_dim = (
int) strtol(stringptr, &stringptr, 0);
13962 stringptr = findfield(stringptr);
13963 if (*stringptr ==
'\0') {
13966 m->nextras = (
int) strtol(stringptr, &stringptr, 0);
13968 stringptr = findfield(stringptr);
13969 if (*stringptr ==
'\0') {
13972 nodemarkers = (
int) strtol(stringptr, &stringptr, 0);
13976 if (
m->invertices < 3) {
13977 printf(
"Error: Input must have at least three input vertices.\n");
13980 if (
m->mesh_dim != 2) {
13981 printf(
"Error: Triangle only works with two-dimensional meshes.\n");
13984 if (
m->nextras == 0) {
13991 for (i = 0; i <
m->invertices; i++) {
13993 stringptr = readline(inputline, infile, infilename);
13995 firstnode = (
int) strtol(stringptr, &stringptr, 0);
13996 if ((firstnode == 0) || (firstnode == 1)) {
13997 b->firstnumber = firstnode;
14000 stringptr = findfield(stringptr);
14001 if (*stringptr ==
'\0') {
14002 printf(
"Error: Vertex %d has no x coordinate.\n",
b->firstnumber + i);
14005 x = (
REAL) strtod(stringptr, &stringptr);
14006 stringptr = findfield(stringptr);
14007 if (*stringptr ==
'\0') {
14008 printf(
"Error: Vertex %d has no y coordinate.\n",
b->firstnumber + i);
14011 y = (
REAL) strtod(stringptr, &stringptr);
14015 for (j = 2; j < 2 +
m->nextras; j++) {
14016 stringptr = findfield(stringptr);
14017 if (*stringptr ==
'\0') {
14018 vertexloop[j] = 0.0;
14020 vertexloop[j] = (
REAL) strtod(stringptr, &stringptr);
14025 stringptr = findfield(stringptr);
14026 if (*stringptr ==
'\0') {
14029 currentmarker = (
int) strtol(stringptr, &stringptr, 0);
14039 m->xmin =
m->xmax =
x;
14040 m->ymin =
m->ymax =
y;
14048 if (
m->readnodefile) {
14054 m->xminextreme = 10 *
m->xmin - 9 *
m->xmax;
14067#ifdef ANSI_DECLARATORS
14069 REAL *pointattriblist,
int *pointmarkerlist,
14070 int numberofpoints,
int numberofpointattribs)
14073 numberofpoints, numberofpointattribs)
14077REAL *pointattriblist;
14078int *pointmarkerlist;
14080int numberofpointattribs;
14090 m->invertices = numberofpoints;
14092 m->nextras = numberofpointattribs;
14093 m->readnodefile = 0;
14094 if (
m->invertices < 3) {
14095 printf(
"Error: Input must have at least three input vertices.\n");
14098 if (
m->nextras == 0) {
14107 for (i = 0; i <
m->invertices; i++) {
14110 x = vertexloop[0] = pointlist[coordindex++];
14111 y = vertexloop[1] = pointlist[coordindex++];
14113 for (j = 0; j < numberofpointattribs; j++) {
14114 vertexloop[2 + j] = pointattriblist[attribindex++];
14116 if (pointmarkerlist != (
int *) NULL) {
14126 m->xmin =
m->xmax =
x;
14127 m->ymin =
m->ymax =
y;
14129 m->xmin = (
x <
m->xmin) ?
x :
m->xmin;
14130 m->xmax = (
x >
m->xmax) ?
x :
m->xmax;
14131 m->ymin = (
y <
m->ymin) ?
y :
m->ymin;
14132 m->ymax = (
y >
m->ymax) ?
y :
m->ymax;
14138 m->xminextreme = 10 *
m->xmin - 9 *
m->xmax;
14152#ifdef ANSI_DECLARATORS
14154 FILE *polyfile,
char *polyfilename,
REAL **hlist,
int *holes,
14155 REAL **rlist,
int *regions)
14157void readholes(
m,
b, polyfile, polyfilename, hlist, holes, rlist, regions)
14177 stringptr = readline(inputline, polyfile, polyfilename);
14178 *holes = (
int) strtol(stringptr, &stringptr, 0);
14182 for (i = 0; i < 2 * *holes; i += 2) {
14183 stringptr = readline(inputline, polyfile, polyfilename);
14184 stringptr = findfield(stringptr);
14185 if (*stringptr ==
'\0') {
14186 printf(
"Error: Hole %d has no x coordinate.\n",
14187 b->firstnumber + (i >> 1));
14190 holelist[i] = (
REAL) strtod(stringptr, &stringptr);
14192 stringptr = findfield(stringptr);
14193 if (*stringptr ==
'\0') {
14194 printf(
"Error: Hole %d has no y coordinate.\n",
14195 b->firstnumber + (i >> 1));
14198 holelist[i + 1] = (
REAL) strtod(stringptr, &stringptr);
14202 *hlist = (
REAL *) NULL;
14206 if ((
b->regionattrib ||
b->vararea) && !
b->refine) {
14208 stringptr = readline(inputline, polyfile, polyfilename);
14209 *regions = (
int) strtol(stringptr, &stringptr, 0);
14210 if (*regions > 0) {
14212 *rlist = regionlist;
14214 for (i = 0; i < *regions; i++) {
14215 stringptr = readline(inputline, polyfile, polyfilename);
14216 stringptr = findfield(stringptr);
14217 if (*stringptr ==
'\0') {
14218 printf(
"Error: Region %d has no x coordinate.\n",
14219 b->firstnumber + i);
14222 regionlist[index++] = (
REAL) strtod(stringptr, &stringptr);
14224 stringptr = findfield(stringptr);
14225 if (*stringptr ==
'\0') {
14226 printf(
"Error: Region %d has no y coordinate.\n",
14227 b->firstnumber + i);
14230 regionlist[index++] = (
REAL) strtod(stringptr, &stringptr);
14232 stringptr = findfield(stringptr);
14233 if (*stringptr ==
'\0') {
14235 "Error: Region %d has no region attribute or area constraint.\n",
14236 b->firstnumber + i);
14239 regionlist[index++] = (
REAL) strtod(stringptr, &stringptr);
14241 stringptr = findfield(stringptr);
14242 if (*stringptr ==
'\0') {
14243 regionlist[index] = regionlist[index - 1];
14245 regionlist[index] = (
REAL) strtod(stringptr, &stringptr);
14253 *rlist = (
REAL *) NULL;
14271#ifdef ANSI_DECLARATORS
14272void finishfile(FILE *outfile,
int argc,
char **argv)
14274void finishfile(outfile, argc, argv)
14283 fprintf(outfile,
"# Generated by");
14284 for (i = 0; i < argc; i++) {
14285 fprintf(outfile,
" ");
14286 fputs(argv[i], outfile);
14288 fprintf(outfile,
"\n");
14305#ifdef ANSI_DECLARATORS
14307 REAL **pointattriblist,
int **pointmarkerlist)
14309void writenodes(
m,
b, pointlist, pointattriblist, pointmarkerlist)
14313REAL **pointattriblist;
14314int **pointmarkerlist;
14319#ifdef ANSI_DECLARATORS
14321 int argc,
char **argv)
14349 outvertices =
m->vertices.items -
m->undeads;
14351 outvertices =
m->vertices.items;
14356 printf(
"Writing vertices.\n");
14359 if (*pointlist == (
REAL *) NULL) {
14363 if ((
m->nextras > 0) && (*pointattriblist == (
REAL *) NULL)) {
14364 *pointattriblist = (
REAL *)
trimalloc((
int) (outvertices *
m->nextras *
14368 if (!
b->nobound && (*pointmarkerlist == (
int *) NULL)) {
14369 *pointmarkerlist = (
int *)
trimalloc((
int) (outvertices *
sizeof(
int)));
14371 plist = *pointlist;
14372 palist = *pointattriblist;
14373 pmlist = *pointmarkerlist;
14378 printf(
"Writing %s.\n", nodefilename);
14380 outfile = fopen(nodefilename,
"w");
14381 if (outfile == (FILE *) NULL) {
14382 printf(
" Error: Cannot create file %s.\n", nodefilename);
14387 fprintf(outfile,
"%ld %d %d %d\n", outvertices,
m->mesh_dim,
14388 m->nextras, 1 -
b->nobound);
14392 vertexnumber =
b->firstnumber;
14394 while (vertexloop != (
vertex) NULL) {
14398 plist[coordindex++] = vertexloop[0];
14399 plist[coordindex++] = vertexloop[1];
14401 for (i = 0; i <
m->nextras; i++) {
14402 palist[attribindex++] = vertexloop[2 + i];
14406 pmlist[vertexnumber -
b->firstnumber] =
vertexmark(vertexloop);
14410 fprintf(outfile,
"%4d %.17g %.17g", vertexnumber, vertexloop[0],
14412 for (i = 0; i <
m->nextras; i++) {
14414 fprintf(outfile,
" %.17g", vertexloop[i + 2]);
14417 fprintf(outfile,
"\n");
14420 fprintf(outfile,
" %d\n",
vertexmark(vertexloop));
14431 finishfile(outfile, argc, argv);
14445#ifdef ANSI_DECLARATORS
14458 vertexnumber =
b->firstnumber;
14460 while (vertexloop != (
vertex) NULL) {
14477#ifdef ANSI_DECLARATORS
14479 int **trianglelist,
REAL **triangleattriblist)
14485REAL **triangleattriblist;
14490#ifdef ANSI_DECLARATORS
14492 int argc,
char **argv)
14513 struct otri triangleloop;
14515 vertex mid1, mid2, mid3;
14516 long elementnumber;
14521 printf(
"Writing triangles.\n");
14524 if (*trianglelist == (
int *) NULL) {
14525 *trianglelist = (
int *)
trimalloc((
int) (
m->triangles.items *
14526 ((
b->order + 1) * (
b->order + 2) /
14527 2) *
sizeof(
int)));
14530 if ((
m->eextras > 0) && (*triangleattriblist == (
REAL *) NULL)) {
14531 *triangleattriblist = (
REAL *)
trimalloc((
int) (
m->triangles.items *
14535 tlist = *trianglelist;
14536 talist = *triangleattriblist;
14541 printf(
"Writing %s.\n", elefilename);
14543 outfile = fopen(elefilename,
"w");
14544 if (outfile == (FILE *) NULL) {
14545 printf(
" Error: Cannot create file %s.\n", elefilename);
14549 fprintf(outfile,
"%ld %d %d\n",
m->triangles.items,
14550 (
b->order + 1) * (
b->order + 2) / 2,
m->eextras);
14555 triangleloop.
orient = 0;
14556 elementnumber =
b->firstnumber;
14558 org(triangleloop, p1);
14559 dest(triangleloop, p2);
14560 apex(triangleloop, p3);
14561 if (
b->order == 1) {
14568 fprintf(outfile,
"%4ld %4d %4d %4d", elementnumber,
14572 mid1 = (
vertex) triangleloop.
tri[
m->highorderindex + 1];
14573 mid2 = (
vertex) triangleloop.
tri[
m->highorderindex + 2];
14574 mid3 = (
vertex) triangleloop.
tri[
m->highorderindex];
14584 fprintf(outfile,
"%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14591 for (i = 0; i <
m->eextras; i++) {
14595 for (i = 0; i <
m->eextras; i++) {
14596 fprintf(outfile,
" %.17g",
elemattribute(triangleloop, i));
14598 fprintf(outfile,
"\n");
14606 finishfile(outfile, argc, argv);
14618#ifdef ANSI_DECLARATORS
14620 int **segmentlist,
int **segmentmarkerlist)
14622void writepoly(
m,
b, segmentlist, segmentmarkerlist)
14626int **segmentmarkerlist;
14631#ifdef ANSI_DECLARATORS
14633 REAL *holelist,
int holes,
REAL *regionlist,
int regions,
14634 int argc,
char **argv)
14636void writepoly(
m,
b, polyfilename, holelist, holes, regionlist, regions,
14658 long holenumber, regionnumber;
14660 struct osub subsegloop;
14661 vertex endpoint1, endpoint2;
14666 printf(
"Writing segments.\n");
14669 if (*segmentlist == (
int *) NULL) {
14670 *segmentlist = (
int *)
trimalloc((
int) (
m->subsegs.items * 2 *
14674 if (!
b->nobound && (*segmentmarkerlist == (
int *) NULL)) {
14675 *segmentmarkerlist = (
int *)
trimalloc((
int) (
m->subsegs.items *
14678 slist = *segmentlist;
14679 smlist = *segmentmarkerlist;
14683 printf(
"Writing %s.\n", polyfilename);
14685 outfile = fopen(polyfilename,
"w");
14686 if (outfile == (FILE *) NULL) {
14687 printf(
" Error: Cannot create file %s.\n", polyfilename);
14693 fprintf(outfile,
"%d %d %d %d\n", 0,
m->mesh_dim,
m->nextras,
14696 fprintf(outfile,
"%ld %d\n",
m->subsegs.items, 1 -
b->nobound);
14702 subsegnumber =
b->firstnumber;
14703 while (subsegloop.
ss != (
subseg *) NULL) {
14704 sorg(subsegloop, endpoint1);
14705 sdest(subsegloop, endpoint2);
14712 smlist[subsegnumber -
b->firstnumber] =
mark(subsegloop);
14717 fprintf(outfile,
"%4ld %4d %4d\n", subsegnumber,
14720 fprintf(outfile,
"%4ld %4d %4d %4d\n", subsegnumber,
14731 fprintf(outfile,
"%d\n", holes);
14733 for (holenumber = 0; holenumber < holes; holenumber++) {
14735 fprintf(outfile,
"%4ld %.17g %.17g\n",
b->firstnumber + holenumber,
14736 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14740 fprintf(outfile,
"%d\n", regions);
14741 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14743 fprintf(outfile,
"%4ld %.17g %.17g %.17g %.17g\n",
14744 b->firstnumber + regionnumber,
14745 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14746 regionlist[4 * regionnumber + 2],
14747 regionlist[4 * regionnumber + 3]);
14752 finishfile(outfile, argc, argv);
14764#ifdef ANSI_DECLARATORS
14766 int **edgelist,
int **edgemarkerlist)
14772int **edgemarkerlist;
14777#ifdef ANSI_DECLARATORS
14779 int argc,
char **argv)
14799 struct otri triangleloop, trisym;
14800 struct osub checkmark;
14808 printf(
"Writing edges.\n");
14811 if (*edgelist == (
int *) NULL) {
14812 *edgelist = (
int *)
trimalloc((
int) (
m->edges * 2 *
sizeof(
int)));
14815 if (!
b->nobound && (*edgemarkerlist == (
int *) NULL)) {
14816 *edgemarkerlist = (
int *)
trimalloc((
int) (
m->edges *
sizeof(
int)));
14819 emlist = *edgemarkerlist;
14823 printf(
"Writing %s.\n", edgefilename);
14825 outfile = fopen(edgefilename,
"w");
14826 if (outfile == (FILE *) NULL) {
14827 printf(
" Error: Cannot create file %s.\n", edgefilename);
14831 fprintf(outfile,
"%ld %d\n",
m->edges, 1 -
b->nobound);
14836 edgenumber =
b->firstnumber;
14844 for (triangleloop.
orient = 0; triangleloop.
orient < 3;
14845 triangleloop.
orient++) {
14846 sym(triangleloop, trisym);
14847 if ((triangleloop.
tri < trisym.
tri) || (trisym.
tri ==
m->dummytri)) {
14848 org(triangleloop, p1);
14849 dest(triangleloop, p2);
14857 fprintf(outfile,
"%4ld %d %d\n", edgenumber,
14863 if (
b->usesegments) {
14864 tspivot(triangleloop, checkmark);
14865 if (checkmark.
ss ==
m->dummysub) {
14867 emlist[edgenumber -
b->firstnumber] = 0;
14869 fprintf(outfile,
"%4ld %d %d %d\n", edgenumber,
14874 emlist[edgenumber -
b->firstnumber] =
mark(checkmark);
14876 fprintf(outfile,
"%4ld %d %d %d\n", edgenumber,
14882 emlist[edgenumber -
b->firstnumber] = trisym.
tri ==
m->dummytri;
14884 fprintf(outfile,
"%4ld %d %d %d\n", edgenumber,
14896 finishfile(outfile, argc, argv);
14918#ifdef ANSI_DECLARATORS
14920 REAL **vpointattriblist,
int **vpointmarkerlist,
14921 int **vedgelist,
int **vedgemarkerlist,
REAL **vnormlist)
14923void writevoronoi(
m,
b, vpointlist, vpointattriblist, vpointmarkerlist,
14924 vedgelist, vedgemarkerlist, vnormlist)
14928REAL **vpointattriblist;
14929int **vpointmarkerlist;
14931int **vedgemarkerlist;
14937#ifdef ANSI_DECLARATORS
14939 char *vedgefilename,
int argc,
char **argv)
14941void writevoronoi(
m,
b, vnodefilename, vedgefilename, argc, argv)
14944char *vnodefilename;
14945char *vedgefilename;
14963 struct otri triangleloop, trisym;
14964 vertex torg, tdest, tapex;
14965 REAL circumcenter[2];
14967 long vnodenumber, vedgenumber;
14974 printf(
"Writing Voronoi vertices.\n");
14977 if (*vpointlist == (
REAL *) NULL) {
14978 *vpointlist = (
REAL *)
trimalloc((
int) (
m->triangles.items * 2 *
14982 if (*vpointattriblist == (
REAL *) NULL) {
14983 *vpointattriblist = (
REAL *)
trimalloc((
int) (
m->triangles.items *
14984 m->nextras *
sizeof(
REAL)));
14986 *vpointmarkerlist = (
int *) NULL;
14987 plist = *vpointlist;
14988 palist = *vpointattriblist;
14993 printf(
"Writing %s.\n", vnodefilename);
14995 outfile = fopen(vnodefilename,
"w");
14996 if (outfile == (FILE *) NULL) {
14997 printf(
" Error: Cannot create file %s.\n", vnodefilename);
15002 fprintf(outfile,
"%ld %d %d %d\n",
m->triangles.items, 2,
m->nextras, 0);
15007 triangleloop.
orient = 0;
15008 vnodenumber =
b->firstnumber;
15010 org(triangleloop, torg);
15011 dest(triangleloop, tdest);
15012 apex(triangleloop, tapex);
15016 plist[coordindex++] = circumcenter[0];
15017 plist[coordindex++] = circumcenter[1];
15018 for (i = 2; i < 2 +
m->nextras; i++) {
15020 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15021 + eta * (tapex[i] - torg[i]);
15025 fprintf(outfile,
"%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15027 for (i = 2; i < 2 +
m->nextras; i++) {
15029 fprintf(outfile,
" %.17g", torg[i] + xi * (tdest[i] - torg[i])
15030 + eta * (tapex[i] - torg[i]));
15032 fprintf(outfile,
"\n");
15035 * (
int *) (triangleloop.
tri + 6) = (
int) vnodenumber;
15041 finishfile(outfile, argc, argv);
15046 printf(
"Writing Voronoi edges.\n");
15049 if (*vedgelist == (
int *) NULL) {
15050 *vedgelist = (
int *)
trimalloc((
int) (
m->edges * 2 *
sizeof(
int)));
15052 *vedgemarkerlist = (
int *) NULL;
15054 if (*vnormlist == (
REAL *) NULL) {
15057 elist = *vedgelist;
15058 normlist = *vnormlist;
15062 printf(
"Writing %s.\n", vedgefilename);
15064 outfile = fopen(vedgefilename,
"w");
15065 if (outfile == (FILE *) NULL) {
15066 printf(
" Error: Cannot create file %s.\n", vedgefilename);
15070 fprintf(outfile,
"%ld %d\n",
m->edges, 0);
15075 vedgenumber =
b->firstnumber;
15083 for (triangleloop.
orient = 0; triangleloop.
orient < 3;
15084 triangleloop.
orient++) {
15085 sym(triangleloop, trisym);
15086 if ((triangleloop.
tri < trisym.
tri) || (trisym.
tri ==
m->dummytri)) {
15088 p1 = * (
int *) (triangleloop.
tri + 6);
15089 if (trisym.
tri ==
m->dummytri) {
15090 org(triangleloop, torg);
15091 dest(triangleloop, tdest);
15094 elist[coordindex] = p1;
15095 normlist[coordindex++] = tdest[1] - torg[1];
15096 elist[coordindex] = -1;
15097 normlist[coordindex++] = torg[0] - tdest[0];
15102 fprintf(outfile,
"%4ld %d %d %.17g %.17g\n", vedgenumber,
15103 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15107 p2 = * (
int *) (trisym.
tri + 6);
15110 elist[coordindex] = p1;
15111 normlist[coordindex++] = 0.0;
15112 elist[coordindex] = p2;
15113 normlist[coordindex++] = 0.0;
15115 fprintf(outfile,
"%4ld %d %d\n", vedgenumber, p1, p2);
15125 finishfile(outfile, argc, argv);
15131#ifdef ANSI_DECLARATORS
15142#ifdef ANSI_DECLARATORS
15144 int argc,
char **argv)
15149char *neighborfilename;
15163 struct otri triangleloop, trisym;
15164 long elementnumber;
15165 int neighbor1, neighbor2, neighbor3;
15170 printf(
"Writing neighbors.\n");
15173 if (*neighborlist == (
int *) NULL) {
15174 *neighborlist = (
int *)
trimalloc((
int) (
m->triangles.items * 3 *
15177 nlist = *neighborlist;
15181 printf(
"Writing %s.\n", neighborfilename);
15183 outfile = fopen(neighborfilename,
"w");
15184 if (outfile == (FILE *) NULL) {
15185 printf(
" Error: Cannot create file %s.\n", neighborfilename);
15189 fprintf(outfile,
"%ld %d\n",
m->triangles.items, 3);
15194 triangleloop.
orient = 0;
15195 elementnumber =
b->firstnumber;
15197 * (
int *) (triangleloop.
tri + 6) = (
int) elementnumber;
15201 * (
int *) (
m->dummytri + 6) = -1;
15205 elementnumber =
b->firstnumber;
15207 triangleloop.
orient = 1;
15208 sym(triangleloop, trisym);
15209 neighbor1 = * (
int *) (trisym.
tri + 6);
15210 triangleloop.
orient = 2;
15211 sym(triangleloop, trisym);
15212 neighbor2 = * (
int *) (trisym.
tri + 6);
15213 triangleloop.
orient = 0;
15214 sym(triangleloop, trisym);
15215 neighbor3 = * (
int *) (trisym.
tri + 6);
15217 nlist[index++] = neighbor1;
15218 nlist[index++] = neighbor2;
15219 nlist[index++] = neighbor3;
15222 fprintf(outfile,
"%4ld %d %d %d\n", elementnumber,
15223 neighbor1, neighbor2, neighbor3);
15231 finishfile(outfile, argc, argv);
15246#ifdef ANSI_DECLARATORS
15247void writeoff(
struct mesh *
m,
struct behavior *
b,
char *offfilename,
15248 int argc,
char **argv)
15250void writeoff(
m,
b, offfilename, argc, argv)
15260 struct otri triangleloop;
15266 printf(
"Writing %s.\n", offfilename);
15270 outvertices =
m->vertices.items -
m->undeads;
15272 outvertices =
m->vertices.items;
15275 outfile = fopen(offfilename,
"w");
15276 if (outfile == (FILE *) NULL) {
15277 printf(
" Error: Cannot create file %s.\n", offfilename);
15281 fprintf(outfile,
"OFF\n%ld %ld %ld\n", outvertices,
m->triangles.items,
15287 while (vertexloop != (
vertex) NULL) {
15290 fprintf(outfile,
" %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15299 triangleloop.orient = 0;
15300 while (triangleloop.tri != (
triangle *) NULL) {
15301 org(triangleloop, p1);
15302 dest(triangleloop, p2);
15303 apex(triangleloop, p3);
15305 fprintf(outfile,
" 3 %4d %4d %4d\n",
vertexmark(p1) -
b->firstnumber,
15309 finishfile(outfile, argc, argv);
15324#ifdef ANSI_DECLARATORS
15333 struct otri triangleloop;
15335 REAL cossquaretable[8];
15336 REAL ratiotable[16];
15338 REAL edgelength[3];
15342 REAL shortest, longest;
15344 REAL smallestarea, biggestarea;
15345 REAL triminaltitude2;
15349 REAL smallestangle, biggestangle;
15350 REAL radconst, degconst;
15351 int angletable[18];
15352 int aspecttable[16];
15358 printf(
"Mesh quality statistics:\n\n");
15359 radconst =
PI / 18.0;
15360 degconst = 180.0 /
PI;
15361 for (i = 0; i < 8; i++) {
15362 cossquaretable[i] = cos(radconst * (
REAL) (i + 1));
15363 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15365 for (i = 0; i < 18; i++) {
15369 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15370 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15371 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15372 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15373 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15374 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15375 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15376 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15377 for (i = 0; i < 16; i++) {
15378 aspecttable[i] = 0;
15382 minaltitude =
m->xmax -
m->xmin +
m->ymax -
m->ymin;
15383 minaltitude = minaltitude * minaltitude;
15384 shortest = minaltitude;
15386 smallestarea = minaltitude;
15389 smallestangle = 0.0;
15390 biggestangle = 2.0;
15395 triangleloop.
orient = 0;
15397 org(triangleloop, p[0]);
15398 dest(triangleloop, p[1]);
15399 apex(triangleloop, p[2]);
15402 for (i = 0; i < 3; i++) {
15405 dx[i] = p[j][0] - p[k][0];
15406 dy[i] = p[j][1] - p[k][1];
15407 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15408 if (edgelength[i] > trilongest2) {
15409 trilongest2 = edgelength[i];
15411 if (edgelength[i] > longest) {
15412 longest = edgelength[i];
15414 if (edgelength[i] < shortest) {
15415 shortest = edgelength[i];
15420 if (triarea < smallestarea) {
15421 smallestarea = triarea;
15423 if (triarea > biggestarea) {
15424 biggestarea = triarea;
15426 triminaltitude2 = triarea * triarea / trilongest2;
15427 if (triminaltitude2 < minaltitude) {
15428 minaltitude = triminaltitude2;
15430 triaspect2 = trilongest2 / triminaltitude2;
15431 if (triaspect2 > worstaspect) {
15432 worstaspect = triaspect2;
15435 while ((aspectindex < 15) &&
15436 (triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15440 aspecttable[aspectindex]++;
15442 for (i = 0; i < 3; i++) {
15445 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15446 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15448 for (ii = 7; ii >= 0; ii--) {
15449 if (cossquare > cossquaretable[ii]) {
15453 if (dotproduct <= 0.0) {
15454 angletable[tendegree]++;
15455 if (cossquare > smallestangle) {
15456 smallestangle = cossquare;
15458 if (acutebiggest && (cossquare < biggestangle)) {
15459 biggestangle = cossquare;
15462 angletable[17 - tendegree]++;
15463 if (acutebiggest || (cossquare > biggestangle)) {
15464 biggestangle = cossquare;
15472 shortest = sqrt(shortest);
15473 longest = sqrt(longest);
15474 minaltitude = sqrt(minaltitude);
15475 worstaspect = sqrt(worstaspect);
15476 smallestarea *= 0.5;
15477 biggestarea *= 0.5;
15478 if (smallestangle >= 1.0) {
15479 smallestangle = 0.0;
15481 smallestangle = degconst * acos(sqrt(smallestangle));
15483 if (biggestangle >= 1.0) {
15484 biggestangle = 180.0;
15486 if (acutebiggest) {
15487 biggestangle = degconst * acos(sqrt(biggestangle));
15489 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15493 printf(
" Smallest area: %16.5g | Largest area: %16.5g\n",
15494 smallestarea, biggestarea);
15495 printf(
" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15496 shortest, longest);
15497 printf(
" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15498 minaltitude, worstaspect);
15500 printf(
" Triangle aspect ratio histogram:\n");
15501 printf(
" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15502 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15504 for (i = 1; i < 7; i++) {
15505 printf(
" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15506 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15507 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15509 printf(
" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15510 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15512 printf(
" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15514 printf(
" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15515 smallestangle, biggestangle);
15517 printf(
" Angle histogram:\n");
15518 for (i = 0; i < 9; i++) {
15519 printf(
" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15520 i * 10, i * 10 + 10, angletable[i],
15521 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15532#ifdef ANSI_DECLARATORS
15541 printf(
"\nStatistics:\n\n");
15542 printf(
" Input vertices: %d\n",
m->invertices);
15544 printf(
" Input triangles: %d\n",
m->inelements);
15547 printf(
" Input segments: %d\n",
m->insegments);
15549 printf(
" Input holes: %d\n",
m->holes);
15553 printf(
"\n Mesh vertices: %ld\n",
m->vertices.items -
m->undeads);
15554 printf(
" Mesh triangles: %ld\n",
m->triangles.items);
15555 printf(
" Mesh edges: %ld\n",
m->edges);
15556 printf(
" Mesh exterior boundary edges: %ld\n",
m->hullsize);
15557 if (
b->poly ||
b->refine) {
15558 printf(
" Mesh interior boundary edges: %ld\n",
15559 m->subsegs.items -
m->hullsize);
15560 printf(
" Mesh subsegments (constrained edges): %ld\n",
15567 printf(
"Memory allocation statistics:\n\n");
15568 printf(
" Maximum number of vertices: %ld\n",
m->vertices.maxitems);
15569 printf(
" Maximum number of triangles: %ld\n",
m->triangles.maxitems);
15570 if (
m->subsegs.maxitems > 0) {
15571 printf(
" Maximum number of subsegments: %ld\n",
m->subsegs.maxitems);
15573 if (
m->viri.maxitems > 0) {
15574 printf(
" Maximum number of viri: %ld\n",
m->viri.maxitems);
15576 if (
m->badsubsegs.maxitems > 0) {
15577 printf(
" Maximum number of encroached subsegments: %ld\n",
15578 m->badsubsegs.maxitems);
15580 if (
m->badtriangles.maxitems > 0) {
15581 printf(
" Maximum number of bad triangles: %ld\n",
15582 m->badtriangles.maxitems);
15584 if (
m->flipstackers.maxitems > 0) {
15585 printf(
" Maximum number of stacked triangle flips: %ld\n",
15586 m->flipstackers.maxitems);
15588 if (
m->splaynodes.maxitems > 0) {
15589 printf(
" Maximum number of splay tree nodes: %ld\n",
15590 m->splaynodes.maxitems);
15592 printf(
" Approximate heap memory use (bytes): %ld\n\n",
15593 m->vertices.maxitems *
m->vertices.itembytes +
15594 m->triangles.maxitems *
m->triangles.itembytes +
15595 m->subsegs.maxitems *
m->subsegs.itembytes +
15596 m->viri.maxitems *
m->viri.itembytes +
15597 m->badsubsegs.maxitems *
m->badsubsegs.itembytes +
15598 m->badtriangles.maxitems *
m->badtriangles.itembytes +
15599 m->flipstackers.maxitems *
m->flipstackers.itembytes +
15600 m->splaynodes.maxitems *
m->splaynodes.itembytes);
15602 printf(
"Algorithmic statistics:\n\n");
15603 if (!
b->weighted) {
15604 printf(
" Number of incircle tests: %ld\n",
m->incirclecount);
15606 printf(
" Number of 3D orientation tests: %ld\n",
m->orient3dcount);
15608 printf(
" Number of 2D orientation tests: %ld\n",
m->counterclockcount);
15609 if (
m->hyperbolacount > 0) {
15610 printf(
" Number of right-of-hyperbola tests: %ld\n",
15611 m->hyperbolacount);
15613 if (
m->circletopcount > 0) {
15614 printf(
" Number of circle top computations: %ld\n",
15615 m->circletopcount);
15617 if (
m->circumcentercount > 0) {
15618 printf(
" Number of triangle circumcenter computations: %ld\n",
15619 m->circumcentercount);
15652#ifdef ANSI_DECLARATORS
15665#ifdef ANSI_DECLARATORS
15666int main(
int argc,
char **argv)
15668int main(argc, argv)
15686 struct timeval tv0,
tv1,
tv2,
tv3, tv4, tv5, tv6;
15687 struct timezone tz;
15691 gettimeofday(&tv0, &tz);
15700 m.steinerleft =
b.steiner;
15707 readnodes(&
m, &
b,
b.innodefilename,
b.inpolyfilename, &polyfile);
15712 gettimeofday(&
tv1, &tz);
15729 m.hullsize = reconstruct(&
m, &
b,
b.inelefilename,
b.areafilename,
15730 b.inpolyfilename, polyfile);
15739 gettimeofday(&
tv2, &tz);
15741 printf(
"Mesh reconstruction");
15743 printf(
"Delaunay");
15745 printf(
" milliseconds: %ld\n", 1000l * (
tv2.tv_sec -
tv1.tv_sec) +
15746 (
tv2.tv_usec -
tv1.tv_usec) / 1000l);
15752 m.infvertex1 = (
vertex) NULL;
15753 m.infvertex2 = (
vertex) NULL;
15754 m.infvertex3 = (
vertex) NULL;
15756 if (
b.usesegments) {
15757 m.checksegments = 1;
15771 gettimeofday(&
tv3, &tz);
15772 if (
b.usesegments && !
b.refine) {
15773 printf(
"Segment milliseconds: %ld\n",
15774 1000l * (
tv3.tv_sec -
tv2.tv_sec) +
15775 (
tv3.tv_usec -
tv2.tv_usec) / 1000l);
15780 if (
b.poly && (
m.triangles.items > 0)) {
15787 readholes(&
m, &
b, polyfile,
b.inpolyfilename, &holearray, &
m.holes,
15788 ®ionarray, &
m.regions);
15804 gettimeofday(&tv4, &tz);
15805 if (
b.poly && !
b.refine) {
15806 printf(
"Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec -
tv3.tv_sec) +
15807 (tv4.tv_usec -
tv3.tv_usec) / 1000l);
15813 if (
b.quality && (
m.triangles.items > 0)) {
15814 enforcequality(&
m, &
b);
15820 gettimeofday(&tv5, &tz);
15823 printf(
"Quality milliseconds: %ld\n",
15824 1000l * (tv5.tv_sec - tv4.tv_sec) +
15825 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15832 m.edges = (3l *
m.triangles.items +
m.hullsize) / 2l;
15852 if (
b.usesegments) {
15865 if (
b.nonodewritten || (
b.noiterationnum &&
m.readnodefile)) {
15868 printf(
"NOT writing vertices.\n");
15870 printf(
"NOT writing a .node file.\n");
15883 if (
b.noelewritten) {
15886 printf(
"NOT writing triangles.\n");
15888 printf(
"NOT writing an .ele file.\n");
15900 if (
b.poly ||
b.convex) {
15902 if (
b.nopolywritten ||
b.noiterationnum) {
15905 printf(
"NOT writing segments.\n");
15907 printf(
"NOT writing a .poly file.\n");
15923 writepoly(&
m, &
b,
b.outpolyfilename, holearray,
m.holes, regionarray,
15924 m.regions, argc, argv);
15930 if (
m.regions > 0) {
15938 writeoff(&
m, &
b,
b.offfilename, argc, argv);
15967 gettimeofday(&tv6, &tz);
15968 printf(
"\nOutput milliseconds: %ld\n",
15969 1000l * (tv6.tv_sec - tv5.tv_sec) +
15970 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15971 printf(
"Total running milliseconds: %ld\n",
15972 1000l * (tv6.tv_sec - tv0.tv_sec) +
15973 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15982 checkdelaunay(&
m, &
b);
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
include TDocParser_001 C image html pict1_TDocParser_001 png width
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
struct badtriang * nexttriang
struct flipstacker * prevflip
struct memorypool badtriangles
struct badtriang * queuetail[4096]
struct memorypool flipstackers
struct memorypool subsegs
struct memorypool triangles
struct memorypool splaynodes
struct flipstacker * lastflip
struct memorypool vertices
struct badtriang * queuefront[4096]
struct memorypool badsubsegs
struct splaynode * lchild
struct splaynode * rchild
REAL * pointattributelist
int numberoftriangleattributes
int numberofpointattributes
REAL * triangleattributelist
static uint64_t sum(uint64_t i)
#define sdest(osub, vertexptr)
#define sorg(osub, vertexptr)
VOID * traverse(struct memorypool *pool)
void highorder(struct mesh *m, struct behavior *b)
#define apex(otri, vertexptr)
void makevertexmap(struct mesh *m, struct behavior *b)
#define dnext(otri1, otri2)
void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist, REAL **pointattriblist, int **pointmarkerlist)
void numbernodes(struct mesh *m, struct behavior *b)
void writepoly(struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist)
vertex getvertex(struct mesh *m, struct behavior *b, int number)
#define setelemattribute(otri, attnum, value)
#define setsorg(osub, vertexptr)
#define segdest(osub, vertexptr)
void poolrestart(struct memorypool *pool)
#define segorg(osub, vertexptr)
#define Two_Product(a, b, x, y)
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
#define sdecode(sptr, osub)
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
#define setorg(otri, vertexptr)
REAL estimate(int elen, REAL *e)
enum locateresult preciselocate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment)
#define elemattribute(otri, attnum)
int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
void makesubseg(struct mesh *m, struct osub *newsubseg)
#define bond(otri1, otri2)
void trifree(VOID *memptr)
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
void pooldealloc(struct memorypool *pool, VOID *dyingitem)
#define setsegorg(osub, vertexptr)
void alternateaxes(vertex *sortarray, int arraysize, int axis)
#define lnext(otri1, otri2)
int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight, REAL permanent)
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
long divconqdelaunay(struct mesh *m, struct behavior *b)
#define Two_Product_Presplit(a, b, bhi, blo, x, y)
void regionplague(struct mesh *m, struct behavior *b, REAL attribute, REAL area)
#define onext(otri1, otri2)
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
void triangledeinit(struct mesh *m, struct behavior *b)
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
vertex vertextraverse(struct mesh *m)
#define lprev(otri1, otri2)
triangle * triangletraverse(struct mesh *m)
#define tspivot(otri, osub)
VOID * poolalloc(struct memorypool *pool)
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
#define Two_Diff_Tail(a, b, x, y)
void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist, REAL **vpointattriblist, int **vpointmarkerlist, int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
void poolzero(struct memorypool *pool)
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
#define dprev(otri1, otri2)
void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments)
#define setvertexmark(vx, value)
#define SPLAYNODEPERBLOCK
void triangulate(char *triswitches, struct triangulateio *in, struct triangulateio *out, struct triangulateio *vorout)
#define setvertex2tri(vx, value)
void initializevertexpool(struct mesh *m, struct behavior *b)
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, struct otri *innerleft, struct otri *innerright, struct otri *farright, int axis)
void parsecommandline(int argc, char **argv, struct behavior *b)
VOID * trimalloc(int size)
#define oprev(otri1, otri2)
#define BADSUBSEGPERBLOCK
void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
void vertexdealloc(struct mesh *m, vertex dyingvertex)
void infecthull(struct mesh *m, struct behavior *b)
void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes, REAL *regionlist, int regions)
#define setapex(otri, vertexptr)
#define dest(otri, vertexptr)
void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist, REAL *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs)
#define otricopy(otri1, otri2)
#define Two_Sum(a, b, x, y)
#define tsbond(otri, osub)
#define setmark(osub, value)
void initializetrisubpools(struct mesh *m, struct behavior *b)
void writeedges(struct mesh *m, struct behavior *b, int **edgelist, int **edgemarkerlist)
#define Two_One_Product(a1, a0, b, x3, x2, x1, x0)
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
long delaunay(struct mesh *m, struct behavior *b)
#define setdest(otri, vertexptr)
void markhull(struct mesh *m, struct behavior *b)
void vertexsort(vertex *sortarray, int arraysize)
REAL incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
#define stpivot(osub, otri)
REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
#define decode(ptr, otri)
#define otriequal(otri1, otri2)
#define org(otri, vertexptr)
void traversalinit(struct memorypool *pool)
REAL nonregular(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
void plague(struct mesh *m, struct behavior *b)
#define setsegdest(osub, vertexptr)
#define FLIPSTACKERPERBLOCK
void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
#define setvertextype(vx, value)
uintptr_t randomnation(unsigned int choices)
void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes)
#define sym(otri1, otri2)
void quality_statistics(struct mesh *m, struct behavior *b)
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
REAL counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
void pooldeinit(struct memorypool *pool)
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
#define setsdest(osub, vertexptr)
#define spivot(osub1, osub2)
#define ssym(osub1, osub2)
void writeelements(struct mesh *m, struct behavior *b, int **trianglelist, REAL **triangleattriblist)
void insertsegment(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0)
void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
#define Fast_Two_Sum(a, b, x, y)
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
void findcircumcenter(struct mesh *m, struct behavior *b, vertex torg, vertex tdest, vertex tapex, vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
#define Split(a, ahi, alo)
subseg * subsegtraverse(struct mesh *m)
REAL orient3d(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd, REAL aheight, REAL bheight, REAL cheight, REAL dheight)
void statistics(struct mesh *m, struct behavior *b)
#define sbond(osub1, osub2)
#define setareabound(otri, value)
void triangleinit(struct mesh *m)