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

3D图形编程

开发平台:

C/C++

  1.               /* A live triangle.  The vertex survives. */
  2.               killorg = 0;
  3.             }
  4.             /* Walk clockwise about the vertex. */
  5.             oprevself(neighbor);
  6.           }
  7.         }
  8.         if (killorg) {
  9.           if (b->verbose > 1) {
  10.             printf("    Deleting vertex (%.12g, %.12g)n",
  11.                    testvertex[0], testvertex[1]);
  12.           }
  13.           setvertextype(testvertex, UNDEADVERTEX);
  14.           m->undeads++;
  15.         }
  16.       }
  17.     }
  18.     /* Record changes in the number of boundary edges, and disconnect */
  19.     /*   dead triangles from their neighbors.                         */
  20.     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
  21.       sym(testtri, neighbor);
  22.       if (neighbor.tri == m->dummytri) {
  23.         /* There is no neighboring triangle on this edge, so this edge    */
  24.         /*   is a boundary edge.  This triangle is being deleted, so this */
  25.         /*   boundary edge is deleted.                                    */
  26.         m->hullsize--;
  27.       } else {
  28.         /* Disconnect the triangle from its neighbor. */
  29.         dissolve(neighbor);
  30.         /* There is a neighboring triangle on this edge, so this edge */
  31.         /*   becomes a boundary edge when this triangle is deleted.   */
  32.         m->hullsize++;
  33.       }
  34.     }
  35.     /* Return the dead triangle to the pool of triangles. */
  36.     triangledealloc(m, testtri.tri);
  37.     virusloop = (triangle **) traverse(&m->viri);
  38.   }
  39.   /* Empty the virus pool. */
  40.   poolrestart(&m->viri);
  41. }
  42. /*****************************************************************************/
  43. /*                                                                           */
  44. /*  regionplague()   Spread regional attributes and/or area constraints      */
  45. /*                   (from a .poly file) throughout the mesh.                */
  46. /*                                                                           */
  47. /*  This procedure operates in two phases.  The first phase spreads an       */
  48. /*  attribute and/or an area constraint through a (segment-bounded) region.  */
  49. /*  The triangles are marked to ensure that each triangle is added to the    */
  50. /*  virus pool only once, so the procedure will terminate.                   */
  51. /*                                                                           */
  52. /*  The second phase uninfects all infected triangles, returning them to     */
  53. /*  normal.                                                                  */
  54. /*                                                                           */
  55. /*****************************************************************************/
  56. #ifdef ANSI_DECLARATORS
  57. void regionplague(struct mesh *m, struct behavior *b,
  58.                   REAL attribute, REAL area)
  59. #else /* not ANSI_DECLARATORS */
  60. void regionplague(m, b, attribute, area)
  61. struct mesh *m;
  62. struct behavior *b;
  63. REAL attribute;
  64. REAL area;
  65. #endif /* not ANSI_DECLARATORS */
  66. {
  67.   struct otri testtri;
  68.   struct otri neighbor;
  69.   triangle **virusloop;
  70.   triangle **regiontri;
  71.   struct osub neighborsubseg;
  72.   vertex regionorg, regiondest, regionapex;
  73.   triangle ptr;             /* Temporary variable used by sym() and onext(). */
  74.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  75.   if (b->verbose > 1) {
  76.     printf("  Marking neighbors of marked triangles.n");
  77.   }
  78.   /* Loop through all the infected triangles, spreading the attribute      */
  79.   /*   and/or area constraint to their neighbors, then to their neighbors' */
  80.   /*   neighbors.                                                          */
  81.   traversalinit(&m->viri);
  82.   virusloop = (triangle **) traverse(&m->viri);
  83.   while (virusloop != (triangle **) NULL) {
  84.     testtri.tri = *virusloop;
  85.     /* A triangle is marked as infected by messing with one of its pointers */
  86.     /*   to subsegments, setting it to an illegal value.  Hence, we have to */
  87.     /*   temporarily uninfect this triangle so that we can examine its      */
  88.     /*   adjacent subsegments.                                              */
  89.     uninfect(testtri);
  90.     if (b->regionattrib) {
  91.       /* Set an attribute. */
  92.       setelemattribute(testtri, m->eextras, attribute);
  93.     }
  94.     if (b->vararea) {
  95.       /* Set an area constraint. */
  96.       setareabound(testtri, area);
  97.     }
  98.     if (b->verbose > 2) {
  99.       /* Assign the triangle an orientation for convenience in */
  100.       /*   checking its vertices.                              */
  101.       testtri.orient = 0;
  102.       org(testtri, regionorg);
  103.       dest(testtri, regiondest);
  104.       apex(testtri, regionapex);
  105.       printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)n",
  106.              regionorg[0], regionorg[1], regiondest[0], regiondest[1],
  107.              regionapex[0], regionapex[1]);
  108.     }
  109.     /* Check each of the triangle's three neighbors. */
  110.     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
  111.       /* Find the neighbor. */
  112.       sym(testtri, neighbor);
  113.       /* Check for a subsegment between the triangle and its neighbor. */
  114.       tspivot(testtri, neighborsubseg);
  115.       /* Make sure the neighbor exists, is not already infected, and */
  116.       /*   isn't protected by a subsegment.                          */
  117.       if ((neighbor.tri != m->dummytri) && !infected(neighbor)
  118.           && (neighborsubseg.ss == m->dummysub)) {
  119.         if (b->verbose > 2) {
  120.           org(neighbor, regionorg);
  121.           dest(neighbor, regiondest);
  122.           apex(neighbor, regionapex);
  123.           printf("    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)n",
  124.                  regionorg[0], regionorg[1], regiondest[0], regiondest[1],
  125.                  regionapex[0], regionapex[1]);
  126.         }
  127.         /* Infect the neighbor. */
  128.         infect(neighbor);
  129.         /* Ensure that the neighbor's neighbors will be infected. */
  130.         regiontri = (triangle **) poolalloc(&m->viri);
  131.         *regiontri = neighbor.tri;
  132.       }
  133.     }
  134.     /* Remark the triangle as infected, so it doesn't get added to the */
  135.     /*   virus pool again.                                             */
  136.     infect(testtri);
  137.     virusloop = (triangle **) traverse(&m->viri);
  138.   }
  139.   /* Uninfect all triangles. */
  140.   if (b->verbose > 1) {
  141.     printf("  Unmarking marked triangles.n");
  142.   }
  143.   traversalinit(&m->viri);
  144.   virusloop = (triangle **) traverse(&m->viri);
  145.   while (virusloop != (triangle **) NULL) {
  146.     testtri.tri = *virusloop;
  147.     uninfect(testtri);
  148.     virusloop = (triangle **) traverse(&m->viri);
  149.   }
  150.   /* Empty the virus pool. */
  151.   poolrestart(&m->viri);
  152. }
  153. /*****************************************************************************/
  154. /*                                                                           */
  155. /*  carveholes()   Find the holes and infect them.  Find the area            */
  156. /*                 constraints and infect them.  Infect the convex hull.     */
  157. /*                 Spread the infection and kill triangles.  Spread the      */
  158. /*                 area constraints.                                         */
  159. /*                                                                           */
  160. /*  This routine mainly calls other routines to carry out all these          */
  161. /*  functions.                                                               */
  162. /*                                                                           */
  163. /*****************************************************************************/
  164. #ifdef ANSI_DECLARATORS
  165. void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
  166.                 REAL *regionlist, int regions)
  167. #else /* not ANSI_DECLARATORS */
  168. void carveholes(m, b, holelist, holes, regionlist, regions)
  169. struct mesh *m;
  170. struct behavior *b;
  171. REAL *holelist;
  172. int holes;
  173. REAL *regionlist;
  174. int regions;
  175. #endif /* not ANSI_DECLARATORS */
  176. {
  177.   struct otri searchtri;
  178.   struct otri triangleloop;
  179.   struct otri *regiontris;
  180.   triangle **holetri;
  181.   triangle **regiontri;
  182.   vertex searchorg, searchdest;
  183.   enum locateresult intersect;
  184.   int i;
  185.   triangle ptr;                         /* Temporary variable used by sym(). */
  186.   if (!(b->quiet || (b->noholes && b->convex))) {
  187.     printf("Removing unwanted triangles.n");
  188.     if (b->verbose && (holes > 0)) {
  189.       printf("  Marking holes for elimination.n");
  190.     }
  191.   }
  192.   if (regions > 0) {
  193.     /* Allocate storage for the triangles in which region points fall. */
  194.     regiontris = (struct otri *) trimalloc(regions *
  195.                                            (int) sizeof(struct otri));
  196.   } else {
  197.     regiontris = (struct otri *) NULL;
  198.   }
  199.   if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
  200.     /* Initialize a pool of viri to be used for holes, concavities, */
  201.     /*   regional attributes, and/or regional area constraints.     */
  202.     poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
  203.   }
  204.   if (!b->convex) {
  205.     /* Mark as infected any unprotected triangles on the boundary. */
  206.     /*   This is one way by which concavities are created.         */
  207.     infecthull(m, b);
  208.   }
  209.   if ((holes > 0) && !b->noholes) {
  210.     /* Infect each triangle in which a hole lies. */
  211.     for (i = 0; i < 2 * holes; i += 2) {
  212.       /* Ignore holes that aren't within the bounds of the mesh. */
  213.       if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
  214.           && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
  215.         /* Start searching from some triangle on the outer boundary. */
  216.         searchtri.tri = m->dummytri;
  217.         searchtri.orient = 0;
  218.         symself(searchtri);
  219.         /* Ensure that the hole is to the left of this boundary edge; */
  220.         /*   otherwise, locate() will falsely report that the hole    */
  221.         /*   falls within the starting triangle.                      */
  222.         org(searchtri, searchorg);
  223.         dest(searchtri, searchdest);
  224.         if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
  225.             0.0) {
  226.           /* Find a triangle that contains the hole. */
  227.           intersect = locate(m, b, &holelist[i], &searchtri);
  228.           if ((intersect != OUTSIDE) && (!infected(searchtri))) {
  229.             /* Infect the triangle.  This is done by marking the triangle  */
  230.             /*   as infected and including the triangle in the virus pool. */
  231.             infect(searchtri);
  232.             holetri = (triangle **) poolalloc(&m->viri);
  233.             *holetri = searchtri.tri;
  234.           }
  235.         }
  236.       }
  237.     }
  238.   }
  239.   /* Now, we have to find all the regions BEFORE we carve the holes, because */
  240.   /*   locate() won't work when the triangulation is no longer convex.       */
  241.   /*   (Incidentally, this is the reason why regional attributes and area    */
  242.   /*   constraints can't be used when refining a preexisting mesh, which     */
  243.   /*   might not be convex; they can only be used with a freshly             */
  244.   /*   triangulated PSLG.)                                                   */
  245.   if (regions > 0) {
  246.     /* Find the starting triangle for each region. */
  247.     for (i = 0; i < regions; i++) {
  248.       regiontris[i].tri = m->dummytri;
  249.       /* Ignore region points that aren't within the bounds of the mesh. */
  250.       if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
  251.           (regionlist[4 * i + 1] >= m->ymin) &&
  252.           (regionlist[4 * i + 1] <= m->ymax)) {
  253.         /* Start searching from some triangle on the outer boundary. */
  254.         searchtri.tri = m->dummytri;
  255.         searchtri.orient = 0;
  256.         symself(searchtri);
  257.         /* Ensure that the region point is to the left of this boundary */
  258.         /*   edge; otherwise, locate() will falsely report that the     */
  259.         /*   region point falls within the starting triangle.           */
  260.         org(searchtri, searchorg);
  261.         dest(searchtri, searchdest);
  262.         if (counterclockwise(m, b, searchorg, searchdest, &regionlist[4 * i]) >
  263.             0.0) {
  264.           /* Find a triangle that contains the region point. */
  265.           intersect = locate(m, b, &regionlist[4 * i], &searchtri);
  266.           if ((intersect != OUTSIDE) && (!infected(searchtri))) {
  267.             /* Record the triangle for processing after the */
  268.             /*   holes have been carved.                    */
  269.             otricopy(searchtri, regiontris[i]);
  270.           }
  271.         }
  272.       }
  273.     }
  274.   }
  275.   if (m->viri.items > 0) {
  276.     /* Carve the holes and concavities. */
  277.     plague(m, b);
  278.   }
  279.   /* The virus pool should be empty now. */
  280.   if (regions > 0) {
  281.     if (!b->quiet) {
  282.       if (b->regionattrib) {
  283.         if (b->vararea) {
  284.           printf("Spreading regional attributes and area constraints.n");
  285.         } else {
  286.           printf("Spreading regional attributes.n");
  287.         }
  288.       } else { 
  289.         printf("Spreading regional area constraints.n");
  290.       }
  291.     }
  292.     if (b->regionattrib && !b->refine) {
  293.       /* Assign every triangle a regional attribute of zero. */
  294.       traversalinit(&m->triangles);
  295.       triangleloop.orient = 0;
  296.       triangleloop.tri = triangletraverse(m);
  297.       while (triangleloop.tri != (triangle *) NULL) {
  298.         setelemattribute(triangleloop, m->eextras, 0.0);
  299.         triangleloop.tri = triangletraverse(m);
  300.       }
  301.     }
  302.     for (i = 0; i < regions; i++) {
  303.       if (regiontris[i].tri != m->dummytri) {
  304.         /* Make sure the triangle under consideration still exists. */
  305.         /*   It may have been eaten by the virus.                   */
  306.         if (!deadtri(regiontris[i].tri)) {
  307.           /* Put one triangle in the virus pool. */
  308.           infect(regiontris[i]);
  309.           regiontri = (triangle **) poolalloc(&m->viri);
  310.           *regiontri = regiontris[i].tri;
  311.           /* Apply one region's attribute and/or area constraint. */
  312.           regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
  313.           /* The virus pool should be empty now. */
  314.         }
  315.       }
  316.     }
  317.     if (b->regionattrib && !b->refine) {
  318.       /* Note the fact that each triangle has an additional attribute. */
  319.       m->eextras++;
  320.     }
  321.   }
  322.   /* Free up memory. */
  323.   if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
  324.     pooldeinit(&m->viri);
  325.   }
  326.   if (regions > 0) {
  327.     trifree((VOID *) regiontris);
  328.   }
  329. }
  330. /**                                                                         **/
  331. /**                                                                         **/
  332. /********* Carving out holes and concavities ends here               *********/
  333. /********* Mesh quality maintenance begins here                      *********/
  334. /**                                                                         **/
  335. /**                                                                         **/
  336. /*****************************************************************************/
  337. /*                                                                           */
  338. /*  tallyencs()   Traverse the entire list of subsegments, and check each    */
  339. /*                to see if it is encroached.  If so, add it to the list.    */
  340. /*                                                                           */
  341. /*****************************************************************************/
  342. #ifndef CDT_ONLY
  343. #ifdef ANSI_DECLARATORS
  344. void tallyencs(struct mesh *m, struct behavior *b)
  345. #else /* not ANSI_DECLARATORS */
  346. void tallyencs(m, b)
  347. struct mesh *m;
  348. struct behavior *b;
  349. #endif /* not ANSI_DECLARATORS */
  350. {
  351.   struct osub subsegloop;
  352.   int dummy;
  353.   traversalinit(&m->subsegs);
  354.   subsegloop.ssorient = 0;
  355.   subsegloop.ss = subsegtraverse(m);
  356.   while (subsegloop.ss != (subseg *) NULL) {
  357.     /* If the segment is encroached, add it to the list. */
  358.     dummy = checkseg4encroach(m, b, &subsegloop);
  359.     subsegloop.ss = subsegtraverse(m);
  360.   }
  361. }
  362. #endif /* not CDT_ONLY */
  363. /*****************************************************************************/
  364. /*                                                                           */
  365. /*  precisionerror()  Print an error message for precision problems.         */
  366. /*                                                                           */
  367. /*****************************************************************************/
  368. #ifndef CDT_ONLY
  369. void precisionerror()
  370. {
  371.   printf("Try increasing the area criterion and/or reducing the minimumn");
  372.   printf("  allowable angle so that tiny triangles are not created.n");
  373. #ifdef SINGLE
  374.   printf("Alternatively, try recompiling me with double precisionn");
  375.   printf("  arithmetic (by removing "#define SINGLE" from then");
  376.   printf("  source file or "-DSINGLE" from the makefile).n");
  377. #endif /* SINGLE */
  378. }
  379. #endif /* not CDT_ONLY */
  380. /*****************************************************************************/
  381. /*                                                                           */
  382. /*  splitencsegs()   Split all the encroached subsegments.                   */
  383. /*                                                                           */
  384. /*  Each encroached subsegment is repaired by splitting it - inserting a     */
  385. /*  vertex at or near its midpoint.  Newly inserted vertices may encroach    */
  386. /*  upon other subsegments; these are also repaired.                         */
  387. /*                                                                           */
  388. /*  `triflaws' is a flag that specifies whether one should take note of new  */
  389. /*  bad triangles that result from inserting vertices to repair encroached   */
  390. /*  subsegments.                                                             */
  391. /*                                                                           */
  392. /*****************************************************************************/
  393. #ifndef CDT_ONLY
  394. #ifdef ANSI_DECLARATORS
  395. void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
  396. #else /* not ANSI_DECLARATORS */
  397. void splitencsegs(m, b, triflaws)
  398. struct mesh *m;
  399. struct behavior *b;
  400. int triflaws;
  401. #endif /* not ANSI_DECLARATORS */
  402. {
  403.   struct otri enctri;
  404.   struct otri testtri;
  405.   struct osub testsh;
  406.   struct osub currentenc;
  407.   struct badsubseg *encloop;
  408.   vertex eorg, edest, eapex;
  409.   vertex newvertex;
  410.   enum insertvertexresult success;
  411.   REAL segmentlength, nearestpoweroftwo;
  412.   REAL split;
  413.   REAL multiplier, divisor;
  414.   int acuteorg, acuteorg2, acutedest, acutedest2;
  415.   int dummy;
  416.   int i;
  417.   triangle ptr;                     /* Temporary variable used by stpivot(). */
  418.   subseg sptr;                        /* Temporary variable used by snext(). */
  419.   /* Note that steinerleft == -1 if an unlimited number */
  420.   /*   of Steiner points is allowed.                    */
  421.   while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
  422.     traversalinit(&m->badsubsegs);
  423.     encloop = badsubsegtraverse(m);
  424.     while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
  425.       sdecode(encloop->encsubseg, currentenc);
  426.       sorg(currentenc, eorg);
  427.       sdest(currentenc, edest);
  428.       /* Make sure that this segment is still the same segment it was   */
  429.       /*   when it was determined to be encroached.  If the segment was */
  430.       /*   enqueued multiple times (because several newly inserted      */
  431.       /*   vertices encroached it), it may have already been split.     */
  432.       if (!deadsubseg(currentenc.ss) &&
  433.           (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
  434.         /* To decide where to split a segment, we need to know if the   */
  435.         /*   segment shares an endpoint with an adjacent segment.       */
  436.         /*   The concern is that, if we simply split every encroached   */
  437.         /*   segment in its center, two adjacent segments with a small  */
  438.         /*   angle between them might lead to an infinite loop; each    */
  439.         /*   vertex added to split one segment will encroach upon the   */
  440.         /*   other segment, which must then be split with a vertex that */
  441.         /*   will encroach upon the first segment, and so on forever.   */
  442.         /* To avoid this, imagine a set of concentric circles, whose    */
  443.         /*   radii are powers of two, about each segment endpoint.      */
  444.         /*   These concentric circles determine where the segment is    */
  445.         /*   split.  (If both endpoints are shared with adjacent        */
  446.         /*   segments, split the segment in the middle, and apply the   */
  447.         /*   concentric circles for later splittings.)                  */
  448.         /* Is the origin shared with another segment? */
  449.         stpivot(currentenc, enctri);
  450.         lnext(enctri, testtri);
  451.         tspivot(testtri, testsh);
  452.         acuteorg = testsh.ss != m->dummysub;
  453.         /* Is the destination shared with another segment? */
  454.         lnextself(testtri);
  455.         tspivot(testtri, testsh);
  456.         acutedest = testsh.ss != m->dummysub;
  457.         /* If we're using Chew's algorithm (rather than Ruppert's) */
  458.         /*   to define encroachment, delete free vertices from the */
  459.         /*   subsegment's diametral circle.                        */
  460.         if (!b->conformdel && !acuteorg && !acutedest) {
  461.           apex(enctri, eapex);
  462.           while ((vertextype(eapex) == FREEVERTEX) &&
  463.                  ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
  464.                   (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
  465.             deletevertex(m, b, &testtri);
  466.             stpivot(currentenc, enctri);
  467.             apex(enctri, eapex);
  468.             lprev(enctri, testtri);
  469.           }
  470.         }
  471.         /* Now, check the other side of the segment, if there's a triangle */
  472.         /*   there.                                                        */
  473.         sym(enctri, testtri);
  474.         if (testtri.tri != m->dummytri) {
  475.           /* Is the destination shared with another segment? */
  476.           lnextself(testtri);
  477.           tspivot(testtri, testsh);
  478.           acutedest2 = testsh.ss != m->dummysub;
  479.           acutedest = acutedest || acutedest2;
  480.           /* Is the origin shared with another segment? */
  481.           lnextself(testtri);
  482.           tspivot(testtri, testsh);
  483.           acuteorg2 = testsh.ss != m->dummysub;
  484.           acuteorg = acuteorg || acuteorg2;
  485.           /* Delete free vertices from the subsegment's diametral circle. */
  486.           if (!b->conformdel && !acuteorg2 && !acutedest2) {
  487.             org(testtri, eapex);
  488.             while ((vertextype(eapex) == FREEVERTEX) &&
  489.                    ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
  490.                     (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
  491.               deletevertex(m, b, &testtri);
  492.               sym(enctri, testtri);
  493.               apex(testtri, eapex);
  494.               lprevself(testtri);
  495.             }
  496.           }
  497.         }
  498.         /* Use the concentric circles if exactly one endpoint is shared */
  499.         /*   with another adjacent segment.                             */
  500.         if (acuteorg || acutedest) {
  501.           segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
  502.                                (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
  503.           /* Find the power of two that most evenly splits the segment.  */
  504.           /*   The worst case is a 2:1 ratio between subsegment lengths. */
  505.           nearestpoweroftwo = 1.0;
  506.           while (segmentlength > 3.0 * nearestpoweroftwo) {
  507.             nearestpoweroftwo *= 2.0;
  508.           }
  509.           while (segmentlength < 1.5 * nearestpoweroftwo) {
  510.             nearestpoweroftwo *= 0.5;
  511.           }
  512.           /* Where do we split the segment? */
  513.           split = nearestpoweroftwo / segmentlength;
  514.           if (acutedest) {
  515.             split = 1.0 - split;
  516.           }
  517.         } else {
  518.           /* If we're not worried about adjacent segments, split */
  519.           /*   this segment in the middle.                       */
  520.           split = 0.5;
  521.         }
  522.         /* Create the new vertex. */
  523.         newvertex = (vertex) poolalloc(&m->vertices);
  524.         /* Interpolate its coordinate and attributes. */
  525.         for (i = 0; i < 2 + m->nextras; i++) {
  526.           newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
  527.         }
  528.         if (!b->noexact) {
  529.           /* Roundoff in the above calculation may yield a `newvertex'   */
  530.           /*   that is not precisely collinear with `eorg' and `edest'.  */
  531.           /*   Improve collinearity by one step of iterative refinement. */
  532.           multiplier = counterclockwise(m, b, eorg, edest, newvertex);
  533.           divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
  534.                      (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
  535.           if ((multiplier != 0.0) && (divisor != 0.0)) {
  536.             multiplier = multiplier / divisor;
  537.             /* Watch out for NANs. */
  538.             if (multiplier == multiplier) {
  539.               newvertex[0] += multiplier * (edest[1] - eorg[1]);
  540.               newvertex[1] += multiplier * (eorg[0] - edest[0]);
  541.             }
  542.           }
  543.         }
  544.         setvertexmark(newvertex, mark(currentenc));
  545.         setvertextype(newvertex, SEGMENTVERTEX);
  546.         if (b->verbose > 1) {
  547.           printf(
  548.   "  Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).n",
  549.                  eorg[0], eorg[1], edest[0], edest[1],
  550.                  newvertex[0], newvertex[1]);
  551.         }
  552.         /* Check whether the new vertex lies on an endpoint. */
  553.         if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
  554.             ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
  555.           printf("Error:  Ran out of precision at (%.12g, %.12g).n",
  556.                  newvertex[0], newvertex[1]);
  557.           printf("I attempted to split a segment to a smaller size thann");
  558.           printf("  can be accommodated by the finite precision ofn");
  559.           printf("  floating point arithmetic.n");
  560.           precisionerror();
  561.           triexit(1);
  562.         }
  563.         /* Insert the splitting vertex.  This should always succeed. */
  564.         success = insertvertex(m, b, newvertex, &enctri, &currentenc,
  565.                                1, triflaws);
  566.         if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
  567.           printf("Internal error in splitencsegs():n");
  568.           printf("  Failure to split a segment.n");
  569.           internalerror();
  570.         }
  571.         if (m->steinerleft > 0) {
  572.           m->steinerleft--;
  573.         }
  574.         /* Check the two new subsegments to see if they're encroached. */
  575.         dummy = checkseg4encroach(m, b, &currentenc);
  576.         snextself(currentenc);
  577.         dummy = checkseg4encroach(m, b, &currentenc);
  578.       }
  579.       badsubsegdealloc(m, encloop);
  580.       encloop = badsubsegtraverse(m);
  581.     }
  582.   }
  583. }
  584. #endif /* not CDT_ONLY */
  585. /*****************************************************************************/
  586. /*                                                                           */
  587. /*  tallyfaces()   Test every triangle in the mesh for quality measures.     */
  588. /*                                                                           */
  589. /*****************************************************************************/
  590. #ifndef CDT_ONLY
  591. #ifdef ANSI_DECLARATORS
  592. void tallyfaces(struct mesh *m, struct behavior *b)
  593. #else /* not ANSI_DECLARATORS */
  594. void tallyfaces(m, b)
  595. struct mesh *m;
  596. struct behavior *b;
  597. #endif /* not ANSI_DECLARATORS */
  598. {
  599.   struct otri triangleloop;
  600.   if (b->verbose) {
  601.     printf("  Making a list of bad triangles.n");
  602.   }
  603.   traversalinit(&m->triangles);
  604.   triangleloop.orient = 0;
  605.   triangleloop.tri = triangletraverse(m);
  606.   while (triangleloop.tri != (triangle *) NULL) {
  607.     /* If the triangle is bad, enqueue it. */
  608.     testtriangle(m, b, &triangleloop);
  609.     triangleloop.tri = triangletraverse(m);
  610.   }
  611. }
  612. #endif /* not CDT_ONLY */
  613. /*****************************************************************************/
  614. /*                                                                           */
  615. /*  splittriangle()   Inserts a vertex at the circumcenter of a triangle.    */
  616. /*                    Deletes the newly inserted vertex if it encroaches     */
  617. /*                    upon a segment.                                        */
  618. /*                                                                           */
  619. /*****************************************************************************/
  620. #ifndef CDT_ONLY
  621. #ifdef ANSI_DECLARATORS
  622. void splittriangle(struct mesh *m, struct behavior *b,
  623.                    struct badtriang *badtri)
  624. #else /* not ANSI_DECLARATORS */
  625. void splittriangle(m, b, badtri)
  626. struct mesh *m;
  627. struct behavior *b;
  628. struct badtriang *badtri;
  629. #endif /* not ANSI_DECLARATORS */
  630. {
  631.   struct otri badotri;
  632.   vertex borg, bdest, bapex;
  633.   vertex newvertex;
  634.   REAL xi, eta;
  635.   enum insertvertexresult success;
  636.   int errorflag;
  637.   int i;
  638.   decode(badtri->poortri, badotri);
  639.   org(badotri, borg);
  640.   dest(badotri, bdest);
  641.   apex(badotri, bapex);
  642.   /* Make sure that this triangle is still the same triangle it was      */
  643.   /*   when it was tested and determined to be of bad quality.           */
  644.   /*   Subsequent transformations may have made it a different triangle. */
  645.   if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
  646.       (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
  647.     if (b->verbose > 1) {
  648.       printf("  Splitting this triangle at its circumcenter:n");
  649.       printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)n", borg[0],
  650.              borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
  651.     }
  652.     errorflag = 0;
  653.     /* Create a new vertex at the triangle's circumcenter. */
  654.     newvertex = (vertex) poolalloc(&m->vertices);
  655.     findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
  656.     /* Check whether the new vertex lies on a triangle vertex. */
  657.     if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
  658.         ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
  659.         ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
  660.       if (!b->quiet) {
  661.         printf(
  662.              "Warning:  New vertex (%.12g, %.12g) falls on existing vertex.n",
  663.                newvertex[0], newvertex[1]);
  664.         errorflag = 1;
  665.       }
  666.       vertexdealloc(m, newvertex);
  667.     } else {
  668.       for (i = 2; i < 2 + m->nextras; i++) {
  669.         /* Interpolate the vertex attributes at the circumcenter. */
  670.         newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
  671.                               + eta * (bapex[i] - borg[i]);
  672.       }
  673.       /* The new vertex must be in the interior, and therefore is a */
  674.       /*   free vertex with a marker of zero.                       */
  675.       setvertexmark(newvertex, 0);
  676.       setvertextype(newvertex, FREEVERTEX);
  677.       /* Ensure that the handle `badotri' does not represent the longest  */
  678.       /*   edge of the triangle.  This ensures that the circumcenter must */
  679.       /*   fall to the left of this edge, so point location will work.    */
  680.       /*   (If the angle org-apex-dest exceeds 90 degrees, then the       */
  681.       /*   circumcenter lies outside the org-dest edge, and eta is        */
  682.       /*   negative.  Roundoff error might prevent eta from being         */
  683.       /*   negative when it should be, so I test eta against xi.)         */
  684.       if (eta < xi) {
  685.         lprevself(badotri);
  686.       }
  687.       /* Insert the circumcenter, searching from the edge of the triangle, */
  688.       /*   and maintain the Delaunay property of the triangulation.        */
  689.       success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
  690.                              1, 1);
  691.       if (success == SUCCESSFULVERTEX) {
  692.         if (m->steinerleft > 0) {
  693.           m->steinerleft--;
  694.         }
  695.       } else if (success == ENCROACHINGVERTEX) {
  696.         /* If the newly inserted vertex encroaches upon a subsegment, */
  697.         /*   delete the new vertex.                                   */
  698.         undovertex(m, b);
  699.         if (b->verbose > 1) {
  700.           printf("  Rejecting (%.12g, %.12g).n", newvertex[0], newvertex[1]);
  701.         }
  702.         vertexdealloc(m, newvertex);
  703.       } else if (success == VIOLATINGVERTEX) {
  704.         /* Failed to insert the new vertex, but some subsegment was */
  705.         /*   marked as being encroached.                            */
  706.         vertexdealloc(m, newvertex);
  707.       } else {                                 /* success == DUPLICATEVERTEX */
  708.         /* Couldn't insert the new vertex because a vertex is already there. */
  709.         if (!b->quiet) {
  710.           printf(
  711.             "Warning:  New vertex (%.12g, %.12g) falls on existing vertex.n",
  712.                  newvertex[0], newvertex[1]);
  713.           errorflag = 1;
  714.         }
  715.         vertexdealloc(m, newvertex);
  716.       }
  717.     }
  718.     if (errorflag) {
  719.       if (b->verbose) {
  720.         printf("  The new vertex is at the circumcenter of trianglen");
  721.         printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)n",
  722.                borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
  723.       }
  724.       printf("This probably means that I am trying to refine trianglesn");
  725.       printf("  to a smaller size than can be accommodated by the finiten");
  726.       printf("  precision of floating point arithmetic.  (You can ben");
  727.       printf("  sure of this if I fail to terminate.)n");
  728.       precisionerror();
  729.     }
  730.   }
  731. }
  732. #endif /* not CDT_ONLY */
  733. /*****************************************************************************/
  734. /*                                                                           */
  735. /*  enforcequality()   Remove all the encroached subsegments and bad         */
  736. /*                     triangles from the triangulation.                     */
  737. /*                                                                           */
  738. /*****************************************************************************/
  739. #ifndef CDT_ONLY
  740. #ifdef ANSI_DECLARATORS
  741. void enforcequality(struct mesh *m, struct behavior *b)
  742. #else /* not ANSI_DECLARATORS */
  743. void enforcequality(m, b)
  744. struct mesh *m;
  745. struct behavior *b;
  746. #endif /* not ANSI_DECLARATORS */
  747. {
  748.   struct badtriang *badtri;
  749.   int i;
  750.   if (!b->quiet) {
  751.     printf("Adding Steiner points to enforce quality.n");
  752.   }
  753.   /* Initialize the pool of encroached subsegments. */
  754.   poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
  755.            BADSUBSEGPERBLOCK, 0);
  756.   if (b->verbose) {
  757.     printf("  Looking for encroached subsegments.n");
  758.   }
  759.   /* Test all segments to see if they're encroached. */
  760.   tallyencs(m, b);
  761.   if (b->verbose && (m->badsubsegs.items > 0)) {
  762.     printf("  Splitting encroached subsegments.n");
  763.   }
  764.   /* Fix encroached subsegments without noting bad triangles. */
  765.   splitencsegs(m, b, 0);
  766.   /* At this point, if we haven't run out of Steiner points, the */
  767.   /*   triangulation should be (conforming) Delaunay.            */
  768.   /* Next, we worry about enforcing triangle quality. */
  769.   if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
  770.     /* Initialize the pool of bad triangles. */
  771.     poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
  772.              BADTRIPERBLOCK, 0);
  773.     /* Initialize the queues of bad triangles. */
  774.     for (i = 0; i < 4096; i++) {
  775.       m->queuefront[i] = (struct badtriang *) NULL;
  776.     }
  777.     m->firstnonemptyq = -1;
  778.     /* Test all triangles to see if they're bad. */
  779.     tallyfaces(m, b);
  780.     /* Initialize the pool of recently flipped triangles. */
  781.     poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
  782.              FLIPSTACKERPERBLOCK, 0);
  783.     m->checkquality = 1;
  784.     if (b->verbose) {
  785.       printf("  Splitting bad triangles.n");
  786.     }
  787.     while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
  788.       /* Fix one bad triangle by inserting a vertex at its circumcenter. */
  789.       badtri = dequeuebadtriang(m);
  790.       splittriangle(m, b, badtri);
  791.       if (m->badsubsegs.items > 0) {
  792.         /* Put bad triangle back in queue for another try later. */
  793.         enqueuebadtriang(m, b, badtri);
  794.         /* Fix any encroached subsegments that resulted. */
  795.         /*   Record any new bad triangles that result.   */
  796.         splitencsegs(m, b, 1);
  797.       } else {
  798.         /* Return the bad triangle to the pool. */
  799.         pooldealloc(&m->badtriangles, (VOID *) badtri);
  800.       }
  801.     }
  802.   }
  803.   /* At this point, if the "-D" switch was selected and we haven't run out  */
  804.   /*   of Steiner points, the triangulation should be (conforming) Delaunay */
  805.   /*   and have no low-quality triangles.                                   */
  806.   /* Might we have run out of Steiner points too soon? */
  807.   if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
  808.       (m->steinerleft == 0)) {
  809.     printf("nWarning:  I ran out of Steiner points, but the mesh hasn");
  810.     if (m->badsubsegs.items == 1) {
  811.       printf("  one encroached subsegment, and therefore might not be trulyn"
  812.              );
  813.     } else {
  814.       printf("  %ld encroached subsegments, and therefore might not be trulyn"
  815.              , m->badsubsegs.items);
  816.     }
  817.     printf("  Delaunay.  If the Delaunay property is important to you,n");
  818.     printf("  try increasing the number of Steiner points (controlled byn");
  819.     printf("  the -S switch) slightly and try again.nn");
  820.   }
  821. }
  822. #endif /* not CDT_ONLY */
  823. /**                                                                         **/
  824. /**                                                                         **/
  825. /********* Mesh quality maintenance ends here                        *********/
  826. /*****************************************************************************/
  827. /*                                                                           */
  828. /*  highorder()   Create extra nodes for quadratic subparametric elements.   */
  829. /*                                                                           */
  830. /*****************************************************************************/
  831. #ifdef ANSI_DECLARATORS
  832. void highorder(struct mesh *m, struct behavior *b)
  833. #else /* not ANSI_DECLARATORS */
  834. void highorder(m, b)
  835. struct mesh *m;
  836. struct behavior *b;
  837. #endif /* not ANSI_DECLARATORS */
  838. {
  839.   struct otri triangleloop, trisym;
  840.   struct osub checkmark;
  841.   vertex newvertex;
  842.   vertex torg, tdest;
  843.   int i;
  844.   triangle ptr;                         /* Temporary variable used by sym(). */
  845.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  846.   if (!b->quiet) {
  847.     printf("Adding vertices for second-order triangles.n");
  848.   }
  849.   /* The following line ensures that dead items in the pool of nodes    */
  850.   /*   cannot be allocated for the extra nodes associated with high     */
  851.   /*   order elements.  This ensures that the primary nodes (at the     */
  852.   /*   corners of elements) will occur earlier in the output files, and */
  853.   /*   have lower indices, than the extra nodes.                        */
  854.   m->vertices.deaditemstack = (VOID *) NULL;
  855.   traversalinit(&m->triangles);
  856.   triangleloop.tri = triangletraverse(m);
  857.   /* To loop over the set of edges, loop over all triangles, and look at   */
  858.   /*   the three edges of each triangle.  If there isn't another triangle  */
  859.   /*   adjacent to the edge, operate on the edge.  If there is another     */
  860.   /*   adjacent triangle, operate on the edge only if the current triangle */
  861.   /*   has a smaller pointer than its neighbor.  This way, each edge is    */
  862.   /*   considered only once.                                               */
  863.   while (triangleloop.tri != (triangle *) NULL) {
  864.     for (triangleloop.orient = 0; triangleloop.orient < 3;
  865.          triangleloop.orient++) {
  866.       sym(triangleloop, trisym);
  867.       if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
  868.         org(triangleloop, torg);
  869.         dest(triangleloop, tdest);
  870.         /* Create a new node in the middle of the edge.  Interpolate */
  871.         /*   its attributes.                                         */
  872.         newvertex = (vertex) poolalloc(&m->vertices);
  873.         for (i = 0; i < 2 + m->nextras; i++) {
  874.           newvertex[i] = 0.5 * (torg[i] + tdest[i]);
  875.         }
  876.         /* Set the new node's marker to zero or one, depending on */
  877.         /*   whether it lies on a boundary.                       */
  878.         setvertexmark(newvertex, trisym.tri == m->dummytri);
  879.         setvertextype(newvertex,
  880.                       trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
  881.         if (b->usesegments) {
  882.           tspivot(triangleloop, checkmark);
  883.           /* If this edge is a segment, transfer the marker to the new node. */
  884.           if (checkmark.ss != m->dummysub) {
  885.             setvertexmark(newvertex, mark(checkmark));
  886.             setvertextype(newvertex, SEGMENTVERTEX);
  887.           }
  888.         }
  889.         if (b->verbose > 1) {
  890.           printf("  Creating (%.12g, %.12g).n", newvertex[0], newvertex[1]);
  891.         }
  892.         /* Record the new node in the (one or two) adjacent elements. */
  893.         triangleloop.tri[m->highorderindex + triangleloop.orient] =
  894.                 (triangle) newvertex;
  895.         if (trisym.tri != m->dummytri) {
  896.           trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
  897.         }
  898.       }
  899.     }
  900.     triangleloop.tri = triangletraverse(m);
  901.   }
  902. }
  903. /********* File I/O routines begin here                              *********/
  904. /**                                                                         **/
  905. /**                                                                         **/
  906. /*****************************************************************************/
  907. /*                                                                           */
  908. /*  readline()   Read a nonempty line from a file.                           */
  909. /*                                                                           */
  910. /*  A line is considered "nonempty" if it contains something that looks like */
  911. /*  a number.  Comments (prefaced by `#') are ignored.                       */
  912. /*                                                                           */
  913. /*****************************************************************************/
  914. #ifndef TRILIBRARY
  915. #ifdef ANSI_DECLARATORS
  916. char *readline(char *string, FILE *infile, char *infilename)
  917. #else /* not ANSI_DECLARATORS */
  918. char *readline(string, infile, infilename)
  919. char *string;
  920. FILE *infile;
  921. char *infilename;
  922. #endif /* not ANSI_DECLARATORS */
  923. {
  924.   char *result;
  925.   /* Search for something that looks like a number. */
  926.   do {
  927.     result = fgets(string, INPUTLINESIZE, infile);
  928.     if (result == (char *) NULL) {
  929.       printf("  Error:  Unexpected end of file in %s.n", infilename);
  930.       triexit(1);
  931.     }
  932.     /* Skip anything that doesn't look like a number, a comment, */
  933.     /*   or the end of a line.                                   */
  934.     while ((*result != '') && (*result != '#')
  935.            && (*result != '.') && (*result != '+') && (*result != '-')
  936.            && ((*result < '0') || (*result > '9'))) {
  937.       result++;
  938.     }
  939.   /* If it's a comment or end of line, read another line and try again. */
  940.   } while ((*result == '#') || (*result == ''));
  941.   return result;
  942. }
  943. #endif /* not TRILIBRARY */
  944. /*****************************************************************************/
  945. /*                                                                           */
  946. /*  findfield()   Find the next field of a string.                           */
  947. /*                                                                           */
  948. /*  Jumps past the current field by searching for whitespace, then jumps     */
  949. /*  past the whitespace to find the next field.                              */
  950. /*                                                                           */
  951. /*****************************************************************************/
  952. #ifndef TRILIBRARY
  953. #ifdef ANSI_DECLARATORS
  954. char *findfield(char *string)
  955. #else /* not ANSI_DECLARATORS */
  956. char *findfield(string)
  957. char *string;
  958. #endif /* not ANSI_DECLARATORS */
  959. {
  960.   char *result;
  961.   result = string;
  962.   /* Skip the current field.  Stop upon reaching whitespace. */
  963.   while ((*result != '') && (*result != '#')
  964.          && (*result != ' ') && (*result != 't')) {
  965.     result++;
  966.   }
  967.   /* Now skip the whitespace and anything else that doesn't look like a */
  968.   /*   number, a comment, or the end of a line.                         */
  969.   while ((*result != '') && (*result != '#')
  970.          && (*result != '.') && (*result != '+') && (*result != '-')
  971.          && ((*result < '0') || (*result > '9'))) {
  972.     result++;
  973.   }
  974.   /* Check for a comment (prefixed with `#'). */
  975.   if (*result == '#') {
  976.     *result = '';
  977.   }
  978.   return result;
  979. }
  980. #endif /* not TRILIBRARY */
  981. /*****************************************************************************/
  982. /*                                                                           */
  983. /*  readnodes()   Read the vertices from a file, which may be a .node or     */
  984. /*                .poly file.                                                */
  985. /*                                                                           */
  986. /*****************************************************************************/
  987. #ifndef TRILIBRARY
  988. #ifdef ANSI_DECLARATORS
  989. void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
  990.                char *polyfilename, FILE **polyfile)
  991. #else /* not ANSI_DECLARATORS */
  992. void readnodes(m, b, nodefilename, polyfilename, polyfile)
  993. struct mesh *m;
  994. struct behavior *b;
  995. char *nodefilename;
  996. char *polyfilename;
  997. FILE **polyfile;
  998. #endif /* not ANSI_DECLARATORS */
  999. {
  1000.   FILE *infile;
  1001.   vertex vertexloop;
  1002.   char inputline[INPUTLINESIZE];
  1003.   char *stringptr;
  1004.   char *infilename;
  1005.   REAL x, y;
  1006.   int firstnode;
  1007.   int nodemarkers;
  1008.   int currentmarker;
  1009.   int i, j;
  1010.   if (b->poly) {
  1011.     /* Read the vertices from a .poly file. */
  1012.     if (!b->quiet) {
  1013.       printf("Opening %s.n", polyfilename);
  1014.     }
  1015.     *polyfile = fopen(polyfilename, "r");
  1016.     if (*polyfile == (FILE *) NULL) {
  1017.       printf("  Error:  Cannot access file %s.n", polyfilename);
  1018.       triexit(1);
  1019.     }
  1020.     /* Read number of vertices, number of dimensions, number of vertex */
  1021.     /*   attributes, and number of boundary markers.                   */
  1022.     stringptr = readline(inputline, *polyfile, polyfilename);
  1023.     m->invertices = (int) strtol(stringptr, &stringptr, 0);
  1024.     stringptr = findfield(stringptr);
  1025.     if (*stringptr == '') {
  1026.       m->mesh_dim = 2;
  1027.     } else {
  1028.       m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
  1029.     }
  1030.     stringptr = findfield(stringptr);
  1031.     if (*stringptr == '') {
  1032.       m->nextras = 0;
  1033.     } else {
  1034.       m->nextras = (int) strtol(stringptr, &stringptr, 0);
  1035.     }
  1036.     stringptr = findfield(stringptr);
  1037.     if (*stringptr == '') {
  1038.       nodemarkers = 0;
  1039.     } else {
  1040.       nodemarkers = (int) strtol(stringptr, &stringptr, 0);
  1041.     }
  1042.     if (m->invertices > 0) {
  1043.       infile = *polyfile;
  1044.       infilename = polyfilename;
  1045.       m->readnodefile = 0;
  1046.     } else {
  1047.       /* If the .poly file claims there are zero vertices, that means that */
  1048.       /*   the vertices should be read from a separate .node file.         */
  1049.       m->readnodefile = 1;
  1050.       infilename = nodefilename;
  1051.     }
  1052.   } else {
  1053.     m->readnodefile = 1;
  1054.     infilename = nodefilename;
  1055.     *polyfile = (FILE *) NULL;
  1056.   }
  1057.   if (m->readnodefile) {
  1058.     /* Read the vertices from a .node file. */
  1059.     if (!b->quiet) {
  1060.       printf("Opening %s.n", nodefilename);
  1061.     }
  1062.     infile = fopen(nodefilename, "r");
  1063.     if (infile == (FILE *) NULL) {
  1064.       printf("  Error:  Cannot access file %s.n", nodefilename);
  1065.       triexit(1);
  1066.     }
  1067.     /* Read number of vertices, number of dimensions, number of vertex */
  1068.     /*   attributes, and number of boundary markers.                   */
  1069.     stringptr = readline(inputline, infile, nodefilename);
  1070.     m->invertices = (int) strtol(stringptr, &stringptr, 0);
  1071.     stringptr = findfield(stringptr);
  1072.     if (*stringptr == '') {
  1073.       m->mesh_dim = 2;
  1074.     } else {
  1075.       m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
  1076.     }
  1077.     stringptr = findfield(stringptr);
  1078.     if (*stringptr == '') {
  1079.       m->nextras = 0;
  1080.     } else {
  1081.       m->nextras = (int) strtol(stringptr, &stringptr, 0);
  1082.     }
  1083.     stringptr = findfield(stringptr);
  1084.     if (*stringptr == '') {
  1085.       nodemarkers = 0;
  1086.     } else {
  1087.       nodemarkers = (int) strtol(stringptr, &stringptr, 0);
  1088.     }
  1089.   }
  1090.   if (m->invertices < 3) {
  1091.     printf("Error:  Input must have at least three input vertices.n");
  1092.     triexit(1);
  1093.   }
  1094.   if (m->mesh_dim != 2) {
  1095.     printf("Error:  Triangle only works with two-dimensional meshes.n");
  1096.     triexit(1);
  1097.   }
  1098.   if (m->nextras == 0) {
  1099.     b->weighted = 0;
  1100.   }
  1101.   initializevertexpool(m, b);
  1102.   /* Read the vertices. */
  1103.   for (i = 0; i < m->invertices; i++) {
  1104.     vertexloop = (vertex) poolalloc(&m->vertices);
  1105.     stringptr = readline(inputline, infile, infilename);
  1106.     if (i == 0) {
  1107.       firstnode = (int) strtol(stringptr, &stringptr, 0);
  1108.       if ((firstnode == 0) || (firstnode == 1)) {
  1109.         b->firstnumber = firstnode;
  1110.       }
  1111.     }
  1112.     stringptr = findfield(stringptr);
  1113.     if (*stringptr == '') {
  1114.       printf("Error:  Vertex %d has no x coordinate.n", b->firstnumber + i);
  1115.       triexit(1);
  1116.     }
  1117.     x = (REAL) strtod(stringptr, &stringptr);
  1118.     stringptr = findfield(stringptr);
  1119.     if (*stringptr == '') {
  1120.       printf("Error:  Vertex %d has no y coordinate.n", b->firstnumber + i);
  1121.       triexit(1);
  1122.     }
  1123.     y = (REAL) strtod(stringptr, &stringptr);
  1124.     vertexloop[0] = x;
  1125.     vertexloop[1] = y;
  1126.     /* Read the vertex attributes. */
  1127.     for (j = 2; j < 2 + m->nextras; j++) {
  1128.       stringptr = findfield(stringptr);
  1129.       if (*stringptr == '') {
  1130.         vertexloop[j] = 0.0;
  1131.       } else {
  1132.         vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
  1133.       }
  1134.     }
  1135.     if (nodemarkers) {
  1136.       /* Read a vertex marker. */
  1137.       stringptr = findfield(stringptr);
  1138.       if (*stringptr == '') {
  1139.         setvertexmark(vertexloop, 0);
  1140.       } else {
  1141.         currentmarker = (int) strtol(stringptr, &stringptr, 0);
  1142.         setvertexmark(vertexloop, currentmarker);
  1143.       }
  1144.     } else {
  1145.       /* If no markers are specified in the file, they default to zero. */
  1146.       setvertexmark(vertexloop, 0);
  1147.     }
  1148.     setvertextype(vertexloop, INPUTVERTEX);
  1149.     /* Determine the smallest and largest x and y coordinates. */
  1150.     if (i == 0) {
  1151.       m->xmin = m->xmax = x;
  1152.       m->ymin = m->ymax = y;
  1153.     } else {
  1154.       m->xmin = (x < m->xmin) ? x : m->xmin;
  1155.       m->xmax = (x > m->xmax) ? x : m->xmax;
  1156.       m->ymin = (y < m->ymin) ? y : m->ymin;
  1157.       m->ymax = (y > m->ymax) ? y : m->ymax;
  1158.     }
  1159.   }
  1160.   if (m->readnodefile) {
  1161.     fclose(infile);
  1162.   }
  1163.   /* Nonexistent x value used as a flag to mark circle events in sweepline */
  1164.   /*   Delaunay algorithm.                                                 */
  1165.   m->xminextreme = 10 * m->xmin - 9 * m->xmax;
  1166. }
  1167. #endif /* not TRILIBRARY */
  1168. /*****************************************************************************/
  1169. /*                                                                           */
  1170. /*  transfernodes()   Read the vertices from memory.                         */
  1171. /*                                                                           */
  1172. /*****************************************************************************/
  1173. #ifdef TRILIBRARY
  1174. #ifdef ANSI_DECLARATORS
  1175. void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
  1176.                    REAL *pointattriblist, int *pointmarkerlist,
  1177.                    int numberofpoints, int numberofpointattribs)
  1178. #else /* not ANSI_DECLARATORS */
  1179. void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
  1180.                    numberofpoints, numberofpointattribs)
  1181. struct mesh *m;
  1182. struct behavior *b;
  1183. REAL *pointlist;
  1184. REAL *pointattriblist;
  1185. int *pointmarkerlist;
  1186. int numberofpoints;
  1187. int numberofpointattribs;
  1188. #endif /* not ANSI_DECLARATORS */
  1189. {
  1190.   vertex vertexloop;
  1191.   REAL x, y;
  1192.   int i, j;
  1193.   int coordindex;
  1194.   int attribindex;
  1195.   m->invertices = numberofpoints;
  1196.   m->mesh_dim = 2;
  1197.   m->nextras = numberofpointattribs;
  1198.   m->readnodefile = 0;
  1199.   if (m->invertices < 3) {
  1200.     printf("Error:  Input must have at least three input vertices.n");
  1201.     triexit(1);
  1202.   }
  1203.   if (m->nextras == 0) {
  1204.     b->weighted = 0;
  1205.   }
  1206.   initializevertexpool(m, b);
  1207.   /* Read the vertices. */
  1208.   coordindex = 0;
  1209.   attribindex = 0;
  1210.   for (i = 0; i < m->invertices; i++) {
  1211.     vertexloop = (vertex) poolalloc(&m->vertices);
  1212.     /* Read the vertex coordinates. */
  1213.     x = vertexloop[0] = pointlist[coordindex++];
  1214.     y = vertexloop[1] = pointlist[coordindex++];
  1215.     /* Read the vertex attributes. */
  1216.     for (j = 0; j < numberofpointattribs; j++) {
  1217.       vertexloop[2 + j] = pointattriblist[attribindex++];
  1218.     }
  1219.     if (pointmarkerlist != (int *) NULL) {
  1220.       /* Read a vertex marker. */
  1221.       setvertexmark(vertexloop, pointmarkerlist[i]);
  1222.     } else {
  1223.       /* If no markers are specified, they default to zero. */
  1224.       setvertexmark(vertexloop, 0);
  1225.     }
  1226.     setvertextype(vertexloop, INPUTVERTEX);
  1227.     /* Determine the smallest and largest x and y coordinates. */
  1228.     if (i == 0) {
  1229.       m->xmin = m->xmax = x;
  1230.       m->ymin = m->ymax = y;
  1231.     } else {
  1232.       m->xmin = (x < m->xmin) ? x : m->xmin;
  1233.       m->xmax = (x > m->xmax) ? x : m->xmax;
  1234.       m->ymin = (y < m->ymin) ? y : m->ymin;
  1235.       m->ymax = (y > m->ymax) ? y : m->ymax;
  1236.     }
  1237.   }
  1238.   /* Nonexistent x value used as a flag to mark circle events in sweepline */
  1239.   /*   Delaunay algorithm.                                                 */
  1240.   m->xminextreme = 10 * m->xmin - 9 * m->xmax;
  1241. }
  1242. #endif /* TRILIBRARY */
  1243. /*****************************************************************************/
  1244. /*                                                                           */
  1245. /*  readholes()   Read the holes, and possibly regional attributes and area  */
  1246. /*                constraints, from a .poly file.                            */
  1247. /*                                                                           */
  1248. /*****************************************************************************/
  1249. #ifndef TRILIBRARY
  1250. #ifdef ANSI_DECLARATORS
  1251. void readholes(struct mesh *m, struct behavior *b,
  1252.                FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
  1253.                REAL **rlist, int *regions)
  1254. #else /* not ANSI_DECLARATORS */
  1255. void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
  1256. struct mesh *m;
  1257. struct behavior *b;
  1258. FILE *polyfile;
  1259. char *polyfilename;
  1260. REAL **hlist;
  1261. int *holes;
  1262. REAL **rlist;
  1263. int *regions;
  1264. #endif /* not ANSI_DECLARATORS */
  1265. {
  1266.   REAL *holelist;
  1267.   REAL *regionlist;
  1268.   char inputline[INPUTLINESIZE];
  1269.   char *stringptr;
  1270.   int index;
  1271.   int i;
  1272.   /* Read the holes. */
  1273.   stringptr = readline(inputline, polyfile, polyfilename);
  1274.   *holes = (int) strtol(stringptr, &stringptr, 0);
  1275.   if (*holes > 0) {
  1276.     holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
  1277.     *hlist = holelist;
  1278.     for (i = 0; i < 2 * *holes; i += 2) {
  1279.       stringptr = readline(inputline, polyfile, polyfilename);
  1280.       stringptr = findfield(stringptr);
  1281.       if (*stringptr == '') {
  1282.         printf("Error:  Hole %d has no x coordinate.n",
  1283.                b->firstnumber + (i >> 1));
  1284.         triexit(1);
  1285.       } else {
  1286.         holelist[i] = (REAL) strtod(stringptr, &stringptr);
  1287.       }
  1288.       stringptr = findfield(stringptr);
  1289.       if (*stringptr == '') {
  1290.         printf("Error:  Hole %d has no y coordinate.n",
  1291.                b->firstnumber + (i >> 1));
  1292.         triexit(1);
  1293.       } else {
  1294.         holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
  1295.       }
  1296.     }
  1297.   } else {
  1298.     *hlist = (REAL *) NULL;
  1299.   }
  1300. #ifndef CDT_ONLY
  1301.   if ((b->regionattrib || b->vararea) && !b->refine) {
  1302.     /* Read the area constraints. */
  1303.     stringptr = readline(inputline, polyfile, polyfilename);
  1304.     *regions = (int) strtol(stringptr, &stringptr, 0);
  1305.     if (*regions > 0) {
  1306.       regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
  1307.       *rlist = regionlist;
  1308.       index = 0;
  1309.       for (i = 0; i < *regions; i++) {
  1310.         stringptr = readline(inputline, polyfile, polyfilename);
  1311.         stringptr = findfield(stringptr);
  1312.         if (*stringptr == '') {
  1313.           printf("Error:  Region %d has no x coordinate.n",
  1314.                  b->firstnumber + i);
  1315.           triexit(1);
  1316.         } else {
  1317.           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
  1318.         }
  1319.         stringptr = findfield(stringptr);
  1320.         if (*stringptr == '') {
  1321.           printf("Error:  Region %d has no y coordinate.n",
  1322.                  b->firstnumber + i);
  1323.           triexit(1);
  1324.         } else {
  1325.           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
  1326.         }
  1327.         stringptr = findfield(stringptr);
  1328.         if (*stringptr == '') {
  1329.           printf(
  1330.             "Error:  Region %d has no region attribute or area constraint.n",
  1331.                  b->firstnumber + i);
  1332.           triexit(1);
  1333.         } else {
  1334.           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
  1335.         }
  1336.         stringptr = findfield(stringptr);
  1337.         if (*stringptr == '') {
  1338.           regionlist[index] = regionlist[index - 1];
  1339.         } else {
  1340.           regionlist[index] = (REAL) strtod(stringptr, &stringptr);
  1341.         }
  1342.         index++;
  1343.       }
  1344.     }
  1345.   } else {
  1346.     /* Set `*regions' to zero to avoid an accidental free() later. */
  1347.     *regions = 0;
  1348.     *rlist = (REAL *) NULL;
  1349.   }
  1350. #endif /* not CDT_ONLY */
  1351.   fclose(polyfile);
  1352. }
  1353. #endif /* not TRILIBRARY */
  1354. /*****************************************************************************/
  1355. /*                                                                           */
  1356. /*  finishfile()   Write the command line to the output file so the user     */
  1357. /*                 can remember how the file was generated.  Close the file. */
  1358. /*                                                                           */
  1359. /*****************************************************************************/
  1360. #ifndef TRILIBRARY
  1361. #ifdef ANSI_DECLARATORS
  1362. void finishfile(FILE *outfile, int argc, char **argv)
  1363. #else /* not ANSI_DECLARATORS */
  1364. void finishfile(outfile, argc, argv)
  1365. FILE *outfile;
  1366. int argc;
  1367. char **argv;
  1368. #endif /* not ANSI_DECLARATORS */
  1369. {
  1370.   int i;
  1371.   fprintf(outfile, "# Generated by");
  1372.   for (i = 0; i < argc; i++) {
  1373.     fprintf(outfile, " ");
  1374.     fputs(argv[i], outfile);
  1375.   }
  1376.   fprintf(outfile, "n");
  1377.   fclose(outfile);
  1378. }
  1379. #endif /* not TRILIBRARY */
  1380. /*****************************************************************************/
  1381. /*                                                                           */
  1382. /*  writenodes()   Number the vertices and write them to a .node file.       */
  1383. /*                                                                           */
  1384. /*  To save memory, the vertex numbers are written over the boundary markers */
  1385. /*  after the vertices are written to a file.                                */
  1386. /*                                                                           */
  1387. /*****************************************************************************/
  1388. #ifdef TRILIBRARY
  1389. #ifdef ANSI_DECLARATORS
  1390. void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
  1391.                 REAL **pointattriblist, int **pointmarkerlist)
  1392. #else /* not ANSI_DECLARATORS */
  1393. void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
  1394. struct mesh *m;
  1395. struct behavior *b;
  1396. REAL **pointlist;
  1397. REAL **pointattriblist;
  1398. int **pointmarkerlist;
  1399. #endif /* not ANSI_DECLARATORS */
  1400. #else /* not TRILIBRARY */
  1401. #ifdef ANSI_DECLARATORS
  1402. void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
  1403.                 int argc, char **argv)
  1404. #else /* not ANSI_DECLARATORS */
  1405. void writenodes(m, b, nodefilename, argc, argv)
  1406. struct mesh *m;
  1407. struct behavior *b;
  1408. char *nodefilename;
  1409. int argc;
  1410. char **argv;
  1411. #endif /* not ANSI_DECLARATORS */
  1412. #endif /* not TRILIBRARY */
  1413. {
  1414. #ifdef TRILIBRARY
  1415.   REAL *plist;
  1416.   REAL *palist;
  1417.   int *pmlist;
  1418.   int coordindex;
  1419.   int attribindex;
  1420. #else /* not TRILIBRARY */
  1421.   FILE *outfile;
  1422. #endif /* not TRILIBRARY */
  1423.   vertex vertexloop;
  1424.   long outvertices;
  1425.   int vertexnumber;
  1426.   int i;
  1427.   if (b->jettison) {
  1428.     outvertices = m->vertices.items - m->undeads;
  1429.   } else {
  1430.     outvertices = m->vertices.items;
  1431.   }
  1432. #ifdef TRILIBRARY
  1433.   if (!b->quiet) {
  1434.     printf("Writing vertices.n");
  1435.   }
  1436.   /* Allocate memory for output vertices if necessary. */
  1437.   if (*pointlist == (REAL *) NULL) {
  1438.     *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
  1439.   }
  1440.   /* Allocate memory for output vertex attributes if necessary. */
  1441.   if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
  1442.     *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
  1443.                                                  sizeof(REAL)));
  1444.   }
  1445.   /* Allocate memory for output vertex markers if necessary. */
  1446.   if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
  1447.     *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
  1448.   }
  1449.   plist = *pointlist;
  1450.   palist = *pointattriblist;
  1451.   pmlist = *pointmarkerlist;
  1452.   coordindex = 0;
  1453.   attribindex = 0;
  1454. #else /* not TRILIBRARY */
  1455.   if (!b->quiet) {
  1456.     printf("Writing %s.n", nodefilename);
  1457.   }
  1458.   outfile = fopen(nodefilename, "w");
  1459.   if (outfile == (FILE *) NULL) {
  1460.     printf("  Error:  Cannot create file %s.n", nodefilename);
  1461.     triexit(1);
  1462.   }
  1463.   /* Number of vertices, number of dimensions, number of vertex attributes, */
  1464.   /*   and number of boundary markers (zero or one).                        */
  1465.   fprintf(outfile, "%ld  %d  %d  %dn", outvertices, m->mesh_dim,
  1466.           m->nextras, 1 - b->nobound);
  1467. #endif /* not TRILIBRARY */
  1468.   traversalinit(&m->vertices);
  1469.   vertexnumber = b->firstnumber;
  1470.   vertexloop = vertextraverse(m);
  1471.   while (vertexloop != (vertex) NULL) {
  1472.     if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
  1473. #ifdef TRILIBRARY
  1474.       /* X and y coordinates. */
  1475.       plist[coordindex++] = vertexloop[0];
  1476.       plist[coordindex++] = vertexloop[1];
  1477.       /* Vertex attributes. */
  1478.       for (i = 0; i < m->nextras; i++) {
  1479.         palist[attribindex++] = vertexloop[2 + i];
  1480.       }
  1481.       if (!b->nobound) {
  1482.         /* Copy the boundary marker. */
  1483.         pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
  1484.       }
  1485. #else /* not TRILIBRARY */
  1486.       /* Vertex number, x and y coordinates. */
  1487.       fprintf(outfile, "%4d    %.17g  %.17g", vertexnumber, vertexloop[0],
  1488.               vertexloop[1]);
  1489.       for (i = 0; i < m->nextras; i++) {
  1490.         /* Write an attribute. */
  1491.         fprintf(outfile, "  %.17g", vertexloop[i + 2]);
  1492.       }
  1493.       if (b->nobound) {
  1494.         fprintf(outfile, "n");
  1495.       } else {
  1496.         /* Write the boundary marker. */
  1497.         fprintf(outfile, "    %dn", vertexmark(vertexloop));
  1498.       }
  1499. #endif /* not TRILIBRARY */
  1500.       setvertexmark(vertexloop, vertexnumber);
  1501.       vertexnumber++;
  1502.     }
  1503.     vertexloop = vertextraverse(m);
  1504.   }
  1505. #ifndef TRILIBRARY
  1506.   finishfile(outfile, argc, argv);
  1507. #endif /* not TRILIBRARY */
  1508. }
  1509. /*****************************************************************************/
  1510. /*                                                                           */
  1511. /*  numbernodes()   Number the vertices.                                     */
  1512. /*                                                                           */
  1513. /*  Each vertex is assigned a marker equal to its number.                    */
  1514. /*                                                                           */
  1515. /*  Used when writenodes() is not called because no .node file is written.   */
  1516. /*                                                                           */
  1517. /*****************************************************************************/
  1518. #ifdef ANSI_DECLARATORS
  1519. void numbernodes(struct mesh *m, struct behavior *b)
  1520. #else /* not ANSI_DECLARATORS */
  1521. void numbernodes(m, b)
  1522. struct mesh *m;
  1523. struct behavior *b;
  1524. #endif /* not ANSI_DECLARATORS */
  1525. {
  1526.   vertex vertexloop;
  1527.   int vertexnumber;
  1528.   traversalinit(&m->vertices);
  1529.   vertexnumber = b->firstnumber;
  1530.   vertexloop = vertextraverse(m);
  1531.   while (vertexloop != (vertex) NULL) {
  1532.     setvertexmark(vertexloop, vertexnumber);
  1533.     if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
  1534.       vertexnumber++;
  1535.     }
  1536.     vertexloop = vertextraverse(m);
  1537.   }
  1538. }
  1539. /*****************************************************************************/
  1540. /*                                                                           */
  1541. /*  writeelements()   Write the triangles to an .ele file.                   */
  1542. /*                                                                           */
  1543. /*****************************************************************************/
  1544. #ifdef TRILIBRARY
  1545. #ifdef ANSI_DECLARATORS
  1546. void writeelements(struct mesh *m, struct behavior *b,
  1547.                    int **trianglelist, REAL **triangleattriblist)
  1548. #else /* not ANSI_DECLARATORS */
  1549. void writeelements(m, b, trianglelist, triangleattriblist)
  1550. struct mesh *m;
  1551. struct behavior *b;
  1552. int **trianglelist;
  1553. REAL **triangleattriblist;
  1554. #endif /* not ANSI_DECLARATORS */
  1555. #else /* not TRILIBRARY */
  1556. #ifdef ANSI_DECLARATORS
  1557. void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
  1558.                    int argc, char **argv)
  1559. #else /* not ANSI_DECLARATORS */
  1560. void writeelements(m, b, elefilename, argc, argv)
  1561. struct mesh *m;
  1562. struct behavior *b;
  1563. char *elefilename;
  1564. int argc;
  1565. char **argv;
  1566. #endif /* not ANSI_DECLARATORS */
  1567. #endif /* not TRILIBRARY */
  1568. {
  1569. #ifdef TRILIBRARY
  1570.   int *tlist;
  1571.   REAL *talist;
  1572.   int vertexindex;
  1573.   int attribindex;
  1574. #else /* not TRILIBRARY */
  1575.   FILE *outfile;
  1576. #endif /* not TRILIBRARY */
  1577.   struct otri triangleloop;
  1578.   vertex p1, p2, p3;
  1579.   vertex mid1, mid2, mid3;
  1580.   long elementnumber;
  1581.   int i;
  1582. #ifdef TRILIBRARY
  1583.   if (!b->quiet) {
  1584.     printf("Writing triangles.n");
  1585.   }
  1586.   /* Allocate memory for output triangles if necessary. */
  1587.   if (*trianglelist == (int *) NULL) {
  1588.     *trianglelist = (int *) trimalloc((int) (m->triangles.items *
  1589.                                              ((b->order + 1) * (b->order + 2) /
  1590.                                               2) * sizeof(int)));
  1591.   }
  1592.   /* Allocate memory for output triangle attributes if necessary. */
  1593.   if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
  1594.     *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
  1595.                                                     m->eextras *
  1596.                                                     sizeof(REAL)));
  1597.   }
  1598.   tlist = *trianglelist;
  1599.   talist = *triangleattriblist;
  1600.   vertexindex = 0;
  1601.   attribindex = 0;
  1602. #else /* not TRILIBRARY */
  1603.   if (!b->quiet) {
  1604.     printf("Writing %s.n", elefilename);
  1605.   }
  1606.   outfile = fopen(elefilename, "w");
  1607.   if (outfile == (FILE *) NULL) {
  1608.     printf("  Error:  Cannot create file %s.n", elefilename);
  1609.     triexit(1);
  1610.   }
  1611.   /* Number of triangles, vertices per triangle, attributes per triangle. */
  1612.   fprintf(outfile, "%ld  %d  %dn", m->triangles.items,
  1613.           (b->order + 1) * (b->order + 2) / 2, m->eextras);
  1614. #endif /* not TRILIBRARY */
  1615.   traversalinit(&m->triangles);
  1616.   triangleloop.tri = triangletraverse(m);
  1617.   triangleloop.orient = 0;
  1618.   elementnumber = b->firstnumber;
  1619.   while (triangleloop.tri != (triangle *) NULL) {
  1620.     org(triangleloop, p1);
  1621.     dest(triangleloop, p2);
  1622.     apex(triangleloop, p3);
  1623.     if (b->order == 1) {
  1624. #ifdef TRILIBRARY
  1625.       tlist[vertexindex++] = vertexmark(p1);
  1626.       tlist[vertexindex++] = vertexmark(p2);
  1627.       tlist[vertexindex++] = vertexmark(p3);
  1628. #else /* not TRILIBRARY */
  1629.       /* Triangle number, indices for three vertices. */
  1630.       fprintf(outfile, "%4ld    %4d  %4d  %4d", elementnumber,
  1631.               vertexmark(p1), vertexmark(p2), vertexmark(p3));
  1632. #endif /* not TRILIBRARY */
  1633.     } else {
  1634.       mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
  1635.       mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
  1636.       mid3 = (vertex) triangleloop.tri[m->highorderindex];
  1637. #ifdef TRILIBRARY
  1638.       tlist[vertexindex++] = vertexmark(p1);
  1639.       tlist[vertexindex++] = vertexmark(p2);
  1640.       tlist[vertexindex++] = vertexmark(p3);
  1641.       tlist[vertexindex++] = vertexmark(mid1);
  1642.       tlist[vertexindex++] = vertexmark(mid2);
  1643.       tlist[vertexindex++] = vertexmark(mid3);
  1644. #else /* not TRILIBRARY */
  1645.       /* Triangle number, indices for six vertices. */
  1646.       fprintf(outfile, "%4ld    %4d  %4d  %4d  %4d  %4d  %4d", elementnumber,
  1647.               vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
  1648.               vertexmark(mid2), vertexmark(mid3));
  1649. #endif /* not TRILIBRARY */
  1650.     }
  1651. #ifdef TRILIBRARY
  1652.     for (i = 0; i < m->eextras; i++) {
  1653.       talist[attribindex++] = elemattribute(triangleloop, i);
  1654.     }
  1655. #else /* not TRILIBRARY */
  1656.     for (i = 0; i < m->eextras; i++) {
  1657.       fprintf(outfile, "  %.17g", elemattribute(triangleloop, i));
  1658.     }
  1659.     fprintf(outfile, "n");
  1660. #endif /* not TRILIBRARY */
  1661.     triangleloop.tri = triangletraverse(m);
  1662.     elementnumber++;
  1663.   }
  1664. #ifndef TRILIBRARY
  1665.   finishfile(outfile, argc, argv);
  1666. #endif /* not TRILIBRARY */
  1667. }
  1668. /*****************************************************************************/
  1669. /*                                                                           */
  1670. /*  writepoly()   Write the segments and holes to a .poly file.              */
  1671. /*                                                                           */
  1672. /*****************************************************************************/
  1673. #ifdef TRILIBRARY
  1674. #ifdef ANSI_DECLARATORS
  1675. void writepoly(struct mesh *m, struct behavior *b,
  1676.                int **segmentlist, int **segmentmarkerlist)
  1677. #else /* not ANSI_DECLARATORS */
  1678. void writepoly(m, b, segmentlist, segmentmarkerlist)
  1679. struct mesh *m;
  1680. struct behavior *b;
  1681. int **segmentlist;
  1682. int **segmentmarkerlist;
  1683. #endif /* not ANSI_DECLARATORS */
  1684. #else /* not TRILIBRARY */
  1685. #ifdef ANSI_DECLARATORS
  1686. void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
  1687.                REAL *holelist, int holes, REAL *regionlist, int regions,
  1688.                int argc, char **argv)
  1689. #else /* not ANSI_DECLARATORS */
  1690. void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
  1691.                argc, argv)
  1692. struct mesh *m;
  1693. struct behavior *b;
  1694. char *polyfilename;
  1695. REAL *holelist;
  1696. int holes;
  1697. REAL *regionlist;
  1698. int regions;
  1699. int argc;
  1700. char **argv;
  1701. #endif /* not ANSI_DECLARATORS */
  1702. #endif /* not TRILIBRARY */
  1703. {
  1704. #ifdef TRILIBRARY
  1705.   int *slist;
  1706.   int *smlist;
  1707.   int index;
  1708. #else /* not TRILIBRARY */
  1709.   FILE *outfile;
  1710.   long holenumber, regionnumber;
  1711. #endif /* not TRILIBRARY */
  1712.   struct osub subsegloop;
  1713.   vertex endpoint1, endpoint2;
  1714.   long subsegnumber;
  1715. #ifdef TRILIBRARY
  1716.   if (!b->quiet) {
  1717.     printf("Writing segments.n");
  1718.   }
  1719.   /* Allocate memory for output segments if necessary. */
  1720.   if (*segmentlist == (int *) NULL) {
  1721.     *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
  1722.                                             sizeof(int)));
  1723.   }
  1724.   /* Allocate memory for output segment markers if necessary. */
  1725.   if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
  1726.     *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
  1727.                                                   sizeof(int)));
  1728.   }
  1729.   slist = *segmentlist;
  1730.   smlist = *segmentmarkerlist;
  1731.   index = 0;
  1732. #else /* not TRILIBRARY */
  1733.   if (!b->quiet) {
  1734.     printf("Writing %s.n", polyfilename);
  1735.   }
  1736.   outfile = fopen(polyfilename, "w");
  1737.   if (outfile == (FILE *) NULL) {
  1738.     printf("  Error:  Cannot create file %s.n", polyfilename);
  1739.     triexit(1);
  1740.   }
  1741.   /* The zero indicates that the vertices are in a separate .node file. */
  1742.   /*   Followed by number of dimensions, number of vertex attributes,   */
  1743.   /*   and number of boundary markers (zero or one).                    */
  1744.   fprintf(outfile, "%d  %d  %d  %dn", 0, m->mesh_dim, m->nextras,
  1745.           1 - b->nobound);
  1746.   /* Number of segments, number of boundary markers (zero or one). */
  1747.   fprintf(outfile, "%ld  %dn", m->subsegs.items, 1 - b->nobound);
  1748. #endif /* not TRILIBRARY */
  1749.   traversalinit(&m->subsegs);
  1750.   subsegloop.ss = subsegtraverse(m);
  1751.   subsegloop.ssorient = 0;
  1752.   subsegnumber = b->firstnumber;
  1753.   while (subsegloop.ss != (subseg *) NULL) {
  1754.     sorg(subsegloop, endpoint1);
  1755.     sdest(subsegloop, endpoint2);
  1756. #ifdef TRILIBRARY
  1757.     /* Copy indices of the segment's two endpoints. */
  1758.     slist[index++] = vertexmark(endpoint1);
  1759.     slist[index++] = vertexmark(endpoint2);
  1760.     if (!b->nobound) {
  1761.       /* Copy the boundary marker. */
  1762.       smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
  1763.     }
  1764. #else /* not TRILIBRARY */
  1765.     /* Segment number, indices of its two endpoints, and possibly a marker. */
  1766.     if (b->nobound) {
  1767.       fprintf(outfile, "%4ld    %4d  %4dn", subsegnumber,
  1768.               vertexmark(endpoint1), vertexmark(endpoint2));
  1769.     } else {
  1770.       fprintf(outfile, "%4ld    %4d  %4d    %4dn", subsegnumber,
  1771.               vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
  1772.     }
  1773. #endif /* not TRILIBRARY */
  1774.     subsegloop.ss = subsegtraverse(m);
  1775.     subsegnumber++;
  1776.   }
  1777. #ifndef TRILIBRARY
  1778. #ifndef CDT_ONLY
  1779.   fprintf(outfile, "%dn", holes);
  1780.   if (holes > 0) {
  1781.     for (holenumber = 0; holenumber < holes; holenumber++) {
  1782.       /* Hole number, x and y coordinates. */
  1783.       fprintf(outfile, "%4ld   %.17g  %.17gn", b->firstnumber + holenumber,
  1784.               holelist[2 * holenumber], holelist[2 * holenumber + 1]);
  1785.     }
  1786.   }
  1787.   if (regions > 0) {
  1788.     fprintf(outfile, "%dn", regions);
  1789.     for (regionnumber = 0; regionnumber < regions; regionnumber++) {
  1790.       /* Region number, x and y coordinates, attribute, maximum area. */
  1791.       fprintf(outfile, "%4ld   %.17g  %.17g  %.17g  %.17gn",
  1792.               b->firstnumber + regionnumber,
  1793.               regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
  1794.               regionlist[4 * regionnumber + 2],
  1795.               regionlist[4 * regionnumber + 3]);
  1796.     }
  1797.   }
  1798. #endif /* not CDT_ONLY */
  1799.   finishfile(outfile, argc, argv);
  1800. #endif /* not TRILIBRARY */
  1801. }
  1802. /*****************************************************************************/
  1803. /*                                                                           */
  1804. /*  writeedges()   Write the edges to an .edge file.                         */
  1805. /*                                                                           */
  1806. /*****************************************************************************/
  1807. #ifdef TRILIBRARY
  1808. #ifdef ANSI_DECLARATORS
  1809. void writeedges(struct mesh *m, struct behavior *b,
  1810.                 int **edgelist, int **edgemarkerlist)
  1811. #else /* not ANSI_DECLARATORS */
  1812. void writeedges(m, b, edgelist, edgemarkerlist)
  1813. struct mesh *m;
  1814. struct behavior *b;
  1815. int **edgelist;
  1816. int **edgemarkerlist;
  1817. #endif /* not ANSI_DECLARATORS */
  1818. #else /* not TRILIBRARY */
  1819. #ifdef ANSI_DECLARATORS
  1820. void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
  1821.                 int argc, char **argv)
  1822. #else /* not ANSI_DECLARATORS */
  1823. void writeedges(m, b, edgefilename, argc, argv)
  1824. struct mesh *m;
  1825. struct behavior *b;
  1826. char *edgefilename;
  1827. int argc;
  1828. char **argv;
  1829. #endif /* not ANSI_DECLARATORS */
  1830. #endif /* not TRILIBRARY */
  1831. {
  1832. #ifdef TRILIBRARY
  1833.   int *elist;
  1834.   int *emlist;
  1835.   int index;
  1836. #else /* not TRILIBRARY */
  1837.   FILE *outfile;
  1838. #endif /* not TRILIBRARY */
  1839.   struct otri triangleloop, trisym;
  1840.   struct osub checkmark;
  1841.   vertex p1, p2;
  1842.   long edgenumber;
  1843.   triangle ptr;                         /* Temporary variable used by sym(). */
  1844.   subseg sptr;                      /* Temporary variable used by tspivot(). */
  1845. #ifdef TRILIBRARY
  1846.   if (!b->quiet) {
  1847.     printf("Writing edges.n");
  1848.   }
  1849.   /* Allocate memory for edges if necessary. */
  1850.   if (*edgelist == (int *) NULL) {
  1851.     *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
  1852.   }
  1853.   /* Allocate memory for edge markers if necessary. */
  1854.   if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
  1855.     *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
  1856.   }
  1857.   elist = *edgelist;
  1858.   emlist = *edgemarkerlist;
  1859.   index = 0;
  1860. #else /* not TRILIBRARY */
  1861.   if (!b->quiet) {
  1862.     printf("Writing %s.n", edgefilename);
  1863.   }
  1864.   outfile = fopen(edgefilename, "w");
  1865.   if (outfile == (FILE *) NULL) {
  1866.     printf("  Error:  Cannot create file %s.n", edgefilename);
  1867.     triexit(1);
  1868.   }
  1869.   /* Number of edges, number of boundary markers (zero or one). */
  1870.   fprintf(outfile, "%ld  %dn", m->edges, 1 - b->nobound);
  1871. #endif /* not TRILIBRARY */
  1872.   traversalinit(&m->triangles);
  1873.   triangleloop.tri = triangletraverse(m);
  1874.   edgenumber = b->firstnumber;
  1875.   /* To loop over the set of edges, loop over all triangles, and look at   */
  1876.   /*   the three edges of each triangle.  If there isn't another triangle  */
  1877.   /*   adjacent to the edge, operate on the edge.  If there is another     */
  1878.   /*   adjacent triangle, operate on the edge only if the current triangle */
  1879.   /*   has a smaller pointer than its neighbor.  This way, each edge is    */
  1880.   /*   considered only once.                                               */
  1881.   while (triangleloop.tri != (triangle *) NULL) {
  1882.     for (triangleloop.orient = 0; triangleloop.orient < 3;
  1883.          triangleloop.orient++) {
  1884.       sym(triangleloop, trisym);
  1885.       if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
  1886.         org(triangleloop, p1);
  1887.         dest(triangleloop, p2);
  1888. #ifdef TRILIBRARY
  1889.         elist[index++] = vertexmark(p1);
  1890.         elist[index++] = vertexmark(p2);
  1891. #endif /* TRILIBRARY */
  1892.         if (b->nobound) {
  1893. #ifndef TRILIBRARY
  1894.           /* Edge number, indices of two endpoints. */
  1895.           fprintf(outfile, "%4ld   %d  %dn", edgenumber,
  1896.                   vertexmark(p1), vertexmark(p2));
  1897. #endif /* not TRILIBRARY */
  1898.         } else {
  1899.           /* Edge number, indices of two endpoints, and a boundary marker. */
  1900.           /*   If there's no subsegment, the boundary marker is zero.      */
  1901.           if (b->usesegments) {
  1902.             tspivot(triangleloop, checkmark);
  1903.             if (checkmark.ss == m->dummysub) {
  1904. #ifdef TRILIBRARY
  1905.               emlist[edgenumber - b->firstnumber] = 0;
  1906. #else /* not TRILIBRARY */
  1907.               fprintf(outfile, "%4ld   %d  %d  %dn", edgenumber,
  1908.                       vertexmark(p1), vertexmark(p2), 0);
  1909. #endif /* not TRILIBRARY */
  1910.             } else {
  1911. #ifdef TRILIBRARY
  1912.               emlist[edgenumber - b->firstnumber] = mark(checkmark);
  1913. #else /* not TRILIBRARY */
  1914.               fprintf(outfile, "%4ld   %d  %d  %dn", edgenumber,
  1915.                       vertexmark(p1), vertexmark(p2), mark(checkmark));
  1916. #endif /* not TRILIBRARY */
  1917.             }
  1918.           } else {
  1919. #ifdef TRILIBRARY
  1920.             emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
  1921. #else /* not TRILIBRARY */
  1922.             fprintf(outfile, "%4ld   %d  %d  %dn", edgenumber,
  1923.                     vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
  1924. #endif /* not TRILIBRARY */
  1925.           }
  1926.         }
  1927.         edgenumber++;
  1928.       }
  1929.     }
  1930.     triangleloop.tri = triangletraverse(m);
  1931.   }
  1932. #ifndef TRILIBRARY
  1933.   finishfile(outfile, argc, argv);
  1934. #endif /* not TRILIBRARY */
  1935. }
  1936. /*****************************************************************************/
  1937. /*                                                                           */
  1938. /*  writevoronoi()   Write the Voronoi diagram to a .v.node and .v.edge      */
  1939. /*                   file.                                                   */
  1940. /*                                                                           */
  1941. /*  The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
  1942. /*  Hence, the Voronoi vertices are listed by traversing the Delaunay        */
  1943. /*  triangles, and the Voronoi edges are listed by traversing the Delaunay   */
  1944. /*  edges.                                                                   */
  1945. /*                                                                           */
  1946. /*  WARNING:  In order to assign numbers to the Voronoi vertices, this       */
  1947. /*  procedure messes up the subsegments or the extra nodes of every          */
  1948. /*  element.  Hence, you should call this procedure last.                    */
  1949. /*                                                                           */
  1950. /*****************************************************************************/
  1951. #ifdef TRILIBRARY
  1952. #ifdef ANSI_DECLARATORS
  1953. void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
  1954.                   REAL **vpointattriblist, int **vpointmarkerlist,
  1955.                   int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
  1956. #else /* not ANSI_DECLARATORS */
  1957. void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
  1958.                   vedgelist, vedgemarkerlist, vnormlist)
  1959. struct mesh *m;
  1960. struct behavior *b;
  1961. REAL **vpointlist;
  1962. REAL **vpointattriblist;
  1963. int **vpointmarkerlist;
  1964. int **vedgelist;
  1965. int **vedgemarkerlist;
  1966. REAL **vnormlist;
  1967. #endif /* not ANSI_DECLARATORS */
  1968. #else /* not TRILIBRARY */
  1969. #ifdef ANSI_DECLARATORS
  1970. void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
  1971.                   char *vedgefilename, int argc, char **argv)
  1972. #else /* not ANSI_DECLARATORS */
  1973. void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
  1974. struct mesh *m;
  1975. struct behavior *b;
  1976. char *vnodefilename;
  1977. char *vedgefilename;
  1978. int argc;
  1979. char **argv;
  1980. #endif /* not ANSI_DECLARATORS */
  1981. #endif /* not TRILIBRARY */
  1982. {
  1983. #ifdef TRILIBRARY
  1984.   REAL *plist;
  1985.   REAL *palist;
  1986.   int *elist;
  1987.   REAL *normlist;
  1988.   int coordindex;
  1989.   int attribindex;
  1990. #else /* not TRILIBRARY */
  1991.   FILE *outfile;
  1992. #endif /* not TRILIBRARY */
  1993.   struct otri triangleloop, trisym;
  1994.   vertex torg, tdest, tapex;
  1995.   REAL circumcenter[2];
  1996.   REAL xi, eta;
  1997.   long vnodenumber, vedgenumber;
  1998.   int p1, p2;
  1999.   int i;
  2000.   triangle ptr;                         /* Temporary variable used by sym(). */
  2001. #ifdef TRILIBRARY
  2002.   if (!b->quiet) {
  2003.     printf("Writing Voronoi vertices.n");
  2004.   }
  2005.   /* Allocate memory for Voronoi vertices if necessary. */
  2006.   if (*vpointlist == (REAL *) NULL) {
  2007.     *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
  2008.                                             sizeof(REAL)));
  2009.   }
  2010.   /* Allocate memory for Voronoi vertex attributes if necessary. */
  2011.   if (*vpointattriblist == (REAL *) NULL) {
  2012.     *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
  2013.                                                   m->nextras * sizeof(REAL)));
  2014.   }
  2015.   *vpointmarkerlist = (int *) NULL;
  2016.   plist = *vpointlist;
  2017.   palist = *vpointattriblist;
  2018.   coordindex = 0;
  2019.   attribindex = 0;
  2020. #else /* not TRILIBRARY */
  2021.   if (!b->quiet) {
  2022.     printf("Writing %s.n", vnodefilename);
  2023.   }
  2024.   outfile = fopen(vnodefilename, "w");
  2025.   if (outfile == (FILE *) NULL) {
  2026.     printf("  Error:  Cannot create file %s.n", vnodefilename);
  2027.     triexit(1);
  2028.   }
  2029.   /* Number of triangles, two dimensions, number of vertex attributes, */
  2030.   /*   no markers.                                                     */
  2031.   fprintf(outfile, "%ld  %d  %d  %dn", m->triangles.items, 2, m->nextras, 0);
  2032. #endif /* not TRILIBRARY */
  2033.   traversalinit(&m->triangles);
  2034.   triangleloop.tri = triangletraverse(m);
  2035.   triangleloop.orient = 0;
  2036.   vnodenumber = b->firstnumber;
  2037.   while (triangleloop.tri != (triangle *) NULL) {
  2038.     org(triangleloop, torg);
  2039.     dest(triangleloop, tdest);
  2040.     apex(triangleloop, tapex);
  2041.     findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
  2042. #ifdef TRILIBRARY
  2043.     /* X and y coordinates. */
  2044.     plist[coordindex++] = circumcenter[0];
  2045.     plist[coordindex++] = circumcenter[1];
  2046.     for (i = 2; i < 2 + m->nextras; i++) {
  2047.       /* Interpolate the vertex attributes at the circumcenter. */
  2048.       palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
  2049.                                      + eta * (tapex[i] - torg[i]);
  2050.     }
  2051. #else /* not TRILIBRARY */
  2052.     /* Voronoi vertex number, x and y coordinates. */
  2053.     fprintf(outfile, "%4ld    %.17g  %.17g", vnodenumber, circumcenter[0],
  2054.             circumcenter[1]);
  2055.     for (i = 2; i < 2 + m->nextras; i++) {
  2056.       /* Interpolate the vertex attributes at the circumcenter. */
  2057.       fprintf(outfile, "  %.17g", torg[i] + xi * (tdest[i] - torg[i])
  2058.                                          + eta * (tapex[i] - torg[i]));
  2059.     }
  2060.     fprintf(outfile, "n");
  2061. #endif /* not TRILIBRARY */
  2062.     * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
  2063.     triangleloop.tri = triangletraverse(m);
  2064.     vnodenumber++;
  2065.   }
  2066. #ifndef TRILIBRARY
  2067.   finishfile(outfile, argc, argv);
  2068. #endif /* not TRILIBRARY */
  2069. #ifdef TRILIBRARY
  2070.   if (!b->quiet) {
  2071.     printf("Writing Voronoi edges.n");
  2072.   }
  2073.   /* Allocate memory for output Voronoi edges if necessary. */
  2074.   if (*vedgelist == (int *) NULL) {
  2075.     *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
  2076.   }
  2077.   *vedgemarkerlist = (int *) NULL;
  2078.   /* Allocate memory for output Voronoi norms if necessary. */
  2079.   if (*vnormlist == (REAL *) NULL) {
  2080.     *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
  2081.   }
  2082.   elist = *vedgelist;
  2083.   normlist = *vnormlist;
  2084.   coordindex = 0;
  2085. #else /* not TRILIBRARY */
  2086.   if (!b->quiet) {
  2087.     printf("Writing %s.n", vedgefilename);
  2088.   }
  2089.   outfile = fopen(vedgefilename, "w");
  2090.   if (outfile == (FILE *) NULL) {
  2091.     printf("  Error:  Cannot create file %s.n", vedgefilename);
  2092.     triexit(1);
  2093.   }
  2094.   /* Number of edges, zero boundary markers. */
  2095.   fprintf(outfile, "%ld  %dn", m->edges, 0);
  2096. #endif /* not TRILIBRARY */
  2097.   traversalinit(&m->triangles);
  2098.   triangleloop.tri = triangletraverse(m);
  2099.   vedgenumber = b->firstnumber;
  2100.   /* To loop over the set of edges, loop over all triangles, and look at   */
  2101.   /*   the three edges of each triangle.  If there isn't another triangle  */
  2102.   /*   adjacent to the edge, operate on the edge.  If there is another     */
  2103.   /*   adjacent triangle, operate on the edge only if the current triangle */
  2104.   /*   has a smaller pointer than its neighbor.  This way, each edge is    */
  2105.   /*   considered only once.                                               */
  2106.   while (triangleloop.tri != (triangle *) NULL) {
  2107.     for (triangleloop.orient = 0; triangleloop.orient < 3;
  2108.          triangleloop.orient++) {
  2109.       sym(triangleloop, trisym);
  2110.       if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
  2111.         /* Find the number of this triangle (and Voronoi vertex). */
  2112.         p1 = * (int *) (triangleloop.tri + 6);
  2113.         if (trisym.tri == m->dummytri) {
  2114.           org(triangleloop, torg);
  2115.           dest(triangleloop, tdest);
  2116. #ifdef TRILIBRARY
  2117.           /* Copy an infinite ray.  Index of one endpoint, and -1. */
  2118.           elist[coordindex] = p1;
  2119.           normlist[coordindex++] = tdest[1] - torg[1];
  2120.           elist[coordindex] = -1;
  2121.           normlist[coordindex++] = torg[0] - tdest[0];
  2122. #else /* not TRILIBRARY */
  2123.           /* Write an infinite ray.  Edge number, index of one endpoint, -1, */
  2124.           /*   and x and y coordinates of a vector representing the          */
  2125.           /*   direction of the ray.                                         */
  2126.           fprintf(outfile, "%4ld   %d  %d   %.17g  %.17gn", vedgenumber,
  2127.                   p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
  2128. #endif /* not TRILIBRARY */
  2129.         } else {
  2130.           /* Find the number of the adjacent triangle (and Voronoi vertex). */
  2131.           p2 = * (int *) (trisym.tri + 6);
  2132.           /* Finite edge.  Write indices of two endpoints. */
  2133. #ifdef TRILIBRARY
  2134.           elist[coordindex] = p1;
  2135.           normlist[coordindex++] = 0.0;
  2136.           elist[coordindex] = p2;
  2137.           normlist[coordindex++] = 0.0;
  2138. #else /* not TRILIBRARY */
  2139.           fprintf(outfile, "%4ld   %d  %dn", vedgenumber, p1, p2);
  2140. #endif /* not TRILIBRARY */
  2141.         }
  2142.         vedgenumber++;
  2143.       }
  2144.     }
  2145.     triangleloop.tri = triangletraverse(m);
  2146.   }
  2147. #ifndef TRILIBRARY
  2148.   finishfile(outfile, argc, argv);
  2149. #endif /* not TRILIBRARY */
  2150. }
  2151. #ifdef TRILIBRARY
  2152. #ifdef ANSI_DECLARATORS
  2153. void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
  2154. #else /* not ANSI_DECLARATORS */
  2155. void writeneighbors(m, b, neighborlist)
  2156. struct mesh *m;
  2157. struct behavior *b;
  2158. int **neighborlist;
  2159. #endif /* not ANSI_DECLARATORS */
  2160. #else /* not TRILIBRARY */
  2161. #ifdef ANSI_DECLARATORS
  2162. void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
  2163.                     int argc, char **argv)
  2164. #else /* not ANSI_DECLARATORS */
  2165. void writeneighbors(m, b, neighborfilename, argc, argv)
  2166. struct mesh *m;
  2167. struct behavior *b;
  2168. char *neighborfilename;
  2169. int argc;
  2170. char **argv;
  2171. #endif /* not ANSI_DECLARATORS */
  2172. #endif /* not TRILIBRARY */
  2173. {
  2174. #ifdef TRILIBRARY
  2175.   int *nlist;
  2176.   int index;
  2177. #else /* not TRILIBRARY */
  2178.   FILE *outfile;
  2179. #endif /* not TRILIBRARY */
  2180.   struct otri triangleloop, trisym;
  2181.   long elementnumber;
  2182.   int neighbor1, neighbor2, neighbor3;
  2183.   triangle ptr;                         /* Temporary variable used by sym(). */
  2184. #ifdef TRILIBRARY
  2185.   if (!b->quiet) {
  2186.     printf("Writing neighbors.n");
  2187.   }
  2188.   /* Allocate memory for neighbors if necessary. */
  2189.   if (*neighborlist == (int *) NULL) {
  2190.     *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
  2191.                                              sizeof(int)));
  2192.   }
  2193.   nlist = *neighborlist;
  2194.   index = 0;
  2195. #else /* not TRILIBRARY */
  2196.   if (!b->quiet) {
  2197.     printf("Writing %s.n", neighborfilename);
  2198.   }
  2199.   outfile = fopen(neighborfilename, "w");
  2200.   if (outfile == (FILE *) NULL) {
  2201.     printf("  Error:  Cannot create file %s.n", neighborfilename);
  2202.     triexit(1);
  2203.   }
  2204.   /* Number of triangles, three neighbors per triangle. */
  2205.   fprintf(outfile, "%ld  %dn", m->triangles.items, 3);
  2206. #endif /* not TRILIBRARY */
  2207.   traversalinit(&m->triangles);
  2208.   triangleloop.tri = triangletraverse(m);
  2209.   triangleloop.orient = 0;
  2210.   elementnumber = b->firstnumber;
  2211.   while (triangleloop.tri != (triangle *) NULL) {
  2212.     * (int *) (triangleloop.tri + 6) = (int) elementnumber;
  2213.     triangleloop.tri = triangletraverse(m);
  2214.     elementnumber++;
  2215.   }
  2216.   * (int *) (m->dummytri + 6) = -1;
  2217.   traversalinit(&m->triangles);
  2218.   triangleloop.tri = triangletraverse(m);
  2219.   elementnumber = b->firstnumber;
  2220.   while (triangleloop.tri != (triangle *) NULL) {
  2221.     triangleloop.orient = 1;
  2222.     sym(triangleloop, trisym);
  2223.     neighbor1 = * (int *) (trisym.tri + 6);
  2224.     triangleloop.orient = 2;
  2225.     sym(triangleloop, trisym);
  2226.     neighbor2 = * (int *) (trisym.tri + 6);
  2227.     triangleloop.orient = 0;
  2228.     sym(triangleloop, trisym);
  2229.     neighbor3 = * (int *) (trisym.tri + 6);
  2230. #ifdef TRILIBRARY
  2231.     nlist[index++] = neighbor1;
  2232.     nlist[index++] = neighbor2;
  2233.     nlist[index++] = neighbor3;
  2234. #else /* not TRILIBRARY */
  2235.     /* Triangle number, neighboring triangle numbers. */
  2236.     fprintf(outfile, "%4ld    %d  %d  %dn", elementnumber,
  2237.             neighbor1, neighbor2, neighbor3);
  2238. #endif /* not TRILIBRARY */
  2239.     triangleloop.tri = triangletraverse(m);
  2240.     elementnumber++;
  2241.   }
  2242. #ifndef TRILIBRARY
  2243.   finishfile(outfile, argc, argv);
  2244. #endif /* not TRILIBRARY */
  2245. }
  2246. /*****************************************************************************/
  2247. /*                                                                           */
  2248. /*  writeoff()   Write the triangulation to an .off file.                    */
  2249. /*                                                                           */
  2250. /*  OFF stands for the Object File Format, a format used by the Geometry     */
  2251. /*  Center's Geomview package.                                               */
  2252. /*                                                                           */
  2253. /*****************************************************************************/
  2254. #ifndef TRILIBRARY
  2255. #ifdef ANSI_DECLARATORS
  2256. void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
  2257.               int argc, char **argv)
  2258. #else /* not ANSI_DECLARATORS */
  2259. void writeoff(m, b, offfilename, argc, argv)
  2260. struct mesh *m;
  2261. struct behavior *b;
  2262. char *offfilename;
  2263. int argc;
  2264. char **argv;
  2265. #endif /* not ANSI_DECLARATORS */
  2266. {
  2267.   FILE *outfile;
  2268.   struct otri triangleloop;
  2269.   vertex vertexloop;
  2270.   vertex p1, p2, p3;
  2271.   long outvertices;
  2272.   if (!b->quiet) {
  2273.     printf("Writing %s.n", offfilename);
  2274.   }
  2275.   if (b->jettison) {
  2276.     outvertices = m->vertices.items - m->undeads;
  2277.   } else {
  2278.     outvertices = m->vertices.items;
  2279.   }
  2280.   outfile = fopen(offfilename, "w");
  2281.   if (outfile == (FILE *) NULL) {
  2282.     printf("  Error:  Cannot create file %s.n", offfilename);
  2283.     triexit(1);
  2284.   }
  2285.   /* Number of vertices, triangles, and edges. */
  2286.   fprintf(outfile, "OFFn%ld  %ld  %ldn", outvertices, m->triangles.items,
  2287.           m->edges);
  2288.   /* Write the vertices. */
  2289.   traversalinit(&m->vertices);
  2290.   vertexloop = vertextraverse(m);
  2291.   while (vertexloop != (vertex) NULL) {
  2292.     if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
  2293.       /* The "0.0" is here because the OFF format uses 3D coordinates. */
  2294.       fprintf(outfile, " %.17g  %.17g  %.17gn", vertexloop[0], vertexloop[1],
  2295.               0.0);
  2296.     }
  2297.     vertexloop = vertextraverse(m);
  2298.   }
  2299.   /* Write the triangles. */
  2300.   traversalinit(&m->triangles);
  2301.   triangleloop.tri = triangletraverse(m);
  2302.   triangleloop.orient = 0;
  2303.   while (triangleloop.tri != (triangle *) NULL) {
  2304.     org(triangleloop, p1);
  2305.     dest(triangleloop, p2);
  2306.     apex(triangleloop, p3);
  2307.     /* The "3" means a three-vertex polygon. */
  2308.     fprintf(outfile, " 3   %4d  %4d  %4dn", vertexmark(p1) - b->firstnumber,
  2309.             vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
  2310.     triangleloop.tri = triangletraverse(m);
  2311.   }
  2312.   finishfile(outfile, argc, argv);
  2313. }
  2314. #endif /* not TRILIBRARY */
  2315. /**                                                                         **/
  2316. /**                                                                         **/
  2317. /********* File I/O routines end here                                *********/
  2318. /*****************************************************************************/
  2319. /*                                                                           */
  2320. /*  quality_statistics()   Print statistics about the quality of the mesh.   */
  2321. /*                                                                           */
  2322. /*****************************************************************************/
  2323. #ifdef ANSI_DECLARATORS
  2324. void quality_statistics(struct mesh *m, struct behavior *b)
  2325. #else /* not ANSI_DECLARATORS */
  2326. void quality_statistics(m, b)
  2327. struct mesh *m;
  2328. struct behavior *b;
  2329. #endif /* not ANSI_DECLARATORS */
  2330. {
  2331.   struct otri triangleloop;
  2332.   vertex p[3];
  2333.   REAL cossquaretable[8];
  2334.   REAL ratiotable[16];
  2335.   REAL dx[3], dy[3];
  2336.   REAL edgelength[3];
  2337.   REAL dotproduct;
  2338.   REAL cossquare;
  2339.   REAL triarea;
  2340.   REAL shortest, longest;
  2341.   REAL trilongest2;
  2342.   REAL smallestarea, biggestarea;
  2343.   REAL triminaltitude2;
  2344.   REAL minaltitude;
  2345.   REAL triaspect2;
  2346.   REAL worstaspect;
  2347.   REAL smallestangle, biggestangle;
  2348.   REAL radconst, degconst;
  2349.   int angletable[18];
  2350.   int aspecttable[16];
  2351.   int aspectindex;
  2352.   int tendegree;
  2353.   int acutebiggest;
  2354.   int i, ii, j, k;
  2355.   printf("Mesh quality statistics:nn");
  2356.   radconst = PI / 18.0;
  2357.   degconst = 180.0 / PI;
  2358.   for (i = 0; i < 8; i++) {
  2359.     cossquaretable[i] = cos(radconst * (REAL) (i + 1));
  2360.     cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
  2361.   }
  2362.   for (i = 0; i < 18; i++) {
  2363.     angletable[i] = 0;
  2364.   }
  2365.   ratiotable[0]  =      1.5;      ratiotable[1]  =     2.0;
  2366.   ratiotable[2]  =      2.5;      ratiotable[3]  =     3.0;
  2367.   ratiotable[4]  =      4.0;      ratiotable[5]  =     6.0;
  2368.   ratiotable[6]  =     10.0;      ratiotable[7]  =    15.0;
  2369.   ratiotable[8]  =     25.0;      ratiotable[9]  =    50.0;
  2370.   ratiotable[10] =    100.0;      ratiotable[11] =   300.0;
  2371.   ratiotable[12] =   1000.0;      ratiotable[13] = 10000.0;
  2372.   ratiotable[14] = 100000.0;      ratiotable[15] =     0.0;
  2373.   for (i = 0; i < 16; i++) {
  2374.     aspecttable[i] = 0;
  2375.   }
  2376.   worstaspect = 0.0;
  2377.   minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
  2378.   minaltitude = minaltitude * minaltitude;
  2379.   shortest = minaltitude;
  2380.   longest = 0.0;
  2381.   smallestarea = minaltitude;
  2382.   biggestarea = 0.0;
  2383.   worstaspect = 0.0;
  2384.   smallestangle = 0.0;
  2385.   biggestangle = 2.0;
  2386.   acutebiggest = 1;
  2387.   traversalinit(&m->triangles);
  2388.   triangleloop.tri = triangletraverse(m);
  2389.   triangleloop.orient = 0;
  2390.   while (triangleloop.tri != (triangle *) NULL) {
  2391.     org(triangleloop, p[0]);
  2392.     dest(triangleloop, p[1]);
  2393.     apex(triangleloop, p[2]);
  2394.     trilongest2 = 0.0;
  2395.     for (i = 0; i < 3; i++) {
  2396.       j = plus1mod3[i];
  2397.       k = minus1mod3[i];
  2398.       dx[i] = p[j][0] - p[k][0];
  2399.       dy[i] = p[j][1] - p[k][1];
  2400.       edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
  2401.       if (edgelength[i] > trilongest2) {
  2402.         trilongest2 = edgelength[i];
  2403.       }
  2404.       if (edgelength[i] > longest) {
  2405.         longest = edgelength[i];
  2406.       }
  2407.       if (edgelength[i] < shortest) {
  2408.         shortest = edgelength[i];
  2409.       }
  2410.     }
  2411.     triarea = counterclockwise(m, b, p[0], p[1], p[2]);
  2412.     if (triarea < smallestarea) {
  2413.       smallestarea = triarea;
  2414.     }
  2415.     if (triarea > biggestarea) {
  2416.       biggestarea = triarea;
  2417.     }
  2418.     triminaltitude2 = triarea * triarea / trilongest2;
  2419.     if (triminaltitude2 < minaltitude) {
  2420.       minaltitude = triminaltitude2;
  2421.     }
  2422.     triaspect2 = trilongest2 / triminaltitude2;
  2423.     if (triaspect2 > worstaspect) {
  2424.       worstaspect = triaspect2;
  2425.     }
  2426.     aspectindex = 0;
  2427.     while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
  2428.            && (aspectindex < 15)) {
  2429.       aspectindex++;
  2430.     }
  2431.     aspecttable[aspectindex]++;
  2432.     for (i = 0; i < 3; i++) {
  2433.       j = plus1mod3[i];
  2434.       k = minus1mod3[i];
  2435.       dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
  2436.       cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
  2437.       tendegree = 8;
  2438.       for (ii = 7; ii >= 0; ii--) {
  2439.         if (cossquare > cossquaretable[ii]) {
  2440.           tendegree = ii;
  2441.         }
  2442.       }
  2443.       if (dotproduct <= 0.0) {
  2444.         angletable[tendegree]++;
  2445.         if (cossquare > smallestangle) {
  2446.           smallestangle = cossquare;
  2447.         }
  2448.         if (acutebiggest && (cossquare < biggestangle)) {
  2449.           biggestangle = cossquare;
  2450.         }
  2451.       } else {
  2452.         angletable[17 - tendegree]++;
  2453.         if (acutebiggest || (cossquare > biggestangle)) {
  2454.           biggestangle = cossquare;
  2455.           acutebiggest = 0;
  2456.         }
  2457.       }
  2458.     }
  2459.     triangleloop.tri = triangletraverse(m);
  2460.   }
  2461.   shortest = sqrt(shortest);
  2462.   longest = sqrt(longest);
  2463.   minaltitude = sqrt(minaltitude);
  2464.   worstaspect = sqrt(worstaspect);
  2465.   smallestarea *= 0.5;
  2466.   biggestarea *= 0.5;
  2467.   if (smallestangle >= 1.0) {
  2468.     smallestangle = 0.0;
  2469.   } else {
  2470.     smallestangle = degconst * acos(sqrt(smallestangle));
  2471.   }
  2472.   if (biggestangle >= 1.0) {
  2473.     biggestangle = 180.0;
  2474.   } else {
  2475.     if (acutebiggest) {
  2476.       biggestangle = degconst * acos(sqrt(biggestangle));
  2477.     } else {
  2478.       biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
  2479.     }
  2480.   }
  2481.   printf("  Smallest area: %16.5g   |  Largest area: %16.5gn",
  2482.          smallestarea, biggestarea);
  2483.   printf("  Shortest edge: %16.5g   |  Longest edge: %16.5gn",
  2484.          shortest, longest);
  2485.   printf("  Shortest altitude: %12.5g   |  Largest aspect ratio: %8.5gnn",
  2486.          minaltitude, worstaspect);
  2487.   printf("  Triangle aspect ratio histogram:n");
  2488.   printf("  1.1547 - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8dn",
  2489.          ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
  2490.          aspecttable[8]);
  2491.   for (i = 1; i < 7; i++) {
  2492.     printf("  %6.6g - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8dn",
  2493.            ratiotable[i - 1], ratiotable[i], aspecttable[i],
  2494.            ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
  2495.   }
  2496.   printf("  %6.6g - %-6.6g    :  %8d    | %6.6g -            :  %8dn",
  2497.          ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
  2498.          aspecttable[15]);
  2499.   printf("  (Aspect ratio is longest edge divided by shortest altitude)nn");
  2500.   printf("  Smallest angle: %15.5g   |  Largest angle: %15.5gnn",
  2501.          smallestangle, biggestangle);
  2502.   printf("  Angle histogram:n");
  2503.   for (i = 0; i < 9; i++) {
  2504.     printf("    %3d - %3d degrees:  %8d    |    %3d - %3d degrees:  %8dn",
  2505.            i * 10, i * 10 + 10, angletable[i],
  2506.            i * 10 + 90, i * 10 + 100, angletable[i + 9]);
  2507.   }
  2508.   printf("n");
  2509. }
  2510. /*****************************************************************************/
  2511. /*                                                                           */
  2512. /*  statistics()   Print all sorts of cool facts.                            */
  2513. /*                                                                           */
  2514. /*****************************************************************************/
  2515. #ifdef ANSI_DECLARATORS
  2516. void statistics(struct mesh *m, struct behavior *b)
  2517. #else /* not ANSI_DECLARATORS */
  2518. void statistics(m, b)
  2519. struct mesh *m;
  2520. struct behavior *b;
  2521. #endif /* not ANSI_DECLARATORS */
  2522. {
  2523.   printf("nStatistics:nn");
  2524.   printf("  Input vertices: %dn", m->invertices);
  2525.   if (b->refine) {
  2526.     printf("  Input triangles: %dn", m->inelements);
  2527.   }
  2528.   if (b->poly) {
  2529.     printf("  Input segments: %dn", m->insegments);
  2530.     if (!b->refine) {
  2531.       printf("  Input holes: %dn", m->holes);
  2532.     }
  2533.   }
  2534.   printf("n  Mesh vertices: %ldn", m->vertices.items - m->undeads);
  2535.   printf("  Mesh triangles: %ldn", m->triangles.items);
  2536.   printf("  Mesh edges: %ldn", m->edges);
  2537.   printf("  Mesh exterior boundary edges: %ldn", m->hullsize);
  2538.   if (b->poly || b->refine) {
  2539.     printf("  Mesh interior boundary edges: %ldn",
  2540.            m->subsegs.items - m->hullsize);
  2541.     printf("  Mesh subsegments (constrained edges): %ldn",
  2542.            m->subsegs.items);
  2543.   }
  2544.   printf("n");
  2545.   if (b->verbose) {
  2546.     quality_statistics(m, b);
  2547.     printf("Memory allocation statistics:nn");
  2548.     printf("  Maximum number of vertices: %ldn", m->vertices.maxitems);
  2549.     printf("  Maximum number of triangles: %ldn", m->triangles.maxitems);
  2550.     if (m->subsegs.maxitems > 0) {
  2551.       printf("  Maximum number of subsegments: %ldn", m->subsegs.maxitems);
  2552.     }
  2553.     if (m->viri.maxitems > 0) {
  2554.       printf("  Maximum number of viri: %ldn", m->viri.maxitems);
  2555.     }
  2556.     if (m->badsubsegs.maxitems > 0) {
  2557.       printf("  Maximum number of encroached subsegments: %ldn",
  2558.              m->badsubsegs.maxitems);
  2559.     }
  2560.     if (m->badtriangles.maxitems > 0) {
  2561.       printf("  Maximum number of bad triangles: %ldn",
  2562.              m->badtriangles.maxitems);
  2563.     }
  2564.     if (m->flipstackers.maxitems > 0) {
  2565.       printf("  Maximum number of stacked triangle flips: %ldn",
  2566.              m->flipstackers.maxitems);
  2567.     }
  2568.     if (m->splaynodes.maxitems > 0) {
  2569.       printf("  Maximum number of splay tree nodes: %ldn",
  2570.              m->splaynodes.maxitems);
  2571.     }
  2572.     printf("  Approximate heap memory use (bytes): %ldnn",
  2573.            m->vertices.maxitems * m->vertices.itembytes +
  2574.            m->triangles.maxitems * m->triangles.itembytes +
  2575.            m->subsegs.maxitems * m->subsegs.itembytes +
  2576.            m->viri.maxitems * m->viri.itembytes +
  2577.            m->badsubsegs.maxitems * m->badsubsegs.itembytes +
  2578.            m->badtriangles.maxitems * m->badtriangles.itembytes +
  2579.            m->flipstackers.maxitems * m->flipstackers.itembytes +
  2580.            m->splaynodes.maxitems * m->splaynodes.itembytes);
  2581.     printf("Algorithmic statistics:nn");
  2582.     if (!b->weighted) {
  2583.       printf("  Number of incircle tests: %ldn", m->incirclecount);
  2584.     } else {
  2585.       printf("  Number of 3D orientation tests: %ldn", m->orient3dcount);
  2586.     }
  2587.     printf("  Number of 2D orientation tests: %ldn", m->counterclockcount);
  2588.     if (m->hyperbolacount > 0) {
  2589.       printf("  Number of right-of-hyperbola tests: %ldn",
  2590.              m->hyperbolacount);
  2591.     }
  2592.     if (m->circletopcount > 0) {
  2593.       printf("  Number of circle top computations: %ldn",
  2594.              m->circletopcount);
  2595.     }
  2596.     if (m->circumcentercount > 0) {
  2597.       printf("  Number of triangle circumcenter computations: %ldn",
  2598.              m->circumcentercount);
  2599.     }
  2600.     printf("n");
  2601.   }
  2602. }
  2603. /*****************************************************************************/
  2604. /*                                                                           */
  2605. /*  main() or triangulate()   Gosh, do everything.                           */
  2606. /*                                                                           */
  2607. /*  The sequence is roughly as follows.  Many of these steps can be skipped, */
  2608. /*  depending on the command line switches.                                  */
  2609. /*                                                                           */
  2610. /*  - Initialize constants and parse the command line.                       */
  2611. /*  - Read the vertices from a file and either                               */
  2612. /*    - triangulate them (no -r), or                                         */
  2613. /*    - read an old mesh from files and reconstruct it (-r).                 */
  2614. /*  - Insert the PSLG segments (-p), and possibly segments on the convex     */
  2615. /*      hull (-c).                                                           */
  2616. /*  - Read the holes (-p), regional attributes (-pA), and regional area      */
  2617. /*      constraints (-pa).  Carve the holes and concavities, and spread the  */
  2618. /*      regional attributes and area constraints.                            */
  2619. /*  - Enforce the constraints on minimum angle (-q) and maximum area (-a).   */
  2620. /*      Also enforce the conforming Delaunay property (-q and -a).           */
  2621. /*  - Compute the number of edges in the resulting mesh.                     */
  2622. /*  - Promote the mesh's linear triangles to higher order elements (-o).     */
  2623. /*  - Write the output files and print the statistics.                       */
  2624. /*  - Check the consistency and Delaunay property of the mesh (-C).          */
  2625. /*                                                                           */
  2626. /*****************************************************************************/
  2627. #ifdef TRILIBRARY
  2628. #ifdef ANSI_DECLARATORS
  2629. void triangulate(char *triswitches, struct triangulateio *in,
  2630.                  struct triangulateio *out, struct triangulateio *vorout)
  2631. #else /* not ANSI_DECLARATORS */
  2632. void triangulate(triswitches, in, out, vorout)
  2633. char *triswitches;
  2634. struct triangulateio *in;
  2635. struct triangulateio *out;
  2636. struct triangulateio *vorout;
  2637. #endif /* not ANSI_DECLARATORS */
  2638. #else /* not TRILIBRARY */
  2639. #ifdef ANSI_DECLARATORS
  2640. int main(int argc, char **argv)
  2641. #else /* not ANSI_DECLARATORS */
  2642. int main(argc, argv)
  2643. int argc;
  2644. char **argv;
  2645. #endif /* not ANSI_DECLARATORS */
  2646. #endif /* not TRILIBRARY */
  2647. {
  2648.   struct mesh m;
  2649.   struct behavior b;
  2650.   REAL *holearray;                                        /* Array of holes. */
  2651.   REAL *regionarray;   /* Array of regional attributes and area constraints. */
  2652. #ifndef TRILIBRARY
  2653.   FILE *polyfile;
  2654. #endif /* not TRILIBRARY */
  2655. #ifndef NO_TIMER
  2656.   /* Variables for timing the performance of Triangle.  The types are */
  2657.   /*   defined in sys/time.h.                                         */
  2658.   struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
  2659.   struct timezone tz;
  2660. #endif /* not NO_TIMER */
  2661. #ifndef NO_TIMER
  2662.   gettimeofday(&tv0, &tz);
  2663. #endif /* not NO_TIMER */
  2664.   triangleinit(&m);
  2665. #ifdef TRILIBRARY
  2666.   parsecommandline(1, &triswitches, &b);
  2667. #else /* not TRILIBRARY */
  2668.   parsecommandline(argc, argv, &b);
  2669. #endif /* not TRILIBRARY */
  2670.   m.steinerleft = b.steiner;
  2671. #ifdef TRILIBRARY
  2672.   transfernodes(&m, &b, in->pointlist, in->pointattributelist,
  2673.                 in->pointmarkerlist, in->numberofpoints,
  2674.                 in->numberofpointattributes);
  2675. #else /* not TRILIBRARY */
  2676.   readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
  2677. #endif /* not TRILIBRARY */
  2678. #ifndef NO_TIMER
  2679.   if (!b.quiet) {
  2680.     gettimeofday(&tv1, &tz);
  2681.   }
  2682. #endif /* not NO_TIMER */
  2683. #ifdef CDT_ONLY
  2684.   m.hullsize = delaunay(&m, &b);                /* Triangulate the vertices. */
  2685. #else /* not CDT_ONLY */
  2686.   if (b.refine) {
  2687.     /* Read and reconstruct a mesh. */
  2688. #ifdef TRILIBRARY
  2689.     m.hullsize = reconstruct(&m, &b, in->trianglelist,
  2690.                              in->triangleattributelist, in->trianglearealist,
  2691.                              in->numberoftriangles, in->numberofcorners,
  2692.                              in->numberoftriangleattributes,
  2693.                              in->segmentlist, in->segmentmarkerlist,
  2694.                              in->numberofsegments);
  2695. #else /* not TRILIBRARY */
  2696.     m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
  2697.                              b.inpolyfilename, polyfile);
  2698. #endif /* not TRILIBRARY */
  2699.   } else {
  2700.     m.hullsize = delaunay(&m, &b);              /* Triangulate the vertices. */
  2701.   }
  2702. #endif /* not CDT_ONLY */
  2703. #ifndef NO_TIMER
  2704.   if (!b.quiet) {
  2705.     gettimeofday(&tv2, &tz);
  2706.     if (b.refine) {
  2707.       printf("Mesh reconstruction");
  2708.     } else {
  2709.       printf("Delaunay");
  2710.     }
  2711.     printf(" milliseconds:  %ldn", 1000l * (tv2.tv_sec - tv1.tv_sec) +
  2712.            (tv2.tv_usec - tv1.tv_usec) / 1000l);
  2713.   }
  2714. #endif /* not NO_TIMER */
  2715.   /* Ensure that no vertex can be mistaken for a triangular bounding */
  2716.   /*   box vertex in insertvertex().                                 */
  2717.   m.infvertex1 = (vertex) NULL;
  2718.   m.infvertex2 = (vertex) NULL;
  2719.   m.infvertex3 = (vertex) NULL;
  2720.   if (b.usesegments) {
  2721.     m.checksegments = 1;                /* Segments will be introduced next. */
  2722.     if (!b.refine) {
  2723.       /* Insert PSLG segments and/or convex hull segments. */
  2724. #ifdef TRILIBRARY
  2725.       formskeleton(&m, &b, in->segmentlist,
  2726.                    in->segmentmarkerlist, in->numberofsegments);
  2727. #else /* not TRILIBRARY */
  2728.       formskeleton(&m, &b, polyfile, b.inpolyfilename);
  2729. #endif /* not TRILIBRARY */
  2730.     }
  2731.   }
  2732. #ifndef NO_TIMER
  2733.   if (!b.quiet) {
  2734.     gettimeofday(&tv3, &tz);
  2735.     if (b.usesegments && !b.refine) {
  2736.       printf("Segment milliseconds:  %ldn",
  2737.              1000l * (tv3.tv_sec - tv2.tv_sec) +
  2738.              (tv3.tv_usec - tv2.tv_usec) / 1000l);
  2739.     }
  2740.   }
  2741. #endif /* not NO_TIMER */
  2742.   if (b.poly && (m.triangles.items > 0)) {
  2743. #ifdef TRILIBRARY
  2744.     holearray = in->holelist;
  2745.     m.holes = in->numberofholes;
  2746.     regionarray = in->regionlist;
  2747.     m.regions = in->numberofregions;
  2748. #else /* not TRILIBRARY */
  2749.     readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
  2750.               &regionarray, &m.regions);
  2751. #endif /* not TRILIBRARY */
  2752.     if (!b.refine) {
  2753.       /* Carve out holes and concavities. */
  2754.       carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
  2755.     }
  2756.   } else {
  2757.     /* Without a PSLG, there can be no holes or regional attributes   */
  2758.     /*   or area constraints.  The following are set to zero to avoid */
  2759.     /*   an accidental free() later.                                  */
  2760.     m.holes = 0;
  2761.     m.regions = 0;
  2762.   }
  2763. #ifndef NO_TIMER
  2764.   if (!b.quiet) {
  2765.     gettimeofday(&tv4, &tz);
  2766.     if (b.poly && !b.refine) {
  2767.       printf("Hole milliseconds:  %ldn", 1000l * (tv4.tv_sec - tv3.tv_sec) +
  2768.              (tv4.tv_usec - tv3.tv_usec) / 1000l);
  2769.     }
  2770.   }
  2771. #endif /* not NO_TIMER */
  2772. #ifndef CDT_ONLY
  2773.   if (b.quality && (m.triangles.items > 0)) {
  2774.     enforcequality(&m, &b);           /* Enforce angle and area constraints. */
  2775.   }
  2776. #endif /* not CDT_ONLY */
  2777. #ifndef NO_TIMER
  2778.   if (!b.quiet) {
  2779.     gettimeofday(&tv5, &tz);
  2780. #ifndef CDT_ONLY
  2781.     if (b.quality) {
  2782.       printf("Quality milliseconds:  %ldn",
  2783.              1000l * (tv5.tv_sec - tv4.tv_sec) +
  2784.              (tv5.tv_usec - tv4.tv_usec) / 1000l);
  2785.     }
  2786. #endif /* not CDT_ONLY */
  2787.   }
  2788. #endif /* not NO_TIMER */
  2789.   /* Calculate the number of edges. */
  2790.   m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
  2791.   if (b.order > 1) {
  2792.     highorder(&m, &b);       /* Promote elements to higher polynomial order. */
  2793.   }
  2794.   if (!b.quiet) {
  2795.     printf("n");
  2796.   }
  2797. #ifdef TRILIBRARY
  2798.   if (b.jettison) {
  2799.     out->numberofpoints = m.vertices.items - m.undeads;
  2800.   } else {
  2801.     out->numberofpoints = m.vertices.items;
  2802.   }
  2803.   out->numberofpointattributes = m.nextras;
  2804.   out->numberoftriangles = m.triangles.items;
  2805.   out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
  2806.   out->numberoftriangleattributes = m.eextras;
  2807.   out->numberofedges = m.edges;
  2808.   if (b.usesegments) {
  2809.     out->numberofsegments = m.subsegs.items;
  2810.   } else {
  2811.     out->numberofsegments = m.hullsize;
  2812.   }
  2813.   if (vorout != (struct triangulateio *) NULL) {
  2814.     vorout->numberofpoints = m.triangles.items;
  2815.     vorout->numberofpointattributes = m.nextras;
  2816.     vorout->numberofedges = m.edges;
  2817.   }
  2818. #endif /* TRILIBRARY */
  2819.   /* If not using iteration numbers, don't write a .node file if one was */
  2820.   /*   read, because the original one would be overwritten!              */
  2821.   if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
  2822.     if (!b.quiet) {
  2823. #ifdef TRILIBRARY
  2824.       printf("NOT writing vertices.n");
  2825. #else /* not TRILIBRARY */
  2826.       printf("NOT writing a .node file.n");
  2827. #endif /* not TRILIBRARY */
  2828.     }
  2829.     numbernodes(&m, &b);         /* We must remember to number the vertices. */
  2830.   } else {
  2831.     /* writenodes() numbers the vertices too. */
  2832. #ifdef TRILIBRARY
  2833.     writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
  2834.                &out->pointmarkerlist);
  2835. #else /* not TRILIBRARY */
  2836.     writenodes(&m, &b, b.outnodefilename, argc, argv);
  2837. #endif /* TRILIBRARY */
  2838.   }
  2839.   if (b.noelewritten) {
  2840.     if (!b.quiet) {
  2841. #ifdef TRILIBRARY
  2842.       printf("NOT writing triangles.n");
  2843. #else /* not TRILIBRARY */
  2844.       printf("NOT writing an .ele file.n");
  2845. #endif /* not TRILIBRARY */
  2846.     }
  2847.   } else {
  2848. #ifdef TRILIBRARY
  2849.     writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
  2850. #else /* not TRILIBRARY */
  2851.     writeelements(&m, &b, b.outelefilename, argc, argv);
  2852. #endif /* not TRILIBRARY */
  2853.   }
  2854.   /* The -c switch (convex switch) causes a PSLG to be written */
  2855.   /*   even if none was read.                                  */
  2856.   if (b.poly || b.convex) {
  2857.     /* If not using iteration numbers, don't overwrite the .poly file. */
  2858.     if (b.nopolywritten || b.noiterationnum) {
  2859.       if (!b.quiet) {
  2860. #ifdef TRILIBRARY
  2861.         printf("NOT writing segments.n");
  2862. #else /* not TRILIBRARY */
  2863.         printf("NOT writing a .poly file.n");
  2864. #endif /* not TRILIBRARY */
  2865.       }
  2866.     } else {
  2867. #ifdef TRILIBRARY
  2868.       writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
  2869.       out->numberofholes = m.holes;
  2870.       out->numberofregions = m.regions;
  2871.       if (b.poly) {
  2872.         out->holelist = in->holelist;
  2873.         out->regionlist = in->regionlist;
  2874.       } else {
  2875.         out->holelist = (REAL *) NULL;
  2876.         out->regionlist = (REAL *) NULL;
  2877.       }
  2878. #else /* not TRILIBRARY */
  2879.       writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
  2880.                 m.regions, argc, argv);
  2881. #endif /* not TRILIBRARY */
  2882.     }
  2883.   }
  2884. #ifndef TRILIBRARY
  2885. #ifndef CDT_ONLY
  2886.   if (m.regions > 0) {
  2887.     trifree((VOID *) regionarray);
  2888.   }
  2889. #endif /* not CDT_ONLY */
  2890.   if (m.holes > 0) {
  2891.     trifree((VOID *) holearray);
  2892.   }
  2893.   if (b.geomview) {
  2894.     writeoff(&m, &b, b.offfilename, argc, argv);
  2895.   }
  2896. #endif /* not TRILIBRARY */
  2897.   if (b.edgesout) {
  2898. #ifdef TRILIBRARY
  2899.     writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
  2900. #else /* not TRILIBRARY */
  2901.     writeedges(&m, &b, b.edgefilename, argc, argv);
  2902. #endif /* not TRILIBRARY */
  2903.   }
  2904.   if (b.voronoi) {
  2905. #ifdef TRILIBRARY
  2906.     writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
  2907.                  &vorout->pointmarkerlist, &vorout->edgelist,
  2908.                  &vorout->edgemarkerlist, &vorout->normlist);
  2909. #else /* not TRILIBRARY */
  2910.     writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
  2911. #endif /* not TRILIBRARY */
  2912.   }
  2913.   if (b.neighbors) {
  2914. #ifdef TRILIBRARY
  2915.     writeneighbors(&m, &b, &out->neighborlist);
  2916. #else /* not TRILIBRARY */
  2917.     writeneighbors(&m, &b, b.neighborfilename, argc, argv);
  2918. #endif /* not TRILIBRARY */
  2919.   }
  2920.   if (!b.quiet) {
  2921. #ifndef NO_TIMER
  2922.     gettimeofday(&tv6, &tz);
  2923.     printf("nOutput milliseconds:  %ldn",
  2924.            1000l * (tv6.tv_sec - tv5.tv_sec) +
  2925.            (tv6.tv_usec - tv5.tv_usec) / 1000l);
  2926.     printf("Total running milliseconds:  %ldn",
  2927.            1000l * (tv6.tv_sec - tv0.tv_sec) +
  2928.            (tv6.tv_usec - tv0.tv_usec) / 1000l);
  2929. #endif /* not NO_TIMER */
  2930.     statistics(&m, &b);
  2931.   }
  2932. #ifndef REDUCED
  2933.   if (b.docheck) {
  2934.     checkmesh(&m, &b);
  2935.     checkdelaunay(&m, &b);
  2936.   }
  2937. #endif /* not REDUCED */
  2938.   triangledeinit(&m, &b);
  2939. #ifndef TRILIBRARY
  2940.   return 0;
  2941. #endif /* not TRILIBRARY */
  2942. }