diff --git a/src/triangle.c b/src/triangle.c
index 2245a9ca998da6e39a75f5cadd3e99d18c2f6be8..f7a57004aa3dd897c1c9b9f4c24ca8955150b2e1 100644
--- a/src/triangle.c
+++ b/src/triangle.c
@@ -11,10 +11,10 @@
 /*  A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.      */
 /*  (triangle.c)                                                             */
 /*                                                                           */
-/*  Version 1.4                                                              */
-/*  November 1, 2002                                                         */
+/*  Version 1.6                                                              */
+/*  July 28, 2005                                                            */
 /*                                                                           */
-/*  Copyright 1993, 1995, 1997, 1998, 2002                                   */
+/*  Copyright 1993, 1995, 1997, 1998, 2002, 2005                             */
 /*  Jonathan Richard Shewchuk                                                */
 /*  2360 Woolsey #H                                                          */
 /*  Berkeley, California  94705-1927                                         */
@@ -38,6 +38,9 @@
 /*                                                                           */
 /*      http://www.cs.cmu.edu/~quake/triangle.html                           */
 /*                                                                           */
+/*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
+/*    whatsoever.  This code is provided "as-is".  Use at your own risk.     */
+/*                                                                           */
 /*  Some of the references listed below are marked with an asterisk.  [*]    */
 /*    These references are available for downloading from the Web page       */
 /*                                                                           */
@@ -60,9 +63,8 @@
 /*    CMU-CS-97-137, School of Computer Science, Carnegie Mellon University, */
 /*    Pittsburgh, Pennsylvania, 18 May 1997.  [*]                            */
 /*                                                                           */
-/*  Triangle was created as part of the Archimedes project in the School of  */
-/*    Computer Science at Carnegie Mellon University.  Archimedes is a       */
-/*    system for compiling parallel finite element solvers.  For further     */
+/*  Triangle was created as part of the Quake Project in the School of       */
+/*    Computer Science at Carnegie Mellon University.  For further           */
 /*    information, see Hesheng Bao, Jacobo Bielak, Omar Ghattas, Loukas F.   */
 /*    Kallivokas, David R. O'Hallaron, Jonathan R. Shewchuk, and Jifeng Xu,  */
 /*    "Large-scale Simulation of Elastic Wave Propagation in Heterogeneous   */
@@ -75,15 +77,14 @@
 /*    18(3):548-585, May 1995 [*], and one due to L. Paul Chew, "Guaranteed- */
 /*    Quality Mesh Generation for Curved Surfaces," Proceedings of the Ninth */
 /*    Annual Symposium on Computational Geometry (San Diego, California),    */
-/*    pages 274-280, Association for Computing Machinery, May 1993.          */
+/*    pages 274-280, Association for Computing Machinery, May 1993,          */
+/*    http://portal.acm.org/citation.cfm?id=161150 .                         */
 /*                                                                           */
-/*  The Delaunay refinement algorithm has been modified so that it           */
-/*    consistently meshes domains with small input angles, as described in   */
-/*    my lengthy journal article listed above, or in abbreviated form in     */
-/*    Jonathan Richard Shewchuk, "Mesh Generation for Domains with Small     */
-/*    Angles," Proceedings of the Sixteenth Annual Symposium on              */
-/*    Computational Geometry (Hong Kong), pages 1-10, Association for        */
-/*    Computing Machinery, June 2000.  [*]                                   */
+/*  The Delaunay refinement algorithm has been modified so that it meshes    */
+/*    domains with small input angles well, as described in Gary L. Miller,  */
+/*    Steven E. Pav, and Noel J. Walkington, "When and Why Ruppert's         */
+/*    Algorithm Works," Twelfth International Meshing Roundtable, pages      */
+/*    91-102, Sandia National Laboratories, September 2003.  [*]             */
 /*                                                                           */
 /*  My implementation of the divide-and-conquer and incremental Delaunay     */
 /*    triangulation algorithms follows closely the presentation of Guibas    */
@@ -95,7 +96,7 @@
 /*    triangulation algorithms are described by Leonidas J. Guibas and Jorge */
 /*    Stolfi, "Primitives for the Manipulation of General Subdivisions and   */
 /*    the Computation of Voronoi Diagrams," ACM Transactions on Graphics     */
-/*    4(2):74-123, April 1985.                                               */
+/*    4(2):74-123, April 1985, http://portal.acm.org/citation.cfm?id=282923 .*/
 /*                                                                           */
 /*  Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai   */
 /*    Lee and Bruce J. Schachter, "Two Algorithms for Constructing the       */
@@ -126,7 +127,8 @@
 /*    boundary of the triangulation are maintained in a splay tree for the   */
 /*    purpose of point location.  Splay trees are described by Daniel        */
 /*    Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
-/*    Trees," Journal of the ACM 32(3):652-686, July 1985.                   */
+/*    Trees," Journal of the ACM 32(3):652-686, July 1985,                   */
+/*    http://portal.acm.org/citation.cfm?id=3835 .                           */
 /*                                                                           */
 /*  The algorithms for exact computation of the signs of determinants are    */
 /*    described in Jonathan Richard Shewchuk, "Adaptive Precision Floating-  */
@@ -149,6 +151,12 @@
 /*    lations," International Journal of Computational Geometry & Applica-   */
 /*    tions 5(1-2):193-213, March-June 1995.                                 */
 /*                                                                           */
+/*  The method of inserting new vertices off-center (not precisely at the    */
+/*    circumcenter of every poor-quality triangle) is from Alper Ungor,      */
+/*    "Off-centers:  A New Type of Steiner Points for Computing Size-Optimal */
+/*    Quality-Guaranteed Delaunay Triangulations," Proceedings of LATIN      */
+/*    2004 (Buenos Aires, Argentina), April 2004.                            */
+/*                                                                           */
 /*  For definitions of and results involving Delaunay triangulations,        */
 /*    constrained and conforming versions thereof, and other aspects of      */
 /*    triangular mesh generation, see the excellent survey by Marshall Bern  */
@@ -163,15 +171,8 @@
 /*    segment before it is inserted.  This doesn't count point location,     */
 /*    which can be much more expensive.  I could improve this to O(d log d)  */
 /*    time, but d is usually quite small, so it's not worth the bother.      */
-/*    (This note does not apply to conforming Delaunay triangulations, for   */
-/*    which a different method is used to insert segments.)                  */
-/*                                                                           */
-/*  The time for adding segments to a conforming Delaunay triangulation is   */
-/*    not clear, but does not depend upon t alone.  In some cases, very      */
-/*    small features (like a vertex lying next to a segment) can cause a     */
-/*    single segment to be split an arbitrary number of times.  Of course,   */
-/*    floating-point precision is a practical barrier to how much this can   */
-/*    happen.                                                                */
+/*    (This note does not apply when the -s switch is used, invoking a       */
+/*    different method is used to insert segments.)                          */
 /*                                                                           */
 /*  The time for deleting a vertex from a Delaunay triangulation is O(d^2)   */
 /*    in the worst case and O(d) in the common case, where d is the degree   */
@@ -185,15 +186,12 @@
 /*                                                                           */
 /*  The geometric predicates (circumcenter calculations, segment             */
 /*    intersection formulae, etc.) appear in my "Lecture Notes on Geometric  */
-/*    Robustness" at http://www.cs.berkeley.edu/~jrs/mesh.html .             */
+/*    Robustness" at http://www.cs.berkeley.edu/~jrs/mesh .                  */
 /*                                                                           */
 /*  If you make any improvements to this code, please please please let me   */
 /*    know, so that I may obtain the improvements.  Even if you don't change */
 /*    the code, I'd still love to hear what it's being used for.             */
 /*                                                                           */
-/*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
-/*    whatsoever.  This code is provided "as-is".  Use at your own risk.     */
-/*                                                                           */
 /*****************************************************************************/
 
 /* For single precision (which will save some memory and reduce paging),     */
@@ -212,13 +210,11 @@
 
 /* #define SINGLE */
 
-#if 0
 #ifdef SINGLE
 #define REAL float
 #else /* not SINGLE */
 #define REAL double
 #endif /* not SINGLE */
-#endif
 
 /* If yours is not a Unix system, define the NO_TIMER compiler switch to     */
 /*   remove the Unix-specific timing code.                                   */
@@ -244,9 +240,10 @@
 /*   all features that are primarily of research interest; specifically, the */
 /*   -i, -F, -s, and -C switches.  Define the CDT_ONLY symbol to eliminate   */
 /*   all meshing algorithms above and beyond constrained Delaunay            */
-/*   triangulation; specifically, the -r, -q, -a, -S, and -s switches.       */
-/*   These reductions are most likely to be useful when generating an object */
-/*   library (triangle.o) by defining the TRILIBRARY symbol.                 */
+/*   triangulation; specifically, the -r, -q, -a, -u, -D, -S, and -s         */
+/*   switches.  These reductions are most likely to be useful when           */
+/*   generating an object library (triangle.o) by defining the TRILIBRARY    */
+/*   symbol.                                                                 */
 
 /* #define REDUCED */
 /* #define CDT_ONLY */
@@ -277,12 +274,12 @@
 
 /* Maximum number of characters in a file name (including the null).         */
 
-#define FILENAMESIZE 512
+#define FILENAMESIZE 2048
 
 /* Maximum number of characters in a line read from a file (including the    */
 /*   null).                                                                  */
 
-#define INPUTLINESIZE 512
+#define INPUTLINESIZE 1024
 
 /* For efficiency, a variety of data structures are allocated in bulk.  The  */
 /*   following constants determine how many of each structure is allocated   */
@@ -315,7 +312,7 @@
 /*   compiler is smarter, feel free to replace the "int" with "void".        */
 /*   Not that it matters.                                                    */
 
-#define VOID void
+#define VOID int
 
 /* Two constants for algorithms based on random sampling.  Both constants    */
 /*   have been chosen empirically to optimize their respective algorithms.   */
@@ -367,11 +364,6 @@ char *readline();
 char *findfield();
 #endif /* not TRILIBRARY */
 
-/* Labels that signify whether a record consists primarily of pointers or of */
-/*   floating-point words.  Used to make decisions about data alignment.     */
-
-enum wordtype {POINTER, FLOATINGPOINT};
-
 /* Labels that signify the result of point location.  The result of a        */
 /*   search indicates that the point falls in the interior of a triangle, on */
 /*   an edge, on a vertex, or outside the mesh.                              */
@@ -438,9 +430,10 @@ enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
 /*  sandwiched between two triangles, or resting against one triangle on an  */
 /*  exterior boundary or hole boundary.                                      */
 /*                                                                           */
-/*  A subsegment consists of a list of two vertices, a list of two           */
-/*  adjoining subsegments, and a list of two adjoining triangles.  One of    */
-/*  the two adjoining triangles may not be present (though there should      */
+/*  A subsegment consists of a list of four vertices--the vertices of the    */
+/*  subsegment, and the vertices of the segment it is a part of--a list of   */
+/*  two adjoining subsegments, and a list of two adjoining triangles.  One   */
+/*  of the two adjoining triangles may not be present (though there should   */
 /*  always be one), and neighboring subsegments might not be present.        */
 /*  Subsegments also store a user-defined integer "boundary marker".         */
 /*  Typically, this integer is used to indicate what boundary conditions are */
@@ -523,8 +516,9 @@ struct otri {
 };
 
 /* The subsegment data structure.  Each subsegment contains two pointers to  */
-/*   adjoining subsegments, plus two pointers to vertices, plus two pointers */
-/*   to adjoining triangles, plus one boundary marker.                       */
+/*   adjoining subsegments, plus four pointers to vertices, plus two         */
+/*   pointers to adjoining triangles, plus one boundary marker, plus one     */
+/*   segment number.                                                         */
 
 typedef REAL **subseg;                  /* Really:  typedef subseg *subseg   */
 
@@ -543,8 +537,7 @@ struct osub {
 /*   marker, and sometimes a pointer to a triangle, is appended after the    */
 /*   REALs.                                                                  */
 
-/* typedef REAL *vertex; */
-/* moved to header file. */
+typedef REAL *vertex;
 
 /* A queue used to store encroached subsegments.  Each subsegment's vertices */
 /*   are stored so that we can check whether a subsegment is still the same. */
@@ -621,15 +614,14 @@ struct splaynode {
 /*   to be traversed.  pathitemsleft is the number of items that remain to   */
 /*   be traversed in pathblock.                                              */
 /*                                                                           */
-/* itemwordtype is set to POINTER or FLOATINGPOINT, and is used to suggest   */
-/*   what sort of word the record is primarily made up of.  alignbytes       */
-/*   determines how new records should be aligned in memory.  itembytes and  */
-/*   itemwords are the length of a record in bytes (after rounding up) and   */
-/*   words.  itemsperblock is the number of items allocated at once in a     */
-/*   single block.  items is the number of currently allocated items.        */
-/*   maxitems is the maximum number of items that have been allocated at     */
-/*   once; it is the current number of items plus the number of records kept */
-/*   on deaditemstack.                                                       */
+/* alignbytes determines how new records should be aligned in memory.        */
+/*   itembytes is the length of a record in bytes (after rounding up).       */
+/*   itemsperblock is the number of items allocated at once in a single      */
+/*   block.  itemsfirstblock is the number of items in the first block,      */
+/*   which can vary from the others.  items is the number of currently       */
+/*   allocated items.  maxitems is the maximum number of items that have     */
+/*   been allocated at once; it is the current number of items plus the      */
+/*   number of records kept on deaditemstack.                                */
 
 struct memorypool {
   VOID **firstblock, **nowblock;
@@ -637,10 +629,10 @@ struct memorypool {
   VOID *deaditemstack;
   VOID **pathblock;
   VOID *pathitem;
-  enum wordtype itemwordtype;
   int alignbytes;
-  int itembytes, itemwords;
+  int itembytes;
   int itemsperblock;
+  int itemsfirstblock;
   long items, maxitems;
   int unallocateditems;
   int pathitemsleft;
@@ -680,11 +672,11 @@ struct mesh {
   struct memorypool splaynodes;
 
 /* Variables that maintain the bad triangle queues.  The queues are          */
-/*   ordered from 63 (highest priority) to 0 (lowest priority).              */
+/*   ordered from 4095 (highest priority) to 0 (lowest priority).            */
 
-  struct badtriang *queuefront[64];
-  struct badtriang *queuetail[64];
-  int nextnonemptyq[64];
+  struct badtriang *queuefront[4096];
+  struct badtriang *queuetail[4096];
+  int nextnonemptyq[4096];
   int firstnonemptyq;
 
 /* Variable that maintains the stack of recently flipped triangles.          */
@@ -758,6 +750,7 @@ struct behavior {
 /*   quality: -q switch.                                                     */
 /*     minangle: minimum angle bound, specified after -q switch.             */
 /*     goodangle: cosine squared of minangle.                                */
+/*     offconstant: constant used to place off-center Steiner points.        */
 /*   vararea: -a switch without number.                                      */
 /*   fixedarea: -a switch with number.                                       */
 /*     maxarea: maximum area bound, specified after -a switch.               */
@@ -778,7 +771,7 @@ struct behavior {
 /*   incremental: -i switch.  sweepline: -F switch.                          */
 /*   dwyer: inverse of -l switch.                                            */
 /*   splitseg: -s switch.                                                    */
-/*   nolenses: -L switch.  docheck: -C switch.                               */
+/*   conformdel: -D switch.  docheck: -C switch.                             */
 /*   quiet: -Q switch.  verbose: count of how often -V switch is selected.   */
 /*   usesegments: -p, -r, -q, or -c switch; determines whether segments are  */
 /*     used at all.                                                          */
@@ -790,7 +783,7 @@ struct behavior {
   int firstnumber;
   int edgesout, voronoi, neighbors, geomview;
   int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
-  int noholes, noexact, nolenses;
+  int noholes, noexact, conformdel;
   int incremental, sweepline, dwyer;
   int splitseg;
   int docheck;
@@ -799,7 +792,7 @@ struct behavior {
   int order;
   int nobisect;
   int steiner;
-  REAL minangle, goodangle;
+  REAL minangle, goodangle, offconstant;
   REAL maxarea;
 
 /* Variables for file names.                                                 */
@@ -1208,7 +1201,7 @@ int minus1mod3[3] = {2, 0, 1};
   sdecode(sptr, osub)
 
 /* These primitives determine or set the origin or destination of a          */
-/*   subsegment.                                                             */
+/*   subsegment or the segment that includes it.                             */
 
 #define sorg(osub, vertexptr)                                                 \
   vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
@@ -1222,14 +1215,26 @@ int minus1mod3[3] = {2, 0, 1};
 #define setsdest(osub, vertexptr)                                             \
   (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
 
+#define segorg(osub, vertexptr)                                               \
+  vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
+
+#define segdest(osub, vertexptr)                                              \
+  vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
+
+#define setsegorg(osub, vertexptr)                                            \
+  (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
+
+#define setsegdest(osub, vertexptr)                                           \
+  (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
+
 /* These primitives read or set a boundary marker.  Boundary markers are     */
 /*   used to hold user-defined tags for setting boundary conditions in       */
 /*   finite element solvers.                                                 */
 
-#define mark(osub)  (* (int *) ((osub).ss + 6))
+#define mark(osub)  (* (int *) ((osub).ss + 8))
 
 #define setmark(osub, value)                                                  \
-  * (int *) ((osub).ss + 6) = value
+  * (int *) ((osub).ss + 8) = value
 
 /* Bond two subsegments together.                                            */
 
@@ -1280,14 +1285,14 @@ int minus1mod3[3] = {2, 0, 1};
 /*   variable `ptr' of type `triangle' be defined.                           */
 
 #define stpivot(osub, otri)                                                   \
-  ptr = (triangle) (osub).ss[4 + (osub).ssorient];                            \
+  ptr = (triangle) (osub).ss[6 + (osub).ssorient];                            \
   decode(ptr, otri)
 
 /* Bond a triangle to a subsegment.                                          */
 
 #define tsbond(otri, osub)                                                    \
   (otri).tri[6 + (otri).orient] = (triangle) sencode(osub);                   \
-  (osub).ss[4 + (osub).ssorient] = (subseg) encode(otri)
+  (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
 
 /* Dissolve a bond (from the triangle side).                                 */
 
@@ -1297,7 +1302,7 @@ int minus1mod3[3] = {2, 0, 1};
 /* Dissolve a bond (from the subsegment side).                               */
 
 #define stdissolve(osub)                                                      \
-  (osub).ss[4 + (osub).ssorient] = (subseg) m->dummytri
+  (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
 
 /********* Primitives for vertices                                   *********/
 /*                                                                           */
@@ -1351,12 +1356,7 @@ int minus1mod3[3] = {2, 0, 1};
 
 #ifdef EXTERNAL_TEST
 
-#ifdef ANSI_DECLARATORS
-extern int triunsuitable(vertex triorg, vertex tridest, vertex triapex,
-                         REAL area);
-#else /* not ANSI_DECLARATORS */
-extern int triunsuitable();
-#endif /* not ANSI_DECLARATORS */
+int triunsuitable();
 
 #else /* not EXTERNAL_TEST */
 
@@ -1403,10 +1403,21 @@ REAL area;                                      /* The area of the triangle. */
 /**                                                                         **/
 /********* User-defined triangle evaluation routine ends here        *********/
 
-/********* Memory allocation wrappers begin here                     *********/
+/********* Memory allocation and program exit wrappers begin here    *********/
 /**                                                                         **/
 /**                                                                         **/
 
+#ifdef ANSI_DECLARATORS
+void triexit(int status)
+#else /* not ANSI_DECLARATORS */
+void triexit(status)
+int status;
+#endif /* not ANSI_DECLARATORS */
+
+{
+  exit(status);
+}
+
 #ifdef ANSI_DECLARATORS
 VOID *trimalloc(int size)
 #else /* not ANSI_DECLARATORS */
@@ -1417,10 +1428,10 @@ int size;
 {
   VOID *memptr;
 
-  memptr = malloc(size);
+  memptr = (VOID *) malloc((unsigned int) size);
   if (memptr == (VOID *) NULL) {
     printf("Error:  Out of memory.\n");
-    exit(1);
+    triexit(1);
   }
   return(memptr);
 }
@@ -1438,7 +1449,7 @@ VOID *memptr;
 
 /**                                                                         **/
 /**                                                                         **/
-/********* Memory allocation wrappers end here                       *********/
+/********* Memory allocation and program exit wrappers end here      *********/
 
 /********* User interaction routines begin here                      *********/
 /**                                                                         **/
@@ -1462,9 +1473,9 @@ void syntax()
 #endif /* not REDUCED */
 #else /* not CDT_ONLY */
 #ifdef REDUCED
-  printf("triangle [-prq__a__uAcjevngBPNEIOXzo_YS__LlQVh] input_file\n");
+  printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
 #else /* not REDUCED */
-  printf("triangle [-prq__a__uAcjevngBPNEIOXzo_YS__LiFlsCQVh] input_file\n");
+  printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
 #endif /* not REDUCED */
 #endif /* not CDT_ONLY */
 
@@ -1479,8 +1490,13 @@ void syntax()
   printf(
     "    -A  Applies attributes to identify triangles in certain regions.\n");
   printf("    -c  Encloses the convex hull with segments.\n");
+#ifndef CDT_ONLY
+  printf("    -D  Conforming Delaunay:  all triangles are truly Delaunay.\n");
+#endif /* not CDT_ONLY */
+/*
   printf("    -w  Weighted Delaunay triangulation.\n");
   printf("    -W  Regular triangulation (lower hull of a height field).\n");
+*/
   printf("    -j  Jettison unused vertices from output .node file.\n");
   printf("    -e  Generates an edge list.\n");
   printf("    -v  Generates a Voronoi diagram.\n");
@@ -1498,7 +1514,6 @@ void syntax()
 #ifndef CDT_ONLY
   printf("    -Y  Suppresses boundary segment splitting.\n");
   printf("    -S  Specifies maximum number of added Steiner points.\n");
-  printf("    -L  Uses equatorial circles, not equatorial lenses.\n");
 #endif /* not CDT_ONLY */
 #ifndef REDUCED
   printf("    -i  Uses incremental method, rather than divide-and-conquer.\n");
@@ -1509,14 +1524,13 @@ void syntax()
 #ifndef CDT_ONLY
   printf(
     "    -s  Force segments into mesh by splitting (instead of using CDT).\n");
-  printf("    -L  Uses Ruppert's diametral spheres, not diametral lenses.\n");
 #endif /* not CDT_ONLY */
   printf("    -C  Check consistency of final mesh.\n");
 #endif /* not REDUCED */
   printf("    -Q  Quiet:  No terminal output except errors.\n");
   printf("    -V  Verbose:  Detailed information on what I'm doing.\n");
   printf("    -h  Help:  Detailed instructions for Triangle.\n");
-  exit(0);
+  triexit(0);
 }
 
 #endif /* not TRILIBRARY */
@@ -1534,12 +1548,13 @@ void info()
   printf("Triangle\n");
   printf(
 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
-  printf("Version 1.4\n\n");
-  printf("Copyright 1993, 1995, 1997, 1998, 2002 Jonathan Richard Shewchuk\n");
+  printf("Version 1.6\n\n");
+  printf(
+"Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
   printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
   printf("Bugs/comments to jrs@cs.berkeley.edu\n");
   printf(
-"Created as part of the Archimedes project (tools for parallel FEM).\n");
+"Created as part of the Quake project (tools for earthquake simulation).\n");
   printf(
 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
   printf("There is no warranty whatsoever.  Use at your own risk.\n");
@@ -1551,20 +1566,19 @@ void info()
   printf(
 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
   printf(
-"triangulations, Voronoi diagrams, and quality conforming Delaunay\n");
+"triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
   printf(
-"triangulations.  The latter can be generated with no small angles, and are\n"
+"high-quality triangular meshes.  The latter can be generated with no small\n"
 );
   printf(
-"thus suitable for finite element analysis.  If no command line switches are\n"
+"or large angles, and are thus suitable for finite element analysis.  If no\n"
 );
   printf(
-"specified, your .node input file is read, and the Delaunay triangulation is\n"
-);
-  printf("returned in .node and .ele output files.  The command syntax is:\n");
-  printf("\n");
-  printf("triangle [-prq__a__uAcjevngBPNEIOXzo_YS__LiFlsCQVh] input_file\n");
-  printf("\n");
+"command line switch is specified, your .node input file is read, and the\n");
+  printf(
+"Delaunay triangulation is returned in .node and .ele output files.  The\n");
+  printf("command syntax is:\n\n");
+  printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
   printf(
 "Underscores indicate that numbers may optionally follow certain switches.\n");
   printf(
@@ -1581,15 +1595,20 @@ void info()
   printf(
 "    -p  Reads a Planar Straight Line Graph (.poly file), which can specify\n"
 );
-  printf("        vertices, segments, holes, regional attributes, and area\n");
+  printf(
+"        vertices, segments, holes, regional attributes, and regional area\n");
   printf(
 "        constraints.  Generates a constrained Delaunay triangulation (CDT)\n"
 );
   printf(
 "        fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
   printf(
-"        constrained Delaunay triangulation (CCDT).  If -p is not used,\n");
-  printf("        Triangle reads a .node file by default.\n");
+"        constrained Delaunay triangulation (CCDT).  If you want a truly\n");
+  printf(
+"        Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
+  printf(
+"        well.  When -p is not used, Triangle reads a .node file by default.\n"
+);
   printf(
 "    -r  Refines a previously generated mesh.  The mesh is read from a .node\n"
 );
@@ -1602,32 +1621,40 @@ void info()
   printf(
 "        impose area constraints on the mesh.  Further details on refinement\n"
 );
-  printf("        are given below.\n");
+  printf("        appear below.\n");
   printf(
-"    -q  Quality mesh generation by my variant of Jim Ruppert's Delaunay\n");
+"    -q  Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
   printf(
-"        refinement algorithm.  Adds vertices to the mesh to ensure that no\n"
+"        Chew's and Jim Ruppert's algorithms).  Adds vertices to the mesh to\n"
 );
   printf(
-"        angles smaller than 20 degrees occur.  An alternative minimum angle\n"
+"        ensure that all angles are between 20 and 140 degrees.  An\n");
+  printf(
+"        alternative bound on the minimum angle, replacing 20 degrees, may\n");
+  printf(
+"        be specified after the `q'.  The specified angle may include a\n");
+  printf(
+"        decimal point, but not exponential notation.  Note that a bound of\n"
 );
   printf(
-"        may be specified after the `q'.  If the minimum angle is 20.7\n");
+"        theta degrees on the smallest angle also implies a bound of\n");
   printf(
-"        degrees or smaller, the triangulation algorithm is mathematically\n");
+"        (180 - 2 theta) on the largest angle.  If the minimum angle is 28.6\n"
+);
   printf(
-"        guaranteed to terminate (assuming infinite precision arithmetic--\n");
+"        degrees or smaller, Triangle is mathematically guaranteed to\n");
   printf(
-"        Triangle may fail to terminate if you run out of precision).  In\n");
+"        terminate (assuming infinite precision arithmetic--Triangle may\n");
   printf(
-"        practice, the algorithm often succeeds for minimum angles up to\n");
+"        fail to terminate if you run out of precision).  In practice,\n");
   printf(
-"        33.8 degrees.  For some meshes, however, it may be necessary to\n");
+"        Triangle often succeeds for minimum angles up to 34 degrees.  For\n");
   printf(
-"        reduce the minimum angle to avoid problems associated with\n");
+"        some meshes, however, you might need to reduce the minimum angle to\n"
+);
   printf(
-"        insufficient floating-point precision.  The specified angle may\n");
-  printf("        include a decimal point.\n");
+"        avoid problems associated with insufficient floating-point\n");
+  printf("        precision.\n");
   printf(
 "    -a  Imposes a maximum triangle area.  If a number follows the `a', no\n");
   printf(
@@ -1669,28 +1696,30 @@ void info()
   printf(
 "        EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
   printf(
-"        link Triangle against a separate object file that implements\n");
+"        link Triangle with a separate object file that implements\n");
   printf(
 "        triunsuitable().  In either case, the -u switch causes the user-\n");
   printf("        defined test to be applied to every triangle.\n");
   printf(
-"    -A  Assigns an additional attribute to each triangle that identifies\n");
+"    -A  Assigns an additional floating-point attribute to each triangle\n");
   printf(
-"        what segment-bounded region each triangle belongs to.  Attributes\n");
+"        that identifies what segment-bounded region each triangle belongs\n");
   printf(
-"        are assigned to regions by the .poly file.  If a region is not\n");
+"        to.  Attributes are assigned to regions by the .poly file.  If a\n");
   printf(
-"        explicitly marked by the .poly file, triangles in that region are\n");
+"        region is not explicitly marked by the .poly file, triangles in\n");
   printf(
-"        assigned an attribute of zero.  The -A switch has an effect only\n");
-  printf("        when the -p switch is used and the -r switch is not.\n");
+"        that region are assigned an attribute of zero.  The -A switch has\n");
+  printf(
+"        an effect only when the -p switch is used and the -r switch is not.\n"
+);
   printf(
 "    -c  Creates segments on the convex hull of the triangulation.  If you\n");
   printf(
 "        are triangulating a vertex set, this switch causes a .poly file to\n"
 );
   printf(
-"        be written, containing all edges in the convex hull.  If you are\n");
+"        be written, containing all edges of the convex hull.  If you are\n");
   printf(
 "        triangulating a PSLG, this switch specifies that the whole convex\n");
   printf(
@@ -1698,7 +1727,8 @@ void info()
   printf(
 "        segments the PSLG has.  If you do not use this switch when\n");
   printf(
-"        triangulating a PSLG, it is assumed that you have identified the\n");
+"        triangulating a PSLG, Triangle assumes that you have identified the\n"
+);
   printf(
 "        region to be triangulated by surrounding it with segments of the\n");
   printf(
@@ -1712,11 +1742,30 @@ void info()
   printf(
 "        possibly failure if Triangle runs out of precision).  If you are\n");
   printf(
-"        refining a mesh, the -c switch works differently; it generates the\n"
+"        refining a mesh, the -c switch works differently:  it causes a\n");
+  printf(
+"        .poly file to be written containing the boundary edges of the mesh\n"
+);
+  printf("        (useful if no .poly file was read).\n");
+  printf(
+"    -D  Conforming Delaunay triangulation:  use this switch if you want to\n"
+);
+  printf(
+"        ensure that all the triangles in the mesh are Delaunay, and not\n");
+  printf(
+"        merely constrained Delaunay; or if you want to ensure that all the\n"
+);
+  printf(
+"        Voronoi vertices lie within the triangulation.  (Some finite volume\n"
 );
   printf(
-"        set of boundary edges of the mesh (useful if no .poly file was\n");
-  printf("        read).\n");
+"        methods have this requirement.)  This switch invokes Ruppert's\n");
+  printf(
+"        original algorithm, which splits every subsegment whose diametral\n");
+  printf(
+"        circle is encroached.  It usually increases the number of vertices\n"
+);
+  printf("        and triangles.\n");
   printf(
 "    -j  Jettisons vertices that are not part of the final triangulation\n");
   printf(
@@ -1727,15 +1776,15 @@ void info()
 "        same order, so their indices do not change.  The -j switch prevents\n"
 );
   printf(
-"        duplicated input vertices from appearing in the output .node file;\n"
-);
+"        duplicated input vertices, or vertices `eaten' by holes, from\n");
+  printf(
+"        appearing in the output .node file.  Thus, if two input vertices\n");
   printf(
-"        hence, if two input vertices have exactly the same coordinates,\n");
+"        have exactly the same coordinates, only the first appears in the\n");
   printf(
-"        only the first appears in the output.  If any vertices are\n");
+"        output.  If any vertices are jettisoned, the vertex numbering in\n");
   printf(
-"        jettisoned, the vertex numbering in the output .node file differs\n");
-  printf("        from that of the input .node file.\n");
+"        the output .node file differs from that of the input .node file.\n");
   printf(
 "    -e  Outputs (to an .edge file) a list of edges of the triangulation.\n");
   printf(
@@ -1791,15 +1840,15 @@ void info()
   printf(
 "        Disabling exact arithmetic with the -X switch causes a small\n");
   printf(
-"        improvement in speed and creates the possibility (albeit small)\n");
-  printf(
-"        that Triangle will fail to produce a valid mesh.  Not recommended.\n"
+"        improvement in speed and creates the possibility that Triangle will\n"
 );
+  printf("        fail to produce a valid mesh.  Not recommended.\n");
   printf(
 "    -z  Numbers all items starting from zero (rather than one).  Note that\n"
 );
   printf(
-"        this switch is normally overrided by the value used to number the\n");
+"        this switch is normally overridden by the value used to number the\n"
+);
   printf(
 "        first vertex of the input .node or .poly file.  However, this\n");
   printf(
@@ -1812,18 +1861,16 @@ void info()
   printf(
 "        mesh boundary must be preserved so that it conforms to some\n");
   printf(
-"        adjacent mesh.  Be forewarned that you will probably sacrifice some\n"
+"        adjacent mesh.  Be forewarned that you will probably sacrifice much\n"
 );
   printf(
 "        of the quality of the mesh; Triangle will try, but the resulting\n");
   printf(
-"        mesh may contain triangles of poor aspect ratio.  Works well if all\n"
-);
+"        mesh may contain poorly shaped triangles.  Works well if all the\n");
   printf(
-"        the boundary vertices are closely spaced.  Specify this switch\n");
+"        boundary vertices are closely spaced.  Specify this switch twice\n");
   printf(
-"        twice (`-YY') to prevent all segment splitting, including internal\n"
-);
+"        (`-YY') to prevent all segment splitting, including internal\n");
   printf("        boundaries.\n");
   printf(
 "    -S  Specifies the maximum number of Steiner points (vertices that are\n");
@@ -1847,35 +1894,20 @@ void info()
 );
   printf("        PLSG are recovered, ignoring the limit if necessary.\n");
   printf(
-"    -L  Do not use diametral lenses to determine whether subsegments are\n");
-  printf(
-"        encroached; use diametral circles instead (as in Ruppert's\n");
-  printf(
-"        algorithm).  Use this switch if you want all triangles in the mesh\n"
-);
-  printf(
-"        to be Delaunay, and not just constrained Delaunay; or if you want\n");
-  printf(
-"        to ensure that all Voronoi vertices lie within the triangulation.\n");
-  printf(
-"        (Applications such as some finite volume methods may have this\n");
+"    -i  Uses an incremental rather than a divide-and-conquer algorithm to\n");
   printf(
-"        requirement.)  This switch may increase the number of vertices in\n");
-  printf("        the mesh to meet these constraints.\n");
+"        construct a Delaunay triangulation.  Try it if the divide-and-\n");
+  printf("        conquer algorithm fails.\n");
   printf(
-"    -i  Uses an incremental rather than divide-and-conquer algorithm to\n");
-  printf(
-"        form a Delaunay triangulation.  Try it if the divide-and-conquer\n");
-  printf("        algorithm fails.\n");
-  printf(
-"    -F  Uses Steven Fortune's sweepline algorithm to form a Delaunay\n");
+"    -F  Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
   printf(
 "        triangulation.  Warning:  does not use exact arithmetic for all\n");
   printf("        calculations.  An exact result is not guaranteed.\n");
   printf(
 "    -l  Uses only vertical cuts in the divide-and-conquer algorithm.  By\n");
   printf(
-"        default, Triangle uses alternating vertical and horizontal cuts,\n");
+"        default, Triangle alternates between vertical and horizontal cuts,\n"
+);
   printf(
 "        which usually improve the speed except with vertex sets that are\n");
   printf(
@@ -1908,14 +1940,15 @@ void info()
 "    -V  Verbose:  Gives detailed information about what Triangle is doing.\n"
 );
   printf(
-"        Add more `V's for increasing amount of detail.  `-V' gives\n");
+"        Add more `V's for increasing amount of detail.  `-V' is most\n");
   printf(
-"        information on algorithmic progress and more detailed statistics.\n");
+"        useful; itgives information on algorithmic progress and much more\n");
   printf(
-"        `-VV' gives vertex-by-vertex details, and prints so much that\n");
+"        detailed statistics.  `-VV' gives vertex-by-vertex details, and\n");
   printf(
-"        Triangle runs much more slowly.  `-VVVV' gives information only\n");
-  printf("        a debugger could love.\n");
+"        prints so much that Triangle runs much more slowly.  `-VVVV' gives\n"
+);
+  printf("        information only a debugger could love.\n");
   printf("    -h  Help:  Displays these instructions.\n");
   printf("\n");
   printf("Definitions:\n");
@@ -1923,26 +1956,28 @@ void info()
   printf(
 "  A Delaunay triangulation of a vertex set is a triangulation whose\n");
   printf(
-"  vertices are the vertex set, wherein no vertex in the vertex set falls in\n"
-);
+"  vertices are the vertex set, that covers the convex hull of the vertex\n");
+  printf(
+"  set.  A Delaunay triangulation has the property that no vertex lies\n");
   printf(
-"  the interior of the circumcircle (circle that passes through all three\n");
+"  inside the circumscribing circle (circle that passes through all three\n");
   printf("  vertices) of any triangle in the triangulation.\n\n");
   printf(
 "  A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
   printf(
-"  polygonal regions (some of which may be infinite), where each region is\n");
+"  polygonal cells (some of which may be unbounded, meaning infinitely\n");
   printf(
-"  the set of points in the plane that are closer to some input vertex than\n"
+"  large), where each cell is the set of points in the plane that are closer\n"
 );
   printf(
-"  to any other input vertex.  (The Voronoi diagram is the geometric dual of\n"
+"  to some input vertex than to any other input vertex.  The Voronoi diagram\n"
 );
-  printf("  the Delaunay triangulation.)\n\n");
+  printf("  is a geometric dual of the Delaunay triangulation.\n\n");
   printf(
 "  A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
   printf(
-"  Segments are simply edges, whose endpoints are vertices in the PSLG.\n");
+"  Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
+);
   printf(
 "  Segments may intersect each other only at their endpoints.  The file\n");
   printf("  format for PSLGs (.poly files) is described below.\n\n");
@@ -1952,26 +1987,47 @@ void info()
 "  Delaunay triangulation, but each PSLG segment is present as a single edge\n"
 );
   printf(
-"  in the triangulation.  (A constrained Delaunay triangulation is not truly\n"
+"  of the CDT.  (A constrained Delaunay triangulation is not truly a\n");
+  printf(
+"  Delaunay triangulation, because some of its triangles might not be\n");
+  printf(
+"  Delaunay.)  By definition, a CDT does not have any vertices other than\n");
+  printf(
+"  those specified in the input PSLG.  Depending on context, a CDT might\n");
+  printf(
+"  cover the convex hull of the PSLG, or it might cover only a segment-\n");
+  printf("  bounded region (e.g. a polygon).\n\n");
+  printf(
+"  A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
 );
   printf(
-"  a Delaunay triangulation.)  By definition, a CDT does not have any\n");
-  printf("  vertices other than those specified in the input PSLG.\n\n");
+"  each triangle is truly Delaunay, and each PSLG segment is represented by\n"
+);
   printf(
-"  A conforming Delaunay triangulation of a PSLG is a true Delaunay\n");
+"  a linear contiguous sequence of edges of the triangulation.  New vertices\n"
+);
   printf(
-"  triangulation in which each PSLG segment is represented by a linear\n");
+"  (not part of the PSLG) may appear, and each input segment may have been\n");
   printf(
-"  contiguous sequence of edges in the triangulation.  Each input segment\n");
+"  subdivided into shorter edges (subsegments) by these additional vertices.\n"
+);
   printf(
-"  may have been subdivided into shorter subsegments by the insertion of\n");
+"  The new vertices are frequently necessary to maintain the Delaunay\n");
+  printf("  property while ensuring that every segment is represented.\n\n");
   printf(
-"  additional vertices.  These inserted vertices are necessary to maintain\n");
+"  A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
   printf(
-"  the Delaunay property while ensuring that every segment is represented.\n");
-  printf("\n");
-  printf("File Formats:\n");
-  printf("\n");
+"  triangulation of a PSLG whose triangles are constrained Delaunay.  New\n");
+  printf("  vertices may appear, and input segments may be subdivided into\n");
+  printf(
+"  subsegments, but not to guarantee that segments are respected; rather, to\n"
+);
+  printf(
+"  improve the quality of the triangles.  The high-quality meshes produced\n");
+  printf(
+"  by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
+  printf("  with the -D switch.\n\n");
+  printf("File Formats:\n\n");
   printf(
 "  All files may contain comments prefixed by the character '#'.  Vertices,\n"
 );
@@ -2007,7 +2063,8 @@ void info()
 "    a finite element mesh, are copied unchanged to the output mesh.  If -q,\n"
 );
   printf(
-"    -a, -u, or -s is selected, each new Steiner point added to the mesh\n");
+"    -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
+);
   printf("    has attributes assigned to it by linear interpolation.\n\n");
   printf(
 "    If the fourth entry of the first line is `1', the last column of the\n");
@@ -2042,15 +2099,15 @@ void info()
 "    The attributes are just like those of .node files.  Because there is no\n"
 );
   printf(
-"    simple mapping from input to output triangles, an attempt is made to\n");
+"    simple mapping from input to output triangles, Triangle attempts to\n");
   printf(
-"    interpolate attributes, which may result in a good deal of diffusion of\n"
+"    interpolate attributes, and may cause a lot of diffusion of attributes\n"
 );
   printf(
-"    attributes among nearby triangles as the triangulation is refined.\n");
-  printf(
-"    Attributes do not diffuse across segments, so attributes used to\n");
-  printf("    identify segment-bounded regions remain intact.\n\n");
+"    among nearby triangles as the triangulation is refined.  Attributes do\n"
+);
+  printf("    not diffuse across segments, so attributes used to identify\n");
+  printf("    segment-bounded regions remain intact.\n\n");
   printf(
 "    In .ele files produced by Triangle, each triangular element has three\n");
   printf(
@@ -2099,22 +2156,21 @@ void info()
   printf(
 "    this way has the advantage that it may easily be triangulated with or\n");
   printf(
-"    without segments (depending on whether the .poly or .node file is\n");
-  printf("    read).\n\n");
+"    without segments (depending on whether the -p switch is invoked).\n");
+  printf("\n");
   printf(
 "    The second section lists the segments.  Segments are edges whose\n");
   printf(
-"    presence in the triangulation is enforced (although each segment may be\n"
+"    presence in the triangulation is enforced.  (Depending on the choice of\n"
 );
   printf(
-"    subdivided into smaller edges).  Each segment is specified by listing\n");
+"    switches, segment might be subdivided into smaller edges).  Each\n");
   printf(
-"    the indices of its two endpoints.  This means that you must include its\n"
+"    segment is specified by listing the indices of its two endpoints.  This\n"
 );
   printf(
-"    endpoints in the vertex list.  Each segment, like each point, may have\n"
-);
-  printf("    a boundary marker.\n\n");
+"    means that you must include its endpoints in the vertex list.  Each\n");
+  printf("    segment, like each point, may have a boundary marker.\n\n");
   printf(
 "    If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
 );
@@ -2127,12 +2183,11 @@ void info()
   printf(
 "    produces a conforming constrained Delaunay triangulation (CCDT), in\n");
   printf(
-"    which segments may be subdivided into smaller edges.  If -L is selected\n"
-);
+"    which segments may be subdivided into smaller edges.  If -D is\n");
   printf(
-"    as well, Triangle produces a conforming Delaunay triangulation, so\n");
+"    selected, Triangle produces a conforming Delaunay triangulation, so\n");
   printf(
-"    every triangle is Delaunay, and not just constrained Delaunay.\n");
+"    that every triangle is Delaunay, and not just constrained Delaunay.\n");
   printf("\n");
   printf(
 "    The third section lists holes (and concavities, if -c is selected) in\n");
@@ -2143,15 +2198,15 @@ void info()
   printf(
 "    by eating triangles, spreading out from each hole point until its\n");
   printf(
-"    progress is blocked by PSLG segments; you must be careful to enclose\n");
+"    progress is blocked by segments in the PSLG.  You must be careful to\n");
   printf(
-"    each hole in segments, or your whole triangulation might be eaten away.\n"
-);
+"    enclose each hole in segments, or your whole triangulation might be\n");
   printf(
-"    If the two triangles abutting a segment are eaten, the segment itself\n");
+"    eaten away.  If the two triangles abutting a segment are eaten, the\n");
   printf(
-"    is also eaten.  Do not place a hole directly on a segment; if you do,\n");
-  printf("    Triangle chooses one side of the segment arbitrarily.\n\n");
+"    segment itself is also eaten.  Do not place a hole directly on a\n");
+  printf("    segment; if you do, Triangle chooses one side of the segment\n");
+  printf("    arbitrarily.\n\n");
   printf(
 "    The optional fourth section lists regional attributes (to be assigned\n");
   printf(
@@ -2164,7 +2219,7 @@ void info()
   printf(
 "    switch is not used.  Regional attributes and area constraints are\n");
   printf(
-"    propagated in the same manner as holes; you specify a point for each\n");
+"    propagated in the same manner as holes:  you specify a point for each\n");
   printf(
 "    attribute and/or constraint, and the attribute and/or constraint\n");
   printf(
@@ -2194,22 +2249,25 @@ void info()
   printf(
 "    enclose the entire region to be triangulated in PSLG segments, or\n");
   printf(
-"    use the -c switch, which encloses the convex hull of the input vertex\n");
+"    use the -c switch, which automatically creates extra segments that\n");
   printf(
-"    set.  If you do not use the -c switch, Triangle eats all triangles that\n"
+"    enclose the convex hull of the PSLG.  If you do not use the -c switch,\n"
 );
   printf(
-"    are not enclosed by segments; if you are not careful, your whole\n");
+"    Triangle eats all triangles that are not enclosed by segments; if you\n");
+  printf(
+"    are not careful, your whole triangulation may be eaten away.  If you do\n"
+);
   printf(
-"    triangulation may be eaten away.  If you do use the -c switch, you can\n"
+"    use the -c switch, you can still produce concavities by the appropriate\n"
 );
   printf(
-"    still produce concavities by the appropriate placement of holes just\n");
-  printf("    within the convex hull.\n\n");
+"    placement of holes just inside the boundary of the convex hull.\n");
+  printf("\n");
   printf(
 "    An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
   printf(
-"    upon segments (except, of course, the endpoints of each segment.)  You\n"
+"    upon segments (except, of course, the endpoints of each segment).  You\n"
 );
   printf(
 "    aren't required to make your .poly files ideal, but you should be aware\n"
@@ -2258,35 +2316,36 @@ void info()
   printf(
 "    When Triangle reads a .poly file, it also writes a .poly file, which\n");
   printf(
-"    includes all edges that are parts of input segments.  If the -c switch\n"
-);
+"    includes all the subsegments--the edges that are parts of input\n");
   printf(
-"    is used, the output .poly file also includes all of the edges on the\n");
+"    segments.  If the -c switch is used, the output .poly file also\n");
   printf(
-"    convex hull.  Hence, the output .poly file is useful for finding edges\n"
+"    includes all of the edges on the convex hull.  Hence, the output .poly\n"
 );
   printf(
-"    associated with input segments and for setting boundary conditions in\n");
-  printf(
-"    finite element simulations.  Moreover, you will need it if you plan to\n"
+"    file is useful for finding edges associated with input segments and for\n"
 );
   printf(
-"    refine the output mesh, and don't want segments to be missing in later\n"
-);
-  printf("    triangulations.\n\n");
+"    setting boundary conditions in finite element simulations.  Moreover,\n");
+  printf(
+"    you will need the output .poly file if you plan to refine the output\n");
+  printf(
+"    mesh, and don't want segments to be missing in later triangulations.\n");
+  printf("\n");
   printf("  .area files:\n");
   printf("    First line:  <# of triangles>\n");
-  printf("    Following lines:  <triangle #> <maximum area>\n\n");
+  printf("    Following lines:  <triangle #> <maximum area>\n");
+  printf("\n");
   printf(
 "    An .area file associates with each triangle a maximum area that is used\n"
 );
   printf(
 "    for mesh refinement.  As with other file formats, every triangle must\n");
   printf(
-"    be represented, and they must be numbered consecutively.  A triangle\n");
+"    be represented, and the triangles must be numbered consecutively.  A\n");
   printf(
-"    may be left unconstrained by assigning it a negative maximum area.\n");
-  printf("\n");
+"    triangle may be left unconstrained by assigning it a negative maximum\n");
+  printf("    area.\n\n");
   printf("  .edge files:\n");
   printf("    First line:  <# of edges> <# of boundary markers (0 or 1)>\n");
   printf(
@@ -2351,10 +2410,9 @@ void info()
   printf(
 "      boundary marker, then the edge is assigned the same marker.\n");
   printf(
-"    - Otherwise, if the edge occurs on a boundary of the triangulation\n");
+"    - Otherwise, if the edge lies on a boundary of the triangulation\n");
   printf(
-"      (including boundaries of holes), then the edge is assigned the marker\n"
-);
+"      (even the boundary of a hole), then the edge is assigned the marker\n");
   printf("      one (1).\n");
   printf("    - Otherwise, the edge is assigned the marker zero (0).\n");
   printf(
@@ -2366,13 +2424,12 @@ void info()
   printf(
 "      then it is assigned the same marker in the output .node file.\n");
   printf(
-"    - Otherwise, if the vertex lies on a PSLG segment (including the\n");
+"    - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
   printf(
-"      segment's endpoints) with a nonzero boundary marker, then the vertex\n"
-);
+"      endpoint of the segment) with a nonzero boundary marker, then the\n");
   printf(
-"      is assigned the same marker.  If the vertex lies on several such\n");
-  printf("      segments, one of the markers is chosen arbitrarily.\n");
+"      vertex is assigned the same marker.  If the vertex lies on several\n");
+  printf("      such segments, one of the markers is chosen arbitrarily.\n");
   printf(
 "    - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
   printf("      then the vertex is assigned the marker one (1).\n");
@@ -2386,7 +2443,7 @@ void info()
 );
   printf(
 "  all) in your input files.  In the output files, all boundary vertices,\n");
-  printf("  edges, and segments are assigned the value one.\n\n");
+  printf("  edges, and segments will be assigned the value one.\n\n");
   printf("Triangulation Iteration Numbers:\n\n");
   printf(
 "  Because Triangle can read and refine its own triangulations, input\n");
@@ -2419,7 +2476,9 @@ void info()
 );
   printf(
 "  being overwritten.  (If the input is a .poly file that contains its own\n");
-  printf("  points, a .node file is written.)\n\n");
+  printf(
+"  points, a .node file is written.  This can be quite convenient for\n");
+  printf("  computing CDTs or quality meshes.)\n\n");
   printf("Examples of How to Use Triangle:\n\n");
   printf(
 "  `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
@@ -2446,9 +2505,10 @@ void info()
 "  `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
 );
   printf(
-"  object.node), generates a mesh whose angles are all 31.5 degrees or\n");
+"  object.node), generates a mesh whose angles are all between 31.5 and 117\n"
+);
   printf(
-"  greater and whose triangles all have areas of 0.1 or less, and writes the\n"
+"  degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
 );
   printf(
 "  mesh to object.1.node and object.1.ele.  Each segment may be broken up\n");
@@ -2485,7 +2545,7 @@ void info()
   printf("     1   1.5 1.5\n");
   printf("\n");
   printf(
-"  Note that some segments are missing from the outer square, so one must\n");
+"  Note that some segments are missing from the outer square, so you must\n");
   printf(
 "  use the `-c' switch.  After `triangle -pqc box.poly', here is the output\n"
 );
@@ -2533,10 +2593,9 @@ void info()
 "  Here is the output file `box.1.poly'.  Note that segments have been added\n"
 );
   printf(
-"  to represent the convex hull, and some segments have been split by newly\n"
-);
+"  to represent the convex hull, and some segments have been subdivided by\n");
   printf(
-"  added vertices.  Note also that <# of vertices> is set to zero to\n");
+"  newly added vertices.  Note also that <# of vertices> is set to zero to\n");
   printf("  indicate that the vertices should be read from the .node file.\n");
   printf("\n");
   printf("    0  2  0  1\n");
@@ -2567,26 +2626,32 @@ void info()
   printf(
 "  specify edges that are constrained and cannot be eliminated (although\n");
   printf(
-"  they can be divided into smaller edges) by the refinement process.\n");
+"  they can be subdivided into smaller edges) by the refinement process.\n");
   printf("\n");
   printf(
-"  When you refine a mesh, you generally want to impose tighter quality\n");
+"  When you refine a mesh, you generally want to impose tighter constraints.\n"
+);
   printf(
-"  constraints.  One way to accomplish this is to use -q with a larger\n");
+"  One way to accomplish this is to use -q with a larger angle, or -a\n");
   printf(
-"  angle, or -a followed by a smaller area than you used to generate the\n");
+"  followed by a smaller area than you used to generate the mesh you are\n");
   printf(
-"  mesh you are refining.  Another way to do this is to create an .area\n");
+"  refining.  Another way to do this is to create an .area file, which\n");
   printf(
-"  file, which specifies a maximum area for each triangle, and use the -a\n");
+"  specifies a maximum area for each triangle, and use the -a switch\n");
   printf(
-"  switch (without a number following).  Each triangle's area constraint is\n"
+"  (without a number following).  Each triangle's area constraint is applied\n"
 );
   printf(
-"  applied to that triangle.  Area constraints tend to diffuse as the mesh\n");
+"  to that triangle.  Area constraints tend to diffuse as the mesh is\n");
+  printf(
+"  refined, so if there are large variations in area constraint between\n");
+  printf(
+"  adjacent triangles, you may not get the results you want.  In that case,\n"
+);
   printf(
-"  is refined, so if there are large variations in area constraint between\n");
-  printf("  adjacent triangles, you may not get the results you want.\n\n");
+"  consider instead using the -u switch and writing a C procedure that\n");
+  printf("  determines which triangles are too large.\n\n");
   printf(
 "  If you are refining a mesh composed of linear (three-node) elements, the\n"
 );
@@ -2598,20 +2663,21 @@ void info()
   printf(
 "  refinement is not hierarchical: there is no guarantee that each output\n");
   printf(
-"  element is contained in a single input element.  Often, output elements\n");
-  printf(
-"  overlap two input elements, and some input edges are not present in the\n");
+"  element is contained in a single input element.  Often, an output element\n"
+);
   printf(
-"  output mesh.  Hence, a sequence of refined meshes forms a hierarchy of\n");
+"  can overlap two or three input elements, and some input edges are not\n");
   printf(
-"  nodes, but not a hierarchy of elements.  If you refine a mesh of higher-\n"
+"  present in the output mesh.  Hence, a sequence of refined meshes forms a\n"
 );
   printf(
-"  order elements, the hierarchical property applies only to the nodes at\n");
+"  hierarchy of nodes, but not a hierarchy of elements.  If you refine a\n");
   printf(
-"  the corners of an element; other nodes may not be present in the refined\n"
+"  mesh of higher-order elements, the hierarchical property applies only to\n"
 );
-  printf("  mesh.\n\n");
+  printf(
+"  the nodes at the corners of an element; the midpoint nodes on each edge\n");
+  printf("  are discarded before the mesh is refined.\n\n");
   printf(
 "  Maximum area constraints in .poly files operate differently from those in\n"
 );
@@ -2658,16 +2724,12 @@ void info()
   printf("  suitable for multigrid.\n\n");
   printf("Convex Hulls and Mesh Boundaries:\n\n");
   printf(
-"  If the input is a vertex set (rather than a PSLG), Triangle produces its\n"
-);
-  printf(
-"  convex hull as a by-product in the output .poly file if you use the -c\n");
+"  If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
   printf(
-"  switch.  There are faster algorithms for finding a two-dimensional convex\n"
-);
+"  hull as a by-product in the output .poly file if you use the -c switch.\n");
   printf(
-"  hull than triangulation, of course, but this one comes for free.\n");
-  printf("\n");
+"  There are faster algorithms for finding a two-dimensional convex hull\n");
+  printf("  than triangulation, of course, but this one comes for free.\n\n");
   printf(
 "  If the input is an unconstrained mesh (you are using the -r switch but\n");
   printf(
@@ -2704,10 +2766,8 @@ void info()
   printf(
 "  Be forewarned that if the Delaunay triangulation is degenerate or\n");
   printf(
-"  near-degenerate, the Voronoi diagram may have duplicate vertices,\n");
-  printf(
-"  crossing edges, or infinite rays whose direction vector is zero.\n");
-  printf("\n");
+"  near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
+  printf("  crossing edges.\n\n");
   printf(
 "  The result is a valid Voronoi diagram only if Triangle's output is a true\n"
 );
@@ -2717,19 +2777,19 @@ void info()
 "  may contain crossing edges and other pathology) if the output is a CDT or\n"
 );
   printf(
-"  CCDT, or if it has holes or concavities.  If the triangulation is convex\n"
-);
+"  CCDT, or if it has holes or concavities.  If the triangulated domain is\n");
   printf(
-"  and has no holes, this can be fixed by using the -L switch to ensure a\n");
-  printf("  conforming Delaunay triangulation is constructed.\n\n");
+"  convex and has no holes, you can use -D switch to force Triangle to\n");
+  printf(
+"  construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
+  printf("  Voronoi diagram will be valid.\n\n");
   printf("Mesh Topology:\n\n");
   printf(
 "  You may wish to know which triangles are adjacent to a certain Delaunay\n");
   printf(
-"  edge in an .edge file, which Voronoi regions are adjacent to a certain\n");
+"  edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
   printf(
-"  Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n"
-);
+"  Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
   printf(
 "  each other.  All of this information can be found by cross-referencing\n");
   printf(
@@ -2742,8 +2802,7 @@ void info()
   printf(
 "  wise from the Voronoi edge.  Triangle j of an .ele file is the dual of\n");
   printf(
-"  vertex j of the corresponding .v.node file.  Voronoi region k is the dual\n"
-);
+"  vertex j of the corresponding .v.node file.  Voronoi cell k is the dual\n");
   printf("  of vertex k of the corresponding .node file.\n\n");
   printf(
 "  Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
@@ -2756,26 +2815,36 @@ void info()
 "  and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
 );
   printf(
-"  respectively.  To find the Voronoi regions adjacent to a Voronoi edge,\n");
-  printf(
-"  look at the endpoints of the corresponding Delaunay edge.  If the\n");
+"  respectively.  To find the Voronoi cells adjacent to a Voronoi edge, look\n"
+);
   printf(
-"  endpoints of a Delaunay edge are input vertices 7 and 12, then Voronoi\n");
+"  at the endpoints of the corresponding Delaunay edge.  If the endpoints of\n"
+);
   printf(
-"  regions 7 and 12 adjoin the right and left sides of the corresponding\n");
+"  a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
+);
   printf(
-"  Voronoi edge, respectively.  To find which Voronoi regions are adjacent\n");
-  printf("  to each other, just read the list of Delaunay edges.\n\n");
+"  adjoin the right and left sides of the corresponding Voronoi edge,\n");
   printf(
-"  Triangle does not write a list of Voronoi regions, but one can be\n");
+"  respectively.  To find which Voronoi cells are adjacent to each other,\n");
+  printf("  just read the list of Delaunay edges.\n\n");
   printf(
-"  reconstructed straightforwardly.  For instance, to find all the edges of\n"
+"  Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
 );
   printf(
-"  Voronoi region 1, search the output .edge file for every edge that has\n");
+"  but you can reconstructed it straightforwardly.  For instance, to find\n");
+  printf(
+"  all the edges of Voronoi cell 1, search the output .edge file for every\n");
+  printf(
+"  edge that has input vertex 1 as an endpoint.  The corresponding dual\n");
   printf(
-"  input vertex 1 as an endpoint.  The corresponding dual edges in the\n");
-  printf("  output .v.edge file form the boundary of Voronoi region 1.\n\n");
+"  edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
+  printf("\n");
+  printf(
+"  For each Voronoi vertex, the .neigh file gives a list of the three\n");
+  printf(
+"  Voronoi vertices attached to it.  You might find this more convenient\n");
+  printf("  than the .v.edge file.\n\n");
   printf("Quadratic Elements:\n\n");
   printf(
 "  Triangle generates meshes with subparametric quadratic elements if the\n");
@@ -2798,26 +2867,54 @@ void info()
   printf(
 "  and sixth nodes appearing opposite the first, second, and third corners\n");
   printf("  respectively.\n\n");
+  printf("Domains with Small Angles:\n\n");
+  printf(
+"  If two input segments adjoin each other at a small angle, clearly the -q\n"
+);
+  printf(
+"  switch cannot remove the small angle.  Moreover, Triangle may have no\n");
+  printf(
+"  choice but to generate additional triangles whose smallest angles are\n");
+  printf(
+"  smaller than the specified bound.  However, these triangles only appear\n");
+  printf(
+"  between input segments separated by small angles.  Moreover, if you\n");
+  printf(
+"  request a minimum angle of theta degrees, Triangle will generally produce\n"
+);
+  printf(
+"  no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
+);
+  printf("  the minimum angle.\n\n");
   printf("Statistics:\n\n");
   printf(
-"  After generating a mesh, Triangle prints a count of the number of\n");
+"  After generating a mesh, Triangle prints a count of entities in the\n");
   printf(
-"  vertices, triangles, edges, exterior boundary edges (including hole\n");
+"  output mesh, including the number of vertices, triangles, edges, exterior\n"
+);
   printf(
-"  boundaries), interior boundary edges, and segments in the output mesh.\n");
+"  boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
   printf(
-"  If you've forgotten the statistics for an existing mesh, run Triangle on\n"
+"  including hole boundaries), interior boundary edges (i.e. subsegments of\n"
 );
   printf(
-"  that mesh with the -rNEP switches to read the mesh and print the\n");
+"  input segments not on the boundary), and total subsegments.  If you've\n");
   printf(
-"  statistics without writing any files.  Use -rpNEP if you've got a .poly\n");
-  printf("  file for the mesh.\n\n");
+"  forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
+);
+  printf(
+"  with the -rNEP switches to read the mesh and print the statistics without\n"
+);
+  printf(
+"  writing any files.  Use -rpNEP if you've got a .poly file for the mesh.\n");
+  printf("\n");
   printf(
 "  The -V switch produces extended statistics, including a rough estimate\n");
   printf(
 "  of memory use, the number of calls to geometric predicates, and\n");
-  printf("  histograms of triangle aspect ratios and angles in the mesh.\n\n");
+  printf(
+"  histograms of the angles and the aspect ratios of the triangles in the\n");
+  printf("  mesh.\n\n");
   printf("Exact Arithmetic:\n\n");
   printf(
 "  Triangle uses adaptive exact arithmetic to perform what computational\n");
@@ -2843,14 +2940,13 @@ void info()
 "  correctness, so they are usually nearly as fast as their approximate\n");
   printf("  counterparts.\n\n");
   printf(
-"  Pentiums have extended precision floating-point registers.  These must be\n"
-);
+"  May CPUs, including Intel x86 processors, have extended precision\n");
   printf(
-"  reconfigured so their precision is reduced to memory precision.  Triangle\n"
+"  floating-point registers.  These must be reconfigured so their precision\n"
 );
   printf(
-"  does this if it is compiled correctly.  See the makefile for details.\n");
-  printf("\n");
+"  is reduced to memory precision.  Triangle does this if it is compiled\n");
+  printf("  correctly.  See the makefile for details.\n\n");
   printf(
 "  The exact tests can be disabled with the -X switch.  On most inputs, this\n"
 );
@@ -2879,7 +2975,7 @@ void info()
   printf(
 "  actually lead to an inverted triangle and an invalid triangulation.\n");
   printf(
-"  (This is one reason to compute your own intersection points in your .poly\n"
+"  (This is one reason to specify your own intersection points in your .poly\n"
 );
   printf(
 "  files.)  Similarly, exact arithmetic is not used to compute the vertices\n"
@@ -2939,7 +3035,7 @@ void info()
   printf(
 "    inside your vertex set, or even inside the densest part of your\n");
   printf(
-"    mesh.  If you're triangulating an object whose x coordinates all fall\n");
+"    mesh.  If you're triangulating an object whose x-coordinates all fall\n");
   printf(
 "    between 6247133 and 6247134, you're not leaving much floating-point\n");
   printf("    precision for Triangle to work with.\n\n");
@@ -2990,15 +3086,14 @@ void info()
   printf(
 "    vertex that you think lies on the convex hull might actually lie just\n");
   printf(
-"    inside the convex hull.  If so, an extremely thin triangle is formed by\n"
-);
+"    inside the convex hull.  If so, the vertex and the nearby convex hull\n");
   printf(
-"    the vertex and the convex hull edge beside it.  When Triangle tries to\n"
-);
+"    edge form an extremely thin triangle.  When Triangle tries to refine\n");
   printf(
-"    refine the mesh to enforce angle and area constraints, extremely tiny\n");
+"    the mesh to enforce angle and area constraints, Triangle might generate\n"
+);
   printf(
-"    triangles may be formed, or Triangle may fail because of insufficient\n");
+"    extremely tiny triangles, or it might fail because of insufficient\n");
   printf("    floating-point precision.\n\n");
   printf(
 "  `The numbering of the output vertices doesn't match the input vertices.'\n"
@@ -3026,6 +3121,19 @@ void info()
 );
   printf("    bug.\n\n");
   printf(
+"  `Triangle executes without incident, but when I look at the resulting\n");
+  printf("  Voronoi diagram, it has overlapping edges or other geometric\n");
+  printf("  inconsistencies.'\n");
+  printf("\n");
+  printf(
+"    If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
+);
+  printf(
+"    diagram if the domain you are triangulating is convex and free of\n");
+  printf(
+"    holes, and you use the -D switch to construct a conforming Delaunay\n");
+  printf("    triangulation (instead of a CDT or CCDT).\n\n");
+  printf(
 "  Strange things can happen if you've taken liberties with your PSLG.  Do\n");
   printf(
 "  you have a vertex lying in the middle of a segment?  Triangle sometimes\n");
@@ -3075,10 +3183,12 @@ void info()
 "  purpose is to check the validity of your input files, and do so more\n");
   printf(
 "  thoroughly than Triangle does.  Unlike Triangle, Show Me requires that\n");
-  printf("  you have the X Windows system.\n\n");
-  printf("Triangle on the Web:\n\n");
   printf(
-"  To see an illustrated, updated version of these instructions, check out\n");
+"  you have the X Windows system.  Sorry, Microsoft Windows users.\n");
+  printf("\n");
+  printf("Triangle on the Web:\n");
+  printf("\n");
+  printf("  To see an illustrated version of these instructions, check out\n");
   printf("\n");
   printf("    http://www.cs.cmu.edu/~quake/triangle.html\n");
   printf("\n");
@@ -3102,7 +3212,23 @@ void info()
   printf(
 "  If you use a mesh generated by Triangle in a publication, please include\n"
 );
-  printf("  an acknowledgment as well.\n\n");
+  printf(
+"  an acknowledgment as well.  And please spell Triangle with a capital `T'!\n"
+);
+  printf(
+"  If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
+  printf(
+"  ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
+  printf(
+"  Triangulator,'' in Applied Computational Geometry:  Towards Geometric\n");
+  printf(
+"  Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
+  printf(
+"  Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
+  printf(
+"  Berlin, May 1996.  (From the First ACM Workshop on Applied Computational\n"
+);
+  printf("  Geometry.)'\n\n");
   printf("Research credit:\n\n");
   printf(
 "  Of course, I can take credit for only a fraction of the ideas that made\n");
@@ -3112,18 +3238,22 @@ void info()
   printf(
 "  of many fine computational geometers and other researchers, including\n");
   printf(
-"  Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n");
+"  Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
+);
   printf(
-"  Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n");
+"  Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
   printf(
-"  Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n");
+"  Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
   printf(
-"  Isaac Saias, Bruce J. Schachter, Micha Sharir, Daniel D. Sleator, Jorge\n");
+"  Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
   printf(
-"  Stolfi, Robert E. Tarjan, Christopher J. Van Wyk, and Binhai Zhu.  See\n");
+"  Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
+);
+  printf("  Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
   printf(
-"  the comments at the beginning of the source code for references.\n");
-  exit(0);
+"  Walkington, and Binhai Zhu.  See the comments at the beginning of the\n");
+  printf("  source code for references.\n\n");
+  triexit(0);
 }
 
 #endif /* not TRILIBRARY */
@@ -3134,12 +3264,12 @@ void info()
 /*                                                                           */
 /*****************************************************************************/
 
-void internalerror(void)
+void internalerror()
 {
   printf("  Please report this bug to jrs@cs.berkeley.edu\n");
   printf("  Include the message above, your input data set, and the exact\n");
   printf("    command line you used to run Triangle.\n");
-  exit(1);
+  triexit(1);
 }
 
 /*****************************************************************************/
@@ -3182,7 +3312,7 @@ struct behavior *b;
   b->splitseg = 0;
   b->docheck = 0;
   b->nobisect = 0;
-  b->nolenses = 0;
+  b->conformdel = 0;
   b->steiner = -1;
   b->order = 1;
   b->minangle = 0.0;
@@ -3237,7 +3367,7 @@ struct behavior *b;
             b->maxarea = (REAL) strtod(workstring, (char **) NULL);
             if (b->maxarea <= 0.0) {
               printf("Error:  Maximum area must be greater than zero.\n");
-              exit(1);
+              triexit(1);
 	    }
 	  } else {
             b->vararea = 1;
@@ -3335,8 +3465,9 @@ struct behavior *b;
         if (argv[i][j] == 's') {
           b->splitseg = 1;
         }
-        if (argv[i][j] == 'L') {
-          b->nolenses = 1;
+        if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
+          b->quality = 1;
+          b->conformdel = 1;
         }
 #endif /* not CDT_ONLY */
         if (argv[i][j] == 'C') {
@@ -3389,11 +3520,16 @@ struct behavior *b;
 #endif /* not TRILIBRARY */
   b->usesegments = b->poly || b->refine || b->quality || b->convex;
   b->goodangle = cos(b->minangle * PI / 180.0);
+  if (b->goodangle == 1.0) {
+    b->offconstant = 0.0;
+  } else {
+    b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
+  }
   b->goodangle *= b->goodangle;
   if (b->refine && b->noiterationnum) {
     printf(
       "Error:  You cannot use the -I switch when refining a triangulation.\n");
-    exit(1);
+    triexit(1);
   }
   /* Be careful not to allocate space for element area constraints that */
   /*   will never be assigned any value (other than the default -1.0).  */
@@ -3665,20 +3801,35 @@ struct osub *s;
            3 - s->ssorient, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
 
-  decode(s->ss[4], printtri);
+  decode(s->ss[6], printtri);
   if (printtri.tri == m->dummytri) {
-    printf("    [4] = Outer space\n");
+    printf("    [6] = Outer space\n");
   } else {
-    printf("    [4] = x%lx  %d\n", (unsigned long) printtri.tri,
+    printf("    [6] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
-  decode(s->ss[5], printtri);
+  decode(s->ss[7], printtri);
   if (printtri.tri == m->dummytri) {
-    printf("    [5] = Outer space\n");
+    printf("    [7] = Outer space\n");
   } else {
-    printf("    [5] = x%lx  %d\n", (unsigned long) printtri.tri,
+    printf("    [7] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
+
+  segorg(*s, printvertex);
+  if (printvertex == (vertex) NULL)
+    printf("    Segment origin[%d] = NULL\n", 4 + s->ssorient);
+  else
+    printf("    Segment origin[%d] = x%lx  (%.12g, %.12g)\n",
+           4 + s->ssorient, (unsigned long) printvertex,
+           printvertex[0], printvertex[1]);
+  segdest(*s, printvertex);
+  if (printvertex == (vertex) NULL)
+    printf("    Segment dest  [%d] = NULL\n", 5 - s->ssorient);
+  else
+    printf("    Segment dest  [%d] = x%lx  (%.12g, %.12g)\n",
+           5 - s->ssorient, (unsigned long) printvertex,
+           printvertex[0], printvertex[1]);
 }
 
 /**                                                                         **/
@@ -3689,6 +3840,39 @@ struct osub *s;
 /**                                                                         **/
 /**                                                                         **/
 
+/*****************************************************************************/
+/*                                                                           */
+/*  poolzero()   Set all of a pool's fields to zero.                         */
+/*                                                                           */
+/*  This procedure should never be called on a pool that has any memory      */
+/*  allocated to it, as that memory would leak.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef ANSI_DECLARATORS
+void poolzero(struct memorypool *pool)
+#else /* not ANSI_DECLARATORS */
+void poolzero(pool)
+struct memorypool *pool;
+#endif /* not ANSI_DECLARATORS */
+
+{
+  pool->firstblock = (VOID **) NULL;
+  pool->nowblock = (VOID **) NULL;
+  pool->nextitem = (VOID *) NULL;
+  pool->deaditemstack = (VOID *) NULL;
+  pool->pathblock = (VOID **) NULL;
+  pool->pathitem = (VOID *) NULL;
+  pool->alignbytes = 0;
+  pool->itembytes = 0;
+  pool->itemsperblock = 0;
+  pool->itemsfirstblock = 0;
+  pool->items = 0;
+  pool->maxitems = 0;
+  pool->unallocateditems = 0;
+  pool->pathitemsleft = 0;
+}
+
 /*****************************************************************************/
 /*                                                                           */
 /*  poolrestart()   Deallocate all items in a pool.                          */
@@ -3721,7 +3905,7 @@ struct memorypool *pool;
     (alignptr + (unsigned long) pool->alignbytes -
      (alignptr % (unsigned long) pool->alignbytes));
   /* There are lots of unallocated items left in this block. */
-  pool->unallocateditems = pool->itemsperblock;
+  pool->unallocateditems = pool->itemsfirstblock;
   /* The stack of deallocated items is empty. */
   pool->deaditemstack = (VOID *) NULL;
 }
@@ -3747,45 +3931,41 @@ struct memorypool *pool;
 
 #ifdef ANSI_DECLARATORS
 void poolinit(struct memorypool *pool, int bytecount, int itemcount,
-              enum wordtype wtype, int alignment)
+              int firstitemcount, int alignment)
 #else /* not ANSI_DECLARATORS */
-void poolinit(pool, bytecount, itemcount, wtype, alignment)
+void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
 struct memorypool *pool;
 int bytecount;
 int itemcount;
-enum wordtype wtype;
+int firstitemcount;
 int alignment;
 #endif /* not ANSI_DECLARATORS */
 
 {
-  int wordsize;
-
-  /* Initialize values in the pool. */
-  pool->itemwordtype = wtype;
-  wordsize = (pool->itemwordtype == POINTER) ? sizeof(VOID *) : sizeof(REAL);
   /* Find the proper alignment, which must be at least as large as:   */
   /*   - The parameter `alignment'.                                   */
-  /*   - The primary word type, to avoid unaligned accesses.          */
   /*   - sizeof(VOID *), so the stack of dead items can be maintained */
   /*       without unaligned accesses.                                */
-  if (alignment > wordsize) {
+  if (alignment > sizeof(VOID *)) {
     pool->alignbytes = alignment;
   } else {
-    pool->alignbytes = wordsize;
-  }
-  if (sizeof(VOID *) > pool->alignbytes) {
     pool->alignbytes = sizeof(VOID *);
   }
-  pool->itemwords = ((bytecount + pool->alignbytes - 1) / pool->alignbytes)
-                  * (pool->alignbytes / wordsize);
-  pool->itembytes = pool->itemwords * wordsize;
+  pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
+                    pool->alignbytes;
   pool->itemsperblock = itemcount;
+  if (firstitemcount == 0) {
+    pool->itemsfirstblock = itemcount;
+  } else {
+    pool->itemsfirstblock = firstitemcount;
+  }
 
-  /* Allocate a block of items.  Space for `itemsperblock' items and one    */
+  /* Allocate a block of items.  Space for `itemsfirstblock' items and one  */
   /*   pointer (to point to the next block) are allocated, as well as space */
   /*   to ensure alignment of the items.                                    */
-  pool->firstblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes
-                                         + sizeof(VOID *) + pool->alignbytes);
+  pool->firstblock = (VOID **)
+    trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
+              pool->alignbytes);
   /* Set the next block pointer to NULL. */
   *(pool->firstblock) = (VOID *) NULL;
   poolrestart(pool);
@@ -3842,11 +4022,13 @@ struct memorypool *pool;
       if (*(pool->nowblock) == (VOID *) NULL) {
         /* Allocate a new block of items, pointed to by the previous block. */
         newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
-                                       sizeof(VOID *) + pool->alignbytes);
+                                       (int) sizeof(VOID *) +
+                                       pool->alignbytes);
         *(pool->nowblock) = (VOID *) newblock;
         /* The next block pointer is NULL. */
         *newblock = (VOID *) NULL;
       }
+
       /* Move to the new block. */
       pool->nowblock = (VOID **) *(pool->nowblock);
       /* Find the first item in the block.    */
@@ -3859,14 +4041,11 @@ struct memorypool *pool;
       /* There are lots of unallocated items left in this block. */
       pool->unallocateditems = pool->itemsperblock;
     }
+
     /* Allocate a new item. */
     newitem = pool->nextitem;
     /* Advance `nextitem' pointer to next free item in block. */
-    if (pool->itemwordtype == POINTER) {
-      pool->nextitem = (VOID *) ((VOID **) pool->nextitem + pool->itemwords);
-    } else {
-      pool->nextitem = (VOID *) ((REAL *) pool->nextitem + pool->itemwords);
-    }
+    pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
     pool->unallocateditems--;
     pool->maxitems++;
   }
@@ -3924,7 +4103,7 @@ struct memorypool *pool;
     (alignptr + (unsigned long) pool->alignbytes -
      (alignptr % (unsigned long) pool->alignbytes));
   /* Set the number of items left in the current block. */
-  pool->pathitemsleft = pool->itemsperblock;
+  pool->pathitemsleft = pool->itemsfirstblock;
 }
 
 /*****************************************************************************/
@@ -3956,6 +4135,7 @@ struct memorypool *pool;
   if (pool->pathitem == pool->nextitem) {
     return (VOID *) NULL;
   }
+
   /* Check whether any untraversed items remain in the current block. */
   if (pool->pathitemsleft == 0) {
     /* Find the next block. */
@@ -3969,13 +4149,10 @@ struct memorypool *pool;
     /* Set the number of items left in the current block. */
     pool->pathitemsleft = pool->itemsperblock;
   }
+
   newitem = pool->pathitem;
   /* Find the next item in the block. */
-  if (pool->itemwordtype == POINTER) {
-    pool->pathitem = (VOID *) ((VOID **) pool->pathitem + pool->itemwords);
-  } else {
-    pool->pathitem = (VOID *) ((REAL *) pool->pathitem + pool->itemwords);
-  }
+  pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
   pool->pathitemsleft--;
   return newitem;
 }
@@ -4009,21 +4186,21 @@ struct memorypool *pool;
 /*****************************************************************************/
 
 #ifdef ANSI_DECLARATORS
-void dummyinit(struct mesh *m, struct behavior *b, int trianglewords,
-               int subsegwords)
+void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
+               int subsegbytes)
 #else /* not ANSI_DECLARATORS */
-void dummyinit(m, b, trianglewords, subsegwords)
+void dummyinit(m, b, trianglebytes, subsegbytes)
 struct mesh *m;
 struct behavior *b;
-int trianglewords;
-int subsegwords;
+int trianglebytes;
+int subsegbytes;
 #endif /* not ANSI_DECLARATORS */
 
 {
   unsigned long alignptr;
 
   /* Set up `dummytri', the `triangle' that occupies "outer space." */
-  m->dummytribase = (triangle *) trimalloc(trianglewords * sizeof(triangle) +
+  m->dummytribase = (triangle *) trimalloc(trianglebytes +
                                            m->triangles.alignbytes);
   /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
   alignptr = (unsigned long) m->dummytribase;
@@ -4046,7 +4223,7 @@ int subsegwords;
     /* Set up `dummysub', the omnipresent subsegment pointed to by any */
     /*   triangle side or subsegment end that isn't attached to a real */
     /*   subsegment.                                                   */
-    m->dummysubbase = (subseg *) trimalloc(subsegwords * sizeof(subseg) +
+    m->dummysubbase = (subseg *) trimalloc(subsegbytes +
                                            m->subsegs.alignbytes);
     /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
     alignptr = (unsigned long) m->dummysubbase;
@@ -4059,14 +4236,16 @@ int subsegwords;
     /*   can legally be dereferenced.                                      */
     m->dummysub[0] = (subseg) m->dummysub;
     m->dummysub[1] = (subseg) m->dummysub;
-    /* Two NULL vertices. */
+    /* Four NULL vertices. */
     m->dummysub[2] = (subseg) NULL;
     m->dummysub[3] = (subseg) NULL;
+    m->dummysub[4] = (subseg) NULL;
+    m->dummysub[5] = (subseg) NULL;
     /* Initialize the two adjoining triangles to be "outer space." */
-    m->dummysub[4] = (subseg) m->dummytri;
-    m->dummysub[5] = (subseg) m->dummytri;
+    m->dummysub[6] = (subseg) m->dummytri;
+    m->dummysub[7] = (subseg) m->dummytri;
     /* Set the boundary marker to zero. */
-    * (int *) (m->dummysub + 6) = 0;
+    * (int *) (m->dummysub + 8) = 0;
 
     /* Initialize the three adjoining subsegments of `dummytri' to be */
     /*   the omnipresent subsegment.                                  */
@@ -4111,9 +4290,11 @@ struct behavior *b;
                          sizeof(triangle);
     vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
   }
+
   /* Initialize the pool of vertices. */
   poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
-           (sizeof(REAL) >= sizeof(triangle)) ? FLOATINGPOINT : POINTER, 0);
+           m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
+           sizeof(REAL));
 }
 
 /*****************************************************************************/
@@ -4168,20 +4349,23 @@ struct behavior *b;
       (trisize < 6 * sizeof(triangle) + sizeof(int))) {
     trisize = 6 * sizeof(triangle) + sizeof(int);
   }
+
   /* Having determined the memory size of a triangle, initialize the pool. */
-  poolinit(&m->triangles, trisize, TRIPERBLOCK, POINTER, 4);
+  poolinit(&m->triangles, trisize, TRIPERBLOCK,
+           (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
+           TRIPERBLOCK, 4);
 
   if (b->usesegments) {
-    /* Initialize the pool of subsegments.  Take into account all six */
-    /*   pointers and one boundary marker.                            */
-    poolinit(&m->subsegs, 6 * sizeof(triangle) + sizeof(int), SUBSEGPERBLOCK,
-             POINTER, 4);
+    /* Initialize the pool of subsegments.  Take into account all eight */
+    /*   pointers and one boundary marker.                              */
+    poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
+             SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
 
     /* Initialize the "outer space" triangle and omnipresent subsegment. */
-    dummyinit(m, b, m->triangles.itemwords, m->subsegs.itemwords);
+    dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
   } else {
     /* Initialize the "outer space" triangle. */
-    dummyinit(m, b, m->triangles.itemwords, 0);
+    dummyinit(m, b, m->triangles.itembytes, 0);
   }
 }
 
@@ -4342,7 +4526,7 @@ struct badsubseg *dyingseg;
 
 {
   /* Set subsegment's origin to NULL.  This makes it possible to detect dead */
-  /*   subsegments when traversing the list of all encroached subsegments.   */
+  /*   badsubsegs when traversing the list of all badsubsegs             .   */
   dyingseg->subsegorg = (vertex) NULL;
   pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
 }
@@ -4401,26 +4585,28 @@ int number;
 
 {
   VOID **getblock;
-  vertex foundvertex;
+  char *foundvertex;
   unsigned long alignptr;
   int current;
 
   getblock = m->vertices.firstblock;
   current = b->firstnumber;
+
   /* Find the right block. */
-  while (current + m->vertices.itemsperblock <= number) {
+  if (current + m->vertices.itemsfirstblock <= number) {
     getblock = (VOID **) *getblock;
-    current += m->vertices.itemsperblock;
+    current += m->vertices.itemsfirstblock;
+    while (current + m->vertices.itemsperblock <= number) {
+      getblock = (VOID **) *getblock;
+      current += m->vertices.itemsperblock;
+    }
   }
+
   /* Now find the right vertex. */
   alignptr = (unsigned long) (getblock + 1);
-  foundvertex = (vertex) (alignptr + (unsigned long) m->vertices.alignbytes -
+  foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
                           (alignptr % (unsigned long) m->vertices.alignbytes));
-  while (current < number) {
-    foundvertex += m->vertices.itemwords;
-    current++;
-  }
-  return foundvertex;
+  return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
 }
 
 /*****************************************************************************/
@@ -4528,12 +4714,14 @@ struct osub *newsubseg;
   /*   subsegment.                                                  */
   newsubseg->ss[0] = (subseg) m->dummysub;
   newsubseg->ss[1] = (subseg) m->dummysub;
-  /* Two NULL vertices. */
+  /* Four NULL vertices. */
   newsubseg->ss[2] = (subseg) NULL;
   newsubseg->ss[3] = (subseg) NULL;
+  newsubseg->ss[4] = (subseg) NULL;
+  newsubseg->ss[5] = (subseg) NULL;
   /* Initialize the two adjoining triangles to be "outer space." */
-  newsubseg->ss[4] = (subseg) m->dummytri;
-  newsubseg->ss[5] = (subseg) m->dummytri;
+  newsubseg->ss[6] = (subseg) m->dummytri;
+  newsubseg->ss[7] = (subseg) m->dummytri;
   /* Set the boundary marker to zero. */
   setmark(*newsubseg, 0);
 
@@ -4695,7 +4883,7 @@ struct osub *newsubseg;
 /*                                                                           */
 /*****************************************************************************/
 
-void exactinit(void)
+void exactinit()
 {
   REAL half;
   REAL check, lastcheck;
@@ -6328,9 +6516,10 @@ vertex pd;
 #ifdef ANSI_DECLARATORS
 void findcircumcenter(struct mesh *m, struct behavior *b,
                       vertex torg, vertex tdest, vertex tapex,
-                      vertex circumcenter, REAL *xi, REAL *eta, REAL *minedge)
+                      vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
 #else /* not ANSI_DECLARATORS */
-void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta, minedge)
+void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
+                      offcenter)
 struct mesh *m;
 struct behavior *b;
 vertex torg;
@@ -6339,14 +6528,14 @@ vertex tapex;
 vertex circumcenter;
 REAL *xi;
 REAL *eta;
-REAL *minedge;
+int offcenter;
 #endif /* not ANSI_DECLARATORS */
 
 {
   REAL xdo, ydo, xao, yao;
   REAL dodist, aodist, dadist;
   REAL denominator;
-  REAL dx, dy;
+  REAL dx, dy, dxoff, dyoff;
 
   m->circumcentercount++;
 
@@ -6369,26 +6558,63 @@ REAL *minedge;
     /* Don't count the above as an orientation test. */
     m->counterclockcount--;
   }
-  circumcenter[0] = torg[0] - (ydo * aodist - yao * dodist) * denominator;  
-  circumcenter[1] = torg[1] + (xdo * aodist - xao * dodist) * denominator;  
+  dx = (yao * dodist - ydo * aodist) * denominator;
+  dy = (xdo * aodist - xao * dodist) * denominator;
+
+  /* Find the (squared) length of the triangle's shortest edge.  This   */
+  /*   serves as a conservative estimate of the insertion radius of the */
+  /*   circumcenter's parent.  The estimate is used to ensure that      */
+  /*   the algorithm terminates even if very small angles appear in     */
+  /*   the input PSLG.                                                  */
+  if ((dodist < aodist) && (dodist < dadist)) {
+    if (offcenter && (b->offconstant > 0.0)) {
+      /* Find the position of the off-center, as described by Alper Ungor. */
+      dxoff = 0.5 * xdo - b->offconstant * ydo;
+      dyoff = 0.5 * ydo + b->offconstant * xdo;
+      /* If the off-center is closer to the origin than the */
+      /*   circumcenter, use the off-center instead.        */
+      if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
+        dx = dxoff;
+        dy = dyoff;
+      }
+    }
+  } else if (aodist < dadist) {
+    if (offcenter && (b->offconstant > 0.0)) {
+      dxoff = 0.5 * xao + b->offconstant * yao;
+      dyoff = 0.5 * yao - b->offconstant * xao;
+      /* If the off-center is closer to the origin than the */
+      /*   circumcenter, use the off-center instead.        */
+      if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
+        dx = dxoff;
+        dy = dyoff;
+      }
+    }
+  } else {
+    if (offcenter && (b->offconstant > 0.0)) {
+      dxoff = 0.5 * (tapex[0] - tdest[0]) -
+              b->offconstant * (tapex[1] - tdest[1]);
+      dyoff = 0.5 * (tapex[1] - tdest[1]) +
+              b->offconstant * (tapex[0] - tdest[0]);
+      /* If the off-center is closer to the destination than the */
+      /*   circumcenter, use the off-center instead.             */
+      if (dxoff * dxoff + dyoff * dyoff <
+          (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
+        dx = xdo + dxoff;
+        dy = ydo + dyoff;
+      }
+    }
+  }
+
+  circumcenter[0] = torg[0] + dx;
+  circumcenter[1] = torg[1] + dy;
 
   /* To interpolate vertex attributes for the new vertex inserted at */
   /*   the circumcenter, define a coordinate system with a xi-axis,  */
   /*   directed from the triangle's origin to its destination, and   */
   /*   an eta-axis, directed from its origin to its apex.            */
   /*   Calculate the xi and eta coordinates of the circumcenter.     */
-  dx = circumcenter[0] - torg[0];
-  dy = circumcenter[1] - torg[1];
-  *xi = (dx * yao - xao * dy) * (2.0 * denominator);
-  *eta = (xdo * dy - dx * ydo) * (2.0 * denominator);
-
-  /* Find the length of the triangle's shortest edge.  This serves as */
-  /*   a conservative estimate of the insertion radius of the         */
-  /*   circumcenter's parent.  The estimate is used to ensure that    */
-  /*   the algorithm terminates even if very small angles appear in   */
-  /*   the input PSLG.                                                */
-  *minedge = ((dodist < aodist) && (dodist < dadist)) ? dodist :
-             (aodist < dadist) ? aodist : dadist;
+  *xi = (yao * dx - xao * dy) * (2.0 * denominator);
+  *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
 }
 
 /**                                                                         **/
@@ -6409,12 +6635,15 @@ struct mesh *m;
 #endif /* not ANSI_DECLARATORS */
 
 {
-  m->vertices.maxitems = m->triangles.maxitems = m->subsegs.maxitems =
-    m->viri.maxitems = m->badsubsegs.maxitems = m->badtriangles.maxitems =
-    m->flipstackers.maxitems = m->splaynodes.maxitems = 0l;
-  m->vertices.itembytes = m->triangles.itembytes = m->subsegs.itembytes =
-    m->viri.itembytes = m->badsubsegs.itembytes = m->badtriangles.itembytes =
-    m->flipstackers.itembytes = m->splaynodes.itembytes = 0;
+  poolzero(&m->vertices);
+  poolzero(&m->triangles);
+  poolzero(&m->subsegs);
+  poolzero(&m->viri);
+  poolzero(&m->badsubsegs);
+  poolzero(&m->badtriangles);
+  poolzero(&m->flipstackers);
+  poolzero(&m->splaynodes);
+
   m->recenttri.tri = (triangle *) NULL; /* No triangle has been visited yet. */
   m->undeads = 0;                       /* No eliminated input vertices yet. */
   m->samples = 1;         /* Point location should take at least one sample. */
@@ -6662,9 +6891,9 @@ struct behavior *b;
 /*  enqueuebadtriang()   Add a bad triangle data structure to the end of a   */
 /*                       queue.                                              */
 /*                                                                           */
-/*  The queue is actually a set of 64 queues.  I use multiple queues to give */
-/*  priority to smaller angles.  I originally implemented a heap, but the    */
-/*  queues are faster by a larger margin than I'd suspected.                 */
+/*  The queue is actually a set of 4096 queues.  I use multiple queues to    */
+/*  give priority to smaller angles.  I originally implemented a heap, but   */
+/*  the queues are faster by a larger margin than I'd suspected.             */
 /*                                                                           */
 /*****************************************************************************/
 
@@ -6681,7 +6910,10 @@ struct badtriang *badtri;
 #endif /* not ANSI_DECLARATORS */
 
 {
+  REAL length, multiplier;
+  int exponent, expincrement;
   int queuenumber;
+  int posexponent;
   int i;
 
   if (b->verbose > 2) {
@@ -6691,15 +6923,42 @@ struct badtriang *badtri;
            badtri->triangdest[0], badtri->triangdest[1],
            badtri->triangapex[0], badtri->triangapex[1]);
   }
-  /* Determine the appropriate queue to put the bad triangle into. */
-  if (badtri->key > 0.6) {
-    queuenumber = (int) (160.0 * (badtri->key - 0.6));
-    if (queuenumber > 63) {
-      queuenumber = 63;
-    }
+
+  /* Determine the appropriate queue to put the bad triangle into.    */
+  /*   Recall that the key is the square of its shortest edge length. */
+  if (badtri->key >= 1.0) {
+    length = badtri->key;
+    posexponent = 1;
   } else {
-    /* It's not a bad angle; put the triangle in the lowest-priority queue. */
-    queuenumber = 0;
+    /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */
+    /*   fact and use the reciprocal of `badtri->key', which is > 1.0.   */
+    length = 1.0 / badtri->key;
+    posexponent = 0;
+  }
+  /* `length' is approximately 2.0 to what exponent?  The following code */
+  /*   determines the answer in time logarithmic in the exponent.        */
+  exponent = 0;
+  while (length > 2.0) {
+    /* Find an approximation by repeated squaring of two. */
+    expincrement = 1;
+    multiplier = 0.5;
+    while (length * multiplier * multiplier > 1.0) {
+      expincrement *= 2;
+      multiplier *= multiplier;
+    }
+    /* Reduce the value of `length', then iterate if necessary. */
+    exponent += expincrement;
+    length *= multiplier;
+  }
+  /* `length' is approximately squareroot(2.0) to what exponent? */
+  exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
+  /* `exponent' is now in the range 0...2047 for IEEE double precision.   */
+  /*   Choose a queue in the range 0...4095.  The shortest edges have the */
+  /*   highest priority (queue 4095).                                     */
+  if (posexponent) {
+    queuenumber = 2047 - exponent;
+  } else {
+    queuenumber = 2048 + exponent;
   }
 
   /* Are we inserting into an empty queue? */
@@ -6748,13 +7007,13 @@ struct badtriang *badtri;
 
 #ifdef ANSI_DECLARATORS
 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
-                   REAL angle, vertex enqapex, vertex enqorg, vertex enqdest)
+                   REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
 #else /* not ANSI_DECLARATORS */
-void enqueuebadtri(m, b, enqtri, angle, enqapex, enqorg, enqdest)
+void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
 struct mesh *m;
 struct behavior *b;
 struct otri *enqtri;
-REAL angle;
+REAL minedge;
 vertex enqapex;
 vertex enqorg;
 vertex enqdest;
@@ -6766,7 +7025,7 @@ vertex enqdest;
   /* Allocate space for the bad triangle. */
   newbad = (struct badtriang *) poolalloc(&m->badtriangles);
   newbad->poortri = encode(*enqtri);
-  newbad->key = angle;
+  newbad->key = minedge;
   newbad->triangapex = enqapex;
   newbad->triangorg = enqorg;
   newbad->triangdest = enqdest;
@@ -6811,302 +7070,24 @@ struct mesh *m;
 
 #endif /* not CDT_ONLY */
 
-/*****************************************************************************/
-/*                                                                           */
-/*  under60degrees()   Return 1 if the two incident input segments are       */
-/*                     separated by an angle less than 60 degrees;           */
-/*                     0 otherwise.                                          */
-/*                                                                           */
-/*  The two input segments MUST have the same origin.                        */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-int under60degrees(struct osub *sub1, struct osub *sub2) {
-  vertex segmentapex, v1, v2;
-  REAL dotprod;
-
-  sorg(*sub1, segmentapex);
-  sdest(*sub1, v1);
-  sdest(*sub2, v2);
-  dotprod = (v2[0] - segmentapex[0]) * (v1[0] - segmentapex[0]) +
-            (v2[1] - segmentapex[1]) * (v1[1] - segmentapex[1]);
-  return (dotprod > 0.0) &&
-         (4.0 * dotprod * dotprod >
-          ((v1[0] - segmentapex[0]) * (v1[0] - segmentapex[0]) +
-           (v1[1] - segmentapex[1]) * (v1[1] - segmentapex[1])) *
-          ((v2[0] - segmentapex[0]) * (v2[0] - segmentapex[0]) +
-           (v2[1] - segmentapex[1]) * (v2[1] - segmentapex[1])));
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  clockwiseseg()   Find the next segment clockwise from `thissub' having   */
-/*                   the same origin and return it as `nextsub' if the       */
-/*                   intervening region is inside the domain.                */
-/*                                                                           */
-/*  Returns 1 if the next segment is separated from `thissub' by less than   */
-/*  60 degrees, and the intervening region is inside the domain.             */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-int clockwiseseg(struct mesh *m, struct osub *thissub, struct osub *nextsub) {
-  struct otri neighbortri;
-  triangle ptr;           /* Temporary variable used by sym() and stpivot(). */
-  subseg sptr;                      /* Temporary variable used by tspivot(). */
-
-  stpivot(*thissub, neighbortri);
-  if (neighbortri.tri == m->dummytri) {
-    return 0;
-  } else {
-    lnextself(neighbortri);
-    tspivot(neighbortri, *nextsub);
-    while (nextsub->ss == m->dummysub) {
-      symself(neighbortri);
-      lnextself(neighbortri);
-      tspivot(neighbortri, *nextsub);
-    }
-    ssymself(*nextsub);
-    return under60degrees(thissub, nextsub);
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  counterclockwiseseg()   Find the next segment counterclockwise from      */
-/*                          `thissub' having the same origin and return it   */
-/*                          as `nextsub' if the intervening region is inside */
-/*                          the domain.                                      */
-/*                                                                           */
-/*  Returns 1 if the next segment is separated from `thissub' by less than   */
-/*  60 degrees, and the intervening region is inside the domain.             */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-int counterclockwiseseg(struct mesh *m, struct osub *thissub,
-                        struct osub *nextsub) {
-  struct otri neighbortri;
-  struct osub subsym;
-  triangle ptr;           /* Temporary variable used by sym() and stpivot(). */
-  subseg sptr;                      /* Temporary variable used by tspivot(). */
-
-  ssym(*thissub, subsym);
-  stpivot(subsym, neighbortri);
-  if (neighbortri.tri == m->dummytri) {
-    return 0;
-  } else {
-    lprevself(neighbortri);
-    tspivot(neighbortri, *nextsub);
-    while (nextsub->ss == m->dummysub) {
-      symself(neighbortri);
-      lprevself(neighbortri);
-      tspivot(neighbortri, *nextsub);
-    }
-    return under60degrees(thissub, nextsub);
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-#ifndef CDT_ONLY
-
-/*****************************************************************************/
-/*                                                                           */
-/*  splitpermitted()   Return 1 if `testsubseg' is part of a subsegment      */
-/*                     cluster that is eligible for splitting.               */
-/*                                                                           */
-/*  The term "subsegment cluster" is formally defined in my paper "Mesh      */
-/*  Generation for Domains with Small Angles."  The algorithm that uses this */
-/*  procedure is also described there.                                       */
-/*                                                                           */
-/*  A subsegment cluster is eligible for splitting if (1) it includes a      */
-/*  subsegment whose length is not a power of two, (2) its subsegments are   */
-/*  not all the same length, or (3) no new edge that will be created by      */
-/*  splitting all the subsegments in the cluster has a length shorter than   */
-/*  the insertion radius of the encroaching vertex, whose square is given    */
-/*  as the parameter `iradius'.  Note that the shortest edges created by     */
-/*  splitting a cluster are those whose endpoints are both subsegment        */
-/*  midpoints introduced when the cluster is split.                          */
-/*                                                                           */
-/*  `testsubseg' is also eligible for splitting (and a 1 will be returned)   */
-/*  if it is part of two subsegment clusters; one at its origin and one at   */
-/*  its destination.                                                         */
-/*                                                                           */
-/*****************************************************************************/
-
-int splitpermitted(struct mesh *m, struct osub *testsubseg, REAL iradius) {
-  struct osub cwsubseg, ccwsubseg, cwsubseg2, ccwsubseg2;
-  struct osub testsym;
-  struct osub startsubseg, nowsubseg;
-  vertex suborg, dest1, dest2;
-  REAL nearestpoweroffour, seglength, prevseglength, edgelength;
-  int cwsmall, ccwsmall, cwsmall2, ccwsmall2;
-  int orgcluster, destcluster;
-  int toosmall;
-
-  /* Find the square of the subsegment's length, and the nearest power of */
-  /*   four (which is the square of the nearest power of two to the       */
-  /*   subsegment's length).                                              */
-  sorg(*testsubseg, suborg);
-  sdest(*testsubseg, dest1);
-  seglength = (dest1[0] - suborg[0]) * (dest1[0] - suborg[0]) +
-              (dest1[1] - suborg[1]) * (dest1[1] - suborg[1]);
-  nearestpoweroffour = 1.0;
-  while (seglength > 2.0 * nearestpoweroffour) {
-    nearestpoweroffour *= 4.0;
-  }
-  while (seglength < 0.5 * nearestpoweroffour) {
-    nearestpoweroffour *= 0.25;
-  }
-  /* If the segment's length is not a power of two, the segment */
-  /*   is eligible for splitting.                               */
-  if ((nearestpoweroffour > 1.001 * seglength) ||
-      (nearestpoweroffour < 0.999 * seglength)) {
-    return 1;
-  }
-
-  /* Is `testsubseg' part of a subsegment cluster at its origin? */
-  cwsmall = clockwiseseg(m, testsubseg, &cwsubseg);
-  ccwsmall = cwsmall ? 0 : counterclockwiseseg(m, testsubseg, &ccwsubseg);
-  orgcluster = cwsmall || ccwsmall;
-
-  /* Is `testsubseg' part of a subsegment cluster at its destination? */
-  ssym(*testsubseg, testsym);
-  cwsmall2 = clockwiseseg(m, &testsym, &cwsubseg2);
-  ccwsmall2 = cwsmall2 ? 0 : counterclockwiseseg(m, &testsym, &ccwsubseg2);
-  destcluster = cwsmall2 || ccwsmall2;
-
-  if (orgcluster == destcluster) {
-    /* `testsubseg' is part of two clusters or none, */
-    /*   and thus should be split.                   */
-    return 1;
-  } else if (orgcluster) {
-    /* `testsubseg' is part of a cluster at its origin. */
-    subsegcopy(*testsubseg, startsubseg);
-  } else {
-    /* `testsubseg' is part of a cluster at its destination; switch to */
-    /*   the symmetric case, so we can use the same code to handle it. */
-    subsegcopy(testsym, startsubseg);
-    subsegcopy(cwsubseg2, cwsubseg);
-    subsegcopy(ccwsubseg2, ccwsubseg);
-    cwsmall = cwsmall2;
-    ccwsmall = ccwsmall2;
-  }
-
-  toosmall = 0;
-  if (cwsmall) {
-    /* Check the subsegment(s) clockwise from `testsubseg'. */
-    subsegcopy(startsubseg, nowsubseg);
-    sorg(nowsubseg, suborg);
-    sdest(nowsubseg, dest1);
-    prevseglength = nearestpoweroffour;
-    do {
-      /* Is the next subsegment shorter than `startsubseg'? */
-      sdest(cwsubseg, dest2);
-      seglength = (dest2[0] - suborg[0]) * (dest2[0] - suborg[0]) +
-                  (dest2[1] - suborg[1]) * (dest2[1] - suborg[1]);
-      if (nearestpoweroffour > 1.001 * seglength) {
-        /* It's shorter; it's safe to split `startsubseg'. */
-        return 1;
-      }
-      /* If the current and previous subsegments are split to a length  */
-      /*   half that of `startsubseg' (which is a likely consequence if */
-      /*   `startsubseg' is split), what will be (the square of) the    */
-      /*   length of the free edge between the splitting vertices?      */
-      edgelength = 0.5 * nearestpoweroffour *
-                   (1 - (((dest1[0] - suborg[0]) * (dest2[0] - suborg[0]) +
-                          (dest1[1] - suborg[1]) * (dest2[1] - suborg[1])) /
-                         sqrt(prevseglength * seglength)));
-      if (edgelength < iradius) {
-        /* If this cluster is split, the new edge dest1-dest2 will be     */
-        /*   smaller than the insertion radius of the encroaching vertex. */
-        /*   Hence, we'd prefer to avoid splitting it if possible.        */
-        toosmall = 1;
-      }
-      if (cwsubseg.ss == startsubseg.ss) {
-        /* We've gone all the way around the vertex.  Split the cluster */
-        /*   if no edges will be too short.                             */
-        return !toosmall;
-      }
-
-      /* Find the next subsegment clockwise around the vertex. */
-      subsegcopy(cwsubseg, nowsubseg);
-      dest1 = dest2;
-      prevseglength = seglength;
-      cwsmall = clockwiseseg(m, &nowsubseg, &cwsubseg);
-    } while (cwsmall);
-
-    /* Prepare to start searching counterclockwise from */
-    /*   the starting subsegment.                       */
-    ccwsmall = counterclockwiseseg(m, &startsubseg, &ccwsubseg);
-  }
-
-  if (ccwsmall) {
-    /* Check the subsegment(s) counterclockwise from `testsubseg'. */
-    subsegcopy(startsubseg, nowsubseg);
-    sorg(nowsubseg, suborg);
-    sdest(nowsubseg, dest1);
-    prevseglength = nearestpoweroffour;
-    do {
-      /* Is the next subsegment shorter than `startsubseg'? */
-      sdest(ccwsubseg, dest2);
-      seglength = (dest2[0] - suborg[0]) * (dest2[0] - suborg[0]) +
-                  (dest2[1] - suborg[1]) * (dest2[1] - suborg[1]);
-      if (nearestpoweroffour > 1.001 * seglength) {
-        /* It's shorter; it's safe to split `startsubseg'. */
-        return 1;
-      }
-      /*   half that of `startsubseg' (which is a likely consequence if */
-      /*   `startsubseg' is split), what will be (the square of) the    */
-      /*   length of the free edge between the splitting vertices?      */
-      edgelength = 0.5 * nearestpoweroffour *
-                   (1 - (((dest1[0] - suborg[0]) * (dest2[0] - suborg[0]) +
-                          (dest1[1] - suborg[1]) * (dest2[1] - suborg[1])) /
-                         sqrt(prevseglength * seglength)));
-      if (edgelength < iradius) {
-        /* If this cluster is split, the new edge dest1-dest2 will be     */
-        /*   smaller than the insertion radius of the encroaching vertex. */
-        /*   Hence, we'd prefer to avoid splitting it if possible.        */
-        toosmall = 1;
-      }
-      if (ccwsubseg.ss == startsubseg.ss) {
-        /* We've gone all the way around the vertex.  Split the cluster */
-        /*   if no edges will be too short.                             */
-        return !toosmall;
-      }
-
-      /* Find the next subsegment counterclockwise around the vertex. */
-      subsegcopy(ccwsubseg, nowsubseg);
-      dest1 = dest2;
-      prevseglength = seglength;
-      ccwsmall = counterclockwiseseg(m, &nowsubseg, &ccwsubseg);
-    } while (ccwsmall);
-  }
-
-  /* We've found every subsegment in the cluster.  Split the cluster */
-  /*   if no edges will be too short.                                */
-  return !toosmall;
-}
-
-#endif /* not CDT_ONLY */
-
 /*****************************************************************************/
 /*                                                                           */
 /*  checkseg4encroach()   Check a subsegment to see if it is encroached; add */
 /*                        it to the list if it is.                           */
 /*                                                                           */
-/*  A subsegment is encroached if there is a vertex in its diametral circle  */
-/*  (that is, the subsegment faces an angle greater than 90 degrees).  This  */
-/*  definition is due to Ruppert.                                            */
+/*  A subsegment is encroached if there is a vertex in its diametral lens.   */
+/*  For Ruppert's algorithm (-D switch), the "diametral lens" is the         */
+/*  diametral circle.  For Chew's algorithm (default), the diametral lens is */
+/*  just big enough to enclose two isosceles triangles whose bases are the   */
+/*  subsegment.  Each of the two isosceles triangles has two angles equal    */
+/*  to `b->minangle'.                                                        */
+/*                                                                           */
+/*  Chew's algorithm does not require diametral lenses at all--but they save */
+/*  time.  Any vertex inside a subsegment's diametral lens implies that the  */
+/*  triangle adjoining the subsegment will be too skinny, so it's only a     */
+/*  matter of time before the encroaching vertex is deleted by Chew's        */
+/*  algorithm.  It's faster to simply not insert the doomed vertex in the    */
+/*  first place, which is why I use diametral lenses with Chew's algorithm.  */
 /*                                                                           */
 /*  Returns a nonzero value if the subsegment is encroached.                 */
 /*                                                                           */
@@ -7116,13 +7097,12 @@ int splitpermitted(struct mesh *m, struct osub *testsubseg, REAL iradius) {
 
 #ifdef ANSI_DECLARATORS
 int checkseg4encroach(struct mesh *m, struct behavior *b,
-                      struct osub *testsubseg, REAL iradius)
+                      struct osub *testsubseg)
 #else /* not ANSI_DECLARATORS */
-int checkseg4encroach(m, b, testsubseg, iradius)
+int checkseg4encroach(m, b, testsubseg)
 struct mesh *m;
 struct behavior *b;
 struct osub *testsubseg;
-REAL iradius;
 #endif /* not ANSI_DECLARATORS */
 
 {
@@ -7132,7 +7112,6 @@ REAL iradius;
   REAL dotproduct;
   int encroached;
   int sides;
-  int enq;
   vertex eorg, edest, eapex;
   triangle ptr;                     /* Temporary variable used by stpivot(). */
 
@@ -7149,19 +7128,20 @@ REAL iradius;
     /* Find a vertex opposite this subsegment. */
     apex(neighbortri, eapex);
     /* Check whether the apex is in the diametral lens of the subsegment */
-    /*   (or the diametral circle, if `nolenses' is set).  A dot product */
+    /*   (the diametral circle if `conformdel' is set).  A dot product   */
     /*   of two sides of the triangle is used to check whether the angle */
-    /*   at the apex is greater than 120 degrees (for lenses; 90 degrees */
-    /*   for diametral circles).                                         */
+    /*   at the apex is greater than (180 - 2 `minangle') degrees (for   */
+    /*   lenses; 90 degrees for diametral circles).                      */
     dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
                  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
     if (dotproduct < 0.0) {
-      if (b->nolenses ||
+      if (b->conformdel ||
           (dotproduct * dotproduct >=
-           0.25 * ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
-                   (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
-                  ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
-                   (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
+           (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
+           ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
+            (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
+           ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
+            (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
         encroached = 1;
       }
     }
@@ -7175,53 +7155,39 @@ REAL iradius;
     /* Find the other vertex opposite this subsegment. */
     apex(neighbortri, eapex);
     /* Check whether the apex is in the diametral lens of the subsegment */
-    /*   (or the diametral circle, if `nolenses' is set).                */
+    /*   (or the diametral circle, if `conformdel' is set).              */
     dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
                  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
     if (dotproduct < 0.0) {
-      if (b->nolenses ||
+      if (b->conformdel ||
           (dotproduct * dotproduct >=
-           0.25 * ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
-                   (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
-                  ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
-                   (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
+           (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
+           ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
+            (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
+           ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
+            (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
         encroached += 2;
       }
     }
   }
 
   if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
-    /* Decide whether `testsubseg' should be split. */
-    if (iradius > 0.0) {
-      /* The encroaching vertex is a triangle circumcenter, which will be   */
-      /*   rejected.  Hence, `testsubseg' probably should be split, unless  */
-      /*   it is part of a subsegment cluster which, according to the rules */
-      /*   described in my paper "Mesh Generation for Domains with Small    */
-      /*   Angles," should not be split.                                    */
-      enq = splitpermitted(m, testsubseg, iradius);
+    if (b->verbose > 2) {
+      printf(
+        "  Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
+        eorg[0], eorg[1], edest[0], edest[1]);
+    }
+    /* Add the subsegment to the list of encroached subsegments. */
+    /*   Be sure to get the orientation right.                   */
+    encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
+    if (encroached == 1) {
+      encroachedseg->encsubseg = sencode(*testsubseg);
+      encroachedseg->subsegorg = eorg;
+      encroachedseg->subsegdest = edest;
     } else {
-      /* The encroaching vertex is an input vertex or was inserted in a */
-      /*   subsegment, so the encroached subsegment must be split.      */
-      enq = 1;
-    }
-    if (enq) {
-      if (b->verbose > 2) {
-        printf(
-          "  Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
-          eorg[0], eorg[1], edest[0], edest[1]);
-      }
-      /* Add the subsegment to the list of encroached subsegments. */
-      /*   Be sure to get the orientation right.                   */
-      encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
-      if (encroached == 1) {
-        encroachedseg->encsubseg = sencode(*testsubseg);
-        encroachedseg->subsegorg = eorg;
-        encroachedseg->subsegdest = edest;
-      } else {
-        encroachedseg->encsubseg = sencode(testsym);
-        encroachedseg->subsegorg = edest;
-        encroachedseg->subsegdest = eorg;
-      }
+      encroachedseg->encsubseg = sencode(testsym);
+      encroachedseg->subsegorg = edest;
+      encroachedseg->subsegdest = eorg;
     }
   }
 
@@ -7232,7 +7198,7 @@ REAL iradius;
 
 /*****************************************************************************/
 /*                                                                           */
-/*  testtriangle()   Test a face for quality measures.                       */
+/*  testtriangle()   Test a triangle for quality and size.                   */
 /*                                                                           */
 /*  Tests a triangle to see if it satisfies the minimum angle condition and  */
 /*  the maximum area condition.  Triangles that aren't up to spec are added  */
@@ -7252,16 +7218,20 @@ struct otri *testtri;
 #endif /* not ANSI_DECLARATORS */
 
 {
-  struct otri sametesttri;
-  struct osub subseg1, subseg2;
+  struct otri tri1, tri2;
+  struct osub testsub;
   vertex torg, tdest, tapex;
-  vertex anglevertex;
+  vertex base1, base2;
+  vertex org1, dest1, org2, dest2;
+  vertex joinvertex;
   REAL dxod, dyod, dxda, dyda, dxao, dyao;
   REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
-  REAL apexlen, orglen, destlen;
+  REAL apexlen, orglen, destlen, minedge;
   REAL angle;
   REAL area;
+  REAL dist1, dist2;
   subseg sptr;                      /* Temporary variable used by tspivot(). */
+  triangle ptr;           /* Temporary variable used by oprev() and dnext(). */
 
   org(*testtri, torg);
   dest(*testtri, tdest);
@@ -7282,49 +7252,34 @@ struct otri *testtri;
   apexlen = dxod2 + dyod2;
   orglen = dxda2 + dyda2;
   destlen = dxao2 + dyao2;
+
   if ((apexlen < orglen) && (apexlen < destlen)) {
     /* The edge opposite the apex is shortest. */
+    minedge = apexlen;
     /* Find the square of the cosine of the angle at the apex. */
     angle = dxda * dxao + dyda * dyao;
     angle = angle * angle / (orglen * destlen);
-    anglevertex = tapex;
-    lnext(*testtri, sametesttri);
-    tspivot(sametesttri, subseg1);
-    lnextself(sametesttri);
-    tspivot(sametesttri, subseg2);
+    base1 = torg;
+    base2 = tdest;
+    otricopy(*testtri, tri1);
   } else if (orglen < destlen) {
     /* The edge opposite the origin is shortest. */
+    minedge = orglen;
     /* Find the square of the cosine of the angle at the origin. */
     angle = dxod * dxao + dyod * dyao;
     angle = angle * angle / (apexlen * destlen);
-    anglevertex = torg;
-    tspivot(*testtri, subseg1);
-    lprev(*testtri, sametesttri);
-    tspivot(sametesttri, subseg2);
+    base1 = tdest;
+    base2 = tapex;
+    lnext(*testtri, tri1);
   } else {
     /* The edge opposite the destination is shortest. */
+    minedge = destlen;
     /* Find the square of the cosine of the angle at the destination. */
     angle = dxod * dxda + dyod * dyda;
     angle = angle * angle / (apexlen * orglen);
-    anglevertex = tdest;
-    tspivot(*testtri, subseg1);
-    lnext(*testtri, sametesttri);
-    tspivot(sametesttri, subseg2);
-  }
-
-  /* Check if both edges that form the angle are segments. */
-  if ((subseg1.ss != m->dummysub) && (subseg2.ss != m->dummysub)) {
-    /* The angle is a segment intersection.  Don't add this bad triangle to */
-    /*   the list; there's nothing that can be done about a small angle     */
-    /*   between two segments.                                              */
-    angle = 0.0;
-  }
-
-  /* Check whether the angle is smaller than permitted. */
-  if (angle > b->goodangle) {
-    /* Add this triangle to the list of bad triangles. */
-    enqueuebadtri(m, b, testtri, angle, tapex, torg, tdest);
-    return;
+    base1 = tapex;
+    base2 = torg;
+    lprev(*testtri, tri1);
   }
 
   if (b->vararea || b->fixedarea || b->usertest) {
@@ -7332,7 +7287,7 @@ struct otri *testtri;
     area = 0.5 * (dxod * dyda - dyod * dxda);
     if (b->fixedarea && (area > b->maxarea)) {
       /* Add this triangle to the list of bad triangles. */
-      enqueuebadtri(m, b, testtri, angle, tapex, torg, tdest);
+      enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
       return;
     }
 
@@ -7340,18 +7295,79 @@ struct otri *testtri;
     if ((b->vararea) && (area > areabound(*testtri)) &&
         (areabound(*testtri) > 0.0)) {
       /* Add this triangle to the list of bad triangles. */
-      enqueuebadtri(m, b, testtri, angle, tapex, torg, tdest);
+      enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
       return;
     }
 
     if (b->usertest) {
       /* Check whether the user thinks this triangle is too large. */
       if (triunsuitable(torg, tdest, tapex, area)) {
-        enqueuebadtri(m, b, testtri, angle, tapex, torg, tdest);
+        enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
         return;
       }
     }
   }
+
+  /* Check whether the angle is smaller than permitted. */
+  if (angle > b->goodangle) {
+    /* Use the rules of Miller, Pav, and Walkington to decide that certain */
+    /*   triangles should not be split, even if they have bad angles.      */
+    /*   A skinny triangle is not split if its shortest edge subtends a    */
+    /*   small input angle, and both endpoints of the edge lie on a        */
+    /*   concentric circular shell.  For convenience, I make a small       */
+    /*   adjustment to that rule:  I check if the endpoints of the edge    */
+    /*   both lie in segment interiors, equidistant from the apex where    */
+    /*   the two segments meet.                                            */
+    /* First, check if both points lie in segment interiors.               */
+    if ((vertextype(base1) == SEGMENTVERTEX) &&
+        (vertextype(base2) == SEGMENTVERTEX)) {
+      /* Check if both points lie in a common segment.  If they do, the */
+      /*   skinny triangle is enqueued to be split as usual.            */
+      tspivot(tri1, testsub);
+      if (testsub.ss == m->dummysub) {
+        /* No common segment.  Find a subsegment that contains `torg'. */
+        otricopy(tri1, tri2);
+        do {
+          oprevself(tri1);
+          tspivot(tri1, testsub);
+        } while (testsub.ss == m->dummysub);
+        /* Find the endpoints of the containing segment. */
+        segorg(testsub, org1);
+        segdest(testsub, dest1);
+        /* Find a subsegment that contains `tdest'. */
+        do {
+          dnextself(tri2);
+          tspivot(tri2, testsub);
+        } while (testsub.ss == m->dummysub);
+        /* Find the endpoints of the containing segment. */
+        segorg(testsub, org2);
+        segdest(testsub, dest2);
+        /* Check if the two containing segments have an endpoint in common. */
+        joinvertex = (vertex) NULL;
+        if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
+          joinvertex = dest1;
+        } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
+          joinvertex = org1;
+        }
+        if (joinvertex != (vertex) NULL) {
+          /* Compute the distance from the common endpoint (of the two  */
+          /*   segments) to each of the endpoints of the shortest edge. */
+          dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
+                   (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
+          dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
+                   (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
+          /* If the two distances are equal, don't split the triangle. */
+          if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
+            /* Return now to avoid enqueueing the bad triangle. */
+            return;
+          }
+        }
+      }
+    }
+
+    /* Add this triangle to the list of bad triangles. */
+    enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
+  }
 }
 
 #endif /* not CDT_ONLY */
@@ -7630,15 +7646,14 @@ struct otri *searchtri;
 
 {
   VOID **sampleblock;
-  triangle *firsttri;
+  char *firsttri;
   struct otri sampletri;
   vertex torg, tdest;
   unsigned long alignptr;
   REAL searchdist, dist;
   REAL ahead;
-  long sampleblocks, samplesperblock, samplenum;
-  long triblocks;
-  long i, j;
+  long samplesperblock, totalsamplesleft, samplesleft;
+  long population, totalpopulation;
   triangle ptr;                         /* Temporary variable used by sym(). */
 
   if (b->verbose > 2) {
@@ -7679,29 +7694,44 @@ struct otri *searchtri;
 
   /* The number of random samples taken is proportional to the cube root of */
   /*   the number of triangles in the mesh.  The next bit of code assumes   */
-  /*   that the number of triangles increases monotonically.                */
+  /*   that the number of triangles increases monotonically (or at least    */
+  /*   doesn't decrease enough to matter).                                  */
   while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
          m->triangles.items) {
     m->samples++;
   }
-  triblocks = (m->triangles.maxitems + TRIPERBLOCK - 1) / TRIPERBLOCK;
-  samplesperblock = (m->samples + triblocks - 1) / triblocks;
-  sampleblocks = m->samples / samplesperblock;
+
+  /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples  */
+  /*   from each block of triangles (except the first)--until we meet the */
+  /*   sample quota.  The ceiling means that blocks at the end might be   */
+  /*   neglected, but I don't care.                                       */
+  samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
+  /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples */
+  /*   from the first block of triangles.                                    */
+  samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
+                m->triangles.maxitems + 1;
+  totalsamplesleft = m->samples;
+  population = m->triangles.itemsfirstblock;
+  totalpopulation = m->triangles.maxitems;
   sampleblock = m->triangles.firstblock;
   sampletri.orient = 0;
-  for (i = 0; i < sampleblocks; i++) {
+  while (totalsamplesleft > 0) {
+    /* If we're in the last block, `population' needs to be corrected. */
+    if (population > totalpopulation) {
+      population = totalpopulation;
+    }
+    /* Find a pointer to the first triangle in the block. */
     alignptr = (unsigned long) (sampleblock + 1);
-    firsttri = (triangle *) (alignptr + (unsigned long) m->triangles.alignbytes
-                      - (alignptr % (unsigned long) m->triangles.alignbytes));
-    for (j = 0; j < samplesperblock; j++) {
-      if (i == triblocks - 1) {
-        samplenum = randomnation((int)
-                                 (m->triangles.maxitems - (i * TRIPERBLOCK)));
-      } else {
-        samplenum = randomnation(TRIPERBLOCK);
-      }
-      sampletri.tri = (triangle *)
-                      (firsttri + (samplenum * m->triangles.itemwords));
+    firsttri = (char *) (alignptr +
+                         (unsigned long) m->triangles.alignbytes -
+                         (alignptr %
+                          (unsigned long) m->triangles.alignbytes));
+
+    /* Choose `samplesleft' randomly sampled triangles in this block. */
+    do {
+      sampletri.tri = (triangle *) (firsttri +
+                                    (randomnation((unsigned int) population) *
+                                     m->triangles.itembytes));
       if (!deadtri(sampletri.tri)) {
         org(sampletri, torg);
         dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
@@ -7715,8 +7745,17 @@ struct otri *searchtri;
           }
         }
       }
+
+      samplesleft--;
+      totalsamplesleft--;
+    } while ((samplesleft > 0) && (totalsamplesleft > 0));
+
+    if (totalsamplesleft > 0) {
+      sampleblock = (VOID **) *sampleblock;
+      samplesleft = samplesperblock;
+      totalpopulation -= population;
+      population = TRIPERBLOCK;
     }
-    sampleblock = (VOID **) *sampleblock;
   }
 
   /* Where are we? */
@@ -7799,6 +7838,8 @@ int subsegmark;                            /* Marker for the new subsegment. */
     makesubseg(m, &newsubseg);
     setsorg(newsubseg, tridest);
     setsdest(newsubseg, triorg);
+    setsegorg(newsubseg, tridest);
+    setsegdest(newsubseg, triorg);
     /* Bond new subsegment to the two triangles it is sandwiched between. */
     /*   Note that the facing triangle `oppotri' might be equal to        */
     /*   `dummytri' (outer space), but the new subsegment is bonded to it */
@@ -8155,11 +8196,10 @@ struct otri *flipedge;                    /* Handle for the triangle abc. */
 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
                                      vertex newvertex, struct otri *searchtri,
                                      struct osub *splitseg,
-                                     int segmentflaws, int triflaws,
-                                     REAL iradius)
+                                     int segmentflaws, int triflaws)
 #else /* not ANSI_DECLARATORS */
 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
-                                     segmentflaws, triflaws, iradius)
+                                     segmentflaws, triflaws)
 struct mesh *m;
 struct behavior *b;
 vertex newvertex;
@@ -8167,7 +8207,6 @@ struct otri *searchtri;
 struct osub *splitseg;
 int segmentflaws;
 int triflaws;
-REAL iradius;
 #endif /* not ANSI_DECLARATORS */
 
 {
@@ -8190,6 +8229,7 @@ REAL iradius;
   struct flipstacker *newflip;
   vertex first;
   vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
+  vertex segmentorg, segmentdest;
   REAL attrib;
   REAL area;
   enum insertvertexresult success;
@@ -8226,6 +8266,7 @@ REAL iradius;
     otricopy(*searchtri, horiz);
     intersect = ONEDGE;
   }
+
   if (intersect == ONVERTEX) {
     /* There's already a vertex there.  Return in `searchtri' a triangle */
     /*   whose origin is the existing vertex.                            */
@@ -8241,15 +8282,7 @@ REAL iradius;
       if (brokensubseg.ss != m->dummysub) {
         /* The vertex falls on a subsegment, and hence will not be inserted. */
         if (segmentflaws) {
-          if (b->nobisect == 2) {
-            enq = 0;
-#ifndef CDT_ONLY
-          } else if (iradius > 0.0) {
-            enq = splitpermitted(m, &brokensubseg, iradius);
-#endif /* not CDT_ONLY */
-          } else {
-            enq = 1;
-          }
+          enq = b->nobisect != 2;
           if (enq && (b->nobisect == 1)) {
             /* This subsegment may be split only if it is an */
             /*   internal boundary.                          */
@@ -8360,10 +8393,14 @@ REAL iradius;
     if (splitseg != (struct osub *) NULL) {
       /* Split the subsegment into two. */
       setsdest(*splitseg, newvertex);
+      segorg(*splitseg, segmentorg);
+      segdest(*splitseg, segmentdest);
       ssymself(*splitseg);
       spivot(*splitseg, rightsubseg);
       insertsubseg(m, b, &newbotright, mark(*splitseg));
       tspivot(newbotright, newsubseg);
+      setsegorg(newsubseg, segmentorg);
+      setsegdest(newsubseg, segmentdest);
       sbond(*splitseg, newsubseg);
       ssymself(newsubseg);
       sbond(newsubseg, rightsubseg);
@@ -8549,7 +8586,7 @@ REAL iradius;
 #ifndef CDT_ONLY
         if (segmentflaws) {
           /* Does the new vertex encroach upon this subsegment? */
-          if (checkseg4encroach(m, b, &checksubseg, iradius)) {
+          if (checkseg4encroach(m, b, &checksubseg)) {
             success = ENCROACHINGVERTEX;
           }
         }
@@ -9187,7 +9224,7 @@ int arraysize;
     return;
   }
   /* Choose a random pivot to split the array. */
-  pivot = (int) randomnation(arraysize);
+  pivot = (int) randomnation((unsigned int) arraysize);
   pivotx = sortarray[pivot][0];
   pivoty = sortarray[pivot][1];
   /* Split the array. */
@@ -9263,7 +9300,7 @@ int axis;
     return;
   }
   /* Choose a random pivot to split the array. */
-  pivot = (int) randomnation(arraysize);
+  pivot = (int) randomnation((unsigned int) arraysize);
   pivot1 = sortarray[pivot][axis];
   pivot2 = sortarray[pivot][1 - axis];
   /* Split the array. */
@@ -9950,7 +9987,7 @@ struct behavior *b;
   }
 
   /* Allocate an array of pointers to vertices for sorting. */
-  sortarray = (vertex *) trimalloc(m->invertices * sizeof(vertex));
+  sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
   traversalinit(&m->vertices);
   for (i = 0; i < m->invertices; i++) {
     sortarray[i] = vertextraverse(m);
@@ -10204,8 +10241,8 @@ struct behavior *b;
   vertexloop = vertextraverse(m);
   while (vertexloop != (vertex) NULL) {
     starttri.tri = m->dummytri;
-    if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0,
-                     0.0) == DUPLICATEVERTEX) {
+    if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
+        == DUPLICATEVERTEX) {
       if (!b->quiet) {
         printf(
 "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
@@ -10389,8 +10426,9 @@ struct event **freeevents;
   int i;
 
   maxevents = (3 * m->invertices) / 2;
-  *eventheap = (struct event **) trimalloc(maxevents * sizeof(struct event *));
-  *events = (struct event *) trimalloc(maxevents * sizeof(struct event));
+  *eventheap = (struct event **) trimalloc(maxevents *
+                                           (int) sizeof(struct event *));
+  *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
   traversalinit(&m->vertices);
   for (i = 0; i < m->invertices; i++) {
     thisvertex = vertextraverse(m);
@@ -10776,7 +10814,7 @@ struct behavior *b;
   triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
 
   poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
-           POINTER, 0);
+           SPLAYNODEPERBLOCK, 0);
   splayroot = (struct splaynode *) NULL;
 
   if (b->verbose) {
@@ -10805,7 +10843,7 @@ struct behavior *b;
   do {
     if (heapsize == 0) {
       printf("Error:  Input vertices are all identical.\n");
-      exit(1);
+      triexit(1);
     }
     secondvertex = (vertex) eventheap[0]->eventptr;
     eventheap[0]->eventptr = (VOID *) freeevents;
@@ -11114,6 +11152,7 @@ FILE *polyfile;
   vertex checkdest, checkapex;
   vertex shorg;
   vertex killvertex;
+  vertex segmentorg, segmentdest;
   REAL area;
   int corner[3];
   int end[2];
@@ -11133,7 +11172,7 @@ FILE *polyfile;
   incorners = corners;
   if (incorners < 3) {
     printf("Error:  Triangles must have at least 3 vertices.\n");
-    exit(1);
+    triexit(1);
   }
   m->eextras = attribs;
 #else /* not TRILIBRARY */
@@ -11144,7 +11183,7 @@ FILE *polyfile;
   elefile = fopen(elefilename, "r");
   if (elefile == (FILE *) NULL) {
     printf("  Error:  Cannot access file %s.\n", elefilename);
-    exit(1);
+    triexit(1);
   }
   /* Read number of triangles, number of vertices per triangle, and */
   /*   number of triangle attributes from .ele file.                */
@@ -11158,7 +11197,7 @@ FILE *polyfile;
     if (incorners < 3) {
       printf("Error:  Triangles in %s must have at least 3 vertices.\n",
              elefilename);
-      exit(1);
+      triexit(1);
     }
   }
   stringptr = findfield(stringptr);
@@ -11178,6 +11217,7 @@ FILE *polyfile;
     triangleloop.tri[3] = (triangle) triangleloop.tri;
   }
 
+  segmentmarkers = 0;
   if (b->poly) {
 #ifdef TRILIBRARY
     m->insegments = numberofsegments;
@@ -11188,9 +11228,7 @@ FILE *polyfile;
     stringptr = readline(inputline, polyfile, b->inpolyfilename);
     m->insegments = (int) strtol(stringptr, &stringptr, 0);
     stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      segmentmarkers = 0;
-    } else {
+    if (*stringptr != '\0') {
       segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
     }
 #endif /* not TRILIBRARY */
@@ -11215,14 +11253,14 @@ FILE *polyfile;
     areafile = fopen(areafilename, "r");
     if (areafile == (FILE *) NULL) {
       printf("  Error:  Cannot access file %s.\n", areafilename);
-      exit(1);
+      triexit(1);
     }
     stringptr = readline(inputline, areafile, areafilename);
     areaelements = (int) strtol(stringptr, &stringptr, 0);
     if (areaelements != m->inelements) {
       printf("Error:  %s and %s disagree on number of triangles.\n",
              elefilename, areafilename);
-      exit(1);
+      triexit(1);
     }
   }
 #endif /* not TRILIBRARY */
@@ -11233,7 +11271,8 @@ FILE *polyfile;
   /* Allocate a temporary array that maps each vertex to some adjacent */
   /*   triangle.  I took care to allocate all the permanent memory for */
   /*   triangles and subsegments first.                                */
-  vertexarray = (triangle *) trimalloc(m->vertices.items * sizeof(triangle));
+  vertexarray = (triangle *) trimalloc(m->vertices.items *
+                                       (int) sizeof(triangle));
   /* Each vertex is initially unrepresented. */
   for (i = 0; i < m->vertices.items; i++) {
     vertexarray[i] = (triangle) m->dummytri;
@@ -11256,7 +11295,7 @@ FILE *polyfile;
           (corner[j] >= b->firstnumber + m->invertices)) {
         printf("Error:  Triangle %ld has an invalid vertex index.\n",
                elementnumber);
-        exit(1);
+        triexit(1);
       }
     }
 #else /* not TRILIBRARY */
@@ -11267,14 +11306,14 @@ FILE *polyfile;
       if (*stringptr == '\0') {
         printf("Error:  Triangle %ld is missing vertex %d in %s.\n",
                elementnumber, j + 1, elefilename);
-        exit(1);
+        triexit(1);
       } else {
         corner[j] = (int) strtol(stringptr, &stringptr, 0);
         if ((corner[j] < b->firstnumber) ||
             (corner[j] >= b->firstnumber + m->invertices)) {
           printf("Error:  Triangle %ld has an invalid vertex index.\n",
                  elementnumber);
-          exit(1);
+          triexit(1);
         }
       }
     }
@@ -11412,7 +11451,7 @@ FILE *polyfile;
       if (*stringptr == '\0') {
         printf("Error:  Segment %ld has no endpoints in %s.\n", segmentnumber,
                polyfilename);
-        exit(1);
+        triexit(1);
       } else {
         end[0] = (int) strtol(stringptr, &stringptr, 0);
       }
@@ -11420,7 +11459,7 @@ FILE *polyfile;
       if (*stringptr == '\0') {
         printf("Error:  Segment %ld is missing its second endpoint in %s.\n",
                segmentnumber, polyfilename);
-        exit(1);
+        triexit(1);
       } else {
         end[1] = (int) strtol(stringptr, &stringptr, 0);
       }
@@ -11438,14 +11477,18 @@ FILE *polyfile;
             (end[j] >= b->firstnumber + m->invertices)) {
           printf("Error:  Segment %ld has an invalid vertex index.\n", 
                  segmentnumber);
-          exit(1);
+          triexit(1);
         }
       }
 
       /* set the subsegment's vertices. */
       subsegloop.ssorient = 0;
-      setsorg(subsegloop, getvertex(m, b, end[0]));
-      setsdest(subsegloop, getvertex(m, b, end[1]));
+      segmentorg = getvertex(m, b, end[0]);
+      segmentdest = getvertex(m, b, end[1]);
+      setsorg(subsegloop, segmentorg);
+      setsdest(subsegloop, segmentdest);
+      setsegorg(subsegloop, segmentorg);
+      setsegdest(subsegloop, segmentdest);
       setmark(subsegloop, boundmarker);
       /* Try linking the subsegment to triangles that share these vertices. */
       for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
@@ -11655,6 +11698,7 @@ vertex endpoint2;
 #endif /* not ANSI_DECLARATORS */
 
 {
+  struct osub opposubseg;
   vertex endpoint1;
   vertex torg, tdest;
   vertex leftvertex, rightvertex;
@@ -11667,6 +11711,7 @@ vertex endpoint2;
   REAL split, denom;
   int i;
   triangle ptr;                       /* Temporary variable used by onext(). */
+  subseg sptr;                        /* Temporary variable used by snext(). */
 
   /* Find the other three segment endpoints. */
   apex(*splittri, endpoint1);
@@ -11700,15 +11745,32 @@ vertex endpoint2;
            torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
   }
   /* Insert the intersection vertex.  This should always succeed. */
-  success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0, 0.0);
+  success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
   if (success != SUCCESSFULVERTEX) {
     printf("Internal error in segmentintersection():\n");
     printf("  Failure to split a segment.\n");
     internalerror();
   }
+  /* Record a triangle whose origin is the new vertex. */
+  setvertex2tri(newvertex, encode(*splittri));
   if (m->steinerleft > 0) {
     m->steinerleft--;
   }
+
+  /* Divide the segment into two, and correct the segment endpoints. */
+  ssymself(*splitsubseg);
+  spivot(*splitsubseg, opposubseg);
+  sdissolve(*splitsubseg);
+  sdissolve(opposubseg);
+  do {
+    setsegorg(*splitsubseg, newvertex);
+    snextself(*splitsubseg);
+  } while (splitsubseg->ss != m->dummysub);
+  do {
+    setsegorg(opposubseg, newvertex);
+    snextself(opposubseg);
+  } while (opposubseg.ss != m->dummysub);
+
   /* Inserting the vertex may have caused edge flips.  We wish to rediscover */
   /*   the edge connecting endpoint1 to the new intersection vertex.         */
   collinear = finddirection(m, b, splittri, endpoint1);
@@ -11871,7 +11933,7 @@ int newmark;
   searchtri1.tri = m->dummytri;
   /* Attempt to insert the new vertex. */
   success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
-                         0, 0, 0.0);
+                         0, 0);
   if (success == DUPLICATEVERTEX) {
     if (b->verbose > 2) {
       printf("  Segment intersects existing vertex (%.12g, %.12g).\n",
@@ -11889,7 +11951,7 @@ int newmark;
       /* By fluke, we've landed right on another segment.  Split it. */
       tspivot(searchtri1, brokensubseg);
       success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
-                             0, 0, 0.0);
+                             0, 0);
       if (success != SUCCESSFULVERTEX) {
         printf("Internal error in conformingedge():\n");
         printf("  Failure to split a segment.\n");
@@ -12435,7 +12497,7 @@ char *polyfilename;
       if (*stringptr == '\0') {
         printf("Error:  Segment %d has no endpoints in %s.\n",
                b->firstnumber + i, polyfilename);
-        exit(1);
+        triexit(1);
       } else {
         end1 = (int) strtol(stringptr, &stringptr, 0);
       }
@@ -12443,7 +12505,7 @@ char *polyfilename;
       if (*stringptr == '\0') {
         printf("Error:  Segment %d is missing its second endpoint in %s.\n",
                b->firstnumber + i, polyfilename);
-        exit(1);
+        triexit(1);
       } else {
         end2 = (int) strtol(stringptr, &stringptr, 0);
       }
@@ -12469,6 +12531,7 @@ char *polyfilename;
                  b->firstnumber + i, polyfilename);
         }
       } else {
+        /* Find the vertices numbered `end1' and `end2'. */
         endpoint1 = getvertex(m, b, end1);
         endpoint2 = getvertex(m, b, end2);
         if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
@@ -12947,13 +13010,16 @@ int regions;
 
   if (regions > 0) {
     /* Allocate storage for the triangles in which region points fall. */
-    regiontris = (struct otri *) trimalloc(regions * sizeof(struct otri));
+    regiontris = (struct otri *) trimalloc(regions *
+                                           (int) sizeof(struct otri));
+  } else {
+    regiontris = (struct otri *) NULL;
   }
 
   if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
     /* Initialize a pool of viri to be used for holes, concavities, */
     /*   regional attributes, and/or regional area constraints.     */
-    poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, POINTER, 0);
+    poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
   }
 
   if (!b->convex) {
@@ -13122,7 +13188,7 @@ struct behavior *b;
   subsegloop.ss = subsegtraverse(m);
   while (subsegloop.ss != (subseg *) NULL) {
     /* If the segment is encroached, add it to the list. */
-    dummy = checkseg4encroach(m, b, &subsegloop, 0.0);
+    dummy = checkseg4encroach(m, b, &subsegloop);
     subsegloop.ss = subsegtraverse(m);
   }
 }
@@ -13233,10 +13299,10 @@ int triflaws;
         tspivot(testtri, testsh);
         acutedest = testsh.ss != m->dummysub;
 
-        /* If we're using diametral lenses (rather than diametral circles) */
-        /*   to define encroachment, delete free vertices from the         */
-        /*   subsegment's diametral circle.                                */
-        if (!b->nolenses && !acuteorg && !acutedest) {
+        /* If we're using Chew's algorithm (rather than Ruppert's) */
+        /*   to define encroachment, delete free vertices from the */
+        /*   subsegment's diametral circle.                        */
+        if (!b->conformdel && !acuteorg && !acutedest) {
           apex(enctri, eapex);
           while ((vertextype(eapex) == FREEVERTEX) &&
                  ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
@@ -13264,7 +13330,7 @@ int triflaws;
           acuteorg = acuteorg || acuteorg2;
 
           /* Delete free vertices from the subsegment's diametral circle. */
-          if (!b->nolenses && !acuteorg2 && !acutedest2) {
+          if (!b->conformdel && !acuteorg2 && !acutedest2) {
             org(testtri, eapex);
             while ((vertextype(eapex) == FREEVERTEX) &&
                    ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
@@ -13343,11 +13409,11 @@ int triflaws;
           printf("  can be accommodated by the finite precision of\n");
           printf("  floating point arithmetic.\n");
           precisionerror();
-          exit(1);
+          triexit(1);
         }
         /* Insert the splitting vertex.  This should always succeed. */
         success = insertvertex(m, b, newvertex, &enctri, &currentenc,
-                               1, triflaws, 0.0);
+                               1, triflaws);
         if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
           printf("Internal error in splitencsegs():\n");
           printf("  Failure to split a segment.\n");
@@ -13357,9 +13423,9 @@ int triflaws;
           m->steinerleft--;
         }
         /* Check the two new subsegments to see if they're encroached. */
-        dummy = checkseg4encroach(m, b, &currentenc, 0.0);
+        dummy = checkseg4encroach(m, b, &currentenc);
         snextself(currentenc);
-        dummy = checkseg4encroach(m, b, &currentenc, 0.0);
+        dummy = checkseg4encroach(m, b, &currentenc);
       }
 
       badsubsegdealloc(m, encloop);
@@ -13429,7 +13495,6 @@ struct badtriang *badtri;
   vertex borg, bdest, bapex;
   vertex newvertex;
   REAL xi, eta;
-  REAL minedge;
   enum insertvertexresult success;
   int errorflag;
   int i;
@@ -13452,7 +13517,7 @@ struct badtriang *badtri;
     errorflag = 0;
     /* Create a new vertex at the triangle's circumcenter. */
     newvertex = (vertex) poolalloc(&m->vertices);
-    findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, &minedge);
+    findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
 
     /* Check whether the new vertex lies on a triangle vertex. */
     if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
@@ -13460,7 +13525,7 @@ struct badtriang *badtri;
         ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
       if (!b->quiet) {
         printf(
-            "Warning:  New vertex (%.12g, %.12g) falls on existing vertex.\n",
+             "Warning:  New vertex (%.12g, %.12g) falls on existing vertex.\n",
                newvertex[0], newvertex[1]);
         errorflag = 1;
       }
@@ -13490,7 +13555,7 @@ struct badtriang *badtri;
       /* Insert the circumcenter, searching from the edge of the triangle, */
       /*   and maintain the Delaunay property of the triangulation.        */
       success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
-                             1, 1, minedge);
+                             1, 1);
       if (success == SUCCESSFULVERTEX) {
         if (m->steinerleft > 0) {
           m->steinerleft--;
@@ -13561,7 +13626,7 @@ struct behavior *b;
   }
   /* Initialize the pool of encroached subsegments. */
   poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
-           POINTER, 0);
+           BADSUBSEGPERBLOCK, 0);
   if (b->verbose) {
     printf("  Looking for encroached subsegments.\n");
   }
@@ -13579,9 +13644,9 @@ struct behavior *b;
   if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
     /* Initialize the pool of bad triangles. */
     poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
-             POINTER, 0);
+             BADTRIPERBLOCK, 0);
     /* Initialize the queues of bad triangles. */
-    for (i = 0; i < 64; i++) {
+    for (i = 0; i < 4096; i++) {
       m->queuefront[i] = (struct badtriang *) NULL;
     }
     m->firstnonemptyq = -1;
@@ -13589,7 +13654,7 @@ struct behavior *b;
     tallyfaces(m, b);
     /* Initialize the pool of recently flipped triangles. */
     poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
-             POINTER, 0);
+             FLIPSTACKERPERBLOCK, 0);
     m->checkquality = 1;
     if (b->verbose) {
       printf("  Splitting bad triangles.\n");
@@ -13610,15 +13675,17 @@ struct behavior *b;
       }
     }
   }
-  /* At this point, if we haven't run out of Steiner points, the */
-  /*   triangulation should be (conforming) Delaunay and have no */
-  /*   low-quality triangles.                                    */
+  /* At this point, if the "-D" switch was selected and we haven't run out  */
+  /*   of Steiner points, the triangulation should be (conforming) Delaunay */
+  /*   and have no low-quality triangles.                                   */
 
   /* Might we have run out of Steiner points too soon? */
-  if (!b->quiet && (m->badsubsegs.items > 0) && (m->steinerleft == 0)) {
+  if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
+      (m->steinerleft == 0)) {
     printf("\nWarning:  I ran out of Steiner points, but the mesh has\n");
     if (m->badsubsegs.items == 1) {
-      printf("  an encroached subsegment, and therefore might not be truly\n");
+      printf("  one encroached subsegment, and therefore might not be truly\n"
+             );
     } else {
       printf("  %ld encroached subsegments, and therefore might not be truly\n"
              , m->badsubsegs.items);
@@ -13749,7 +13816,7 @@ char *infilename;
     result = fgets(string, INPUTLINESIZE, infile);
     if (result == (char *) NULL) {
       printf("  Error:  Unexpected end of file in %s.\n", infilename);
-      exit(1);
+      triexit(1);
     }
     /* Skip anything that doesn't look like a number, a comment, */
     /*   or the end of a line.                                   */
@@ -13849,7 +13916,7 @@ FILE **polyfile;
     *polyfile = fopen(polyfilename, "r");
     if (*polyfile == (FILE *) NULL) {
       printf("  Error:  Cannot access file %s.\n", polyfilename);
-      exit(1);
+      triexit(1);
     }
     /* Read number of vertices, number of dimensions, number of vertex */
     /*   attributes, and number of boundary markers.                   */
@@ -13897,7 +13964,7 @@ FILE **polyfile;
     infile = fopen(nodefilename, "r");
     if (infile == (FILE *) NULL) {
       printf("  Error:  Cannot access file %s.\n", nodefilename);
-      exit(1);
+      triexit(1);
     }
     /* Read number of vertices, number of dimensions, number of vertex */
     /*   attributes, and number of boundary markers.                   */
@@ -13925,11 +13992,11 @@ FILE **polyfile;
 
   if (m->invertices < 3) {
     printf("Error:  Input must have at least three input vertices.\n");
-    exit(1);
+    triexit(1);
   }
   if (m->mesh_dim != 2) {
     printf("Error:  Triangle only works with two-dimensional meshes.\n");
-    exit(1);
+    triexit(1);
   }
   if (m->nextras == 0) {
     b->weighted = 0;
@@ -13950,13 +14017,13 @@ FILE **polyfile;
     stringptr = findfield(stringptr);
     if (*stringptr == '\0') {
       printf("Error:  Vertex %d has no x coordinate.\n", b->firstnumber + i);
-      exit(1);
+      triexit(1);
     }
     x = (REAL) strtod(stringptr, &stringptr);
     stringptr = findfield(stringptr);
     if (*stringptr == '\0') {
       printf("Error:  Vertex %d has no y coordinate.\n", b->firstnumber + i);
-      exit(1);
+      triexit(1);
     }
     y = (REAL) strtod(stringptr, &stringptr);
     vertexloop[0] = x;
@@ -14043,7 +14110,7 @@ int numberofpointattribs;
   m->readnodefile = 0;
   if (m->invertices < 3) {
     printf("Error:  Input must have at least three input vertices.\n");
-    exit(1);
+    triexit(1);
   }
   if (m->nextras == 0) {
     b->weighted = 0;
@@ -14127,7 +14194,7 @@ int *regions;
   stringptr = readline(inputline, polyfile, polyfilename);
   *holes = (int) strtol(stringptr, &stringptr, 0);
   if (*holes > 0) {
-    holelist = (REAL *) trimalloc(2 * *holes * sizeof(REAL));
+    holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
     *hlist = holelist;
     for (i = 0; i < 2 * *holes; i += 2) {
       stringptr = readline(inputline, polyfile, polyfilename);
@@ -14135,7 +14202,7 @@ int *regions;
       if (*stringptr == '\0') {
         printf("Error:  Hole %d has no x coordinate.\n",
                b->firstnumber + (i >> 1));
-        exit(1);
+        triexit(1);
       } else {
         holelist[i] = (REAL) strtod(stringptr, &stringptr);
       }
@@ -14143,7 +14210,7 @@ int *regions;
       if (*stringptr == '\0') {
         printf("Error:  Hole %d has no y coordinate.\n",
                b->firstnumber + (i >> 1));
-        exit(1);
+        triexit(1);
       } else {
         holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
       }
@@ -14158,7 +14225,7 @@ int *regions;
     stringptr = readline(inputline, polyfile, polyfilename);
     *regions = (int) strtol(stringptr, &stringptr, 0);
     if (*regions > 0) {
-      regionlist = (REAL *) trimalloc(4 * *regions * sizeof(REAL));
+      regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
       *rlist = regionlist;
       index = 0;
       for (i = 0; i < *regions; i++) {
@@ -14167,7 +14234,7 @@ int *regions;
         if (*stringptr == '\0') {
           printf("Error:  Region %d has no x coordinate.\n",
                  b->firstnumber + i);
-          exit(1);
+          triexit(1);
         } else {
           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
         }
@@ -14175,7 +14242,7 @@ int *regions;
         if (*stringptr == '\0') {
           printf("Error:  Region %d has no y coordinate.\n",
                  b->firstnumber + i);
-          exit(1);
+          triexit(1);
         } else {
           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
         }
@@ -14184,7 +14251,7 @@ int *regions;
           printf(
             "Error:  Region %d has no region attribute or area constraint.\n",
                  b->firstnumber + i);
-          exit(1);
+          triexit(1);
         } else {
           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
         }
@@ -14307,16 +14374,16 @@ char **argv;
   }
   /* Allocate memory for output vertices if necessary. */
   if (*pointlist == (REAL *) NULL) {
-    *pointlist = (REAL *) trimalloc(outvertices * 2 * sizeof(REAL));
+    *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
   }
   /* Allocate memory for output vertex attributes if necessary. */
   if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
-    *pointattriblist = (REAL *) trimalloc(outvertices * m->nextras *
-                                          sizeof(REAL));
+    *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
+                                                 sizeof(REAL)));
   }
   /* Allocate memory for output vertex markers if necessary. */
   if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
-    *pointmarkerlist = (int *) trimalloc(outvertices * sizeof(int));
+    *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
   }
   plist = *pointlist;
   palist = *pointattriblist;
@@ -14330,7 +14397,7 @@ char **argv;
   outfile = fopen(nodefilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", nodefilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of vertices, number of dimensions, number of vertex attributes, */
   /*   and number of boundary markers (zero or one).                        */
@@ -14472,14 +14539,15 @@ char **argv;
   }
   /* Allocate memory for output triangles if necessary. */
   if (*trianglelist == (int *) NULL) {
-    *trianglelist = (int *) trimalloc(m->triangles.items *
-                                      ((b->order + 1) * (b->order + 2) / 2) *
-                                      sizeof(int));
+    *trianglelist = (int *) trimalloc((int) (m->triangles.items *
+                                             ((b->order + 1) * (b->order + 2) /
+                                              2) * sizeof(int)));
   }
   /* Allocate memory for output triangle attributes if necessary. */
   if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
-    *triangleattriblist = (REAL *) trimalloc(m->triangles.items * m->eextras *
-                                             sizeof(REAL));
+    *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
+                                                    m->eextras *
+                                                    sizeof(REAL)));
   }
   tlist = *trianglelist;
   talist = *triangleattriblist;
@@ -14492,7 +14560,7 @@ char **argv;
   outfile = fopen(elefilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", elefilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of triangles, vertices per triangle, attributes per triangle. */
   fprintf(outfile, "%ld  %d  %d\n", m->triangles.items,
@@ -14616,11 +14684,13 @@ char **argv;
   }
   /* Allocate memory for output segments if necessary. */
   if (*segmentlist == (int *) NULL) {
-    *segmentlist = (int *) trimalloc(m->subsegs.items * 2 * sizeof(int));
+    *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
+                                            sizeof(int)));
   }
   /* Allocate memory for output segment markers if necessary. */
   if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
-    *segmentmarkerlist = (int *) trimalloc(m->subsegs.items * sizeof(int));
+    *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
+                                                  sizeof(int)));
   }
   slist = *segmentlist;
   smlist = *segmentmarkerlist;
@@ -14632,7 +14702,7 @@ char **argv;
   outfile = fopen(polyfilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", polyfilename);
-    exit(1);
+    triexit(1);
   }
   /* The zero indicates that the vertices are in a separate .node file. */
   /*   Followed by number of dimensions, number of vertex attributes,   */
@@ -14756,11 +14826,11 @@ char **argv;
   }
   /* Allocate memory for edges if necessary. */
   if (*edgelist == (int *) NULL) {
-    *edgelist = (int *) trimalloc(m->edges * 2 * sizeof(int));
+    *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
   }
   /* Allocate memory for edge markers if necessary. */
   if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
-    *edgemarkerlist = (int *) trimalloc(m->edges * sizeof(int));
+    *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
   }
   elist = *edgelist;
   emlist = *edgemarkerlist;
@@ -14772,7 +14842,7 @@ char **argv;
   outfile = fopen(edgefilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", edgefilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of edges, number of boundary markers (zero or one). */
   fprintf(outfile, "%ld  %d\n", m->edges, 1 - b->nobound);
@@ -14911,7 +14981,6 @@ char **argv;
   vertex torg, tdest, tapex;
   REAL circumcenter[2];
   REAL xi, eta;
-  REAL dum;
   long vnodenumber, vedgenumber;
   int p1, p2;
   int i;
@@ -14923,12 +14992,13 @@ char **argv;
   }
   /* Allocate memory for Voronoi vertices if necessary. */
   if (*vpointlist == (REAL *) NULL) {
-    *vpointlist = (REAL *) trimalloc(m->triangles.items * 2 * sizeof(REAL));
+    *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
+                                            sizeof(REAL)));
   }
   /* Allocate memory for Voronoi vertex attributes if necessary. */
   if (*vpointattriblist == (REAL *) NULL) {
-    *vpointattriblist = (REAL *) trimalloc(m->triangles.items * m->nextras *
-                                           sizeof(REAL));
+    *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
+                                                  m->nextras * sizeof(REAL)));
   }
   *vpointmarkerlist = (int *) NULL;
   plist = *vpointlist;
@@ -14942,7 +15012,7 @@ char **argv;
   outfile = fopen(vnodefilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", vnodefilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of triangles, two dimensions, number of vertex attributes, */
   /*   no markers.                                                     */
@@ -14957,7 +15027,7 @@ char **argv;
     org(triangleloop, torg);
     dest(triangleloop, tdest);
     apex(triangleloop, tapex);
-    findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, &dum);
+    findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
 #ifdef TRILIBRARY
     /* X and y coordinates. */
     plist[coordindex++] = circumcenter[0];
@@ -14994,12 +15064,12 @@ char **argv;
   }
   /* Allocate memory for output Voronoi edges if necessary. */
   if (*vedgelist == (int *) NULL) {
-    *vedgelist = (int *) trimalloc(m->edges * 2 * sizeof(int));
+    *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
   }
   *vedgemarkerlist = (int *) NULL;
   /* Allocate memory for output Voronoi norms if necessary. */
   if (*vnormlist == (REAL *) NULL) {
-    *vnormlist = (REAL *) trimalloc(m->edges * 2 * sizeof(REAL));
+    *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
   }
   elist = *vedgelist;
   normlist = *vnormlist;
@@ -15011,7 +15081,7 @@ char **argv;
   outfile = fopen(vedgefilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", vedgefilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of edges, zero boundary markers. */
   fprintf(outfile, "%ld  %d\n", m->edges, 0);
@@ -15118,7 +15188,8 @@ char **argv;
   }
   /* Allocate memory for neighbors if necessary. */
   if (*neighborlist == (int *) NULL) {
-    *neighborlist = (int *) trimalloc(m->triangles.items * 3 * sizeof(int));
+    *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
+                                             sizeof(int)));
   }
   nlist = *neighborlist;
   index = 0;
@@ -15129,7 +15200,7 @@ char **argv;
   outfile = fopen(neighborfilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", neighborfilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of triangles, three neighbors per triangle. */
   fprintf(outfile, "%ld  %d\n", m->triangles.items, 3);
@@ -15221,7 +15292,7 @@ char **argv;
   outfile = fopen(offfilename, "w");
   if (outfile == (FILE *) NULL) {
     printf("  Error:  Cannot create file %s.\n", offfilename);
-    exit(1);
+    triexit(1);
   }
   /* Number of vertices, triangles, and edges. */
   fprintf(outfile, "OFF\n%ld  %ld  %ld\n", outvertices, m->triangles.items,
@@ -15248,8 +15319,8 @@ char **argv;
     dest(triangleloop, p2);
     apex(triangleloop, p3);
     /* The "3" means a three-vertex polygon. */
-    fprintf(outfile, " 3   %4d  %4d  %4d\n", vertexmark(p1) - 1,
-            vertexmark(p2) - 1, vertexmark(p3) - 1);
+    fprintf(outfile, " 3   %4d  %4d  %4d\n", vertexmark(p1) - b->firstnumber,
+            vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
     triangleloop.tri = triangletraverse(m);
   }
   finishfile(outfile, argc, argv);
@@ -15784,7 +15855,11 @@ char **argv;
   }
 
 #ifdef TRILIBRARY
-  out->numberofpoints = m.vertices.items;
+  if (b.jettison) {
+    out->numberofpoints = m.vertices.items - m.undeads;
+  } else {
+    out->numberofpoints = m.vertices.items;
+  }
   out->numberofpointattributes = m.nextras;
   out->numberoftriangles = m.triangles.items;
   out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
diff --git a/src/triangle.h b/src/triangle.h
index 27bf2d11092484308a364f3dcf9d14ea098d1244..9df1f39ea45df28eeb315f4a7c6a59af4eae3151 100644
--- a/src/triangle.h
+++ b/src/triangle.h
@@ -1,302 +1,289 @@
-#ifndef __TRIANGLE_H
-#define __TRIANGLE_H
-
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*****************************************************************************/
-/*                                                                           */
-/*  (triangle.h)                                                             */
-/*                                                                           */
-/*  Include file for programs that call Triangle.                            */
-/*                                                                           */
-/*  Accompanies Triangle Versions 1.3 and 1.4                                */
-/*  July 19, 1996                                                            */
-/*                                                                           */
-/*  Copyright 1996                                                           */
-/*  Jonathan Richard Shewchuk                                                */
-/*  2360 Woolsey #H                                                          */
-/*  Berkeley, California  94705-1927                                         */
-/*  jrs@cs.berkeley.edu                                                      */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  How to call Triangle from another program                                */
-/*                                                                           */
-/*                                                                           */
-/*  If you haven't read Triangle's instructions (run "triangle -h" to read   */
-/*  them), you won't understand what follows.                                */
-/*                                                                           */
-/*  Triangle must be compiled into an object file (triangle.o) with the      */
-/*  TRILIBRARY symbol defined (preferably by using the -DTRILIBRARY compiler */
-/*  switch).  The makefile included with Triangle will do this for you if    */
-/*  you run "make trilibrary".  The resulting object file can be called via  */
-/*  the procedure triangulate().                                             */
-/*                                                                           */
-/*  If the size of the object file is important to you, you may wish to      */
-/*  generate a reduced version of triangle.o.  The REDUCED symbol gets rid   */
-/*  of all features that are primarily of research interest.  Specifically,  */
-/*  the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches.  */
-/*  The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond  */
-/*  constrained Delaunay triangulation.  Specifically, the -DCDT_ONLY switch */
-/*  eliminates Triangle's -r, -q, -a, -S, and -s switches.                   */
-/*                                                                           */
-/*  IMPORTANT:  These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be    */
-/*  made in the makefile or in triangle.c itself.  Putting these definitions */
-/*  in this file will not create the desired effect.                         */
-/*                                                                           */
-/*                                                                           */
-/*  The calling convention for triangulate() follows.                        */
-/*                                                                           */
-/*      void triangulate(triswitches, in, out, vorout)                       */
-/*      char *triswitches;                                                   */
-/*      struct triangulateio *in;                                            */
-/*      struct triangulateio *out;                                           */
-/*      struct triangulateio *vorout;                                        */
-/*                                                                           */
-/*  `triswitches' is a string containing the command line switches you wish  */
-/*  to invoke.  No initial dash is required.  Some suggestions:              */
-/*                                                                           */
-/*  - You'll probably find it convenient to use the `z' switch so that       */
-/*    points (and other items) are numbered from zero.  This simplifies      */
-/*    indexing, because the first item of any type always starts at index    */
-/*    [0] of the corresponding array, whether that item's number is zero or  */
-/*    one.                                                                   */
-/*  - You'll probably want to use the `Q' (quiet) switch in your final code, */
-/*    but you can take advantage of Triangle's printed output (including the */
-/*    `V' switch) while debugging.                                           */
-/*  - If you are not using the `q' or `a' switches, then the output points   */
-/*    will be identical to the input points, except possibly for the         */
-/*    boundary markers.  If you don't need the boundary markers, you should  */
-/*    use the `N' (no nodes output) switch to save memory.  (If you do need  */
-/*    boundary markers, but need to save memory, a good nasty trick is to    */
-/*    set out->pointlist equal to in->pointlist before calling triangulate(),*/
-/*    so that Triangle overwrites the input points with identical copies.)   */
-/*  - The `I' (no iteration numbers) and `g' (.off file output) switches     */
-/*    have no effect when Triangle is compiled with TRILIBRARY defined.      */
-/*                                                                           */
-/*  `in', `out', and `vorout' are descriptions of the input, the output,     */
-/*  and the Voronoi output.  If the `v' (Voronoi output) switch is not used, */
-/*  `vorout' may be NULL.  `in' and `out' may never be NULL.                 */
-/*                                                                           */
-/*  Certain fields of the input and output structures must be initialized,   */
-/*  as described below.                                                      */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  The `triangulateio' structure.                                           */
-/*                                                                           */
-/*  Used to pass data into and out of the triangulate() procedure.           */
-/*                                                                           */
-/*                                                                           */
-/*  Arrays are used to store points, triangles, markers, and so forth.  In   */
-/*  all cases, the first item in any array is stored starting at index [0].  */
-/*  However, that item is item number `1' unless the `z' switch is used, in  */
-/*  which case it is item number `0'.  Hence, you may find it easier to      */
-/*  index points (and triangles in the neighbor list) if you use the `z'     */
-/*  switch.  Unless, of course, you're calling Triangle from a Fortran       */
-/*  program.                                                                 */
-/*                                                                           */
-/*  Description of fields (except the `numberof' fields, which are obvious): */
-/*                                                                           */
-/*  `pointlist':  An array of point coordinates.  The first point's x        */
-/*    coordinate is at index [0] and its y coordinate at index [1], followed */
-/*    by the coordinates of the remaining points.  Each point occupies two   */
-/*    REALs.                                                                 */
-/*  `pointattributelist':  An array of point attributes.  Each point's       */
-/*    attributes occupy `numberofpointattributes' REALs.                     */
-/*  `pointmarkerlist':  An array of point markers; one int per point.        */
-/*                                                                           */
-/*  `trianglelist':  An array of triangle corners.  The first triangle's     */
-/*    first corner is at index [0], followed by its other two corners in     */
-/*    counterclockwise order, followed by any other nodes if the triangle    */
-/*    represents a nonlinear element.  Each triangle occupies                */
-/*    `numberofcorners' ints.                                                */
-/*  `triangleattributelist':  An array of triangle attributes.  Each         */
-/*    triangle's attributes occupy `numberoftriangleattributes' REALs.       */
-/*  `trianglearealist':  An array of triangle area constraints; one REAL per */
-/*    triangle.  Input only.                                                 */
-/*  `neighborlist':  An array of triangle neighbors; three ints per          */
-/*    triangle.  Output only.                                                */
-/*                                                                           */
-/*  `segmentlist':  An array of segment endpoints.  The first segment's      */
-/*    endpoints are at indices [0] and [1], followed by the remaining        */
-/*    segments.  Two ints per segment.                                       */
-/*  `segmentmarkerlist':  An array of segment markers; one int per segment.  */
-/*                                                                           */
-/*  `holelist':  An array of holes.  The first hole's x and y coordinates    */
-/*    are at indices [0] and [1], followed by the remaining holes.  Two      */
-/*    REALs per hole.  Input only, although the pointer is copied to the     */
-/*    output structure for your convenience.                                 */
-/*                                                                           */
-/*  `regionlist':  An array of regional attributes and area constraints.     */
-/*    The first constraint's x and y coordinates are at indices [0] and [1], */
-/*    followed by the regional attribute and index [2], followed by the      */
-/*    maximum area at index [3], followed by the remaining area constraints. */
-/*    Four REALs per area constraint.  Note that each regional attribute is  */
-/*    used only if you select the `A' switch, and each area constraint is    */
-/*    used only if you select the `a' switch (with no number following), but */
-/*    omitting one of these switches does not change the memory layout.      */
-/*    Input only, although the pointer is copied to the output structure for */
-/*    your convenience.                                                      */
-/*                                                                           */
-/*  `edgelist':  An array of edge endpoints.  The first edge's endpoints are */
-/*    at indices [0] and [1], followed by the remaining edges.  Two ints per */
-/*    edge.  Output only.                                                    */
-/*  `edgemarkerlist':  An array of edge markers; one int per edge.  Output   */
-/*    only.                                                                  */
-/*  `normlist':  An array of normal vectors, used for infinite rays in       */
-/*    Voronoi diagrams.  The first normal vector's x and y magnitudes are    */
-/*    at indices [0] and [1], followed by the remaining vectors.  For each   */
-/*    finite edge in a Voronoi diagram, the normal vector written is the     */
-/*    zero vector.  Two REALs per edge.  Output only.                        */
-/*                                                                           */
-/*                                                                           */
-/*  Any input fields that Triangle will examine must be initialized.         */
-/*  Furthermore, for each output array that Triangle will write to, you      */
-/*  must either provide space by setting the appropriate pointer to point    */
-/*  to the space you want the data written to, or you must initialize the    */
-/*  pointer to NULL, which tells Triangle to allocate space for the results. */
-/*  The latter option is preferable, because Triangle always knows exactly   */
-/*  how much space to allocate.  The former option is provided mainly for    */
-/*  people who need to call Triangle from Fortran code, though it also makes */
-/*  possible some nasty space-saving tricks, like writing the output to the  */
-/*  same arrays as the input.                                                */
-/*                                                                           */
-/*  Triangle will not free() any input or output arrays, including those it  */
-/*  allocates itself; that's up to you.                                      */
-/*                                                                           */
-/*  Here's a guide to help you decide which fields you must initialize       */
-/*  before you call triangulate().                                           */
-/*                                                                           */
-/*  `in':                                                                    */
-/*                                                                           */
-/*    - `pointlist' must always point to a list of points; `numberofpoints'  */
-/*      and `numberofpointattributes' must be properly set.                  */
-/*      `pointmarkerlist' must either be set to NULL (in which case all      */
-/*      markers default to zero), or must point to a list of markers.  If    */
-/*      `numberofpointattributes' is not zero, `pointattributelist' must     */
-/*      point to a list of point attributes.                                 */
-/*    - If the `r' switch is used, `trianglelist' must point to a list of    */
-/*      triangles, and `numberoftriangles', `numberofcorners', and           */
-/*      `numberoftriangleattributes' must be properly set.  If               */
-/*      `numberoftriangleattributes' is not zero, `triangleattributelist'    */
-/*      must point to a list of triangle attributes.  If the `a' switch is   */
-/*      used (with no number following), `trianglearealist' must point to a  */
-/*      list of triangle area constraints.  `neighborlist' may be ignored.   */
-/*    - If the `p' switch is used, `segmentlist' must point to a list of     */
-/*      segments, `numberofsegments' must be properly set, and               */
-/*      `segmentmarkerlist' must either be set to NULL (in which case all    */
-/*      markers default to zero), or must point to a list of markers.        */
-/*    - If the `p' switch is used without the `r' switch, then               */
-/*      `numberofholes' and `numberofregions' must be properly set.  If      */
-/*      `numberofholes' is not zero, `holelist' must point to a list of      */
-/*      holes.  If `numberofregions' is not zero, `regionlist' must point to */
-/*      a list of region constraints.                                        */
-/*    - If the `p' switch is used, `holelist', `numberofholes',              */
-/*      `regionlist', and `numberofregions' is copied to `out'.  (You can    */
-/*      nonetheless get away with not initializing them if the `r' switch is */
-/*      used.)                                                               */
-/*    - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
-/*      ignored.                                                             */
-/*                                                                           */
-/*  `out':                                                                   */
-/*                                                                           */
-/*    - `pointlist' must be initialized (NULL or pointing to memory) unless  */
-/*      the `N' switch is used.  `pointmarkerlist' must be initialized       */
-/*      unless the `N' or `B' switch is used.  If `N' is not used and        */
-/*      `in->numberofpointattributes' is not zero, `pointattributelist' must */
-/*      be initialized.                                                      */
-/*    - `trianglelist' must be initialized unless the `E' switch is used.    */
-/*      `neighborlist' must be initialized if the `n' switch is used.  If    */
-/*      the `E' switch is not used and (`in->numberofelementattributes' is   */
-/*      not zero or the `A' switch is used), `elementattributelist' must be  */
-/*      initialized.  `trianglearealist' may be ignored.                     */
-/*    - `segmentlist' must be initialized if the `p' or `c' switch is used,  */
-/*      and the `P' switch is not used.  `segmentmarkerlist' must also be    */
-/*      initialized under these circumstances unless the `B' switch is used. */
-/*    - `edgelist' must be initialized if the `e' switch is used.            */
-/*      `edgemarkerlist' must be initialized if the `e' switch is used and   */
-/*      the `B' switch is not.                                               */
-/*    - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
-/*                                                                           */
-/*  `vorout' (only needed if `v' switch is used):                            */
-/*                                                                           */
-/*    - `pointlist' must be initialized.  If `in->numberofpointattributes'   */
-/*      is not zero, `pointattributelist' must be initialized.               */
-/*      `pointmarkerlist' may be ignored.                                    */
-/*    - `edgelist' and `normlist' must both be initialized.                  */
-/*      `edgemarkerlist' may be ignored.                                     */
-/*    - Everything else may be ignored.                                      */
-/*                                                                           */
-/*  After a call to triangulate(), the valid fields of `out' and `vorout'    */
-/*  will depend, in an obvious way, on the choice of switches used.  Note    */
-/*  that when the `p' switch is used, the pointers `holelist' and            */
-/*  `regionlist' are copied from `in' to `out', but no new space is          */
-/*  allocated; be careful that you don't free() the same array twice.  On    */
-/*  the other hand, Triangle will never copy the `pointlist' pointer (or any */
-/*  others); new space is allocated for `out->pointlist', or if the `N'      */
-/*  switch is used, `out->pointlist' remains uninitialized.                  */
-/*                                                                           */
-/*  All of the meaningful `numberof' fields will be properly set; for        */
-/*  instance, `numberofedges' will represent the number of edges in the      */
-/*  triangulation whether or not the edges were written.  If segments are    */
-/*  not used, `numberofsegments' will indicate the number of boundary edges. */
-/*                                                                           */
-/*****************************************************************************/
-
-typedef double REAL;
-
-struct triangulateio {
-  REAL *pointlist;                                               /* In / out */
-  REAL *pointattributelist;                                      /* In / out */
-  int *pointmarkerlist;                                          /* In / out */
-  int numberofpoints;                                            /* In / out */
-  int numberofpointattributes;                                   /* In / out */
-
-  int *trianglelist;                                             /* In / out */
-  REAL *triangleattributelist;                                   /* In / out */
-  REAL *trianglearealist;                                         /* In only */
-  int *neighborlist;                                             /* Out only */
-  int numberoftriangles;                                         /* In / out */
-  int numberofcorners;                                           /* In / out */
-  int numberoftriangleattributes;                                /* In / out */
-
-  int *segmentlist;                                              /* In / out */
-  int *segmentmarkerlist;                                        /* In / out */
-  int numberofsegments;                                          /* In / out */
-
-  REAL *holelist;                        /* In / pointer to array copied out */
-  int numberofholes;                                      /* In / copied out */
-
-  REAL *regionlist;                      /* In / pointer to array copied out */
-  int numberofregions;                                    /* In / copied out */
-
-  int *edgelist;                                                 /* Out only */
-  int *edgemarkerlist;            /* Not used with Voronoi diagram; out only */
-  REAL *normlist;                /* Used only with Voronoi diagram; out only */
-  int numberofedges;                                             /* Out only */
-};
-
-void triangulate(char *, struct triangulateio *, struct triangulateio *,
-                 struct triangulateio *);
-
-/* external refinement test */
-typedef REAL *vertex;
-
-int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-
-#endif
+/*****************************************************************************/
+/*                                                                           */
+/*  (triangle.h)                                                             */
+/*                                                                           */
+/*  Include file for programs that call Triangle.                            */
+/*                                                                           */
+/*  Accompanies Triangle Version 1.6                                         */
+/*  July 28, 2005                                                            */
+/*                                                                           */
+/*  Copyright 1996, 2005                                                     */
+/*  Jonathan Richard Shewchuk                                                */
+/*  2360 Woolsey #H                                                          */
+/*  Berkeley, California  94705-1927                                         */
+/*  jrs@cs.berkeley.edu                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  How to call Triangle from another program                                */
+/*                                                                           */
+/*                                                                           */
+/*  If you haven't read Triangle's instructions (run "triangle -h" to read   */
+/*  them), you won't understand what follows.                                */
+/*                                                                           */
+/*  Triangle must be compiled into an object file (triangle.o) with the      */
+/*  TRILIBRARY symbol defined (generally by using the -DTRILIBRARY compiler  */
+/*  switch).  The makefile included with Triangle will do this for you if    */
+/*  you run "make trilibrary".  The resulting object file can be called via  */
+/*  the procedure triangulate().                                             */
+/*                                                                           */
+/*  If the size of the object file is important to you, you may wish to      */
+/*  generate a reduced version of triangle.o.  The REDUCED symbol gets rid   */
+/*  of all features that are primarily of research interest.  Specifically,  */
+/*  the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches.  */
+/*  The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond  */
+/*  constrained Delaunay triangulation.  Specifically, the -DCDT_ONLY switch */
+/*  eliminates Triangle's -r, -q, -a, -u, -D, -Y, -S, and -s switches.       */
+/*                                                                           */
+/*  IMPORTANT:  These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be    */
+/*  made in the makefile or in triangle.c itself.  Putting these definitions */
+/*  in this file (triangle.h) will not create the desired effect.            */
+/*                                                                           */
+/*                                                                           */
+/*  The calling convention for triangulate() follows.                        */
+/*                                                                           */
+/*      void triangulate(triswitches, in, out, vorout)                       */
+/*      char *triswitches;                                                   */
+/*      struct triangulateio *in;                                            */
+/*      struct triangulateio *out;                                           */
+/*      struct triangulateio *vorout;                                        */
+/*                                                                           */
+/*  `triswitches' is a string containing the command line switches you wish  */
+/*  to invoke.  No initial dash is required.  Some suggestions:              */
+/*                                                                           */
+/*  - You'll probably find it convenient to use the `z' switch so that       */
+/*    points (and other items) are numbered from zero.  This simplifies      */
+/*    indexing, because the first item of any type always starts at index    */
+/*    [0] of the corresponding array, whether that item's number is zero or  */
+/*    one.                                                                   */
+/*  - You'll probably want to use the `Q' (quiet) switch in your final code, */
+/*    but you can take advantage of Triangle's printed output (including the */
+/*    `V' switch) while debugging.                                           */
+/*  - If you are not using the `q', `a', `u', `D', `j', or `s' switches,     */
+/*    then the output points will be identical to the input points, except   */
+/*    possibly for the boundary markers.  If you don't need the boundary     */
+/*    markers, you should use the `N' (no nodes output) switch to save       */
+/*    memory.  (If you do need boundary markers, but need to save memory, a  */
+/*    good nasty trick is to set out->pointlist equal to in->pointlist       */
+/*    before calling triangulate(), so that Triangle overwrites the input    */
+/*    points with identical copies.)                                         */
+/*  - The `I' (no iteration numbers) and `g' (.off file output) switches     */
+/*    have no effect when Triangle is compiled with TRILIBRARY defined.      */
+/*                                                                           */
+/*  `in', `out', and `vorout' are descriptions of the input, the output,     */
+/*  and the Voronoi output.  If the `v' (Voronoi output) switch is not used, */
+/*  `vorout' may be NULL.  `in' and `out' may never be NULL.                 */
+/*                                                                           */
+/*  Certain fields of the input and output structures must be initialized,   */
+/*  as described below.                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  The `triangulateio' structure.                                           */
+/*                                                                           */
+/*  Used to pass data into and out of the triangulate() procedure.           */
+/*                                                                           */
+/*                                                                           */
+/*  Arrays are used to store points, triangles, markers, and so forth.  In   */
+/*  all cases, the first item in any array is stored starting at index [0].  */
+/*  However, that item is item number `1' unless the `z' switch is used, in  */
+/*  which case it is item number `0'.  Hence, you may find it easier to      */
+/*  index points (and triangles in the neighbor list) if you use the `z'     */
+/*  switch.  Unless, of course, you're calling Triangle from a Fortran       */
+/*  program.                                                                 */
+/*                                                                           */
+/*  Description of fields (except the `numberof' fields, which are obvious): */
+/*                                                                           */
+/*  `pointlist':  An array of point coordinates.  The first point's x        */
+/*    coordinate is at index [0] and its y coordinate at index [1], followed */
+/*    by the coordinates of the remaining points.  Each point occupies two   */
+/*    REALs.                                                                 */
+/*  `pointattributelist':  An array of point attributes.  Each point's       */
+/*    attributes occupy `numberofpointattributes' REALs.                     */
+/*  `pointmarkerlist':  An array of point markers; one int per point.        */
+/*                                                                           */
+/*  `trianglelist':  An array of triangle corners.  The first triangle's     */
+/*    first corner is at index [0], followed by its other two corners in     */
+/*    counterclockwise order, followed by any other nodes if the triangle    */
+/*    represents a nonlinear element.  Each triangle occupies                */
+/*    `numberofcorners' ints.                                                */
+/*  `triangleattributelist':  An array of triangle attributes.  Each         */
+/*    triangle's attributes occupy `numberoftriangleattributes' REALs.       */
+/*  `trianglearealist':  An array of triangle area constraints; one REAL per */
+/*    triangle.  Input only.                                                 */
+/*  `neighborlist':  An array of triangle neighbors; three ints per          */
+/*    triangle.  Output only.                                                */
+/*                                                                           */
+/*  `segmentlist':  An array of segment endpoints.  The first segment's      */
+/*    endpoints are at indices [0] and [1], followed by the remaining        */
+/*    segments.  Two ints per segment.                                       */
+/*  `segmentmarkerlist':  An array of segment markers; one int per segment.  */
+/*                                                                           */
+/*  `holelist':  An array of holes.  The first hole's x and y coordinates    */
+/*    are at indices [0] and [1], followed by the remaining holes.  Two      */
+/*    REALs per hole.  Input only, although the pointer is copied to the     */
+/*    output structure for your convenience.                                 */
+/*                                                                           */
+/*  `regionlist':  An array of regional attributes and area constraints.     */
+/*    The first constraint's x and y coordinates are at indices [0] and [1], */
+/*    followed by the regional attribute at index [2], followed by the       */
+/*    maximum area at index [3], followed by the remaining area constraints. */
+/*    Four REALs per area constraint.  Note that each regional attribute is  */
+/*    used only if you select the `A' switch, and each area constraint is    */
+/*    used only if you select the `a' switch (with no number following), but */
+/*    omitting one of these switches does not change the memory layout.      */
+/*    Input only, although the pointer is copied to the output structure for */
+/*    your convenience.                                                      */
+/*                                                                           */
+/*  `edgelist':  An array of edge endpoints.  The first edge's endpoints are */
+/*    at indices [0] and [1], followed by the remaining edges.  Two ints per */
+/*    edge.  Output only.                                                    */
+/*  `edgemarkerlist':  An array of edge markers; one int per edge.  Output   */
+/*    only.                                                                  */
+/*  `normlist':  An array of normal vectors, used for infinite rays in       */
+/*    Voronoi diagrams.  The first normal vector's x and y magnitudes are    */
+/*    at indices [0] and [1], followed by the remaining vectors.  For each   */
+/*    finite edge in a Voronoi diagram, the normal vector written is the     */
+/*    zero vector.  Two REALs per edge.  Output only.                        */
+/*                                                                           */
+/*                                                                           */
+/*  Any input fields that Triangle will examine must be initialized.         */
+/*  Furthermore, for each output array that Triangle will write to, you      */
+/*  must either provide space by setting the appropriate pointer to point    */
+/*  to the space you want the data written to, or you must initialize the    */
+/*  pointer to NULL, which tells Triangle to allocate space for the results. */
+/*  The latter option is preferable, because Triangle always knows exactly   */
+/*  how much space to allocate.  The former option is provided mainly for    */
+/*  people who need to call Triangle from Fortran code, though it also makes */
+/*  possible some nasty space-saving tricks, like writing the output to the  */
+/*  same arrays as the input.                                                */
+/*                                                                           */
+/*  Triangle will not free() any input or output arrays, including those it  */
+/*  allocates itself; that's up to you.  You should free arrays allocated by */
+/*  Triangle by calling the trifree() procedure defined below.  (By default, */
+/*  trifree() just calls the standard free() library procedure, but          */
+/*  applications that call triangulate() may replace trimalloc() and         */
+/*  trifree() in triangle.c to use specialized memory allocators.)           */
+/*                                                                           */
+/*  Here's a guide to help you decide which fields you must initialize       */
+/*  before you call triangulate().                                           */
+/*                                                                           */
+/*  `in':                                                                    */
+/*                                                                           */
+/*    - `pointlist' must always point to a list of points; `numberofpoints'  */
+/*      and `numberofpointattributes' must be properly set.                  */
+/*      `pointmarkerlist' must either be set to NULL (in which case all      */
+/*      markers default to zero), or must point to a list of markers.  If    */
+/*      `numberofpointattributes' is not zero, `pointattributelist' must     */
+/*      point to a list of point attributes.                                 */
+/*    - If the `r' switch is used, `trianglelist' must point to a list of    */
+/*      triangles, and `numberoftriangles', `numberofcorners', and           */
+/*      `numberoftriangleattributes' must be properly set.  If               */
+/*      `numberoftriangleattributes' is not zero, `triangleattributelist'    */
+/*      must point to a list of triangle attributes.  If the `a' switch is   */
+/*      used (with no number following), `trianglearealist' must point to a  */
+/*      list of triangle area constraints.  `neighborlist' may be ignored.   */
+/*    - If the `p' switch is used, `segmentlist' must point to a list of     */
+/*      segments, `numberofsegments' must be properly set, and               */
+/*      `segmentmarkerlist' must either be set to NULL (in which case all    */
+/*      markers default to zero), or must point to a list of markers.        */
+/*    - If the `p' switch is used without the `r' switch, then               */
+/*      `numberofholes' and `numberofregions' must be properly set.  If      */
+/*      `numberofholes' is not zero, `holelist' must point to a list of      */
+/*      holes.  If `numberofregions' is not zero, `regionlist' must point to */
+/*      a list of region constraints.                                        */
+/*    - If the `p' switch is used, `holelist', `numberofholes',              */
+/*      `regionlist', and `numberofregions' is copied to `out'.  (You can    */
+/*      nonetheless get away with not initializing them if the `r' switch is */
+/*      used.)                                                               */
+/*    - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
+/*      ignored.                                                             */
+/*                                                                           */
+/*  `out':                                                                   */
+/*                                                                           */
+/*    - `pointlist' must be initialized (NULL or pointing to memory) unless  */
+/*      the `N' switch is used.  `pointmarkerlist' must be initialized       */
+/*      unless the `N' or `B' switch is used.  If `N' is not used and        */
+/*      `in->numberofpointattributes' is not zero, `pointattributelist' must */
+/*      be initialized.                                                      */
+/*    - `trianglelist' must be initialized unless the `E' switch is used.    */
+/*      `neighborlist' must be initialized if the `n' switch is used.  If    */
+/*      the `E' switch is not used and (`in->numberofelementattributes' is   */
+/*      not zero or the `A' switch is used), `elementattributelist' must be  */
+/*      initialized.  `trianglearealist' may be ignored.                     */
+/*    - `segmentlist' must be initialized if the `p' or `c' switch is used,  */
+/*      and the `P' switch is not used.  `segmentmarkerlist' must also be    */
+/*      initialized under these circumstances unless the `B' switch is used. */
+/*    - `edgelist' must be initialized if the `e' switch is used.            */
+/*      `edgemarkerlist' must be initialized if the `e' switch is used and   */
+/*      the `B' switch is not.                                               */
+/*    - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
+/*                                                                           */
+/*  `vorout' (only needed if `v' switch is used):                            */
+/*                                                                           */
+/*    - `pointlist' must be initialized.  If `in->numberofpointattributes'   */
+/*      is not zero, `pointattributelist' must be initialized.               */
+/*      `pointmarkerlist' may be ignored.                                    */
+/*    - `edgelist' and `normlist' must both be initialized.                  */
+/*      `edgemarkerlist' may be ignored.                                     */
+/*    - Everything else may be ignored.                                      */
+/*                                                                           */
+/*  After a call to triangulate(), the valid fields of `out' and `vorout'    */
+/*  will depend, in an obvious way, on the choice of switches used.  Note    */
+/*  that when the `p' switch is used, the pointers `holelist' and            */
+/*  `regionlist' are copied from `in' to `out', but no new space is          */
+/*  allocated; be careful that you don't free() the same array twice.  On    */
+/*  the other hand, Triangle will never copy the `pointlist' pointer (or any */
+/*  others); new space is allocated for `out->pointlist', or if the `N'      */
+/*  switch is used, `out->pointlist' remains uninitialized.                  */
+/*                                                                           */
+/*  All of the meaningful `numberof' fields will be properly set; for        */
+/*  instance, `numberofedges' will represent the number of edges in the      */
+/*  triangulation whether or not the edges were written.  If segments are    */
+/*  not used, `numberofsegments' will indicate the number of boundary edges. */
+/*                                                                           */
+/*****************************************************************************/
+
+struct triangulateio {
+  REAL *pointlist;                                               /* In / out */
+  REAL *pointattributelist;                                      /* In / out */
+  int *pointmarkerlist;                                          /* In / out */
+  int numberofpoints;                                            /* In / out */
+  int numberofpointattributes;                                   /* In / out */
+
+  int *trianglelist;                                             /* In / out */
+  REAL *triangleattributelist;                                   /* In / out */
+  REAL *trianglearealist;                                         /* In only */
+  int *neighborlist;                                             /* Out only */
+  int numberoftriangles;                                         /* In / out */
+  int numberofcorners;                                           /* In / out */
+  int numberoftriangleattributes;                                /* In / out */
+
+  int *segmentlist;                                              /* In / out */
+  int *segmentmarkerlist;                                        /* In / out */
+  int numberofsegments;                                          /* In / out */
+
+  REAL *holelist;                        /* In / pointer to array copied out */
+  int numberofholes;                                      /* In / copied out */
+
+  REAL *regionlist;                      /* In / pointer to array copied out */
+  int numberofregions;                                    /* In / copied out */
+
+  int *edgelist;                                                 /* Out only */
+  int *edgemarkerlist;            /* Not used with Voronoi diagram; out only */
+  REAL *normlist;                /* Used only with Voronoi diagram; out only */
+  int numberofedges;                                             /* Out only */
+};
+
+#ifdef ANSI_DECLARATORS
+void triangulate(char *, struct triangulateio *, struct triangulateio *,
+                 struct triangulateio *);
+void trifree(VOID *memptr);
+#else /* not ANSI_DECLARATORS */
+void triangulate();
+void trifree();
+#endif /* not ANSI_DECLARATORS */