triangle.c
上传用户:yflamps
上传日期:2010-04-01
资源大小:155k
文件大小:636k
源码类别:

3D图形编程

开发平台:

C/C++

  1.       symself(nextedge);
  2.       apex(nextedge, nextapex);
  3.       /* If nextapex is NULL, then no vertex would be exposed; the */
  4.       /*   triangulation would have been eaten right through.      */
  5.       if (nextapex != (vertex) NULL) {
  6.         /* Check whether the edge is Delaunay. */
  7.         badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
  8.                   0.0;
  9.         while (badedge) {
  10.           /* Eliminate the edge with an edge flip.  As a result, the    */
  11.           /*   left triangulation will have one more boundary triangle. */
  12.           lnextself(nextedge);
  13.           sym(nextedge, topcasing);
  14.           lnextself(nextedge);
  15.           sym(nextedge, sidecasing);
  16.           bond(nextedge, topcasing);
  17.           bond(leftcand, sidecasing);
  18.           lnextself(leftcand);
  19.           sym(leftcand, outercasing);
  20.           lprevself(nextedge);
  21.           bond(nextedge, outercasing);
  22.           /* Correct the vertices to reflect the edge flip. */
  23.           setorg(leftcand, lowerleft);
  24.           setdest(leftcand, NULL);
  25.           setapex(leftcand, nextapex);
  26.           setorg(nextedge, NULL);
  27.           setdest(nextedge, upperleft);
  28.           setapex(nextedge, nextapex);
  29.           /* Consider the newly exposed vertex. */
  30.           upperleft = nextapex;
  31.           /* What vertex would be exposed if another edge were deleted? */
  32.           otricopy(sidecasing, nextedge);
  33.           apex(nextedge, nextapex);
  34.           if (nextapex != (vertex) NULL) {
  35.             /* Check whether the edge is Delaunay. */
  36.             badedge = incircle(m, b, lowerleft, lowerright, upperleft,
  37.                                nextapex) > 0.0;
  38.           } else {
  39.             /* Avoid eating right through the triangulation. */
  40.             badedge = 0;
  41.           }
  42.         }
  43.       }
  44.     }
  45.     /* Consider eliminating edges from the right triangulation. */
  46.     if (!rightfinished) {
  47.       /* What vertex would be exposed if an edge were deleted? */
  48.       lnext(rightcand, nextedge);
  49.       symself(nextedge);
  50.       apex(nextedge, nextapex);
  51.       /* If nextapex is NULL, then no vertex would be exposed; the */
  52.       /*   triangulation would have been eaten right through.      */
  53.       if (nextapex != (vertex) NULL) {
  54.         /* Check whether the edge is Delaunay. */
  55.         badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
  56.                   0.0;
  57.         while (badedge) {
  58.           /* Eliminate the edge with an edge flip.  As a result, the     */
  59.           /*   right triangulation will have one more boundary triangle. */
  60.           lprevself(nextedge);
  61.           sym(nextedge, topcasing);
  62.           lprevself(nextedge);
  63.           sym(nextedge, sidecasing);
  64.           bond(nextedge, topcasing);
  65.           bond(rightcand, sidecasing);
  66.           lprevself(rightcand);
  67.           sym(rightcand, outercasing);
  68.           lnextself(nextedge);
  69.           bond(nextedge, outercasing);
  70.           /* Correct the vertices to reflect the edge flip. */
  71.           setorg(rightcand, NULL);
  72.           setdest(rightcand, lowerright);
  73.           setapex(rightcand, nextapex);
  74.           setorg(nextedge, upperright);
  75.           setdest(nextedge, NULL);
  76.           setapex(nextedge, nextapex);
  77.           /* Consider the newly exposed vertex. */
  78.           upperright = nextapex;
  79.           /* What vertex would be exposed if another edge were deleted? */
  80.           otricopy(sidecasing, nextedge);
  81.           apex(nextedge, nextapex);
  82.           if (nextapex != (vertex) NULL) {
  83.             /* Check whether the edge is Delaunay. */
  84.             badedge = incircle(m, b, lowerleft, lowerright, upperright,
  85.                                nextapex) > 0.0;
  86.           } else {
  87.             /* Avoid eating right through the triangulation. */
  88.             badedge = 0;
  89.           }
  90.         }
  91.       }
  92.     }
  93.     if (leftfinished || (!rightfinished &&
  94.            (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
  95.             0.0))) {
  96.       /* Knit the triangulations, adding an edge from `lowerleft' */
  97.       /*   to `upperright'.                                       */
  98.       bond(baseedge, rightcand);
  99.       lprev(rightcand, baseedge);
  100.       setdest(baseedge, lowerleft);
  101.       lowerright = upperright;
  102.       sym(baseedge, rightcand);
  103.       apex(rightcand, upperright);
  104.     } else {
  105.       /* Knit the triangulations, adding an edge from `upperleft' */
  106.       /*   to `lowerright'.                                       */
  107.       bond(baseedge, leftcand);
  108.       lnext(leftcand, baseedge);
  109.       setorg(baseedge, lowerright);
  110.       lowerleft = upperleft;
  111.       sym(baseedge, leftcand);
  112.       apex(leftcand, upperleft);
  113.     }
  114.     if (b->verbose > 2) {
  115.       printf("  Connecting ");
  116.       printtriangle(m, b, &baseedge);
  117.     }
  118.   }
  119. }
  120. /*****************************************************************************/
  121. /*                                                                           */
  122. /*  divconqrecurse()   Recursively form a Delaunay triangulation by the      */
  123. /*                     divide-and-conquer method.                            */
  124. /*                                                                           */
  125. /*  Recursively breaks down the problem into smaller pieces, which are       */
  126. /*  knitted together by mergehulls().  The base cases (problems of two or    */
  127. /*  three vertices) are handled specially here.                              */
  128. /*                                                                           */
  129. /*  On completion, `farleft' and `farright' are bounding triangles such that */
  130. /*  the origin of `farleft' is the leftmost vertex (breaking ties by         */
  131. /*  choosing the highest leftmost vertex), and the destination of            */
  132. /*  `farright' is the rightmost vertex (breaking ties by choosing the        */
  133. /*  lowest rightmost vertex).                                                */
  134. /*                                                                           */
  135. /*****************************************************************************/
  136. #ifdef ANSI_DECLARATORS
  137. void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
  138.                     int vertices, int axis,
  139.                     struct otri *farleft, struct otri *farright)
  140. #else /* not ANSI_DECLARATORS */
  141. void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
  142. struct mesh *m;
  143. struct behavior *b;
  144. vertex *sortarray;
  145. int vertices;
  146. int axis;
  147. struct otri *farleft;
  148. struct otri *farright;
  149. #endif /* not ANSI_DECLARATORS */
  150. {
  151.   struct otri midtri, tri1, tri2, tri3;
  152.   struct otri innerleft, innerright;
  153.   REAL area;
  154.   int divider;
  155.   if (b->verbose > 2) {
  156.     printf("  Triangulating %d vertices.n", vertices);
  157.   }
  158.   if (vertices == 2) {
  159.     /* The triangulation of two vertices is an edge.  An edge is */
  160.     /*   represented by two bounding triangles.                  */
  161.     maketriangle(m, b, farleft);
  162.     setorg(*farleft, sortarray[0]);
  163.     setdest(*farleft, sortarray[1]);
  164.     /* The apex is intentionally left NULL. */
  165.     maketriangle(m, b, farright);
  166.     setorg(*farright, sortarray[1]);
  167.     setdest(*farright, sortarray[0]);
  168.     /* The apex is intentionally left NULL. */
  169.     bond(*farleft, *farright);
  170.     lprevself(*farleft);
  171.     lnextself(*farright);
  172.     bond(*farleft, *farright);
  173.     lprevself(*farleft);
  174.     lnextself(*farright);
  175.     bond(*farleft, *farright);
  176.     if (b->verbose > 2) {
  177.       printf("  Creating ");
  178.       printtriangle(m, b, farleft);
  179.       printf("  Creating ");
  180.       printtriangle(m, b, farright);
  181.     }
  182.     /* Ensure that the origin of `farleft' is sortarray[0]. */
  183.     lprev(*farright, *farleft);
  184.     return;
  185.   } else if (vertices == 3) {
  186.     /* The triangulation of three vertices is either a triangle (with */
  187.     /*   three bounding triangles) or two edges (with four bounding   */
  188.     /*   triangles).  In either case, four triangles are created.     */
  189.     maketriangle(m, b, &midtri);
  190.     maketriangle(m, b, &tri1);
  191.     maketriangle(m, b, &tri2);
  192.     maketriangle(m, b, &tri3);
  193.     area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
  194.     if (area == 0.0) {
  195.       /* Three collinear vertices; the triangulation is two edges. */
  196.       setorg(midtri, sortarray[0]);
  197.       setdest(midtri, sortarray[1]);
  198.       setorg(tri1, sortarray[1]);
  199.       setdest(tri1, sortarray[0]);
  200.       setorg(tri2, sortarray[2]);
  201.       setdest(tri2, sortarray[1]);
  202.       setorg(tri3, sortarray[1]);
  203.       setdest(tri3, sortarray[2]);
  204.       /* All apices are intentionally left NULL. */
  205.       bond(midtri, tri1);
  206.       bond(tri2, tri3);
  207.       lnextself(midtri);
  208.       lprevself(tri1);
  209.       lnextself(tri2);
  210.       lprevself(tri3);
  211.       bond(midtri, tri3);
  212.       bond(tri1, tri2);
  213.       lnextself(midtri);
  214.       lprevself(tri1);
  215.       lnextself(tri2);
  216.       lprevself(tri3);
  217.       bond(midtri, tri1);
  218.       bond(tri2, tri3);
  219.       /* Ensure that the origin of `farleft' is sortarray[0]. */
  220.       otricopy(tri1, *farleft);
  221.       /* Ensure that the destination of `farright' is sortarray[2]. */
  222.       otricopy(tri2, *farright);
  223.     } else {
  224.       /* The three vertices are not collinear; the triangulation is one */
  225.       /*   triangle, namely `midtri'.                                   */
  226.       setorg(midtri, sortarray[0]);
  227.       setdest(tri1, sortarray[0]);
  228.       setorg(tri3, sortarray[0]);
  229.       /* Apices of tri1, tri2, and tri3 are left NULL. */
  230.       if (area > 0.0) {
  231.         /* The vertices are in counterclockwise order. */
  232.         setdest(midtri, sortarray[1]);
  233.         setorg(tri1, sortarray[1]);
  234.         setdest(tri2, sortarray[1]);
  235.         setapex(midtri, sortarray[2]);
  236.         setorg(tri2, sortarray[2]);
  237.         setdest(tri3, sortarray[2]);
  238.       } else {
  239.         /* The vertices are in clockwise order. */
  240.         setdest(midtri, sortarray[2]);
  241.         setorg(tri1, sortarray[2]);
  242.         setdest(tri2, sortarray[2]);
  243.         setapex(midtri, sortarray[1]);
  244.         setorg(tri2, sortarray[1]);
  245.         setdest(tri3, sortarray[1]);
  246.       }
  247.       /* The topology does not depend on how the vertices are ordered. */
  248.       bond(midtri, tri1);
  249.       lnextself(midtri);
  250.       bond(midtri, tri2);
  251.       lnextself(midtri);
  252.       bond(midtri, tri3);
  253.       lprevself(tri1);
  254.       lnextself(tri2);
  255.       bond(tri1, tri2);
  256.       lprevself(tri1);
  257.       lprevself(tri3);
  258.       bond(tri1, tri3);
  259.       lnextself(tri2);
  260.       lprevself(tri3);
  261.       bond(tri2, tri3);
  262.       /* Ensure that the origin of `farleft' is sortarray[0]. */
  263.       otricopy(tri1, *farleft);
  264.       /* Ensure that the destination of `farright' is sortarray[2]. */
  265.       if (area > 0.0) {
  266.         otricopy(tri2, *farright);
  267.       } else {
  268.         lnext(*farleft, *farright);
  269.       }
  270.     }
  271.     if (b->verbose > 2) {
  272.       printf("  Creating ");
  273.       printtriangle(m, b, &midtri);
  274.       printf("  Creating ");
  275.       printtriangle(m, b, &tri1);
  276.       printf("  Creating ");
  277.       printtriangle(m, b, &tri2);
  278.       printf("  Creating ");
  279.       printtriangle(m, b, &tri3);
  280.     }
  281.     return;
  282.   } else {
  283.     /* Split the vertices in half. */
  284.     divider = vertices >> 1;
  285.     /* Recursively triangulate each half. */
  286.     divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
  287.     divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
  288.                    &innerright, farright);
  289.     if (b->verbose > 1) {
  290.       printf("  Joining triangulations with %d and %d vertices.n", divider,
  291.              vertices - divider);
  292.     }
  293.     /* Merge the two triangulations into one. */
  294.     mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
  295.   }
  296. }
  297. #ifdef ANSI_DECLARATORS
  298. long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
  299. #else /* not ANSI_DECLARATORS */
  300. long removeghosts(m, b, startghost)
  301. struct mesh *m;
  302. struct behavior *b;
  303. struct otri *startghost;
  304. #endif /* not ANSI_DECLARATORS */
  305. {
  306.   struct otri searchedge;
  307.   struct otri dissolveedge;
  308.   struct otri deadtriangle;
  309.   vertex markorg;
  310.   long hullsize;
  311.   triangle ptr;                         /* Temporary variable used by sym(). */
  312.   if (b->verbose) {
  313.     printf("  Removing ghost triangles.n");
  314.   }
  315.   /* Find an edge on the convex hull to start point location from. */
  316.   lprev(*startghost, searchedge);
  317.   symself(searchedge);
  318.   m->dummytri[0] = encode(searchedge);
  319.   /* Remove the bounding box and count the convex hull edges. */
  320.   otricopy(*startghost, dissolveedge);
  321.   hullsize = 0;
  322.   do {
  323.     hullsize++;
  324.     lnext(dissolveedge, deadtriangle);
  325.     lprevself(dissolveedge);
  326.     symself(dissolveedge);
  327.     /* If no PSLG is involved, set the boundary markers of all the vertices */
  328.     /*   on the convex hull.  If a PSLG is used, this step is done later.   */
  329.     if (!b->poly) {
  330.       /* Watch out for the case where all the input vertices are collinear. */
  331.       if (dissolveedge.tri != m->dummytri) {
  332.         org(dissolveedge, markorg);
  333.         if (vertexmark(markorg) == 0) {
  334.           setvertexmark(markorg, 1);
  335.         }
  336.       }
  337.     }
  338.     /* Remove a bounding triangle from a convex hull triangle. */
  339.     dissolve(dissolveedge);
  340.     /* Find the next bounding triangle. */
  341.     sym(deadtriangle, dissolveedge);
  342.     /* Delete the bounding triangle. */
  343.     triangledealloc(m, deadtriangle.tri);
  344.   } while (!otriequal(dissolveedge, *startghost));
  345.   return hullsize;
  346. }
  347. /*****************************************************************************/
  348. /*                                                                           */
  349. /*  divconqdelaunay()   Form a Delaunay triangulation by the divide-and-     */
  350. /*                      conquer method.                                      */
  351. /*                                                                           */
  352. /*  Sorts the vertices, calls a recursive procedure to triangulate them, and */
  353. /*  removes the bounding box, setting boundary markers as appropriate.       */
  354. /*                                                                           */
  355. /*****************************************************************************/
  356. #ifdef ANSI_DECLARATORS
  357. long divconqdelaunay(struct mesh *m, struct behavior *b)
  358. #else /* not ANSI_DECLARATORS */
  359. long divconqdelaunay(m, b)
  360. struct mesh *m;
  361. struct behavior *b;
  362. #endif /* not ANSI_DECLARATORS */
  363. {
  364.   vertex *sortarray;
  365.   struct otri hullleft, hullright;
  366.   int divider;
  367.   int i, j;
  368.   if (b->verbose) {
  369.     printf("  Sorting vertices.n");
  370.   }
  371.   /* Allocate an array of pointers to vertices for sorting. */
  372.   sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
  373.   traversalinit(&m->vertices);
  374.   for (i = 0; i < m->invertices; i++) {
  375.     sortarray[i] = vertextraverse(m);
  376.   }
  377.   /* Sort the vertices. */
  378.   vertexsort(sortarray, m->invertices);
  379.   /* Discard duplicate vertices, which can really mess up the algorithm. */
  380.   i = 0;
  381.   for (j = 1; j < m->invertices; j++) {
  382.     if ((sortarray[i][0] == sortarray[j][0])
  383.         && (sortarray[i][1] == sortarray[j][1])) {
  384.       if (!b->quiet) {
  385.         printf(
  386. "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.n",
  387.                sortarray[j][0], sortarray[j][1]);
  388.       }
  389.       setvertextype(sortarray[j], UNDEADVERTEX);
  390.       m->undeads++;
  391.     } else {
  392.       i++;
  393.       sortarray[i] = sortarray[j];
  394.     }
  395.   }
  396.   i++;
  397.   if (b->dwyer) {
  398.     /* Re-sort the array of vertices to accommodate alternating cuts. */
  399.     divider = i >> 1;
  400.     if (i - divider >= 2) {
  401.       if (divider >= 2) {
  402.         alternateaxes(sortarray, divider, 1);
  403.       }
  404.       alternateaxes(&sortarray[divider], i - divider, 1);
  405.     }
  406.   }
  407.   if (b->verbose) {
  408.     printf("  Forming triangulation.n");
  409.   }
  410.   /* Form the Delaunay triangulation. */
  411.   divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
  412.   trifree((VOID *) sortarray);
  413.   return removeghosts(m, b, &hullleft);
  414. }
  415. /**                                                                         **/
  416. /**                                                                         **/
  417. /********* Divide-and-conquer Delaunay triangulation ends here       *********/
  418. /********* Incremental Delaunay triangulation begins here            *********/
  419. /**                                                                         **/
  420. /**                                                                         **/
  421. /*****************************************************************************/
  422. /*                                                                           */
  423. /*  boundingbox()   Form an "infinite" bounding triangle to insert vertices  */
  424. /*                  into.                                                    */
  425. /*                                                                           */
  426. /*  The vertices at "infinity" are assigned finite coordinates, which are    */
  427. /*  used by the point location routines, but (mostly) ignored by the         */
  428. /*  Delaunay edge flip routines.                                             */
  429. /*                                                                           */
  430. /*****************************************************************************/
  431. #ifndef REDUCED
  432. #ifdef ANSI_DECLARATORS
  433. void boundingbox(struct mesh *m, struct behavior *b)
  434. #else /* not ANSI_DECLARATORS */
  435. void boundingbox(m, b)
  436. struct mesh *m;
  437. struct behavior *b;
  438. #endif /* not ANSI_DECLARATORS */
  439. {
  440.   struct otri inftri;          /* Handle for the triangular bounding box. */
  441.   REAL width;
  442.   if (b->verbose) {
  443.     printf("  Creating triangular bounding box.n");
  444.   }
  445.   /* Find the width (or height, whichever is larger) of the triangulation. */
  446.   width = m->xmax - m->xmin;
  447.   if (m->ymax - m->ymin > width) {
  448.     width = m->ymax - m->ymin;
  449.   }
  450.   if (width == 0.0) {
  451.     width = 1.0;
  452.   }
  453.   /* Create the vertices of the bounding box. */
  454.   m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
  455.   m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
  456.   m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
  457.   m->infvertex1[0] = m->xmin - 50.0 * width;
  458.   m->infvertex1[1] = m->ymin - 40.0 * width;
  459.   m->infvertex2[0] = m->xmax + 50.0 * width;
  460.   m->infvertex2[1] = m->ymin - 40.0 * width;
  461.   m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
  462.   m->infvertex3[1] = m->ymax + 60.0 * width;
  463.   /* Create the bounding box. */
  464.   maketriangle(m, b, &inftri);
  465.   setorg(inftri, m->infvertex1);
  466.   setdest(inftri, m->infvertex2);
  467.   setapex(inftri, m->infvertex3);
  468.   /* Link dummytri to the bounding box so we can always find an */
  469.   /*   edge to begin searching (point location) from.           */
  470.   m->dummytri[0] = (triangle) inftri.tri;
  471.   if (b->verbose > 2) {
  472.     printf("  Creating ");
  473.     printtriangle(m, b, &inftri);
  474.   }
  475. }
  476. #endif /* not REDUCED */
  477. /*****************************************************************************/
  478. /*                                                                           */
  479. /*  removebox()   Remove the "infinite" bounding triangle, setting boundary  */
  480. /*                markers as appropriate.                                    */
  481. /*                                                                           */
  482. /*  The triangular bounding box has three boundary triangles (one for each   */
  483. /*  side of the bounding box), and a bunch of triangles fanning out from     */
  484. /*  the three bounding box vertices (one triangle for each edge of the       */
  485. /*  convex hull of the inner mesh).  This routine removes these triangles.   */
  486. /*                                                                           */
  487. /*  Returns the number of edges on the convex hull of the triangulation.     */
  488. /*                                                                           */
  489. /*****************************************************************************/
  490. #ifndef REDUCED
  491. #ifdef ANSI_DECLARATORS
  492. long removebox(struct mesh *m, struct behavior *b)
  493. #else /* not ANSI_DECLARATORS */
  494. long removebox(m, b)
  495. struct mesh *m;
  496. struct behavior *b;
  497. #endif /* not ANSI_DECLARATORS */
  498. {
  499.   struct otri deadtriangle;
  500.   struct otri searchedge;
  501.   struct otri checkedge;
  502.   struct otri nextedge, finaledge, dissolveedge;
  503.   vertex markorg;
  504.   long hullsize;
  505.   triangle ptr;                         /* Temporary variable used by sym(). */
  506.   if (b->verbose) {
  507.     printf("  Removing triangular bounding box.n");
  508.   }
  509.   /* Find a boundary triangle. */
  510.   nextedge.tri = m->dummytri;
  511.   nextedge.orient = 0;
  512.   symself(nextedge);
  513.   /* Mark a place to stop. */
  514.   lprev(nextedge, finaledge);
  515.   lnextself(nextedge);
  516.   symself(nextedge);
  517.   /* Find a triangle (on the boundary of the vertex set) that isn't */
  518.   /*   a bounding box triangle.                                     */
  519.   lprev(nextedge, searchedge);
  520.   symself(searchedge);
  521.   /* Check whether nextedge is another boundary triangle */
  522.   /*   adjacent to the first one.                        */
  523.   lnext(nextedge, checkedge);
  524.   symself(checkedge);
  525.   if (checkedge.tri == m->dummytri) {
  526.     /* Go on to the next triangle.  There are only three boundary   */
  527.     /*   triangles, and this next triangle cannot be the third one, */
  528.     /*   so it's safe to stop here.                                 */
  529.     lprevself(searchedge);
  530.     symself(searchedge);
  531.   }
  532.   /* Find a new boundary edge to search from, as the current search */
  533.   /*   edge lies on a bounding box triangle and will be deleted.    */
  534.   m->dummytri[0] = encode(searchedge);
  535.   hullsize = -2l;
  536.   while (!otriequal(nextedge, finaledge)) {
  537.     hullsize++;
  538.     lprev(nextedge, dissolveedge);
  539.     symself(dissolveedge);
  540.     /* If not using a PSLG, the vertices should be marked now. */
  541.     /*   (If using a PSLG, markhull() will do the job.)        */
  542.     if (!b->poly) {
  543.       /* Be careful!  One must check for the case where all the input     */
  544.       /*   vertices are collinear, and thus all the triangles are part of */
  545.       /*   the bounding box.  Otherwise, the setvertexmark() call below   */
  546.       /*   will cause a bad pointer reference.                            */
  547.       if (dissolveedge.tri != m->dummytri) {
  548.         org(dissolveedge, markorg);
  549.         if (vertexmark(markorg) == 0) {
  550.           setvertexmark(markorg, 1);
  551.         }
  552.       }
  553.     }
  554.     /* Disconnect the bounding box triangle from the mesh triangle. */
  555.     dissolve(dissolveedge);
  556.     lnext(nextedge, deadtriangle);
  557.     sym(deadtriangle, nextedge);
  558.     /* Get rid of the bounding box triangle. */
  559.     triangledealloc(m, deadtriangle.tri);
  560.     /* Do we need to turn the corner? */
  561.     if (nextedge.tri == m->dummytri) {
  562.       /* Turn the corner. */
  563.       otricopy(dissolveedge, nextedge);
  564.     }
  565.   }
  566.   triangledealloc(m, finaledge.tri);
  567.   trifree((VOID *) m->infvertex1);  /* Deallocate the bounding box vertices. */
  568.   trifree((VOID *) m->infvertex2);
  569.   trifree((VOID *) m->infvertex3);
  570.   return hullsize;
  571. }
  572. #endif /* not REDUCED */
  573. /*****************************************************************************/
  574. /*                                                                           */
  575. /*  incrementaldelaunay()   Form a Delaunay triangulation by incrementally   */
  576. /*                          inserting vertices.                              */
  577. /*                                                                           */
  578. /*  Returns the number of edges on the convex hull of the triangulation.     */
  579. /*                                                                           */
  580. /*****************************************************************************/
  581. #ifndef REDUCED
  582. #ifdef ANSI_DECLARATORS
  583. long incrementaldelaunay(struct mesh *m, struct behavior *b)
  584. #else /* not ANSI_DECLARATORS */
  585. long incrementaldelaunay(m, b)
  586. struct mesh *m;
  587. struct behavior *b;
  588. #endif /* not ANSI_DECLARATORS */
  589. {
  590.   struct otri starttri;
  591.   vertex vertexloop;
  592.   /* Create a triangular bounding box. */
  593.   boundingbox(m, b);
  594.   if (b->verbose) {
  595.     printf("  Incrementally inserting vertices.n");
  596.   }
  597.   traversalinit(&m->vertices);
  598.   vertexloop = vertextraverse(m);
  599.   while (vertexloop != (vertex) NULL) {
  600.     starttri.tri = m->dummytri;
  601.     if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
  602.         == DUPLICATEVERTEX) {
  603.       if (!b->quiet) {
  604.         printf(
  605. "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.n",
  606.                vertexloop[0], vertexloop[1]);
  607.       }
  608.       setvertextype(vertexloop, UNDEADVERTEX);
  609.       m->undeads++;
  610.     }
  611.     vertexloop = vertextraverse(m);
  612.   }
  613.   /* Remove the bounding box. */
  614.   return removebox(m, b);
  615. }
  616. #endif /* not REDUCED */
  617. /**                                                                         **/
  618. /**                                                                         **/
  619. /********* Incremental Delaunay triangulation ends here              *********/
  620. /********* Sweepline Delaunay triangulation begins here              *********/
  621. /**                                                                         **/
  622. /**                                                                         **/
  623. #ifndef REDUCED
  624. #ifdef ANSI_DECLARATORS
  625. void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
  626. #else /* not ANSI_DECLARATORS */
  627. void eventheapinsert(heap, heapsize, newevent)
  628. struct event **heap;
  629. int heapsize;
  630. struct event *newevent;
  631. #endif /* not ANSI_DECLARATORS */
  632. {
  633.   REAL eventx, eventy;
  634.   int eventnum;
  635.   int parent;
  636.   int notdone;
  637.   eventx = newevent->xkey;
  638.   eventy = newevent->ykey;
  639.   eventnum = heapsize;
  640.   notdone = eventnum > 0;
  641.   while (notdone) {
  642.     parent = (eventnum - 1) >> 1;
  643.     if ((heap[parent]->ykey < eventy) ||
  644.         ((heap[parent]->ykey == eventy)
  645.          && (heap[parent]->xkey <= eventx))) {
  646.       notdone = 0;
  647.     } else {
  648.       heap[eventnum] = heap[parent];
  649.       heap[eventnum]->heapposition = eventnum;
  650.       eventnum = parent;
  651.       notdone = eventnum > 0;
  652.     }
  653.   }
  654.   heap[eventnum] = newevent;
  655.   newevent->heapposition = eventnum;
  656. }
  657. #endif /* not REDUCED */
  658. #ifndef REDUCED
  659. #ifdef ANSI_DECLARATORS
  660. void eventheapify(struct event **heap, int heapsize, int eventnum)
  661. #else /* not ANSI_DECLARATORS */
  662. void eventheapify(heap, heapsize, eventnum)
  663. struct event **heap;
  664. int heapsize;
  665. int eventnum;
  666. #endif /* not ANSI_DECLARATORS */
  667. {
  668.   struct event *thisevent;
  669.   REAL eventx, eventy;
  670.   int leftchild, rightchild;
  671.   int smallest;
  672.   int notdone;
  673.   thisevent = heap[eventnum];
  674.   eventx = thisevent->xkey;
  675.   eventy = thisevent->ykey;
  676.   leftchild = 2 * eventnum + 1;
  677.   notdone = leftchild < heapsize;
  678.   while (notdone) {
  679.     if ((heap[leftchild]->ykey < eventy) ||
  680.         ((heap[leftchild]->ykey == eventy)
  681.          && (heap[leftchild]->xkey < eventx))) {
  682.       smallest = leftchild;
  683.     } else {
  684.       smallest = eventnum;
  685.     }
  686.     rightchild = leftchild + 1;
  687.     if (rightchild < heapsize) {
  688.       if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
  689.           ((heap[rightchild]->ykey == heap[smallest]->ykey)
  690.            && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
  691.         smallest = rightchild;
  692.       }
  693.     }
  694.     if (smallest == eventnum) {
  695.       notdone = 0;
  696.     } else {
  697.       heap[eventnum] = heap[smallest];
  698.       heap[eventnum]->heapposition = eventnum;
  699.       heap[smallest] = thisevent;
  700.       thisevent->heapposition = smallest;
  701.       eventnum = smallest;
  702.       leftchild = 2 * eventnum + 1;
  703.       notdone = leftchild < heapsize;
  704.     }
  705.   }
  706. }
  707. #endif /* not REDUCED */
  708. #ifndef REDUCED
  709. #ifdef ANSI_DECLARATORS
  710. void eventheapdelete(struct event **heap, int heapsize, int eventnum)
  711. #else /* not ANSI_DECLARATORS */
  712. void eventheapdelete(heap, heapsize, eventnum)
  713. struct event **heap;
  714. int heapsize;
  715. int eventnum;
  716. #endif /* not ANSI_DECLARATORS */
  717. {
  718.   struct event *moveevent;
  719.   REAL eventx, eventy;
  720.   int parent;
  721.   int notdone;
  722.   moveevent = heap[heapsize - 1];
  723.   if (eventnum > 0) {
  724.     eventx = moveevent->xkey;
  725.     eventy = moveevent->ykey;
  726.     do {
  727.       parent = (eventnum - 1) >> 1;
  728.       if ((heap[parent]->ykey < eventy) ||
  729.           ((heap[parent]->ykey == eventy)
  730.            && (heap[parent]->xkey <= eventx))) {
  731.         notdone = 0;
  732.       } else {
  733.         heap[eventnum] = heap[parent];
  734.         heap[eventnum]->heapposition = eventnum;
  735.         eventnum = parent;
  736.         notdone = eventnum > 0;
  737.       }
  738.     } while (notdone);
  739.   }
  740.   heap[eventnum] = moveevent;
  741.   moveevent->heapposition = eventnum;
  742.   eventheapify(heap, heapsize - 1, eventnum);
  743. }
  744. #endif /* not REDUCED */
  745. #ifndef REDUCED
  746. #ifdef ANSI_DECLARATORS
  747. void createeventheap(struct mesh *m, struct event ***eventheap,
  748.                      struct event **events, struct event **freeevents)
  749. #else /* not ANSI_DECLARATORS */
  750. void createeventheap(m, eventheap, events, freeevents)
  751. struct mesh *m;
  752. struct event ***eventheap;
  753. struct event **events;
  754. struct event **freeevents;
  755. #endif /* not ANSI_DECLARATORS */
  756. {
  757.   vertex thisvertex;
  758.   int maxevents;
  759.   int i;
  760.   maxevents = (3 * m->invertices) / 2;
  761.   *eventheap = (struct event **) trimalloc(maxevents *
  762.                                            (int) sizeof(struct event *));
  763.   *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
  764.   traversalinit(&m->vertices);
  765.   for (i = 0; i < m->invertices; i++) {
  766.     thisvertex = vertextraverse(m);
  767.     (*events)[i].eventptr = (VOID *) thisvertex;
  768.     (*events)[i].xkey = thisvertex[0];
  769.     (*events)[i].ykey = thisvertex[1];
  770.     eventheapinsert(*eventheap, i, *events + i);
  771.   }
  772.   *freeevents = (struct event *) NULL;
  773.   for (i = maxevents - 1; i >= m->invertices; i--) {
  774.     (*events)[i].eventptr = (VOID *) *freeevents;
  775.     *freeevents = *events + i;
  776.   }
  777. }
  778. #endif /* not REDUCED */
  779. #ifndef REDUCED
  780. #ifdef ANSI_DECLARATORS
  781. int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
  782. #else /* not ANSI_DECLARATORS */
  783. int rightofhyperbola(m, fronttri, newsite)
  784. struct mesh *m;
  785. struct otri *fronttri;
  786. vertex newsite;
  787. #endif /* not ANSI_DECLARATORS */
  788. {
  789.   vertex leftvertex, rightvertex;
  790.   REAL dxa, dya, dxb, dyb;
  791.   m->hyperbolacount++;
  792.   dest(*fronttri, leftvertex);
  793.   apex(*fronttri, rightvertex);
  794.   if ((leftvertex[1] < rightvertex[1]) ||
  795.       ((leftvertex[1] == rightvertex[1]) &&
  796.        (leftvertex[0] < rightvertex[0]))) {
  797.     if (newsite[0] >= rightvertex[0]) {
  798.       return 1;
  799.     }
  800.   } else {
  801.     if (newsite[0] <= leftvertex[0]) {
  802.       return 0;
  803.     }
  804.   }
  805.   dxa = leftvertex[0] - newsite[0];
  806.   dya = leftvertex[1] - newsite[1];
  807.   dxb = rightvertex[0] - newsite[0];
  808.   dyb = rightvertex[1] - newsite[1];
  809.   return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
  810. }
  811. #endif /* not REDUCED */
  812. #ifndef REDUCED
  813. #ifdef ANSI_DECLARATORS
  814. REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
  815. #else /* not ANSI_DECLARATORS */
  816. REAL circletop(m, pa, pb, pc, ccwabc)
  817. struct mesh *m;
  818. vertex pa;
  819. vertex pb;
  820. vertex pc;
  821. REAL ccwabc;
  822. #endif /* not ANSI_DECLARATORS */
  823. {
  824.   REAL xac, yac, xbc, ybc, xab, yab;
  825.   REAL aclen2, bclen2, ablen2;
  826.   m->circletopcount++;
  827.   xac = pa[0] - pc[0];
  828.   yac = pa[1] - pc[1];
  829.   xbc = pb[0] - pc[0];
  830.   ybc = pb[1] - pc[1];
  831.   xab = pa[0] - pb[0];
  832.   yab = pa[1] - pb[1];
  833.   aclen2 = xac * xac + yac * yac;
  834.   bclen2 = xbc * xbc + ybc * ybc;
  835.   ablen2 = xab * xab + yab * yab;
  836.   return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
  837.                / (2.0 * ccwabc);
  838. }
  839. #endif /* not REDUCED */
  840. #ifndef REDUCED
  841. #ifdef ANSI_DECLARATORS
  842. void check4deadevent(struct otri *checktri, struct event **freeevents,
  843.                      struct event **eventheap, int *heapsize)
  844. #else /* not ANSI_DECLARATORS */
  845. void check4deadevent(checktri, freeevents, eventheap, heapsize)
  846. struct otri *checktri;
  847. struct event **freeevents;
  848. struct event **eventheap;
  849. int *heapsize;
  850. #endif /* not ANSI_DECLARATORS */
  851. {
  852.   struct event *deadevent;
  853.   vertex eventvertex;
  854.   int eventnum;
  855.   org(*checktri, eventvertex);
  856.   if (eventvertex != (vertex) NULL) {
  857.     deadevent = (struct event *) eventvertex;
  858.     eventnum = deadevent->heapposition;
  859.     deadevent->eventptr = (VOID *) *freeevents;
  860.     *freeevents = deadevent;
  861.     eventheapdelete(eventheap, *heapsize, eventnum);
  862.     (*heapsize)--;
  863.     setorg(*checktri, NULL);
  864.   }
  865. }
  866. #endif /* not REDUCED */
  867. #ifndef REDUCED
  868. #ifdef ANSI_DECLARATORS
  869. struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
  870.                         vertex searchpoint, struct otri *searchtri)
  871. #else /* not ANSI_DECLARATORS */
  872. struct splaynode *splay(m, splaytree, searchpoint, searchtri)
  873. struct mesh *m;
  874. struct splaynode *splaytree;
  875. vertex searchpoint;
  876. struct otri *searchtri;
  877. #endif /* not ANSI_DECLARATORS */
  878. {
  879.   struct splaynode *child, *grandchild;
  880.   struct splaynode *lefttree, *righttree;
  881.   struct splaynode *leftright;
  882.   vertex checkvertex;
  883.   int rightofroot, rightofchild;
  884.   if (splaytree == (struct splaynode *) NULL) {
  885.     return (struct splaynode *) NULL;
  886.   }
  887.   dest(splaytree->keyedge, checkvertex);
  888.   if (checkvertex == splaytree->keydest) {
  889.     rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
  890.     if (rightofroot) {
  891.       otricopy(splaytree->keyedge, *searchtri);
  892.       child = splaytree->rchild;
  893.     } else {
  894.       child = splaytree->lchild;
  895.     }
  896.     if (child == (struct splaynode *) NULL) {
  897.       return splaytree;
  898.     }
  899.     dest(child->keyedge, checkvertex);
  900.     if (checkvertex != child->keydest) {
  901.       child = splay(m, child, searchpoint, searchtri);
  902.       if (child == (struct splaynode *) NULL) {
  903.         if (rightofroot) {
  904.           splaytree->rchild = (struct splaynode *) NULL;
  905.         } else {
  906.           splaytree->lchild = (struct splaynode *) NULL;
  907.         }
  908.         return splaytree;
  909.       }
  910.     }
  911.     rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
  912.     if (rightofchild) {
  913.       otricopy(child->keyedge, *searchtri);
  914.       grandchild = splay(m, child->rchild, searchpoint, searchtri);
  915.       child->rchild = grandchild;
  916.     } else {
  917.       grandchild = splay(m, child->lchild, searchpoint, searchtri);
  918.       child->lchild = grandchild;
  919.     }
  920.     if (grandchild == (struct splaynode *) NULL) {
  921.       if (rightofroot) {
  922.         splaytree->rchild = child->lchild;
  923.         child->lchild = splaytree;
  924.       } else {
  925.         splaytree->lchild = child->rchild;
  926.         child->rchild = splaytree;
  927.       }
  928.       return child;
  929.     }
  930.     if (rightofchild) {
  931.       if (rightofroot) {
  932.         splaytree->rchild = child->lchild;
  933.         child->lchild = splaytree;
  934.       } else {
  935.         splaytree->lchild = grandchild->rchild;
  936.         grandchild->rchild = splaytree;
  937.       }
  938.       child->rchild = grandchild->lchild;
  939.       grandchild->lchild = child;
  940.     } else {
  941.       if (rightofroot) {
  942.         splaytree->rchild = grandchild->lchild;
  943.         grandchild->lchild = splaytree;
  944.       } else {
  945.         splaytree->lchild = child->rchild;
  946.         child->rchild = splaytree;
  947.       }
  948.       child->lchild = grandchild->rchild;
  949.       grandchild->rchild = child;
  950.     }
  951.     return grandchild;
  952.   } else {
  953.     lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
  954.     righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
  955.     pooldealloc(&m->splaynodes, (VOID *) splaytree);
  956.     if (lefttree == (struct splaynode *) NULL) {
  957.       return righttree;
  958.     } else if (righttree == (struct splaynode *) NULL) {
  959.       return lefttree;
  960.     } else if (lefttree->rchild == (struct splaynode *) NULL) {
  961.       lefttree->rchild = righttree->lchild;
  962.       righttree->lchild = lefttree;
  963.       return righttree;
  964.     } else if (righttree->lchild == (struct splaynode *) NULL) {
  965.       righttree->lchild = lefttree->rchild;
  966.       lefttree->rchild = righttree;
  967.       return lefttree;
  968.     } else {
  969. /*      printf("Holy Toledo!!!n"); */
  970.       leftright = lefttree->rchild;
  971.       while (leftright->rchild != (struct splaynode *) NULL) {
  972.         leftright = leftright->rchild;
  973.       }
  974.       leftright->rchild = righttree;
  975.       return lefttree;
  976.     }
  977.   }
  978. }
  979. #endif /* not REDUCED */
  980. #ifndef REDUCED
  981. #ifdef ANSI_DECLARATORS
  982. struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
  983.                               struct otri *newkey, vertex searchpoint)
  984. #else /* not ANSI_DECLARATORS */
  985. struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
  986. struct mesh *m;
  987. struct splaynode *splayroot;
  988. struct otri *newkey;
  989. vertex searchpoint;
  990. #endif /* not ANSI_DECLARATORS */
  991. {
  992.   struct splaynode *newsplaynode;
  993.   newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
  994.   otricopy(*newkey, newsplaynode->keyedge);
  995.   dest(*newkey, newsplaynode->keydest);
  996.   if (splayroot == (struct splaynode *) NULL) {
  997.     newsplaynode->lchild = (struct splaynode *) NULL;
  998.     newsplaynode->rchild = (struct splaynode *) NULL;
  999.   } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
  1000.     newsplaynode->lchild = splayroot;
  1001.     newsplaynode->rchild = splayroot->rchild;
  1002.     splayroot->rchild = (struct splaynode *) NULL;
  1003.   } else {
  1004.     newsplaynode->lchild = splayroot->lchild;
  1005.     newsplaynode->rchild = splayroot;
  1006.     splayroot->lchild = (struct splaynode *) NULL;
  1007.   }
  1008.   return newsplaynode;
  1009. }
  1010. #endif /* not REDUCED */
  1011. #ifndef REDUCED
  1012. #ifdef ANSI_DECLARATORS
  1013. struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
  1014.                                   struct splaynode *splayroot,
  1015.                                   struct otri *newkey,
  1016.                                   vertex pa, vertex pb, vertex pc, REAL topy)
  1017. #else /* not ANSI_DECLARATORS */
  1018. struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
  1019. struct mesh *m;
  1020. struct behavior *b;
  1021. struct splaynode *splayroot;
  1022. struct otri *newkey;
  1023. vertex pa;
  1024. vertex pb;
  1025. vertex pc;
  1026. REAL topy;
  1027. #endif /* not ANSI_DECLARATORS */
  1028. {
  1029.   REAL ccwabc;
  1030.   REAL xac, yac, xbc, ybc;
  1031.   REAL aclen2, bclen2;
  1032.   REAL searchpoint[2];
  1033.   struct otri dummytri;
  1034.   ccwabc = counterclockwise(m, b, pa, pb, pc);
  1035.   xac = pa[0] - pc[0];
  1036.   yac = pa[1] - pc[1];
  1037.   xbc = pb[0] - pc[0];
  1038.   ybc = pb[1] - pc[1];
  1039.   aclen2 = xac * xac + yac * yac;
  1040.   bclen2 = xbc * xbc + ybc * ybc;
  1041.   searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
  1042.   searchpoint[1] = topy;
  1043.   return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
  1044.                      newkey, (vertex) searchpoint);
  1045. }
  1046. #endif /* not REDUCED */
  1047. #ifndef REDUCED
  1048. #ifdef ANSI_DECLARATORS
  1049. struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
  1050.                               struct otri *bottommost, vertex searchvertex,
  1051.                               struct otri *searchtri, int *farright)
  1052. #else /* not ANSI_DECLARATORS */
  1053. struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
  1054.                               searchtri, farright)
  1055. struct mesh *m;
  1056. struct splaynode *splayroot;
  1057. struct otri *bottommost;
  1058. vertex searchvertex;
  1059. struct otri *searchtri;
  1060. int *farright;
  1061. #endif /* not ANSI_DECLARATORS */
  1062. {
  1063.   int farrightflag;
  1064.   triangle ptr;                       /* Temporary variable used by onext(). */
  1065.   otricopy(*bottommost, *searchtri);
  1066.   splayroot = splay(m, splayroot, searchvertex, searchtri);
  1067.   farrightflag = 0;
  1068.   while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
  1069.     onextself(*searchtri);
  1070.     farrightflag = otriequal(*searchtri, *bottommost);
  1071.   }
  1072.   *farright = farrightflag;
  1073.   return splayroot;
  1074. }
  1075. #endif /* not REDUCED */
  1076. #ifndef REDUCED
  1077. #ifdef ANSI_DECLARATORS
  1078. long sweeplinedelaunay(struct mesh *m, struct behavior *b)
  1079. #else /* not ANSI_DECLARATORS */
  1080. long sweeplinedelaunay(m, b)
  1081. struct mesh *m;
  1082. struct behavior *b;
  1083. #endif /* not ANSI_DECLARATORS */
  1084. {
  1085.   struct event **eventheap;
  1086.   struct event *events;
  1087.   struct event *freeevents;
  1088.   struct event *nextevent;
  1089.   struct event *newevent;
  1090.   struct splaynode *splayroot;
  1091.   struct otri bottommost;
  1092.   struct otri searchtri;
  1093.   struct otri fliptri;
  1094.   struct otri lefttri, righttri, farlefttri, farrighttri;
  1095.   struct otri inserttri;
  1096.   vertex firstvertex, secondvertex;
  1097.   vertex nextvertex, lastvertex;
  1098.   vertex connectvertex;
  1099.   vertex leftvertex, midvertex, rightvertex;
  1100.   REAL lefttest, righttest;
  1101.   int heapsize;
  1102.   int check4events, farrightflag;
  1103.   triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
  1104.   poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
  1105.            SPLAYNODEPERBLOCK, 0);
  1106.   splayroot = (struct splaynode *) NULL;
  1107.   if (b->verbose) {
  1108.     printf("  Placing vertices in event heap.n");
  1109.   }
  1110.   createeventheap(m, &eventheap, &events, &freeevents);
  1111.   heapsize = m->invertices;
  1112.   if (b->verbose) {
  1113.     printf("  Forming triangulation.n");
  1114.   }
  1115.   maketriangle(m, b, &lefttri);
  1116.   maketriangle(m, b, &righttri);
  1117.   bond(lefttri, righttri);
  1118.   lnextself(lefttri);
  1119.   lprevself(righttri);
  1120.   bond(lefttri, righttri);
  1121.   lnextself(lefttri);
  1122.   lprevself(righttri);
  1123.   bond(lefttri, righttri);
  1124.   firstvertex = (vertex) eventheap[0]->eventptr;
  1125.   eventheap[0]->eventptr = (VOID *) freeevents;
  1126.   freeevents = eventheap[0];
  1127.   eventheapdelete(eventheap, heapsize, 0);
  1128.   heapsize--;
  1129.   do {
  1130.     if (heapsize == 0) {
  1131.       printf("Error:  Input vertices are all identical.n");
  1132.       triexit(1);
  1133.     }
  1134.     secondvertex = (vertex) eventheap[0]->eventptr;
  1135.     eventheap[0]->eventptr = (VOID *) freeevents;
  1136.     freeevents = eventheap[0];
  1137.     eventheapdelete(eventheap, heapsize, 0);
  1138.     heapsize--;
  1139.     if ((firstvertex[0] == secondvertex[0]) &&
  1140.         (firstvertex[1] == secondvertex[1])) {
  1141.       if (!b->quiet) {
  1142.         printf(
  1143. "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.n",
  1144.                secondvertex[0], secondvertex[1]);
  1145.       }
  1146.       setvertextype(secondvertex, UNDEADVERTEX);
  1147.       m->undeads++;
  1148.     }
  1149.   } while ((firstvertex[0] == secondvertex[0]) &&
  1150.            (firstvertex[1] == secondvertex[1]));
  1151.   setorg(lefttri, firstvertex);
  1152.   setdest(lefttri, secondvertex);
  1153.   setorg(righttri, secondvertex);
  1154.   setdest(righttri, firstvertex);
  1155.   lprev(lefttri, bottommost);
  1156.   lastvertex = secondvertex;
  1157.   while (heapsize > 0) {
  1158.     nextevent = eventheap[0];
  1159.     eventheapdelete(eventheap, heapsize, 0);
  1160.     heapsize--;
  1161.     check4events = 1;
  1162.     if (nextevent->xkey < m->xmin) {
  1163.       decode(nextevent->eventptr, fliptri);
  1164.       oprev(fliptri, farlefttri);
  1165.       check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
  1166.       onext(fliptri, farrighttri);
  1167.       check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
  1168.       if (otriequal(farlefttri, bottommost)) {
  1169.         lprev(fliptri, bottommost);
  1170.       }
  1171.       flip(m, b, &fliptri);
  1172.       setapex(fliptri, NULL);
  1173.       lprev(fliptri, lefttri);
  1174.       lnext(fliptri, righttri);
  1175.       sym(lefttri, farlefttri);
  1176.       if (randomnation(SAMPLERATE) == 0) {
  1177.         symself(fliptri);
  1178.         dest(fliptri, leftvertex);
  1179.         apex(fliptri, midvertex);
  1180.         org(fliptri, rightvertex);
  1181.         splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
  1182.                                     midvertex, rightvertex, nextevent->ykey);
  1183.       }
  1184.     } else {
  1185.       nextvertex = (vertex) nextevent->eventptr;
  1186.       if ((nextvertex[0] == lastvertex[0]) &&
  1187.           (nextvertex[1] == lastvertex[1])) {
  1188.         if (!b->quiet) {
  1189.           printf(
  1190. "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.n",
  1191.                  nextvertex[0], nextvertex[1]);
  1192.         }
  1193.         setvertextype(nextvertex, UNDEADVERTEX);
  1194.         m->undeads++;
  1195.         check4events = 0;
  1196.       } else {
  1197.         lastvertex = nextvertex;
  1198.         splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
  1199.                                 &searchtri, &farrightflag);
  1200. /*
  1201.         otricopy(bottommost, searchtri);
  1202.         farrightflag = 0;
  1203.         while (!farrightflag && rightofhyperbola(m, &searchtri, nextvertex)) {
  1204.           onextself(searchtri);
  1205.           farrightflag = otriequal(searchtri, bottommost);
  1206.         }
  1207. */
  1208.         check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
  1209.         otricopy(searchtri, farrighttri);
  1210.         sym(searchtri, farlefttri);
  1211.         maketriangle(m, b, &lefttri);
  1212.         maketriangle(m, b, &righttri);
  1213.         dest(farrighttri, connectvertex);
  1214.         setorg(lefttri, connectvertex);
  1215.         setdest(lefttri, nextvertex);
  1216.         setorg(righttri, nextvertex);
  1217.         setdest(righttri, connectvertex);
  1218.         bond(lefttri, righttri);
  1219.         lnextself(lefttri);
  1220.         lprevself(righttri);
  1221.         bond(lefttri, righttri);
  1222.         lnextself(lefttri);
  1223.         lprevself(righttri);
  1224.         bond(lefttri, farlefttri);
  1225.         bond(righttri, farrighttri);
  1226.         if (!farrightflag && otriequal(farrighttri, bottommost)) {
  1227.           otricopy(lefttri, bottommost);
  1228.         }
  1229.         if (randomnation(SAMPLERATE) == 0) {
  1230.           splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
  1231.         } else if (randomnation(SAMPLERATE) == 0) {
  1232.           lnext(righttri, inserttri);
  1233.           splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
  1234.         }
  1235.       }
  1236.     }
  1237.     nextevent->eventptr = (VOID *) freeevents;
  1238.     freeevents = nextevent;
  1239.     if (check4events) {
  1240.       apex(farlefttri, leftvertex);
  1241.       dest(lefttri, midvertex);
  1242.       apex(lefttri, rightvertex);
  1243.       lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
  1244.       if (lefttest > 0.0) {
  1245.         newevent = freeevents;
  1246.         freeevents = (struct event *) freeevents->eventptr;
  1247.         newevent->xkey = m->xminextreme;
  1248.         newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
  1249.                                    lefttest);
  1250.         newevent->eventptr = (VOID *) encode(lefttri);
  1251.         eventheapinsert(eventheap, heapsize, newevent);
  1252.         heapsize++;
  1253.         setorg(lefttri, newevent);
  1254.       }
  1255.       apex(righttri, leftvertex);
  1256.       org(righttri, midvertex);
  1257.       apex(farrighttri, rightvertex);
  1258.       righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
  1259.       if (righttest > 0.0) {
  1260.         newevent = freeevents;
  1261.         freeevents = (struct event *) freeevents->eventptr;
  1262.         newevent->xkey = m->xminextreme;
  1263.         newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
  1264.                                    righttest);
  1265.         newevent->eventptr = (VOID *) encode(farrighttri);
  1266.         eventheapinsert(eventheap, heapsize, newevent);
  1267.         heapsize++;
  1268.         setorg(farrighttri, newevent);
  1269.       }
  1270.     }
  1271.   }
  1272.   pooldeinit(&m->splaynodes);
  1273.   lprevself(bottommost);
  1274.   return removeghosts(m, b, &bottommost);
  1275. }
  1276. #endif /* not REDUCED */
  1277. /**                                                                         **/
  1278. /**                                                                         **/
  1279. /********* Sweepline Delaunay triangulation ends here                *********/
  1280. /********* General mesh construction routines begin here             *********/
  1281. /**                                                                         **/
  1282. /**                                                                         **/
  1283. /*****************************************************************************/
  1284. /*                                                                           */
  1285. /*  delaunay()   Form a Delaunay triangulation.                              */
  1286. /*                                                                           */
  1287. /*****************************************************************************/
  1288. #ifdef ANSI_DECLARATORS
  1289. long delaunay(struct mesh *m, struct behavior *b)
  1290. #else /* not ANSI_DECLARATORS */
  1291. long delaunay(m, b)
  1292. struct mesh *m;
  1293. struct behavior *b;
  1294. #endif /* not ANSI_DECLARATORS */
  1295. {
  1296.   long hulledges;
  1297.   m->eextras = 0;
  1298.   initializetrisubpools(m, b);
  1299. #ifdef REDUCED
  1300.   if (!b->quiet) {
  1301.     printf(
  1302.       "Constructing Delaunay triangulation by divide-and-conquer method.n");
  1303.   }
  1304.   hulledges = divconqdelaunay(m, b);
  1305. #else /* not REDUCED */
  1306.   if (!b->quiet) {
  1307.     printf("Constructing Delaunay triangulation ");
  1308.     if (b->incremental) {
  1309.       printf("by incremental method.n");
  1310.     } else if (b->sweepline) {
  1311.       printf("by sweepline method.n");
  1312.     } else {
  1313.       printf("by divide-and-conquer method.n");
  1314.     }
  1315.   }
  1316.   if (b->incremental) {
  1317.     hulledges = incrementaldelaunay(m, b);
  1318.   } else if (b->sweepline) {
  1319.     hulledges = sweeplinedelaunay(m, b);
  1320.   } else {
  1321.     hulledges = divconqdelaunay(m, b);
  1322.   }
  1323. #endif /* not REDUCED */
  1324.   if (m->triangles.items == 0) {
  1325.     /* The input vertices were all collinear, so there are no triangles. */
  1326.     return 0l;
  1327.   } else {
  1328.     return hulledges;
  1329.   }
  1330. }
  1331. /*****************************************************************************/
  1332. /*                                                                           */
  1333. /*  reconstruct()   Reconstruct a triangulation from its .ele (and possibly  */
  1334. /*                  .poly) file.  Used when the -r switch is used.           */
  1335. /*                                                                           */
  1336. /*  Reads an .ele file and reconstructs the original mesh.  If the -p switch */
  1337. /*  is used, this procedure will also read a .poly file and reconstruct the  */
  1338. /*  subsegments of the original mesh.  If the -a switch is used, this        */
  1339. /*  procedure will also read an .area file and set a maximum area constraint */
  1340. /*  on each triangle.                                                        */
  1341. /*                                                                           */
  1342. /*  Vertices that are not corners of triangles, such as nodes on edges of    */
  1343. /*  subparametric elements, are discarded.                                   */
  1344. /*                                                                           */
  1345. /*  This routine finds the adjacencies between triangles (and subsegments)   */
  1346. /*  by forming one stack of triangles for each vertex.  Each triangle is on  */
  1347. /*  three different stacks simultaneously.  Each triangle's subsegment       */
  1348. /*  pointers are used to link the items in each stack.  This memory-saving   */
  1349. /*  feature makes the code harder to read.  The most important thing to keep */
  1350. /*  in mind is that each triangle is removed from a stack precisely when     */
  1351. /*  the corresponding pointer is adjusted to refer to a subsegment rather    */
  1352. /*  than the next triangle of the stack.                                     */
  1353. /*                                                                           */
  1354. /*****************************************************************************/
  1355. #ifndef CDT_ONLY
  1356. #ifdef TRILIBRARY
  1357. #ifdef ANSI_DECLARATORS
  1358. int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
  1359.                 REAL *triangleattriblist, REAL *trianglearealist,
  1360.                 int elements, int corners, int attribs,
  1361.                 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
  1362. #else /* not ANSI_DECLARATORS */
  1363. int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
  1364.                 elements, corners, attribs, segmentlist, segmentmarkerlist,
  1365.                 numberofsegments)
  1366. struct mesh *m;
  1367. struct behavior *b;
  1368. int *trianglelist;
  1369. REAL *triangleattriblist;
  1370. REAL *trianglearealist;
  1371. int elements;
  1372. int corners;
  1373. int attribs;
  1374. int *segmentlist;
  1375. int *segmentmarkerlist;
  1376. int numberofsegments;
  1377. #endif /* not ANSI_DECLARATORS */
  1378. #else /* not TRILIBRARY */
  1379. #ifdef ANSI_DECLARATORS
  1380. long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
  1381.                  char *areafilename, char *polyfilename, FILE *polyfile)
  1382. #else /* not ANSI_DECLARATORS */
  1383. long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
  1384. struct mesh *m;
  1385. struct behavior *b;
  1386. char *elefilename;
  1387. char *areafilename;
  1388. char *polyfilename;
  1389. FILE *polyfile;
  1390. #endif /* not ANSI_DECLARATORS */
  1391. #endif /* not TRILIBRARY */
  1392. {
  1393. #ifdef TRILIBRARY
  1394.   int vertexindex;
  1395.   int attribindex;
  1396. #else /* not TRILIBRARY */
  1397.   FILE *elefile;
  1398.   FILE *areafile;
  1399.   char inputline[INPUTLINESIZE];
  1400.   char *stringptr;
  1401.   int areaelements;
  1402. #endif /* not TRILIBRARY */
  1403.   struct otri triangleloop;
  1404.   struct otri triangleleft;
  1405.   struct otri checktri;
  1406.   struct otri checkleft;
  1407.   struct otri checkneighbor;
  1408.   struct osub subsegloop;
  1409.   triangle *vertexarray;
  1410.   triangle *prevlink;
  1411.   triangle nexttri;
  1412.   vertex tdest, tapex;
  1413.   vertex checkdest, checkapex;
  1414.   vertex shorg;
  1415.   vertex killvertex;
  1416.   vertex segmentorg, segmentdest;
  1417.   REAL area;
  1418.   int corner[3];
  1419.   int end[2];
  1420.   int killvertexindex;
  1421.   int incorners;
  1422.   int segmentmarkers;
  1423.   int boundmarker;
  1424.   int aroundvertex;
  1425.   long hullsize;
  1426.   int notfound;
  1427.   long elementnumber, segmentnumber;
  1428.   int i, j;
  1429.   triangle ptr;                         /* Temporary variable used by sym(). */
  1430. #ifdef TRILIBRARY
  1431.   m->inelements = elements;
  1432.   incorners = corners;
  1433.   if (incorners < 3) {
  1434.     printf("Error:  Triangles must have at least 3 vertices.n");
  1435.     triexit(1);
  1436.   }
  1437.   m->eextras = attribs;
  1438. #else /* not TRILIBRARY */
  1439.   /* Read the triangles from an .ele file. */
  1440.   if (!b->quiet) {
  1441.     printf("Opening %s.n", elefilename);
  1442.   }
  1443.   elefile = fopen(elefilename, "r");
  1444.   if (elefile == (FILE *) NULL) {
  1445.     printf("  Error:  Cannot access file %s.n", elefilename);
  1446.     triexit(1);
  1447.   }
  1448.   /* Read number of triangles, number of vertices per triangle, and */
  1449.   /*   number of triangle attributes from .ele file.                */
  1450.   stringptr = readline(inputline, elefile, elefilename);
  1451.   m->inelements = (int) strtol(stringptr, &stringptr, 0);
  1452.   stringptr = findfield(stringptr);
  1453.   if (*stringptr == '') {
  1454.     incorners = 3;
  1455.   } else {
  1456.     incorners = (int) strtol(stringptr, &stringptr, 0);
  1457.     if (incorners < 3) {
  1458.       printf("Error:  Triangles in %s must have at least 3 vertices.n",
  1459.              elefilename);
  1460.       triexit(1);
  1461.     }
  1462.   }
  1463.   stringptr = findfield(stringptr);
  1464.   if (*stringptr == '') {
  1465.     m->eextras = 0;
  1466.   } else {
  1467.     m->eextras = (int) strtol(stringptr, &stringptr, 0);
  1468.   }
  1469. #endif /* not TRILIBRARY */
  1470.   initializetrisubpools(m, b);
  1471.   /* Create the triangles. */
  1472.   for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
  1473.     maketriangle(m, b, &triangleloop);
  1474.     /* Mark the triangle as living. */
  1475.     triangleloop.tri[3] = (triangle) triangleloop.tri;
  1476.   }
  1477.   segmentmarkers = 0;
  1478.   if (b->poly) {
  1479. #ifdef TRILIBRARY
  1480.     m->insegments = numberofsegments;
  1481.     segmentmarkers = segmentmarkerlist != (int *) NULL;
  1482. #else /* not TRILIBRARY */
  1483.     /* Read number of segments and number of segment */
  1484.     /*   boundary markers from .poly file.           */
  1485.     stringptr = readline(inputline, polyfile, b->inpolyfilename);
  1486.     m->insegments = (int) strtol(stringptr, &stringptr, 0);
  1487.     stringptr = findfield(stringptr);
  1488.     if (*stringptr != '') {
  1489.       segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
  1490.     }
  1491. #endif /* not TRILIBRARY */
  1492.     /* Create the subsegments. */
  1493.     for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
  1494.       makesubseg(m, &subsegloop);
  1495.       /* Mark the subsegment as living. */
  1496.       subsegloop.ss[2] = (subseg) subsegloop.ss;
  1497.     }
  1498.   }
  1499. #ifdef TRILIBRARY
  1500.   vertexindex = 0;
  1501.   attribindex = 0;
  1502. #else /* not TRILIBRARY */
  1503.   if (b->vararea) {
  1504.     /* Open an .area file, check for consistency with the .ele file. */
  1505.     if (!b->quiet) {
  1506.       printf("Opening %s.n", areafilename);
  1507.     }
  1508.     areafile = fopen(areafilename, "r");
  1509.     if (areafile == (FILE *) NULL) {
  1510.       printf("  Error:  Cannot access file %s.n", areafilename);
  1511.       triexit(1);
  1512.     }
  1513.     stringptr = readline(inputline, areafile, areafilename);
  1514.     areaelements = (int) strtol(stringptr, &stringptr, 0);
  1515.     if (areaelements != m->inelements) {
  1516.       printf("Error:  %s and %s disagree on number of triangles.n",
  1517.              elefilename, areafilename);
  1518.       triexit(1);
  1519.     }
  1520.   }
  1521. #endif /* not TRILIBRARY */
  1522.   if (!b->quiet) {
  1523.     printf("Reconstructing mesh.n");
  1524.   }
  1525.   /* Allocate a temporary array that maps each vertex to some adjacent */
  1526.   /*   triangle.  I took care to allocate all the permanent memory for */
  1527.   /*   triangles and subsegments first.                                */
  1528.   vertexarray = (triangle *) trimalloc(m->vertices.items *
  1529.                                        (int) sizeof(triangle));
  1530.   /* Each vertex is initially unrepresented. */
  1531.   for (i = 0; i < m->vertices.items; i++) {
  1532.     vertexarray[i] = (triangle) m->dummytri;
  1533.   }
  1534.   if (b->verbose) {
  1535.     printf("  Assembling triangles.n");
  1536.   }
  1537.   /* Read the triangles from the .ele file, and link */
  1538.   /*   together those that share an edge.            */
  1539.   traversalinit(&m->triangles);
  1540.   triangleloop.tri = triangletraverse(m);
  1541.   elementnumber = b->firstnumber;
  1542.   while (triangleloop.tri != (triangle *) NULL) {
  1543. #ifdef TRILIBRARY
  1544.     /* Copy the triangle's three corners. */
  1545.     for (j = 0; j < 3; j++) {
  1546.       corner[j] = trianglelist[vertexindex++];
  1547.       if ((corner[j] < b->firstnumber) ||
  1548.           (corner[j] >= b->firstnumber + m->invertices)) {
  1549.         printf("Error:  Triangle %ld has an invalid vertex index.n",
  1550.                elementnumber);
  1551.         triexit(1);
  1552.       }
  1553.     }
  1554. #else /* not TRILIBRARY */
  1555.     /* Read triangle number and the triangle's three corners. */
  1556.     stringptr = readline(inputline, elefile, elefilename);
  1557.     for (j = 0; j < 3; j++) {
  1558.       stringptr = findfield(stringptr);
  1559.       if (*stringptr == '') {
  1560.         printf("Error:  Triangle %ld is missing vertex %d in %s.n",
  1561.                elementnumber, j + 1, elefilename);
  1562.         triexit(1);
  1563.       } else {
  1564.         corner[j] = (int) strtol(stringptr, &stringptr, 0);
  1565.         if ((corner[j] < b->firstnumber) ||
  1566.             (corner[j] >= b->firstnumber + m->invertices)) {
  1567.           printf("Error:  Triangle %ld has an invalid vertex index.n",
  1568.                  elementnumber);
  1569.           triexit(1);
  1570.         }
  1571.       }
  1572.     }
  1573. #endif /* not TRILIBRARY */
  1574.     /* Find out about (and throw away) extra nodes. */
  1575.     for (j = 3; j < incorners; j++) {
  1576. #ifdef TRILIBRARY
  1577.       killvertexindex = trianglelist[vertexindex++];
  1578. #else /* not TRILIBRARY */
  1579.       stringptr = findfield(stringptr);
  1580.       if (*stringptr != '') {
  1581.         killvertexindex = (int) strtol(stringptr, &stringptr, 0);
  1582. #endif /* not TRILIBRARY */
  1583.         if ((killvertexindex >= b->firstnumber) &&
  1584.             (killvertexindex < b->firstnumber + m->invertices)) {
  1585.           /* Delete the non-corner vertex if it's not already deleted. */
  1586.           killvertex = getvertex(m, b, killvertexindex);
  1587.           if (vertextype(killvertex) != DEADVERTEX) {
  1588.             vertexdealloc(m, killvertex);
  1589.           }
  1590.         }
  1591. #ifndef TRILIBRARY
  1592.       }
  1593. #endif /* not TRILIBRARY */
  1594.     }
  1595.     /* Read the triangle's attributes. */
  1596.     for (j = 0; j < m->eextras; j++) {
  1597. #ifdef TRILIBRARY
  1598.       setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
  1599. #else /* not TRILIBRARY */
  1600.       stringptr = findfield(stringptr);
  1601.       if (*stringptr == '') {
  1602.         setelemattribute(triangleloop, j, 0);
  1603.       } else {
  1604.         setelemattribute(triangleloop, j,
  1605.                          (REAL) strtod(stringptr, &stringptr));
  1606.       }
  1607. #endif /* not TRILIBRARY */
  1608.     }
  1609.     if (b->vararea) {
  1610. #ifdef TRILIBRARY
  1611.       area = trianglearealist[elementnumber - b->firstnumber];
  1612. #else /* not TRILIBRARY */
  1613.       /* Read an area constraint from the .area file. */
  1614.       stringptr = readline(inputline, areafile, areafilename);
  1615.       stringptr = findfield(stringptr);
  1616.       if (*stringptr == '') {
  1617.         area = -1.0;                      /* No constraint on this triangle. */
  1618.       } else {
  1619.         area = (REAL) strtod(stringptr, &stringptr);
  1620.       }
  1621. #endif /* not TRILIBRARY */
  1622.       setareabound(triangleloop, area);
  1623.     }
  1624.     /* Set the triangle's vertices. */
  1625.     triangleloop.orient = 0;
  1626.     setorg(triangleloop, getvertex(m, b, corner[0]));
  1627.     setdest(triangleloop, getvertex(m, b, corner[1]));
  1628.     setapex(triangleloop, getvertex(m, b, corner[2]));
  1629.     /* Try linking the triangle to others that share these vertices. */
  1630.     for (triangleloop.orient = 0; triangleloop.orient < 3;
  1631.          triangleloop.orient++) {
  1632.       /* Take the number for the origin of triangleloop. */
  1633.       aroundvertex = corner[triangleloop.orient];
  1634.       /* Look for other triangles having this vertex. */
  1635.       nexttri = vertexarray[aroundvertex - b->firstnumber];
  1636.       /* Link the current triangle to the next one in the stack. */
  1637.       triangleloop.tri[6 + triangleloop.orient] = nexttri;
  1638.       /* Push the current triangle onto the stack. */
  1639.       vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
  1640.       decode(nexttri, checktri);
  1641.       if (checktri.tri != m->dummytri) {
  1642.         dest(triangleloop, tdest);
  1643.         apex(triangleloop, tapex);
  1644.         /* Look for other triangles that share an edge. */
  1645.         do {
  1646.           dest(checktri, checkdest);
  1647.           apex(checktri, checkapex);
  1648.           if (tapex == checkdest) {
  1649.             /* The two triangles share an edge; bond them together. */
  1650.             lprev(triangleloop, triangleleft);
  1651.             bond(triangleleft, checktri);
  1652.           }
  1653.           if (tdest == checkapex) {
  1654.             /* The two triangles share an edge; bond them together. */
  1655.             lprev(checktri, checkleft);
  1656.             bond(triangleloop, checkleft);
  1657.           }
  1658.           /* Find the next triangle in the stack. */
  1659.           nexttri = checktri.tri[6 + checktri.orient];
  1660.           decode(nexttri, checktri);
  1661.         } while (checktri.tri != m->dummytri);
  1662.       }
  1663.     }
  1664.     triangleloop.tri = triangletraverse(m);
  1665.     elementnumber++;
  1666.   }
  1667. #ifdef TRILIBRARY
  1668.   vertexindex = 0;
  1669. #else /* not TRILIBRARY */
  1670.   fclose(elefile);
  1671.   if (b->vararea) {
  1672.     fclose(areafile);
  1673.   }
  1674. #endif /* not TRILIBRARY */
  1675.   hullsize = 0;                      /* Prepare to count the boundary edges. */
  1676.   if (b->poly) {
  1677.     if (b->verbose) {
  1678.       printf("  Marking segments in triangulation.n");
  1679.     }
  1680.     /* Read the segments from the .poly file, and link them */
  1681.     /*   to their neighboring triangles.                    */
  1682.     boundmarker = 0;
  1683.     traversalinit(&m->subsegs);
  1684.     subsegloop.ss = subsegtraverse(m);
  1685.     segmentnumber = b->firstnumber;
  1686.     while (subsegloop.ss != (subseg *) NULL) {
  1687. #ifdef TRILIBRARY
  1688.       end[0] = segmentlist[vertexindex++];
  1689.       end[1] = segmentlist[vertexindex++];
  1690.       if (segmentmarkers) {
  1691.         boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
  1692.       }
  1693. #else /* not TRILIBRARY */
  1694.       /* Read the endpoints of each segment, and possibly a boundary marker. */
  1695.       stringptr = readline(inputline, polyfile, b->inpolyfilename);
  1696.       /* Skip the first (segment number) field. */
  1697.       stringptr = findfield(stringptr);
  1698.       if (*stringptr == '') {
  1699.         printf("Error:  Segment %ld has no endpoints in %s.n", segmentnumber,
  1700.                polyfilename);
  1701.         triexit(1);
  1702.       } else {
  1703.         end[0] = (int) strtol(stringptr, &stringptr, 0);
  1704.       }
  1705.       stringptr = findfield(stringptr);
  1706.       if (*stringptr == '') {
  1707.         printf("Error:  Segment %ld is missing its second endpoint in %s.n",
  1708.                segmentnumber, polyfilename);
  1709.         triexit(1);
  1710.       } else {
  1711.         end[1] = (int) strtol(stringptr, &stringptr, 0);
  1712.       }
  1713.       if (segmentmarkers) {
  1714.         stringptr = findfield(stringptr);
  1715.         if (*stringptr == '') {
  1716.           boundmarker = 0;
  1717.         } else {
  1718.           boundmarker = (int) strtol(stringptr, &stringptr, 0);
  1719.         }
  1720.       }
  1721. #endif /* not TRILIBRARY */
  1722.       for (j = 0; j < 2; j++) {
  1723.         if ((end[j] < b->firstnumber) ||
  1724.             (end[j] >= b->firstnumber + m->invertices)) {
  1725.           printf("Error:  Segment %ld has an invalid vertex index.n", 
  1726.                  segmentnumber);
  1727.           triexit(1);
  1728.         }
  1729.       }
  1730.       /* set the subsegment's vertices. */
  1731.       subsegloop.ssorient = 0;
  1732.       segmentorg = getvertex(m, b, end[0]);
  1733.       segmentdest = getvertex(m, b, end[1]);
  1734.       setsorg(subsegloop, segmentorg);
  1735.       setsdest(subsegloop, segmentdest);
  1736.       setsegorg(subsegloop, segmentorg);
  1737.       setsegdest(subsegloop, segmentdest);
  1738.       setmark(subsegloop, boundmarker);
  1739.       /* Try linking the subsegment to triangles that share these vertices. */
  1740.       for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
  1741.            subsegloop.ssorient++) {
  1742.         /* Take the number for the destination of subsegloop. */
  1743.         aroundvertex = end[1 - subsegloop.ssorient];
  1744.         /* Look for triangles having this vertex. */
  1745.         prevlink = &vertexarray[aroundvertex - b->firstnumber];
  1746.         nexttri = vertexarray[aroundvertex - b->firstnumber];
  1747.         decode(nexttri, checktri);
  1748.         sorg(subsegloop, shorg);
  1749.         notfound = 1;
  1750.         /* Look for triangles having this edge.  Note that I'm only       */
  1751.         /*   comparing each triangle's destination with the subsegment;   */
  1752.         /*   each triangle's apex is handled through a different vertex.  */
  1753.         /*   Because each triangle appears on three vertices' lists, each */
  1754.         /*   occurrence of a triangle on a list can (and does) represent  */
  1755.         /*   an edge.  In this way, most edges are represented twice, and */
  1756.         /*   every triangle-subsegment bond is represented once.          */
  1757.         while (notfound && (checktri.tri != m->dummytri)) {
  1758.           dest(checktri, checkdest);
  1759.           if (shorg == checkdest) {
  1760.             /* We have a match.  Remove this triangle from the list. */
  1761.             *prevlink = checktri.tri[6 + checktri.orient];
  1762.             /* Bond the subsegment to the triangle. */
  1763.             tsbond(checktri, subsegloop);
  1764.             /* Check if this is a boundary edge. */
  1765.             sym(checktri, checkneighbor);
  1766.             if (checkneighbor.tri == m->dummytri) {
  1767.               /* The next line doesn't insert a subsegment (because there's */
  1768.               /*   already one there), but it sets the boundary markers of  */
  1769.               /*   the existing subsegment and its vertices.                */
  1770.               insertsubseg(m, b, &checktri, 1);
  1771.               hullsize++;
  1772.             }
  1773.             notfound = 0;
  1774.           }
  1775.           /* Find the next triangle in the stack. */
  1776.           prevlink = &checktri.tri[6 + checktri.orient];
  1777.           nexttri = checktri.tri[6 + checktri.orient];
  1778.           decode(nexttri, checktri);
  1779.         }
  1780.       }
  1781.       subsegloop.ss = subsegtraverse(m);
  1782.       segmentnumber++;
  1783.     }
  1784.   }
  1785.   /* Mark the remaining edges as not being attached to any subsegment. */
  1786.   /* Also, count the (yet uncounted) boundary edges.                   */
  1787.   for (i = 0; i < m->vertices.items; i++) {
  1788.     /* Search the stack of triangles adjacent to a vertex. */
  1789.     nexttri = vertexarray[i];
  1790.     decode(nexttri, checktri);
  1791.     while (checktri.tri != m->dummytri) {
  1792.       /* Find the next triangle in the stack before this */
  1793.       /*   information gets overwritten.                 */
  1794.       nexttri = checktri.tri[6 + checktri.orient];
  1795.       /* No adjacent subsegment.  (This overwrites the stack info.) */
  1796.       tsdissolve(checktri);
  1797.       sym(checktri, checkneighbor);
  1798.       if (checkneighbor.tri == m->dummytri) {
  1799.         insertsubseg(m, b, &checktri, 1);
  1800.         hullsize++;
  1801.       }
  1802.       decode(nexttri, checktri);
  1803.     }
  1804.   }
  1805.   trifree((VOID *) vertexarray);
  1806.   return hullsize;
  1807. }
  1808. #endif /* not CDT_ONLY */
  1809. /**                                                                         **/
  1810. /**                                                                         **/
  1811. /********* General mesh construction routines end here               *********/
  1812. /********* Segment insertion begins here                             *********/
  1813. /**                                                                         **/
  1814. /**                                                                         **/
  1815. /*****************************************************************************/
  1816. /*                                                                           */
  1817. /*  finddirection()   Find the first triangle on the path from one point     */
  1818. /*                    to another.                                            */
  1819. /*                                                                           */
  1820. /*  Finds the triangle that intersects a line segment drawn from the         */
  1821. /*  origin of `searchtri' to the point `searchpoint', and returns the result */
  1822. /*  in `searchtri'.  The origin of `searchtri' does not change, even though  */
  1823. /*  the triangle returned may differ from the one passed in.  This routine   */
  1824. /*  is used to find the direction to move in to get from one point to        */
  1825. /*  another.                                                                 */
  1826. /*                                                                           */
  1827. /*  The return value notes whether the destination or apex of the found      */
  1828. /*  triangle is collinear with the two points in question.                   */
  1829. /*                                                                           */
  1830. /*****************************************************************************/
  1831. #ifdef ANSI_DECLARATORS
  1832. enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
  1833.                                        struct otri *searchtri,
  1834.                                        vertex searchpoint)
  1835. #else /* not ANSI_DECLARATORS */
  1836. enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
  1837. struct mesh *m;
  1838. struct behavior *b;
  1839. struct otri *searchtri;
  1840. vertex searchpoint;
  1841. #endif /* not ANSI_DECLARATORS */
  1842. {
  1843.   struct otri checktri;
  1844.   vertex startvertex;
  1845.   vertex leftvertex, rightvertex;
  1846.   REAL leftccw, rightccw;
  1847.   int leftflag, rightflag;
  1848.   triangle ptr;           /* Temporary variable used by onext() and oprev(). */
  1849.   org(*searchtri, startvertex);
  1850.   dest(*searchtri, rightvertex);
  1851.   apex(*searchtri, leftvertex);
  1852.   /* Is `searchpoint' to the left? */
  1853.   leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
  1854.   leftflag = leftccw > 0.0;
  1855.   /* Is `searchpoint' to the right? */
  1856.   rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
  1857.   rightflag = rightccw > 0.0;
  1858.   if (leftflag && rightflag) {
  1859.     /* `searchtri' faces directly away from `searchpoint'.  We could go left */
  1860.     /*   or right.  Ask whether it's a triangle or a boundary on the left.   */
  1861.     onext(*searchtri, checktri);
  1862.     if (checktri.tri == m->dummytri) {
  1863.       leftflag = 0;
  1864.     } else {
  1865.       rightflag = 0;
  1866.     }
  1867.   }
  1868.   while (leftflag) {
  1869.     /* Turn left until satisfied. */
  1870.     onextself(*searchtri);
  1871.     if (searchtri->tri == m->dummytri) {
  1872.       printf("Internal error in finddirection():  Unable to find an");
  1873.       printf("  triangle leading from (%.12g, %.12g) to", startvertex[0],
  1874.              startvertex[1]);
  1875.       printf("  (%.12g, %.12g).n", searchpoint[0], searchpoint[1]);
  1876.       internalerror();
  1877.     }
  1878.     apex(*searchtri, leftvertex);
  1879.     rightccw = leftccw;
  1880.     leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
  1881.     leftflag = leftccw > 0.0;
  1882.   }
  1883.   while (rightflag) {
  1884.     /* Turn right until satisfied. */
  1885.     oprevself(*searchtri);
  1886.     if (searchtri->tri == m->dummytri) {
  1887.       printf("Internal error in finddirection():  Unable to find an");
  1888.       printf("  triangle leading from (%.12g, %.12g) to", startvertex[0],
  1889.              startvertex[1]);
  1890.       printf("  (%.12g, %.12g).n", searchpoint[0], searchpoint[1]);
  1891.       internalerror();
  1892.     }
  1893.     dest(*searchtri, rightvertex);
  1894.     leftccw = rightccw;
  1895.     rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
  1896.     rightflag = rightccw > 0.0;
  1897.   }
  1898.   if (leftccw == 0.0) {
  1899.     return LEFTCOLLINEAR;
  1900.   } else if (rightccw == 0.0) {
  1901.     return RIGHTCOLLINEAR;
  1902.   } else {
  1903.     return WITHIN;
  1904.   }
  1905. }
  1906. /*****************************************************************************/
  1907. /*                                                                           */
  1908. /*  segmentintersection()   Find the intersection of an existing segment     */
  1909. /*                          and a segment that is being inserted.  Insert    */
  1910. /*                          a vertex at the intersection, splitting an       */
  1911. /*                          existing subsegment.                             */
  1912. /*                                                                           */
  1913. /*  The segment being inserted connects the apex of splittri to endpoint2.   */
  1914. /*  splitsubseg is the subsegment being split, and MUST adjoin splittri.     */
  1915. /*  Hence, endpoints of the subsegment being split are the origin and        */
  1916. /*  destination of splittri.                                                 */
  1917. /*                                                                           */
  1918. /*  On completion, splittri is a handle having the newly inserted            */
  1919. /*  intersection point as its origin, and endpoint1 as its destination.      */
  1920. /*                                                                           */
  1921. /*****************************************************************************/
  1922. #ifdef ANSI_DECLARATORS
  1923. void segmentintersection(struct mesh *m, struct behavior *b,
  1924.                          struct otri *splittri, struct osub *splitsubseg,
  1925.                          vertex endpoint2)
  1926. #else /* not ANSI_DECLARATORS */
  1927. void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
  1928. struct mesh *m;
  1929. struct behavior *b;
  1930. struct otri *splittri;
  1931. struct osub *splitsubseg;
  1932. vertex endpoint2;
  1933. #endif /* not ANSI_DECLARATORS */
  1934. {
  1935.   struct osub opposubseg;
  1936.   vertex endpoint1;
  1937.   vertex torg, tdest;
  1938.   vertex leftvertex, rightvertex;
  1939.   vertex newvertex;
  1940.   enum insertvertexresult success;
  1941.   enum finddirectionresult collinear;
  1942.   REAL ex, ey;
  1943.   REAL tx, ty;
  1944.   REAL etx, ety;
  1945.   REAL split, denom;
  1946.   int i;
  1947.   triangle ptr;                       /* Temporary variable used by onext(). */
  1948.   subseg sptr;                        /* Temporary variable used by snext(). */
  1949.   /* Find the other three segment endpoints. */
  1950.   apex(*splittri, endpoint1);
  1951.   org(*splittri, torg);
  1952.   dest(*splittri, tdest);
  1953.   /* Segment intersection formulae; see the Antonio reference. */
  1954.   tx = tdest[0] - torg[0];
  1955.   ty = tdest[1] - torg[1];
  1956.   ex = endpoint2[0] - endpoint1[0];
  1957.   ey = endpoint2[1] - endpoint1[1];
  1958.   etx = torg[0] - endpoint2[0];
  1959.   ety = torg[1] - endpoint2[1];
  1960.   denom = ty * ex - tx * ey;
  1961.   if (denom == 0.0) {
  1962.     printf("Internal error in segmentintersection():");
  1963.     printf("  Attempt to find intersection of parallel segments.n");
  1964.     internalerror();
  1965.   }
  1966.   split = (ey * etx - ex * ety) / denom;
  1967.   /* Create the new vertex. */
  1968.   newvertex = (vertex) poolalloc(&m->vertices);
  1969.   /* Interpolate its coordinate and attributes. */
  1970.   for (i = 0; i < 2 + m->nextras; i++) {
  1971.     newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
  1972.   }
  1973.   setvertexmark(newvertex, mark(*splitsubseg));
  1974.   setvertextype(newvertex, INPUTVERTEX);
  1975.   if (b->verbose > 1) {
  1976.     printf(
  1977.   "  Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).n",
  1978.            torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
  1979.   }
  1980.   /* Insert the intersection vertex.  This should always succeed. */
  1981.   success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
  1982.   if (success != SUCCESSFULVERTEX) {
  1983.     printf("Internal error in segmentintersection():n");
  1984.     printf("  Failure to split a segment.n");
  1985.     internalerror();
  1986.   }
  1987.   /* Record a triangle whose origin is the new vertex. */
  1988.   setvertex2tri(newvertex, encode(*splittri));
  1989.   if (m->steinerleft > 0) {
  1990.     m->steinerleft--;
  1991.   }
  1992.   /* Divide the segment into two, and correct the segment endpoints. */
  1993.   ssymself(*splitsubseg);
  1994.   spivot(*splitsubseg, opposubseg);
  1995.   sdissolve(*splitsubseg);
  1996.   sdissolve(opposubseg);
  1997.   do {
  1998.     setsegorg(*splitsubseg, newvertex);
  1999.     snextself(*splitsubseg);
  2000.   } while (splitsubseg->ss != m->dummysub);
  2001.   do {
  2002.     setsegorg(opposubseg, newvertex);
  2003.     snextself(opposubseg);
  2004.   } while (opposubseg.ss != m->dummysub);
  2005.   /* Inserting the vertex may have caused edge flips.  We wish to rediscover */
  2006.   /*   the edge connecting endpoint1 to the new intersection vertex.         */
  2007.   collinear = finddirection(m, b, splittri, endpoint1);
  2008.   dest(*splittri, rightvertex);
  2009.   apex(*splittri, leftvertex);
  2010.   if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
  2011.     onextself(*splittri);
  2012.   } else if ((rightvertex[0] != endpoint1[0]) ||
  2013.              (rightvertex[1] != endpoint1[1])) {
  2014.     printf("Internal error in segmentintersection():n");
  2015.     printf("  Topological inconsistency after splitting a segment.n");
  2016.     internalerror();
  2017.   }
  2018.   /* `splittri' should have destination endpoint1. */
  2019. }
  2020. /*****************************************************************************/
  2021. /*                                                                           */
  2022. /*  scoutsegment()   Scout the first triangle on the path from one endpoint  */
  2023. /*                   to another, and check for completion (reaching the      */
  2024. /*                   second endpoint), a collinear vertex, or the            */
  2025. /*                   intersection of two segments.                           */
  2026. /*                                                                           */
  2027. /*  Returns one if the entire segment is successfully inserted, and zero if  */
  2028. /*  the job must be finished by conformingedge() or constrainededge().       */
  2029. /*                                                                           */
  2030. /*  If the first triangle on the path has the second endpoint as its         */
  2031. /*  destination or apex, a subsegment is inserted and the job is done.       */
  2032. /*                                                                           */
  2033. /*  If the first triangle on the path has a destination or apex that lies on */
  2034. /*  the segment, a subsegment is inserted connecting the first endpoint to   */
  2035. /*  the collinear vertex, and the search is continued from the collinear     */
  2036. /*  vertex.                                                                  */
  2037. /*                                                                           */
  2038. /*  If the first triangle on the path has a subsegment opposite its origin,  */
  2039. /*  then there is a segment that intersects the segment being inserted.      */
  2040. /*  Their intersection vertex is inserted, splitting the subsegment.         */
  2041. /*                                                                           */
  2042. /*****************************************************************************/
  2043. #ifdef ANSI_DECLARATORS
  2044. int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
  2045.                  vertex endpoint2, int newmark)
  2046. #else /* not ANSI_DECLARATORS */
  2047. int scoutsegment(m, b, searchtri, endpoint2, newmark)
  2048. struct mesh *m;
  2049. struct behavior *b;
  2050. struct otri *searchtri;
  2051. vertex endpoint2;
  2052. int newmark;
  2053. #endif /* not ANSI_DECLARATORS */
  2054. {
  2055.   struct otri crosstri;
  2056.   struct osub crosssubseg;
  2057.   vertex leftvertex, rightvertex;
  2058.   enum finddirectionresult collinear;
  2059.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  2060.   collinear = finddirection(m, b, searchtri, endpoint2);
  2061.   dest(*searchtri, rightvertex);
  2062.   apex(*searchtri, leftvertex);
  2063.   if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
  2064.       ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
  2065.     /* The segment is already an edge in the mesh. */
  2066.     if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
  2067.       lprevself(*searchtri);
  2068.     }
  2069.     /* Insert a subsegment, if there isn't already one there. */
  2070.     insertsubseg(m, b, searchtri, newmark);
  2071.     return 1;
  2072.   } else if (collinear == LEFTCOLLINEAR) {
  2073.     /* We've collided with a vertex between the segment's endpoints. */
  2074.     /* Make the collinear vertex be the triangle's origin. */
  2075.     lprevself(*searchtri);
  2076.     insertsubseg(m, b, searchtri, newmark);
  2077.     /* Insert the remainder of the segment. */
  2078.     return scoutsegment(m, b, searchtri, endpoint2, newmark);
  2079.   } else if (collinear == RIGHTCOLLINEAR) {
  2080.     /* We've collided with a vertex between the segment's endpoints. */
  2081.     insertsubseg(m, b, searchtri, newmark);
  2082.     /* Make the collinear vertex be the triangle's origin. */
  2083.     lnextself(*searchtri);
  2084.     /* Insert the remainder of the segment. */
  2085.     return scoutsegment(m, b, searchtri, endpoint2, newmark);
  2086.   } else {
  2087.     lnext(*searchtri, crosstri);
  2088.     tspivot(crosstri, crosssubseg);
  2089.     /* Check for a crossing segment. */
  2090.     if (crosssubseg.ss == m->dummysub) {
  2091.       return 0;
  2092.     } else {
  2093.       /* Insert a vertex at the intersection. */
  2094.       segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
  2095.       otricopy(crosstri, *searchtri);
  2096.       insertsubseg(m, b, searchtri, newmark);
  2097.       /* Insert the remainder of the segment. */
  2098.       return scoutsegment(m, b, searchtri, endpoint2, newmark);
  2099.     }
  2100.   }
  2101. }
  2102. /*****************************************************************************/
  2103. /*                                                                           */
  2104. /*  conformingedge()   Force a segment into a conforming Delaunay            */
  2105. /*                     triangulation by inserting a vertex at its midpoint,  */
  2106. /*                     and recursively forcing in the two half-segments if   */
  2107. /*                     necessary.                                            */
  2108. /*                                                                           */
  2109. /*  Generates a sequence of subsegments connecting `endpoint1' to            */
  2110. /*  `endpoint2'.  `newmark' is the boundary marker of the segment, assigned  */
  2111. /*  to each new splitting vertex and subsegment.                             */
  2112. /*                                                                           */
  2113. /*  Note that conformingedge() does not always maintain the conforming       */
  2114. /*  Delaunay property.  Once inserted, segments are locked into place;       */
  2115. /*  vertices inserted later (to force other segments in) may render these    */
  2116. /*  fixed segments non-Delaunay.  The conforming Delaunay property will be   */
  2117. /*  restored by enforcequality() by splitting encroached subsegments.        */
  2118. /*                                                                           */
  2119. /*****************************************************************************/
  2120. #ifndef REDUCED
  2121. #ifndef CDT_ONLY
  2122. #ifdef ANSI_DECLARATORS
  2123. void conformingedge(struct mesh *m, struct behavior *b,
  2124.                     vertex endpoint1, vertex endpoint2, int newmark)
  2125. #else /* not ANSI_DECLARATORS */
  2126. void conformingedge(m, b, endpoint1, endpoint2, newmark)
  2127. struct mesh *m;
  2128. struct behavior *b;
  2129. vertex endpoint1;
  2130. vertex endpoint2;
  2131. int newmark;
  2132. #endif /* not ANSI_DECLARATORS */
  2133. {
  2134.   struct otri searchtri1, searchtri2;
  2135.   struct osub brokensubseg;
  2136.   vertex newvertex;
  2137.   vertex midvertex1, midvertex2;
  2138.   enum insertvertexresult success;
  2139.   int i;
  2140.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  2141.   if (b->verbose > 2) {
  2142.     printf("Forcing segment into triangulation by recursive splitting:n");
  2143.     printf("  (%.12g, %.12g) (%.12g, %.12g)n", endpoint1[0], endpoint1[1],
  2144.            endpoint2[0], endpoint2[1]);
  2145.   }
  2146.   /* Create a new vertex to insert in the middle of the segment. */
  2147.   newvertex = (vertex) poolalloc(&m->vertices);
  2148.   /* Interpolate coordinates and attributes. */
  2149.   for (i = 0; i < 2 + m->nextras; i++) {
  2150.     newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
  2151.   }
  2152.   setvertexmark(newvertex, newmark);
  2153.   setvertextype(newvertex, SEGMENTVERTEX);
  2154.   /* No known triangle to search from. */
  2155.   searchtri1.tri = m->dummytri;
  2156.   /* Attempt to insert the new vertex. */
  2157.   success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
  2158.                          0, 0);
  2159.   if (success == DUPLICATEVERTEX) {
  2160.     if (b->verbose > 2) {
  2161.       printf("  Segment intersects existing vertex (%.12g, %.12g).n",
  2162.              newvertex[0], newvertex[1]);
  2163.     }
  2164.     /* Use the vertex that's already there. */
  2165.     vertexdealloc(m, newvertex);
  2166.     org(searchtri1, newvertex);
  2167.   } else {
  2168.     if (success == VIOLATINGVERTEX) {
  2169.       if (b->verbose > 2) {
  2170.         printf("  Two segments intersect at (%.12g, %.12g).n",
  2171.                newvertex[0], newvertex[1]);
  2172.       }
  2173.       /* By fluke, we've landed right on another segment.  Split it. */
  2174.       tspivot(searchtri1, brokensubseg);
  2175.       success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
  2176.                              0, 0);
  2177.       if (success != SUCCESSFULVERTEX) {
  2178.         printf("Internal error in conformingedge():n");
  2179.         printf("  Failure to split a segment.n");
  2180.         internalerror();
  2181.       }
  2182.     }
  2183.     /* The vertex has been inserted successfully. */
  2184.     if (m->steinerleft > 0) {
  2185.       m->steinerleft--;
  2186.     }
  2187.   }
  2188.   otricopy(searchtri1, searchtri2);
  2189.   /* `searchtri1' and `searchtri2' are fastened at their origins to         */
  2190.   /*   `newvertex', and will be directed toward `endpoint1' and `endpoint2' */
  2191.   /*   respectively.  First, we must get `searchtri2' out of the way so it  */
  2192.   /*   won't be invalidated during the insertion of the first half of the   */
  2193.   /*   segment.                                                             */
  2194.   finddirection(m, b, &searchtri2, endpoint2);
  2195.   if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
  2196.     /* The origin of searchtri1 may have changed if a collision with an */
  2197.     /*   intervening vertex on the segment occurred.                    */
  2198.     org(searchtri1, midvertex1);
  2199.     conformingedge(m, b, midvertex1, endpoint1, newmark);
  2200.   }
  2201.   if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
  2202.     /* The origin of searchtri2 may have changed if a collision with an */
  2203.     /*   intervening vertex on the segment occurred.                    */
  2204.     org(searchtri2, midvertex2);
  2205.     conformingedge(m, b, midvertex2, endpoint2, newmark);
  2206.   }
  2207. }
  2208. #endif /* not CDT_ONLY */
  2209. #endif /* not REDUCED */
  2210. /*****************************************************************************/
  2211. /*                                                                           */
  2212. /*  delaunayfixup()   Enforce the Delaunay condition at an edge, fanning out */
  2213. /*                    recursively from an existing vertex.  Pay special      */
  2214. /*                    attention to stacking inverted triangles.              */
  2215. /*                                                                           */
  2216. /*  This is a support routine for inserting segments into a constrained      */
  2217. /*  Delaunay triangulation.                                                  */
  2218. /*                                                                           */
  2219. /*  The origin of fixuptri is treated as if it has just been inserted, and   */
  2220. /*  the local Delaunay condition needs to be enforced.  It is only enforced  */
  2221. /*  in one sector, however, that being the angular range defined by          */
  2222. /*  fixuptri.                                                                */
  2223. /*                                                                           */
  2224. /*  This routine also needs to make decisions regarding the "stacking" of    */
  2225. /*  triangles.  (Read the description of constrainededge() below before      */
  2226. /*  reading on here, so you understand the algorithm.)  If the position of   */
  2227. /*  the new vertex (the origin of fixuptri) indicates that the vertex before */
  2228. /*  it on the polygon is a reflex vertex, then "stack" the triangle by       */
  2229. /*  doing nothing.  (fixuptri is an inverted triangle, which is how stacked  */
  2230. /*  triangles are identified.)                                               */
  2231. /*                                                                           */
  2232. /*  Otherwise, check whether the vertex before that was a reflex vertex.     */
  2233. /*  If so, perform an edge flip, thereby eliminating an inverted triangle    */
  2234. /*  (popping it off the stack).  The edge flip may result in the creation    */
  2235. /*  of a new inverted triangle, depending on whether or not the new vertex   */
  2236. /*  is visible to the vertex three edges behind on the polygon.              */
  2237. /*                                                                           */
  2238. /*  If neither of the two vertices behind the new vertex are reflex          */
  2239. /*  vertices, fixuptri and fartri, the triangle opposite it, are not         */
  2240. /*  inverted; hence, ensure that the edge between them is locally Delaunay.  */
  2241. /*                                                                           */
  2242. /*  `leftside' indicates whether or not fixuptri is to the left of the       */
  2243. /*  segment being inserted.  (Imagine that the segment is pointing up from   */
  2244. /*  endpoint1 to endpoint2.)                                                 */
  2245. /*                                                                           */
  2246. /*****************************************************************************/
  2247. #ifdef ANSI_DECLARATORS
  2248. void delaunayfixup(struct mesh *m, struct behavior *b,
  2249.                    struct otri *fixuptri, int leftside)
  2250. #else /* not ANSI_DECLARATORS */
  2251. void delaunayfixup(m, b, fixuptri, leftside)
  2252. struct mesh *m;
  2253. struct behavior *b;
  2254. struct otri *fixuptri;
  2255. int leftside;
  2256. #endif /* not ANSI_DECLARATORS */
  2257. {
  2258.   struct otri neartri;
  2259.   struct otri fartri;
  2260.   struct osub faredge;
  2261.   vertex nearvertex, leftvertex, rightvertex, farvertex;
  2262.   triangle ptr;                         /* Temporary variable used by sym(). */
  2263.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  2264.   lnext(*fixuptri, neartri);
  2265.   sym(neartri, fartri);
  2266.   /* Check if the edge opposite the origin of fixuptri can be flipped. */
  2267.   if (fartri.tri == m->dummytri) {
  2268.     return;
  2269.   }
  2270.   tspivot(neartri, faredge);
  2271.   if (faredge.ss != m->dummysub) {
  2272.     return;
  2273.   }
  2274.   /* Find all the relevant vertices. */
  2275.   apex(neartri, nearvertex);
  2276.   org(neartri, leftvertex);
  2277.   dest(neartri, rightvertex);
  2278.   apex(fartri, farvertex);
  2279.   /* Check whether the previous polygon vertex is a reflex vertex. */
  2280.   if (leftside) {
  2281.     if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
  2282.       /* leftvertex is a reflex vertex too.  Nothing can */
  2283.       /*   be done until a convex section is found.      */
  2284.       return;
  2285.     }
  2286.   } else {
  2287.     if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
  2288.       /* rightvertex is a reflex vertex too.  Nothing can */
  2289.       /*   be done until a convex section is found.       */
  2290.       return;
  2291.     }
  2292.   }
  2293.   if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
  2294.     /* fartri is not an inverted triangle, and farvertex is not a reflex */
  2295.     /*   vertex.  As there are no reflex vertices, fixuptri isn't an     */
  2296.     /*   inverted triangle, either.  Hence, test the edge between the    */
  2297.     /*   triangles to ensure it is locally Delaunay.                     */
  2298.     if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
  2299.         0.0) {
  2300.       return;
  2301.     }
  2302.     /* Not locally Delaunay; go on to an edge flip. */
  2303.   }        /* else fartri is inverted; remove it from the stack by flipping. */
  2304.   flip(m, b, &neartri);
  2305.   lprevself(*fixuptri);    /* Restore the origin of fixuptri after the flip. */
  2306.   /* Recursively process the two triangles that result from the flip. */
  2307.   delaunayfixup(m, b, fixuptri, leftside);
  2308.   delaunayfixup(m, b, &fartri, leftside);
  2309. }
  2310. /*****************************************************************************/
  2311. /*                                                                           */
  2312. /*  constrainededge()   Force a segment into a constrained Delaunay          */
  2313. /*                      triangulation by deleting the triangles it           */
  2314. /*                      intersects, and triangulating the polygons that      */
  2315. /*                      form on each side of it.                             */
  2316. /*                                                                           */
  2317. /*  Generates a single subsegment connecting `endpoint1' to `endpoint2'.     */
  2318. /*  The triangle `starttri' has `endpoint1' as its origin.  `newmark' is the */
  2319. /*  boundary marker of the segment.                                          */
  2320. /*                                                                           */
  2321. /*  To insert a segment, every triangle whose interior intersects the        */
  2322. /*  segment is deleted.  The union of these deleted triangles is a polygon   */
  2323. /*  (which is not necessarily monotone, but is close enough), which is       */
  2324. /*  divided into two polygons by the new segment.  This routine's task is    */
  2325. /*  to generate the Delaunay triangulation of these two polygons.            */
  2326. /*                                                                           */
  2327. /*  You might think of this routine's behavior as a two-step process.  The   */
  2328. /*  first step is to walk from endpoint1 to endpoint2, flipping each edge    */
  2329. /*  encountered.  This step creates a fan of edges connected to endpoint1,   */
  2330. /*  including the desired edge to endpoint2.  The second step enforces the   */
  2331. /*  Delaunay condition on each side of the segment in an incremental manner: */
  2332. /*  proceeding along the polygon from endpoint1 to endpoint2 (this is done   */
  2333. /*  independently on each side of the segment), each vertex is "enforced"    */
  2334. /*  as if it had just been inserted, but affecting only the previous         */
  2335. /*  vertices.  The result is the same as if the vertices had been inserted   */
  2336. /*  in the order they appear on the polygon, so the result is Delaunay.      */
  2337. /*                                                                           */
  2338. /*  In truth, constrainededge() interleaves these two steps.  The procedure  */
  2339. /*  walks from endpoint1 to endpoint2, and each time an edge is encountered  */
  2340. /*  and flipped, the newly exposed vertex (at the far end of the flipped     */
  2341. /*  edge) is "enforced" upon the previously flipped edges, usually affecting */
  2342. /*  only one side of the polygon (depending upon which side of the segment   */
  2343. /*  the vertex falls on).                                                    */
  2344. /*                                                                           */
  2345. /*  The algorithm is complicated by the need to handle polygons that are not */
  2346. /*  convex.  Although the polygon is not necessarily monotone, it can be     */
  2347. /*  triangulated in a manner similar to the stack-based algorithms for       */
  2348. /*  monotone polygons.  For each reflex vertex (local concavity) of the      */
  2349. /*  polygon, there will be an inverted triangle formed by one of the edge    */
  2350. /*  flips.  (An inverted triangle is one with negative area - that is, its   */
  2351. /*  vertices are arranged in clockwise order - and is best thought of as a   */
  2352. /*  wrinkle in the fabric of the mesh.)  Each inverted triangle can be       */
  2353. /*  thought of as a reflex vertex pushed on the stack, waiting to be fixed   */
  2354. /*  later.                                                                   */
  2355. /*                                                                           */
  2356. /*  A reflex vertex is popped from the stack when a vertex is inserted that  */
  2357. /*  is visible to the reflex vertex.  (However, if the vertex behind the     */
  2358. /*  reflex vertex is not visible to the reflex vertex, a new inverted        */
  2359. /*  triangle will take its place on the stack.)  These details are handled   */
  2360. /*  by the delaunayfixup() routine above.                                    */
  2361. /*                                                                           */
  2362. /*****************************************************************************/
  2363. #ifdef ANSI_DECLARATORS
  2364. void constrainededge(struct mesh *m, struct behavior *b,
  2365.                      struct otri *starttri, vertex endpoint2, int newmark)
  2366. #else /* not ANSI_DECLARATORS */
  2367. void constrainededge(m, b, starttri, endpoint2, newmark)
  2368. struct mesh *m;
  2369. struct behavior *b;
  2370. struct otri *starttri;
  2371. vertex endpoint2;
  2372. int newmark;
  2373. #endif /* not ANSI_DECLARATORS */
  2374. {
  2375.   struct otri fixuptri, fixuptri2;
  2376.   struct osub crosssubseg;
  2377.   vertex endpoint1;
  2378.   vertex farvertex;
  2379.   REAL area;
  2380.   int collision;
  2381.   int done;
  2382.   triangle ptr;             /* Temporary variable used by sym() and oprev(). */
  2383.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  2384.   org(*starttri, endpoint1);
  2385.   lnext(*starttri, fixuptri);
  2386.   flip(m, b, &fixuptri);
  2387.   /* `collision' indicates whether we have found a vertex directly */
  2388.   /*   between endpoint1 and endpoint2.                            */
  2389.   collision = 0;
  2390.   done = 0;
  2391.   do {
  2392.     org(fixuptri, farvertex);
  2393.     /* `farvertex' is the extreme point of the polygon we are "digging" */
  2394.     /*   to get from endpoint1 to endpoint2.                           */
  2395.     if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
  2396.       oprev(fixuptri, fixuptri2);
  2397.       /* Enforce the Delaunay condition around endpoint2. */
  2398.       delaunayfixup(m, b, &fixuptri, 0);
  2399.       delaunayfixup(m, b, &fixuptri2, 1);
  2400.       done = 1;
  2401.     } else {
  2402.       /* Check whether farvertex is to the left or right of the segment */
  2403.       /*   being inserted, to decide which edge of fixuptri to dig      */
  2404.       /*   through next.                                                */
  2405.       area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
  2406.       if (area == 0.0) {
  2407.         /* We've collided with a vertex between endpoint1 and endpoint2. */
  2408.         collision = 1;
  2409.         oprev(fixuptri, fixuptri2);
  2410.         /* Enforce the Delaunay condition around farvertex. */
  2411.         delaunayfixup(m, b, &fixuptri, 0);
  2412.         delaunayfixup(m, b, &fixuptri2, 1);
  2413.         done = 1;
  2414.       } else {
  2415.         if (area > 0.0) {        /* farvertex is to the left of the segment. */
  2416.           oprev(fixuptri, fixuptri2);
  2417.           /* Enforce the Delaunay condition around farvertex, on the */
  2418.           /*   left side of the segment only.                        */
  2419.           delaunayfixup(m, b, &fixuptri2, 1);
  2420.           /* Flip the edge that crosses the segment.  After the edge is */
  2421.           /*   flipped, one of its endpoints is the fan vertex, and the */
  2422.           /*   destination of fixuptri is the fan vertex.               */
  2423.           lprevself(fixuptri);
  2424.         } else {                /* farvertex is to the right of the segment. */
  2425.           delaunayfixup(m, b, &fixuptri, 0);
  2426.           /* Flip the edge that crosses the segment.  After the edge is */
  2427.           /*   flipped, one of its endpoints is the fan vertex, and the */
  2428.           /*   destination of fixuptri is the fan vertex.               */
  2429.           oprevself(fixuptri);
  2430.         }
  2431.         /* Check for two intersecting segments. */
  2432.         tspivot(fixuptri, crosssubseg);
  2433.         if (crosssubseg.ss == m->dummysub) {
  2434.           flip(m, b, &fixuptri);    /* May create inverted triangle at left. */
  2435.         } else {
  2436.           /* We've collided with a segment between endpoint1 and endpoint2. */
  2437.           collision = 1;
  2438.           /* Insert a vertex at the intersection. */
  2439.           segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
  2440.           done = 1;
  2441.         }
  2442.       }
  2443.     }
  2444.   } while (!done);
  2445.   /* Insert a subsegment to make the segment permanent. */
  2446.   insertsubseg(m, b, &fixuptri, newmark);
  2447.   /* If there was a collision with an interceding vertex, install another */
  2448.   /*   segment connecting that vertex with endpoint2.                     */
  2449.   if (collision) {
  2450.     /* Insert the remainder of the segment. */
  2451.     if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
  2452.       constrainededge(m, b, &fixuptri, endpoint2, newmark);
  2453.     }
  2454.   }
  2455. }
  2456. /*****************************************************************************/
  2457. /*                                                                           */
  2458. /*  insertsegment()   Insert a PSLG segment into a triangulation.            */
  2459. /*                                                                           */
  2460. /*****************************************************************************/
  2461. #ifdef ANSI_DECLARATORS
  2462. void insertsegment(struct mesh *m, struct behavior *b,
  2463.                    vertex endpoint1, vertex endpoint2, int newmark)
  2464. #else /* not ANSI_DECLARATORS */
  2465. void insertsegment(m, b, endpoint1, endpoint2, newmark)
  2466. struct mesh *m;
  2467. struct behavior *b;
  2468. vertex endpoint1;
  2469. vertex endpoint2;
  2470. int newmark;
  2471. #endif /* not ANSI_DECLARATORS */
  2472. {
  2473.   struct otri searchtri1, searchtri2;
  2474.   triangle encodedtri;
  2475.   vertex checkvertex;
  2476.   triangle ptr;                         /* Temporary variable used by sym(). */
  2477.   if (b->verbose > 1) {
  2478.     printf("  Connecting (%.12g, %.12g) to (%.12g, %.12g).n",
  2479.            endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
  2480.   }
  2481.   /* Find a triangle whose origin is the segment's first endpoint. */
  2482.   checkvertex = (vertex) NULL;
  2483.   encodedtri = vertex2tri(endpoint1);
  2484.   if (encodedtri != (triangle) NULL) {
  2485.     decode(encodedtri, searchtri1);
  2486.     org(searchtri1, checkvertex);
  2487.   }
  2488.   if (checkvertex != endpoint1) {
  2489.     /* Find a boundary triangle to search from. */
  2490.     searchtri1.tri = m->dummytri;
  2491.     searchtri1.orient = 0;
  2492.     symself(searchtri1);
  2493.     /* Search for the segment's first endpoint by point location. */
  2494.     if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
  2495.       printf(
  2496.         "Internal error in insertsegment():  Unable to locate PSLG vertexn");
  2497.       printf("  (%.12g, %.12g) in triangulation.n",
  2498.              endpoint1[0], endpoint1[1]);
  2499.       internalerror();
  2500.     }
  2501.   }
  2502.   /* Remember this triangle to improve subsequent point location. */
  2503.   otricopy(searchtri1, m->recenttri);
  2504.   /* Scout the beginnings of a path from the first endpoint */
  2505.   /*   toward the second.                                   */
  2506.   if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
  2507.     /* The segment was easily inserted. */
  2508.     return;
  2509.   }
  2510.   /* The first endpoint may have changed if a collision with an intervening */
  2511.   /*   vertex on the segment occurred.                                      */
  2512.   org(searchtri1, endpoint1);
  2513.   /* Find a triangle whose origin is the segment's second endpoint. */
  2514.   checkvertex = (vertex) NULL;
  2515.   encodedtri = vertex2tri(endpoint2);
  2516.   if (encodedtri != (triangle) NULL) {
  2517.     decode(encodedtri, searchtri2);
  2518.     org(searchtri2, checkvertex);
  2519.   }
  2520.   if (checkvertex != endpoint2) {
  2521.     /* Find a boundary triangle to search from. */
  2522.     searchtri2.tri = m->dummytri;
  2523.     searchtri2.orient = 0;
  2524.     symself(searchtri2);
  2525.     /* Search for the segment's second endpoint by point location. */
  2526.     if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
  2527.       printf(
  2528.         "Internal error in insertsegment():  Unable to locate PSLG vertexn");
  2529.       printf("  (%.12g, %.12g) in triangulation.n",
  2530.              endpoint2[0], endpoint2[1]);
  2531.       internalerror();
  2532.     }
  2533.   }
  2534.   /* Remember this triangle to improve subsequent point location. */
  2535.   otricopy(searchtri2, m->recenttri);
  2536.   /* Scout the beginnings of a path from the second endpoint */
  2537.   /*   toward the first.                                     */
  2538.   if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
  2539.     /* The segment was easily inserted. */
  2540.     return;
  2541.   }
  2542.   /* The second endpoint may have changed if a collision with an intervening */
  2543.   /*   vertex on the segment occurred.                                       */
  2544.   org(searchtri2, endpoint2);
  2545. #ifndef REDUCED
  2546. #ifndef CDT_ONLY
  2547.   if (b->splitseg) {
  2548.     /* Insert vertices to force the segment into the triangulation. */
  2549.     conformingedge(m, b, endpoint1, endpoint2, newmark);
  2550.   } else {
  2551. #endif /* not CDT_ONLY */
  2552. #endif /* not REDUCED */
  2553.     /* Insert the segment directly into the triangulation. */
  2554.     constrainededge(m, b, &searchtri1, endpoint2, newmark);
  2555. #ifndef REDUCED
  2556. #ifndef CDT_ONLY
  2557.   }
  2558. #endif /* not CDT_ONLY */
  2559. #endif /* not REDUCED */
  2560. }
  2561. /*****************************************************************************/
  2562. /*                                                                           */
  2563. /*  markhull()   Cover the convex hull of a triangulation with subsegments.  */
  2564. /*                                                                           */
  2565. /*****************************************************************************/
  2566. #ifdef ANSI_DECLARATORS
  2567. void markhull(struct mesh *m, struct behavior *b)
  2568. #else /* not ANSI_DECLARATORS */
  2569. void markhull(m, b)
  2570. struct mesh *m;
  2571. struct behavior *b;
  2572. #endif /* not ANSI_DECLARATORS */
  2573. {
  2574.   struct otri hulltri;
  2575.   struct otri nexttri;
  2576.   struct otri starttri;
  2577.   triangle ptr;             /* Temporary variable used by sym() and oprev(). */
  2578.   /* Find a triangle handle on the hull. */
  2579.   hulltri.tri = m->dummytri;
  2580.   hulltri.orient = 0;
  2581.   symself(hulltri);
  2582.   /* Remember where we started so we know when to stop. */
  2583.   otricopy(hulltri, starttri);
  2584.   /* Go once counterclockwise around the convex hull. */
  2585.   do {
  2586.     /* Create a subsegment if there isn't already one here. */
  2587.     insertsubseg(m, b, &hulltri, 1);
  2588.     /* To find the next hull edge, go clockwise around the next vertex. */
  2589.     lnextself(hulltri);
  2590.     oprev(hulltri, nexttri);
  2591.     while (nexttri.tri != m->dummytri) {
  2592.       otricopy(nexttri, hulltri);
  2593.       oprev(hulltri, nexttri);
  2594.     }
  2595.   } while (!otriequal(hulltri, starttri));
  2596. }
  2597. /*****************************************************************************/
  2598. /*                                                                           */
  2599. /*  formskeleton()   Create the segments of a triangulation, including PSLG  */
  2600. /*                   segments and edges on the convex hull.                  */
  2601. /*                                                                           */
  2602. /*  The PSLG segments are read from a .poly file.  The return value is the   */
  2603. /*  number of segments in the file.                                          */
  2604. /*                                                                           */
  2605. /*****************************************************************************/
  2606. #ifdef TRILIBRARY
  2607. #ifdef ANSI_DECLARATORS
  2608. void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
  2609.                   int *segmentmarkerlist, int numberofsegments)
  2610. #else /* not ANSI_DECLARATORS */
  2611. void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
  2612. struct mesh *m;
  2613. struct behavior *b;
  2614. int *segmentlist;
  2615. int *segmentmarkerlist;
  2616. int numberofsegments;
  2617. #endif /* not ANSI_DECLARATORS */
  2618. #else /* not TRILIBRARY */
  2619. #ifdef ANSI_DECLARATORS
  2620. void formskeleton(struct mesh *m, struct behavior *b,
  2621.                   FILE *polyfile, char *polyfilename)
  2622. #else /* not ANSI_DECLARATORS */
  2623. void formskeleton(m, b, polyfile, polyfilename)
  2624. struct mesh *m;
  2625. struct behavior *b;
  2626. FILE *polyfile;
  2627. char *polyfilename;
  2628. #endif /* not ANSI_DECLARATORS */
  2629. #endif /* not TRILIBRARY */
  2630. {
  2631. #ifdef TRILIBRARY
  2632.   char polyfilename[6];
  2633.   int index;
  2634. #else /* not TRILIBRARY */
  2635.   char inputline[INPUTLINESIZE];
  2636.   char *stringptr;
  2637. #endif /* not TRILIBRARY */
  2638.   vertex endpoint1, endpoint2;
  2639.   int segmentmarkers;
  2640.   int end1, end2;
  2641.   int boundmarker;
  2642.   int i;
  2643.   if (b->poly) {
  2644.     if (!b->quiet) {
  2645.       printf("Recovering segments in Delaunay triangulation.n");
  2646.     }
  2647. #ifdef TRILIBRARY
  2648.     strcpy(polyfilename, "input");
  2649.     m->insegments = numberofsegments;
  2650.     segmentmarkers = segmentmarkerlist != (int *) NULL;
  2651.     index = 0;
  2652. #else /* not TRILIBRARY */
  2653.     /* Read the segments from a .poly file. */
  2654.     /* Read number of segments and number of boundary markers. */
  2655.     stringptr = readline(inputline, polyfile, polyfilename);
  2656.     m->insegments = (int) strtol(stringptr, &stringptr, 0);
  2657.     stringptr = findfield(stringptr);
  2658.     if (*stringptr == '') {
  2659.       segmentmarkers = 0;
  2660.     } else {
  2661.       segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
  2662.     }
  2663. #endif /* not TRILIBRARY */
  2664.     /* If the input vertices are collinear, there is no triangulation, */
  2665.     /*   so don't try to insert segments.                              */
  2666.     if (m->triangles.items == 0) {
  2667.       return;
  2668.     }
  2669.     /* If segments are to be inserted, compute a mapping */
  2670.     /*   from vertices to triangles.                     */
  2671.     if (m->insegments > 0) {
  2672.       makevertexmap(m, b);
  2673.       if (b->verbose) {
  2674.         printf("  Recovering PSLG segments.n");
  2675.       }
  2676.     }
  2677.     boundmarker = 0;
  2678.     /* Read and insert the segments. */
  2679.     for (i = 0; i < m->insegments; i++) {
  2680. #ifdef TRILIBRARY
  2681.       end1 = segmentlist[index++];
  2682.       end2 = segmentlist[index++];
  2683.       if (segmentmarkers) {
  2684.         boundmarker = segmentmarkerlist[i];
  2685.       }
  2686. #else /* not TRILIBRARY */
  2687.       stringptr = readline(inputline, polyfile, b->inpolyfilename);
  2688.       stringptr = findfield(stringptr);
  2689.       if (*stringptr == '') {
  2690.         printf("Error:  Segment %d has no endpoints in %s.n",
  2691.                b->firstnumber + i, polyfilename);
  2692.         triexit(1);
  2693.       } else {
  2694.         end1 = (int) strtol(stringptr, &stringptr, 0);
  2695.       }
  2696.       stringptr = findfield(stringptr);
  2697.       if (*stringptr == '') {
  2698.         printf("Error:  Segment %d is missing its second endpoint in %s.n",
  2699.                b->firstnumber + i, polyfilename);
  2700.         triexit(1);
  2701.       } else {
  2702.         end2 = (int) strtol(stringptr, &stringptr, 0);
  2703.       }
  2704.       if (segmentmarkers) {
  2705.         stringptr = findfield(stringptr);
  2706.         if (*stringptr == '') {
  2707.           boundmarker = 0;
  2708.         } else {
  2709.           boundmarker = (int) strtol(stringptr, &stringptr, 0);
  2710.         }
  2711.       }
  2712. #endif /* not TRILIBRARY */
  2713.       if ((end1 < b->firstnumber) ||
  2714.           (end1 >= b->firstnumber + m->invertices)) {
  2715.         if (!b->quiet) {
  2716.           printf("Warning:  Invalid first endpoint of segment %d in %s.n",
  2717.                  b->firstnumber + i, polyfilename);
  2718.         }
  2719.       } else if ((end2 < b->firstnumber) ||
  2720.                  (end2 >= b->firstnumber + m->invertices)) {
  2721.         if (!b->quiet) {
  2722.           printf("Warning:  Invalid second endpoint of segment %d in %s.n",
  2723.                  b->firstnumber + i, polyfilename);
  2724.         }
  2725.       } else {
  2726.         /* Find the vertices numbered `end1' and `end2'. */
  2727.         endpoint1 = getvertex(m, b, end1);
  2728.         endpoint2 = getvertex(m, b, end2);
  2729.         if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
  2730.           if (!b->quiet) {
  2731.             printf("Warning:  Endpoints of segment %d are coincident in %s.n",
  2732.                    b->firstnumber + i, polyfilename);
  2733.           }
  2734.         } else {
  2735.           insertsegment(m, b, endpoint1, endpoint2, boundmarker);
  2736.         }
  2737.       }
  2738.     }
  2739.   } else {
  2740.     m->insegments = 0;
  2741.   }
  2742.   if (b->convex || !b->poly) {
  2743.     /* Enclose the convex hull with subsegments. */
  2744.     if (b->verbose) {
  2745.       printf("  Enclosing convex hull with segments.n");
  2746.     }
  2747.     markhull(m, b);
  2748.   }
  2749. }
  2750. /**                                                                         **/
  2751. /**                                                                         **/
  2752. /********* Segment insertion ends here                               *********/
  2753. /********* Carving out holes and concavities begins here             *********/
  2754. /**                                                                         **/
  2755. /**                                                                         **/
  2756. /*****************************************************************************/
  2757. /*                                                                           */
  2758. /*  infecthull()   Virally infect all of the triangles of the convex hull    */
  2759. /*                 that are not protected by subsegments.  Where there are   */
  2760. /*                 subsegments, set boundary markers as appropriate.         */
  2761. /*                                                                           */
  2762. /*****************************************************************************/
  2763. #ifdef ANSI_DECLARATORS
  2764. void infecthull(struct mesh *m, struct behavior *b)
  2765. #else /* not ANSI_DECLARATORS */
  2766. void infecthull(m, b)
  2767. struct mesh *m;
  2768. struct behavior *b;
  2769. #endif /* not ANSI_DECLARATORS */
  2770. {
  2771.   struct otri hulltri;
  2772.   struct otri nexttri;
  2773.   struct otri starttri;
  2774.   struct osub hullsubseg;
  2775.   triangle **deadtriangle;
  2776.   vertex horg, hdest;
  2777.   triangle ptr;                         /* Temporary variable used by sym(). */
  2778.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  2779.   if (b->verbose) {
  2780.     printf("  Marking concavities (external triangles) for elimination.n");
  2781.   }
  2782.   /* Find a triangle handle on the hull. */
  2783.   hulltri.tri = m->dummytri;
  2784.   hulltri.orient = 0;
  2785.   symself(hulltri);
  2786.   /* Remember where we started so we know when to stop. */
  2787.   otricopy(hulltri, starttri);
  2788.   /* Go once counterclockwise around the convex hull. */
  2789.   do {
  2790.     /* Ignore triangles that are already infected. */
  2791.     if (!infected(hulltri)) {
  2792.       /* Is the triangle protected by a subsegment? */
  2793.       tspivot(hulltri, hullsubseg);
  2794.       if (hullsubseg.ss == m->dummysub) {
  2795.         /* The triangle is not protected; infect it. */
  2796.         if (!infected(hulltri)) {
  2797.           infect(hulltri);
  2798.           deadtriangle = (triangle **) poolalloc(&m->viri);
  2799.           *deadtriangle = hulltri.tri;
  2800.         }
  2801.       } else {
  2802.         /* The triangle is protected; set boundary markers if appropriate. */
  2803.         if (mark(hullsubseg) == 0) {
  2804.           setmark(hullsubseg, 1);
  2805.           org(hulltri, horg);
  2806.           dest(hulltri, hdest);
  2807.           if (vertexmark(horg) == 0) {
  2808.             setvertexmark(horg, 1);
  2809.           }
  2810.           if (vertexmark(hdest) == 0) {
  2811.             setvertexmark(hdest, 1);
  2812.           }
  2813.         }
  2814.       }
  2815.     }
  2816.     /* To find the next hull edge, go clockwise around the next vertex. */
  2817.     lnextself(hulltri);
  2818.     oprev(hulltri, nexttri);
  2819.     while (nexttri.tri != m->dummytri) {
  2820.       otricopy(nexttri, hulltri);
  2821.       oprev(hulltri, nexttri);
  2822.     }
  2823.   } while (!otriequal(hulltri, starttri));
  2824. }
  2825. /*****************************************************************************/
  2826. /*                                                                           */
  2827. /*  plague()   Spread the virus from all infected triangles to any neighbors */
  2828. /*             not protected by subsegments.  Delete all infected triangles. */
  2829. /*                                                                           */
  2830. /*  This is the procedure that actually creates holes and concavities.       */
  2831. /*                                                                           */
  2832. /*  This procedure operates in two phases.  The first phase identifies all   */
  2833. /*  the triangles that will die, and marks them as infected.  They are       */
  2834. /*  marked to ensure that each triangle is added to the virus pool only      */
  2835. /*  once, so the procedure will terminate.                                   */
  2836. /*                                                                           */
  2837. /*  The second phase actually eliminates the infected triangles.  It also    */
  2838. /*  eliminates orphaned vertices.                                            */
  2839. /*                                                                           */
  2840. /*****************************************************************************/
  2841. #ifdef ANSI_DECLARATORS
  2842. void plague(struct mesh *m, struct behavior *b)
  2843. #else /* not ANSI_DECLARATORS */
  2844. void plague(m, b)
  2845. struct mesh *m;
  2846. struct behavior *b;
  2847. #endif /* not ANSI_DECLARATORS */
  2848. {
  2849.   struct otri testtri;
  2850.   struct otri neighbor;
  2851.   triangle **virusloop;
  2852.   triangle **deadtriangle;
  2853.   struct osub neighborsubseg;
  2854.   vertex testvertex;
  2855.   vertex norg, ndest;
  2856.   vertex deadorg, deaddest, deadapex;
  2857.   int killorg;
  2858.   triangle ptr;             /* Temporary variable used by sym() and onext(). */
  2859.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  2860.   if (b->verbose) {
  2861.     printf("  Marking neighbors of marked triangles.n");
  2862.   }
  2863.   /* Loop through all the infected triangles, spreading the virus to */
  2864.   /*   their neighbors, then to their neighbors' neighbors.          */
  2865.   traversalinit(&m->viri);
  2866.   virusloop = (triangle **) traverse(&m->viri);
  2867.   while (virusloop != (triangle **) NULL) {
  2868.     testtri.tri = *virusloop;
  2869.     /* A triangle is marked as infected by messing with one of its pointers */
  2870.     /*   to subsegments, setting it to an illegal value.  Hence, we have to */
  2871.     /*   temporarily uninfect this triangle so that we can examine its      */
  2872.     /*   adjacent subsegments.                                              */
  2873.     uninfect(testtri);
  2874.     if (b->verbose > 2) {
  2875.       /* Assign the triangle an orientation for convenience in */
  2876.       /*   checking its vertices.                              */
  2877.       testtri.orient = 0;
  2878.       org(testtri, deadorg);
  2879.       dest(testtri, deaddest);
  2880.       apex(testtri, deadapex);
  2881.       printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)n",
  2882.              deadorg[0], deadorg[1], deaddest[0], deaddest[1],
  2883.              deadapex[0], deadapex[1]);
  2884.     }
  2885.     /* Check each of the triangle's three neighbors. */
  2886.     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
  2887.       /* Find the neighbor. */
  2888.       sym(testtri, neighbor);
  2889.       /* Check for a subsegment between the triangle and its neighbor. */
  2890.       tspivot(testtri, neighborsubseg);
  2891.       /* Check if the neighbor is nonexistent or already infected. */
  2892.       if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
  2893.         if (neighborsubseg.ss != m->dummysub) {
  2894.           /* There is a subsegment separating the triangle from its      */
  2895.           /*   neighbor, but both triangles are dying, so the subsegment */
  2896.           /*   dies too.                                                 */
  2897.           subsegdealloc(m, neighborsubseg.ss);
  2898.           if (neighbor.tri != m->dummytri) {
  2899.             /* Make sure the subsegment doesn't get deallocated again */
  2900.             /*   later when the infected neighbor is visited.         */
  2901.             uninfect(neighbor);
  2902.             tsdissolve(neighbor);
  2903.             infect(neighbor);
  2904.           }
  2905.         }
  2906.       } else {                   /* The neighbor exists and is not infected. */
  2907.         if (neighborsubseg.ss == m->dummysub) {
  2908.           /* There is no subsegment protecting the neighbor, so */
  2909.           /*   the neighbor becomes infected.                   */
  2910.           if (b->verbose > 2) {
  2911.             org(neighbor, deadorg);
  2912.             dest(neighbor, deaddest);
  2913.             apex(neighbor, deadapex);
  2914.             printf(
  2915.               "    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)n",
  2916.                    deadorg[0], deadorg[1], deaddest[0], deaddest[1],
  2917.                    deadapex[0], deadapex[1]);
  2918.           }
  2919.           infect(neighbor);
  2920.           /* Ensure that the neighbor's neighbors will be infected. */
  2921.           deadtriangle = (triangle **) poolalloc(&m->viri);
  2922.           *deadtriangle = neighbor.tri;
  2923.         } else {               /* The neighbor is protected by a subsegment. */
  2924.           /* Remove this triangle from the subsegment. */
  2925.           stdissolve(neighborsubseg);
  2926.           /* The subsegment becomes a boundary.  Set markers accordingly. */
  2927.           if (mark(neighborsubseg) == 0) {
  2928.             setmark(neighborsubseg, 1);
  2929.           }
  2930.           org(neighbor, norg);
  2931.           dest(neighbor, ndest);
  2932.           if (vertexmark(norg) == 0) {
  2933.             setvertexmark(norg, 1);
  2934.           }
  2935.           if (vertexmark(ndest) == 0) {
  2936.             setvertexmark(ndest, 1);
  2937.           }
  2938.         }
  2939.       }
  2940.     }
  2941.     /* Remark the triangle as infected, so it doesn't get added to the */
  2942.     /*   virus pool again.                                             */
  2943.     infect(testtri);
  2944.     virusloop = (triangle **) traverse(&m->viri);
  2945.   }
  2946.   if (b->verbose) {
  2947.     printf("  Deleting marked triangles.n");
  2948.   }
  2949.   traversalinit(&m->viri);
  2950.   virusloop = (triangle **) traverse(&m->viri);
  2951.   while (virusloop != (triangle **) NULL) {
  2952.     testtri.tri = *virusloop;
  2953.     /* Check each of the three corners of the triangle for elimination. */
  2954.     /*   This is done by walking around each vertex, checking if it is  */
  2955.     /*   still connected to at least one live triangle.                 */
  2956.     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
  2957.       org(testtri, testvertex);
  2958.       /* Check if the vertex has already been tested. */
  2959.       if (testvertex != (vertex) NULL) {
  2960.         killorg = 1;
  2961.         /* Mark the corner of the triangle as having been tested. */
  2962.         setorg(testtri, NULL);
  2963.         /* Walk counterclockwise about the vertex. */
  2964.         onext(testtri, neighbor);
  2965.         /* Stop upon reaching a boundary or the starting triangle. */
  2966.         while ((neighbor.tri != m->dummytri) &&
  2967.                (!otriequal(neighbor, testtri))) {
  2968.           if (infected(neighbor)) {
  2969.             /* Mark the corner of this triangle as having been tested. */
  2970.             setorg(neighbor, NULL);
  2971.           } else {
  2972.             /* A live triangle.  The vertex survives. */
  2973.             killorg = 0;
  2974.           }
  2975.           /* Walk counterclockwise about the vertex. */
  2976.           onextself(neighbor);
  2977.         }
  2978.         /* If we reached a boundary, we must walk clockwise as well. */
  2979.         if (neighbor.tri == m->dummytri) {
  2980.           /* Walk clockwise about the vertex. */
  2981.           oprev(testtri, neighbor);
  2982.           /* Stop upon reaching a boundary. */
  2983.           while (neighbor.tri != m->dummytri) {
  2984.             if (infected(neighbor)) {
  2985.             /* Mark the corner of this triangle as having been tested. */
  2986.               setorg(neighbor, NULL);
  2987.             } else {