LCOV - code coverage report
Current view: top level - alg/internal_libqhull - io_r.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 52 2204 2.4 %
Date: 2024-11-21 22:18:42 Functions: 5 72 6.9 %

          Line data    Source code
       1             : /*<html><pre>  -<a                             href="qh-io_r.htm"
       2             :   >-------------------------------</a><a name="TOP">-</a>
       3             : 
       4             :    io_r.c
       5             :    Input/Output routines of qhull application
       6             : 
       7             :    see qh-io_r.htm and io_r.h
       8             : 
       9             :    see user_r.c for qh_errprint and qh_printfacetlist
      10             : 
      11             :    unix_r.c calls qh_readpoints and qh_produce_output
      12             : 
      13             :    unix_r.c and user_r.c are the only callers of io_r.c functions
      14             :    This allows the user to avoid loading io_r.o from qhull.a
      15             : 
      16             :    Copyright (c) 1993-2020 The Geometry Center.
      17             :    $Id: //main/2019/qhull/src/libqhull_r/io_r.c#12 $$Change: 2965 $
      18             :    $DateTime: 2020/06/04 15:37:41 $$Author: bbarber $
      19             : */
      20             : 
      21             : #include "qhull_ra.h"
      22             : 
      23             : /*========= -functions in alphabetical order after qh_produce_output(qh)  =====*/
      24             : 
      25             : /*-<a                             href="qh-io_r.htm#TOC"
      26             :   >-------------------------------</a><a name="produce_output">-</a>
      27             : 
      28             :   qh_produce_output(qh )
      29             :   qh_produce_output2(qh )
      30             :     prints out the result of qhull in desired format
      31             :     qh_produce_output2 does not call qh_prepare_output
      32             :       qh_checkpolygon is valid for qh_prepare_output
      33             :     if qh.GETarea
      34             :       computes and prints area and volume
      35             :     qh.PRINTout[] is an array of output formats
      36             : 
      37             :   notes:
      38             :     prints output in qh.PRINTout order
      39             : */
      40           0 : void qh_produce_output(qhT *qh) {
      41           0 :     int tempsize= qh_setsize(qh, qh->qhmem.tempstack);
      42             : 
      43           0 :     qh_prepare_output(qh);
      44           0 :     qh_produce_output2(qh);
      45           0 :     if (qh_setsize(qh, qh->qhmem.tempstack) != tempsize) {
      46           0 :         qh_fprintf(qh, qh->ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
      47             :             qh_setsize(qh, qh->qhmem.tempstack));
      48           0 :         qh_errexit(qh, qh_ERRqhull, NULL, NULL);
      49             :     }
      50           0 : } /* produce_output */
      51             : 
      52             : 
      53           0 : void qh_produce_output2(qhT *qh) {
      54           0 :   int i, tempsize= qh_setsize(qh, qh->qhmem.tempstack), d_1;
      55             : 
      56           0 :   fflush(NULL);
      57           0 :   if (qh->PRINTsummary)
      58           0 :     qh_printsummary(qh, qh->ferr);
      59           0 :   else if (qh->PRINTout[0] == qh_PRINTnone)
      60           0 :     qh_printsummary(qh, qh->fout);
      61           0 :   for (i=0; i < qh_PRINTEND; i++)
      62           0 :     qh_printfacets(qh, qh->fout, qh->PRINTout[i], qh->facet_list, NULL, !qh_ALL);
      63           0 :   fflush(NULL);
      64             : 
      65           0 :   qh_allstatistics(qh);
      66           0 :   if (qh->PRINTprecision && !qh->MERGING && (qh->JOGGLEmax > REALmax/2 || qh->RERUN))
      67           0 :     qh_printstats(qh, qh->ferr, qh->qhstat.precision, NULL);
      68           0 :   if (qh->VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
      69           0 :     qh_printstats(qh, qh->ferr, qh->qhstat.vridges, NULL);
      70           0 :   if (qh->PRINTstatistics) {
      71           0 :     qh_printstatistics(qh, qh->ferr, "");
      72           0 :     qh_memstatistics(qh, qh->ferr);
      73           0 :     d_1= (int)sizeof(setT) + (qh->hull_dim - 1) * SETelemsize;
      74           0 :     qh_fprintf(qh, qh->ferr, 8040, "\
      75             :     size in bytes: merge %d ridge %d vertex %d facet %d\n\
      76             :          normal %d ridge vertices %d facet vertices or neighbors %d\n",
      77             :             (int)sizeof(mergeT), (int)sizeof(ridgeT),
      78             :             (int)sizeof(vertexT), (int)sizeof(facetT),
      79             :             qh->normal_size, d_1, d_1 + SETelemsize);
      80             :   }
      81           0 :   if (qh_setsize(qh, qh->qhmem.tempstack) != tempsize) {
      82           0 :     qh_fprintf(qh, qh->ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
      83             :              qh_setsize(qh, qh->qhmem.tempstack));
      84           0 :     qh_errexit(qh, qh_ERRqhull, NULL, NULL);
      85             :   }
      86           0 : } /* produce_output2 */
      87             : 
      88             : /*-<a                             href="qh-io_r.htm#TOC"
      89             :   >-------------------------------</a><a name="dfacet">-</a>
      90             : 
      91             :   qh_dfacet(qh, id )
      92             :     print facet by id, for debugging
      93             : 
      94             : */
      95           0 : void qh_dfacet(qhT *qh, unsigned int id) {
      96             :   facetT *facet;
      97             : 
      98           0 :   FORALLfacets {
      99           0 :     if (facet->id == id) {
     100           0 :       qh_printfacet(qh, qh->fout, facet);
     101           0 :       break;
     102             :     }
     103             :   }
     104           0 : } /* dfacet */
     105             : 
     106             : 
     107             : /*-<a                             href="qh-io_r.htm#TOC"
     108             :   >-------------------------------</a><a name="dvertex">-</a>
     109             : 
     110             :   qh_dvertex(qh, id )
     111             :     print vertex by id, for debugging
     112             : */
     113           0 : void qh_dvertex(qhT *qh, unsigned int id) {
     114             :   vertexT *vertex;
     115             : 
     116           0 :   FORALLvertices {
     117           0 :     if (vertex->id == id) {
     118           0 :       qh_printvertex(qh, qh->fout, vertex);
     119           0 :       break;
     120             :     }
     121             :   }
     122           0 : } /* dvertex */
     123             : 
     124             : 
     125             : /*-<a                             href="qh-io_r.htm#TOC"
     126             :   >-------------------------------</a><a name="compare_facetarea">-</a>
     127             : 
     128             :   qh_compare_facetarea( p1, p2 )
     129             :     used by qsort() to order facets by area
     130             : */
     131           0 : int qh_compare_facetarea(const void *p1, const void *p2) {
     132           0 :   const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
     133             : 
     134           0 :   if (!a->isarea)
     135           0 :     return -1;
     136           0 :   if (!b->isarea)
     137           0 :     return 1;
     138           0 :   if (a->f.area > b->f.area)
     139           0 :     return 1;
     140           0 :   else if (a->f.area == b->f.area)
     141           0 :     return 0;
     142           0 :   return -1;
     143             : } /* compare_facetarea */
     144             : 
     145             : /*-<a                             href="qh-io_r.htm#TOC"
     146             :   >-------------------------------</a><a name="compare_facetvisit">-</a>
     147             : 
     148             :   qh_compare_facetvisit( p1, p2 )
     149             :     used by qsort() to order facets by visit id or id
     150             : */
     151           0 : int qh_compare_facetvisit(const void *p1, const void *p2) {
     152           0 :   const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
     153             :   int i,j;
     154             : 
     155           0 :   if (!(i= (int)a->visitid))
     156           0 :     i= (int)(0 - a->id); /* sign distinguishes id from visitid */
     157           0 :   if (!(j= (int)b->visitid))
     158           0 :     j= (int)(0 - b->id);
     159           0 :   return(i - j);
     160             : } /* compare_facetvisit */
     161             : 
     162             : /*-<a                             href="qh-io_r.htm#TOC"
     163             :   >-------------------------------</a><a name="compare_nummerge">-</a>
     164             : 
     165             :   qh_compare_nummerge( p1, p2 )
     166             :     used by qsort() to order facets by number of merges
     167             : 
     168             : notes:
     169             :     called by qh_markkeep ('PMerge-keep')
     170             : */
     171           0 : int qh_compare_nummerge(const void *p1, const void *p2) {
     172           0 :   const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
     173             : 
     174           0 :   return(a->nummerge - b->nummerge);
     175             : } /* compare_nummerge */
     176             : 
     177             : /*-<a                             href="qh-io_r.htm#TOC"
     178             :   >-------------------------------</a><a name="copyfilename">-</a>
     179             : 
     180             :   qh_copyfilename(qh, dest, size, source, length )
     181             :     copy filename identified by qh_skipfilename()
     182             : 
     183             :   notes:
     184             :     see qh_skipfilename() for syntax
     185             : */
     186           0 : void qh_copyfilename(qhT *qh, char *filename, int size, const char* source, int length) {
     187           0 :   char c= *source;
     188             : 
     189           0 :   if (length > size + 1) {
     190           0 :       qh_fprintf(qh, qh->ferr, 6040, "qhull error: filename is more than %d characters, %s\n",  size-1, source);
     191           0 :       qh_errexit(qh, qh_ERRinput, NULL, NULL);
     192             :   }
     193           0 :   strncpy(filename, source, (size_t)length);
     194           0 :   filename[length]= '\0';
     195           0 :   if (c == '\'' || c == '"') {
     196           0 :     char *s= filename + 1;
     197           0 :     char *t= filename;
     198           0 :     while (*s) {
     199           0 :       if (*s == c) {
     200           0 :           if (s[-1] == '\\')
     201           0 :               t[-1]= c;
     202             :       }else
     203           0 :           *t++= *s;
     204           0 :       s++;
     205             :     }
     206           0 :     *t= '\0';
     207             :   }
     208           0 : } /* copyfilename */
     209             : 
     210             : /*-<a                             href="qh-io_r.htm#TOC"
     211             :   >-------------------------------</a><a name="countfacets">-</a>
     212             : 
     213             :   qh_countfacets(qh, facetlist, facets, printall,
     214             :           numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
     215             :     count good facets for printing and set visitid
     216             :     if allfacets, ignores qh_skipfacet()
     217             : 
     218             :   notes:
     219             :     qh_printsummary and qh_countfacets must match counts
     220             : 
     221             :   returns:
     222             :     numfacets, numsimplicial, total neighbors, numridges, coplanars
     223             :     each facet with ->visitid indicating 1-relative position
     224             :       ->visitid==0 indicates not good
     225             : 
     226             :   notes
     227             :     numfacets >= numsimplicial
     228             :     if qh.NEWfacets,
     229             :       does not count visible facets (matches qh_printafacet)
     230             : 
     231             :   design:
     232             :     for all facets on facetlist and in facets set
     233             :       unless facet is skipped or visible (i.e., will be deleted)
     234             :         mark facet->visitid
     235             :         update counts
     236             : */
     237           0 : void qh_countfacets(qhT *qh, facetT *facetlist, setT *facets, boolT printall,
     238             :     int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
     239             :   facetT *facet, **facetp;
     240           0 :   int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
     241             : 
     242           0 :   FORALLfacet_(facetlist) {
     243           0 :     if ((facet->visible && qh->NEWfacets)
     244           0 :     || (!printall && qh_skipfacet(qh, facet)))
     245           0 :       facet->visitid= 0;
     246             :     else {
     247           0 :       facet->visitid= (unsigned int)(++numfacets);
     248           0 :       totneighbors += qh_setsize(qh, facet->neighbors);
     249           0 :       if (facet->simplicial) {
     250           0 :         numsimplicial++;
     251           0 :         if (facet->keepcentrum && facet->tricoplanar)
     252           0 :           numtricoplanars++;
     253             :       }else
     254           0 :         numridges += qh_setsize(qh, facet->ridges);
     255           0 :       if (facet->coplanarset)
     256           0 :         numcoplanars += qh_setsize(qh, facet->coplanarset);
     257             :     }
     258             :   }
     259             : 
     260           0 :   FOREACHfacet_(facets) {
     261           0 :     if ((facet->visible && qh->NEWfacets)
     262           0 :     || (!printall && qh_skipfacet(qh, facet)))
     263           0 :       facet->visitid= 0;
     264             :     else {
     265           0 :       facet->visitid= (unsigned int)(++numfacets);
     266           0 :       totneighbors += qh_setsize(qh, facet->neighbors);
     267           0 :       if (facet->simplicial){
     268           0 :         numsimplicial++;
     269           0 :         if (facet->keepcentrum && facet->tricoplanar)
     270           0 :           numtricoplanars++;
     271             :       }else
     272           0 :         numridges += qh_setsize(qh, facet->ridges);
     273           0 :       if (facet->coplanarset)
     274           0 :         numcoplanars += qh_setsize(qh, facet->coplanarset);
     275             :     }
     276             :   }
     277           0 :   qh->visit_id += (unsigned int)numfacets + 1;
     278           0 :   *numfacetsp= numfacets;
     279           0 :   *numsimplicialp= numsimplicial;
     280           0 :   *totneighborsp= totneighbors;
     281           0 :   *numridgesp= numridges;
     282           0 :   *numcoplanarsp= numcoplanars;
     283           0 :   *numtricoplanarsp= numtricoplanars;
     284           0 : } /* countfacets */
     285             : 
     286             : /*-<a                             href="qh-io_r.htm#TOC"
     287             :   >-------------------------------</a><a name="detvnorm">-</a>
     288             : 
     289             :   qh_detvnorm(qh, vertex, vertexA, centers, offset )
     290             :     compute separating plane of the Voronoi diagram for a pair of input sites
     291             :     centers= set of facets (i.e., Voronoi vertices)
     292             :       facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
     293             : 
     294             :   assumes:
     295             :     qh_ASvoronoi and qh_vertexneighbors() already set
     296             : 
     297             :   returns:
     298             :     norm
     299             :       a pointer into qh.gm_matrix to qh.hull_dim-1 reals
     300             :       copy the data before reusing qh.gm_matrix
     301             :     offset
     302             :       if 'QVn'
     303             :         sign adjusted so that qh.GOODvertexp is inside
     304             :       else
     305             :         sign adjusted so that vertex is inside
     306             : 
     307             :     qh.gm_matrix= simplex of points from centers relative to first center
     308             : 
     309             :   notes:
     310             :     in io_r.c so that code for 'v Tv' can be removed by removing io_r.c
     311             :     returns pointer into qh.gm_matrix to avoid tracking of temporary memory
     312             : 
     313             :   design:
     314             :     determine midpoint of input sites
     315             :     build points as the set of Voronoi vertices
     316             :     select a simplex from points (if necessary)
     317             :       include midpoint if the Voronoi region is unbounded
     318             :     relocate the first vertex of the simplex to the origin
     319             :     compute the normalized hyperplane through the simplex
     320             :     orient the hyperplane toward 'QVn' or 'vertex'
     321             :     if 'Tv' or 'Ts'
     322             :       if bounded
     323             :         test that hyperplane is the perpendicular bisector of the input sites
     324             :       test that Voronoi vertices not in the simplex are still on the hyperplane
     325             :     free up temporary memory
     326             : */
     327           0 : pointT *qh_detvnorm(qhT *qh, vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
     328             :   facetT *facet, **facetp;
     329             :   int  i, k, pointid, pointidA, point_i, point_n;
     330           0 :   setT *simplex= NULL;
     331             :   pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
     332             :   coordT *coord, *gmcoord, *normalp;
     333           0 :   setT *points= qh_settemp(qh, qh->TEMPsize);
     334           0 :   boolT nearzero= False;
     335           0 :   boolT unbounded= False;
     336           0 :   int numcenters= 0;
     337           0 :   int dim= qh->hull_dim - 1;
     338           0 :   realT dist, offset, angle, zero= 0.0;
     339             : 
     340           0 :   midpoint= qh->gm_matrix + qh->hull_dim * qh->hull_dim;  /* last row */
     341           0 :   for (k=0; k < dim; k++)
     342           0 :     midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
     343           0 :   FOREACHfacet_(centers) {
     344           0 :     numcenters++;
     345           0 :     if (!facet->visitid)
     346           0 :       unbounded= True;
     347             :     else {
     348           0 :       if (!facet->center)
     349           0 :         facet->center= qh_facetcenter(qh, facet->vertices);
     350           0 :       qh_setappend(qh, &points, facet->center);
     351             :     }
     352             :   }
     353           0 :   if (numcenters > dim) {
     354           0 :     simplex= qh_settemp(qh, qh->TEMPsize);
     355           0 :     qh_setappend(qh, &simplex, vertex->point);
     356           0 :     if (unbounded)
     357           0 :       qh_setappend(qh, &simplex, midpoint);
     358           0 :     qh_maxsimplex(qh, dim, points, NULL, 0, &simplex);
     359           0 :     qh_setdelnth(qh, simplex, 0);
     360           0 :   }else if (numcenters == dim) {
     361           0 :     if (unbounded)
     362           0 :       qh_setappend(qh, &points, midpoint);
     363           0 :     simplex= points;
     364             :   }else {
     365           0 :     qh_fprintf(qh, qh->ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
     366           0 :     qh_errexit(qh, qh_ERRqhull, NULL, NULL);
     367             :   }
     368           0 :   i= 0;
     369           0 :   gmcoord= qh->gm_matrix;
     370           0 :   point0= SETfirstt_(simplex, pointT);
     371           0 :   FOREACHpoint_(simplex) {
     372           0 :     if (qh->IStracing >= 4)
     373           0 :       qh_printmatrix(qh, qh->ferr, "qh_detvnorm: Voronoi vertex or midpoint",
     374             :                               &point, 1, dim);
     375           0 :     if (point != point0) {
     376           0 :       qh->gm_row[i++]= gmcoord;
     377           0 :       coord= point0;
     378           0 :       for (k=dim; k--; )
     379           0 :         *(gmcoord++)= *point++ - *coord++;
     380             :     }
     381             :   }
     382           0 :   qh->gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
     383           0 :   normal= gmcoord;
     384           0 :   qh_sethyperplane_gauss(qh, dim, qh->gm_row, point0, True,
     385             :                 normal, &offset, &nearzero);
     386             :   /* nearzero is true for axis-parallel hyperplanes (e.g., a bounding box).  Should detect degenerate hyperplanes.  See 'Tv' check following */
     387           0 :   if (qh->GOODvertexp == vertexA->point)
     388           0 :     inpoint= vertexA->point;
     389             :   else
     390           0 :     inpoint= vertex->point;
     391           0 :   zinc_(Zdistio);
     392           0 :   dist= qh_distnorm(dim, inpoint, normal, &offset);
     393           0 :   if (dist > 0) {
     394           0 :     offset= -offset;
     395           0 :     normalp= normal;
     396           0 :     for (k=dim; k--; ) {
     397           0 :       *normalp= -(*normalp);
     398           0 :       normalp++;
     399             :     }
     400             :   }
     401           0 :   if (qh->VERIFYoutput || qh->PRINTstatistics) {
     402           0 :     pointid= qh_pointid(qh, vertex->point);
     403           0 :     pointidA= qh_pointid(qh, vertexA->point);
     404           0 :     if (!unbounded) {
     405           0 :       zinc_(Zdiststat);
     406           0 :       dist= qh_distnorm(dim, midpoint, normal, &offset);
     407           0 :       if (dist < 0)
     408           0 :         dist= -dist;
     409           0 :       zzinc_(Zridgemid);
     410           0 :       wwmax_(Wridgemidmax, dist);
     411           0 :       wwadd_(Wridgemid, dist);
     412           0 :       trace4((qh, qh->ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
     413             :                  pointid, pointidA, dist));
     414           0 :       for (k=0; k < dim; k++)
     415           0 :         midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
     416           0 :       qh_normalize(qh, midpoint, dim, False);
     417           0 :       angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
     418           0 :       if (angle < 0.0)
     419           0 :         angle= angle + 1.0;
     420             :       else
     421           0 :         angle= angle - 1.0;
     422           0 :       if (angle < 0.0)
     423           0 :         angle= -angle;
     424           0 :       trace4((qh, qh->ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
     425             :                  pointid, pointidA, angle, nearzero));
     426           0 :       if (nearzero) {
     427           0 :         zzinc_(Zridge0);
     428           0 :         wwmax_(Wridge0max, angle);
     429           0 :         wwadd_(Wridge0, angle);
     430             :       }else {
     431           0 :         zzinc_(Zridgeok)
     432           0 :         wwmax_(Wridgeokmax, angle);
     433           0 :         wwadd_(Wridgeok, angle);
     434             :       }
     435             :     }
     436           0 :     if (simplex != points) {
     437           0 :       FOREACHpoint_i_(qh, points) {
     438           0 :         if (!qh_setin(simplex, point)) {
     439           0 :           facet= SETelemt_(centers, point_i, facetT);
     440           0 :           zinc_(Zdiststat);
     441           0 :           dist= qh_distnorm(dim, point, normal, &offset);
     442           0 :           if (dist < 0)
     443           0 :             dist= -dist;
     444           0 :           zzinc_(Zridge);
     445           0 :           wwmax_(Wridgemax, dist);
     446           0 :           wwadd_(Wridge, dist);
     447           0 :           trace4((qh, qh->ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
     448             :                              pointid, pointidA, facet->visitid, dist));
     449             :         }
     450             :       }
     451             :     }
     452             :   }
     453           0 :   *offsetp= offset;
     454           0 :   if (simplex != points)
     455           0 :     qh_settempfree(qh, &simplex);
     456           0 :   qh_settempfree(qh, &points);
     457           0 :   return normal;
     458             : } /* detvnorm */
     459             : 
     460             : /*-<a                             href="qh-io_r.htm#TOC"
     461             :   >-------------------------------</a><a name="detvridge">-</a>
     462             : 
     463             :   qh_detvridge(qh, vertexA )
     464             :     determine Voronoi ridge from 'seen' neighbors of vertexA
     465             :     include one vertex-at-infinite if an !neighbor->visitid
     466             : 
     467             :   returns:
     468             :     temporary set of centers (facets, i.e., Voronoi vertices)
     469             :     sorted by center id
     470             : */
     471           0 : setT *qh_detvridge(qhT *qh, vertexT *vertex) {
     472           0 :   setT *centers= qh_settemp(qh, qh->TEMPsize);
     473           0 :   setT *tricenters= qh_settemp(qh, qh->TEMPsize);
     474             :   facetT *neighbor, **neighborp;
     475           0 :   boolT firstinf= True;
     476             : 
     477           0 :   FOREACHneighbor_(vertex) {
     478           0 :     if (neighbor->seen) {
     479           0 :       if (neighbor->visitid) {
     480           0 :         if (!neighbor->tricoplanar || qh_setunique(qh, &tricenters, neighbor->center))
     481           0 :           qh_setappend(qh, &centers, neighbor);
     482           0 :       }else if (firstinf) {
     483           0 :         firstinf= False;
     484           0 :         qh_setappend(qh, &centers, neighbor);
     485             :       }
     486             :     }
     487             :   }
     488           0 :   qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(qh, centers),
     489             :              sizeof(facetT *), qh_compare_facetvisit);
     490           0 :   qh_settempfree(qh, &tricenters);
     491           0 :   return centers;
     492             : } /* detvridge */
     493             : 
     494             : /*-<a                             href="qh-io_r.htm#TOC"
     495             :   >-------------------------------</a><a name="detvridge3">-</a>
     496             : 
     497             :   qh_detvridge3(qh, atvertex, vertex )
     498             :     determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
     499             :     include one vertex-at-infinite for !neighbor->visitid
     500             :     assumes all facet->seen2= True
     501             : 
     502             :   returns:
     503             :     temporary set of centers (facets, i.e., Voronoi vertices)
     504             :     listed in adjacency order (!oriented)
     505             :     all facet->seen2= True
     506             : 
     507             :   design:
     508             :     mark all neighbors of atvertex
     509             :     for each adjacent neighbor of both atvertex and vertex
     510             :       if neighbor selected
     511             :         add neighbor to set of Voronoi vertices
     512             : */
     513           0 : setT *qh_detvridge3(qhT *qh, vertexT *atvertex, vertexT *vertex) {
     514           0 :   setT *centers= qh_settemp(qh, qh->TEMPsize);
     515           0 :   setT *tricenters= qh_settemp(qh, qh->TEMPsize);
     516           0 :   facetT *neighbor, **neighborp, *facet= NULL;
     517           0 :   boolT firstinf= True;
     518             : 
     519           0 :   FOREACHneighbor_(atvertex)
     520           0 :     neighbor->seen2= False;
     521           0 :   FOREACHneighbor_(vertex) {
     522           0 :     if (!neighbor->seen2) {
     523           0 :       facet= neighbor;
     524           0 :       break;
     525             :     }
     526             :   }
     527           0 :   while (facet) {
     528           0 :     facet->seen2= True;
     529           0 :     if (neighbor->seen) {
     530           0 :       if (facet->visitid) {
     531           0 :         if (!facet->tricoplanar || qh_setunique(qh, &tricenters, facet->center))
     532           0 :           qh_setappend(qh, &centers, facet);
     533           0 :       }else if (firstinf) {
     534           0 :         firstinf= False;
     535           0 :         qh_setappend(qh, &centers, facet);
     536             :       }
     537             :     }
     538           0 :     FOREACHneighbor_(facet) {
     539           0 :       if (!neighbor->seen2) {
     540           0 :         if (qh_setin(vertex->neighbors, neighbor))
     541           0 :           break;
     542             :         else
     543           0 :           neighbor->seen2= True;
     544             :       }
     545             :     }
     546           0 :     facet= neighbor;
     547             :   }
     548           0 :   if (qh->CHECKfrequently) {
     549           0 :     FOREACHneighbor_(vertex) {
     550           0 :       if (!neighbor->seen2) {
     551           0 :           qh_fprintf(qh, qh->ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
     552             :                  qh_pointid(qh, vertex->point), neighbor->id);
     553           0 :         qh_errexit(qh, qh_ERRqhull, neighbor, NULL);
     554             :       }
     555             :     }
     556             :   }
     557           0 :   FOREACHneighbor_(atvertex)
     558           0 :     neighbor->seen2= True;
     559           0 :   qh_settempfree(qh, &tricenters);
     560           0 :   return centers;
     561             : } /* detvridge3 */
     562             : 
     563             : /*-<a                             href="qh-io_r.htm#TOC"
     564             :   >-------------------------------</a><a name="eachvoronoi">-</a>
     565             : 
     566             :   qh_eachvoronoi(qh, fp, printvridge, vertex, visitall, innerouter, inorder )
     567             :     if visitall,
     568             :       visit all Voronoi ridges for vertex (i.e., an input site)
     569             :     else
     570             :       visit all unvisited Voronoi ridges for vertex
     571             :       all vertex->seen= False if unvisited
     572             :     assumes
     573             :       all facet->seen= False
     574             :       all facet->seen2= True (for qh_detvridge3)
     575             :       all facet->visitid == 0 if vertex_at_infinity
     576             :                          == index of Voronoi vertex
     577             :                          >= qh.num_facets if ignored
     578             :     innerouter:
     579             :       qh_RIDGEall--  both inner (bounded) and outer(unbounded) ridges
     580             :       qh_RIDGEinner- only inner
     581             :       qh_RIDGEouter- only outer
     582             : 
     583             :     if inorder
     584             :       orders vertices for 3-d Voronoi diagrams
     585             : 
     586             :   returns:
     587             :     number of visited ridges (does not include previously visited ridges)
     588             : 
     589             :     if printvridge,
     590             :       calls printvridge( fp, vertex, vertexA, centers)
     591             :         fp== any pointer (assumes FILE*)
     592             :              fp may be NULL for QhullQh::qh_fprintf which calls appendQhullMessage
     593             :         vertex,vertexA= pair of input sites that define a Voronoi ridge
     594             :         centers= set of facets (i.e., Voronoi vertices)
     595             :                  ->visitid == index or 0 if vertex_at_infinity
     596             :                  ordered for 3-d Voronoi diagram
     597             :   notes:
     598             :     uses qh.vertex_visit
     599             : 
     600             :   see:
     601             :     qh_eachvoronoi_all()
     602             : 
     603             :   design:
     604             :     mark selected neighbors of atvertex
     605             :     for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
     606             :       for each unvisited vertex
     607             :         if atvertex and vertex share more than d-1 neighbors
     608             :           bump totalcount
     609             :           if printvridge defined
     610             :             build the set of shared neighbors (i.e., Voronoi vertices)
     611             :             call printvridge
     612             : */
     613           0 : int qh_eachvoronoi(qhT *qh, FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
     614             :   boolT unbounded;
     615             :   int count;
     616             :   facetT *neighbor, **neighborp, *neighborA, **neighborAp;
     617             :   setT *centers;
     618           0 :   setT *tricenters= qh_settemp(qh, qh->TEMPsize);
     619             : 
     620             :   vertexT *vertex, **vertexp;
     621             :   boolT firstinf;
     622           0 :   unsigned int numfacets= (unsigned int)qh->num_facets;
     623           0 :   int totridges= 0;
     624             : 
     625           0 :   qh->vertex_visit++;
     626           0 :   atvertex->seen= True;
     627           0 :   if (visitall) {
     628           0 :     FORALLvertices
     629           0 :       vertex->seen= False;
     630             :   }
     631           0 :   FOREACHneighbor_(atvertex) {
     632           0 :     if (neighbor->visitid < numfacets)
     633           0 :       neighbor->seen= True;
     634             :   }
     635           0 :   FOREACHneighbor_(atvertex) {
     636           0 :     if (neighbor->seen) {
     637           0 :       FOREACHvertex_(neighbor->vertices) {
     638           0 :         if (vertex->visitid != qh->vertex_visit && !vertex->seen) {
     639           0 :           vertex->visitid= qh->vertex_visit;
     640           0 :           count= 0;
     641           0 :           firstinf= True;
     642           0 :           qh_settruncate(qh, tricenters, 0);
     643           0 :           FOREACHneighborA_(vertex) {
     644           0 :             if (neighborA->seen) {
     645           0 :               if (neighborA->visitid) {
     646           0 :                 if (!neighborA->tricoplanar || qh_setunique(qh, &tricenters, neighborA->center))
     647           0 :                   count++;
     648           0 :               }else if (firstinf) {
     649           0 :                 count++;
     650           0 :                 firstinf= False;
     651             :               }
     652             :             }
     653             :           }
     654           0 :           if (count >= qh->hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
     655           0 :             if (firstinf) {
     656           0 :               if (innerouter == qh_RIDGEouter)
     657           0 :                 continue;
     658           0 :               unbounded= False;
     659             :             }else {
     660           0 :               if (innerouter == qh_RIDGEinner)
     661           0 :                 continue;
     662           0 :               unbounded= True;
     663             :             }
     664           0 :             totridges++;
     665           0 :             trace4((qh, qh->ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
     666             :                   count, qh_pointid(qh, atvertex->point), qh_pointid(qh, vertex->point)));
     667           0 :             if (printvridge) {
     668           0 :               if (inorder && qh->hull_dim == 3+1) /* 3-d Voronoi diagram */
     669           0 :                 centers= qh_detvridge3(qh, atvertex, vertex);
     670             :               else
     671           0 :                 centers= qh_detvridge(qh, vertex);
     672           0 :               (*printvridge)(qh, fp, atvertex, vertex, centers, unbounded);
     673           0 :               qh_settempfree(qh, &centers);
     674             :             }
     675             :           }
     676             :         }
     677             :       }
     678             :     }
     679             :   }
     680           0 :   FOREACHneighbor_(atvertex)
     681           0 :     neighbor->seen= False;
     682           0 :   qh_settempfree(qh, &tricenters);
     683           0 :   return totridges;
     684             : } /* eachvoronoi */
     685             : 
     686             : 
     687             : /*-<a                             href="qh-poly_r.htm#TOC"
     688             :   >-------------------------------</a><a name="eachvoronoi_all">-</a>
     689             : 
     690             :   qh_eachvoronoi_all(qh, fp, printvridge, isUpper, innerouter, inorder )
     691             :     visit all Voronoi ridges
     692             : 
     693             :     innerouter:
     694             :       see qh_eachvoronoi()
     695             : 
     696             :     if inorder
     697             :       orders vertices for 3-d Voronoi diagrams
     698             : 
     699             :   returns
     700             :     total number of ridges
     701             : 
     702             :     if isUpper == facet->upperdelaunay  (i.e., a Vornoi vertex)
     703             :       facet->visitid= Voronoi vertex index(same as 'o' format)
     704             :     else
     705             :       facet->visitid= 0
     706             : 
     707             :     if printvridge,
     708             :       calls printvridge( fp, vertex, vertexA, centers)
     709             :       [see qh_eachvoronoi]
     710             : 
     711             :   notes:
     712             :     Not used for qhull.exe
     713             :     same effect as qh_printvdiagram but ridges not sorted by point id
     714             : */
     715           0 : int qh_eachvoronoi_all(qhT *qh, FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
     716             :   facetT *facet;
     717             :   vertexT *vertex;
     718           0 :   int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
     719           0 :   int totridges= 0;
     720             : 
     721           0 :   qh_clearcenters(qh, qh_ASvoronoi);
     722           0 :   qh_vertexneighbors(qh);
     723           0 :   maximize_(qh->visit_id, (unsigned int)qh->num_facets);
     724           0 :   FORALLfacets {
     725           0 :     facet->visitid= 0;
     726           0 :     facet->seen= False;
     727           0 :     facet->seen2= True;
     728             :   }
     729           0 :   FORALLfacets {
     730           0 :     if (facet->upperdelaunay == isUpper)
     731           0 :       facet->visitid= (unsigned int)(numcenters++);
     732             :   }
     733           0 :   FORALLvertices
     734           0 :     vertex->seen= False;
     735           0 :   FORALLvertices {
     736           0 :     if (qh->GOODvertex > 0 && qh_pointid(qh, vertex->point)+1 != qh->GOODvertex)
     737           0 :       continue;
     738           0 :     totridges += qh_eachvoronoi(qh, fp, printvridge, vertex,
     739             :                    !qh_ALL, innerouter, inorder);
     740             :   }
     741           0 :   return totridges;
     742             : } /* eachvoronoi_all */
     743             : 
     744             : /*-<a                             href="qh-io_r.htm#TOC"
     745             :   >-------------------------------</a><a name="facet2point">-</a>
     746             : 
     747             :   qh_facet2point(qh, facet, point0, point1, mindist )
     748             :     return two projected temporary vertices for a 2-d facet
     749             :     may be non-simplicial
     750             : 
     751             :   returns:
     752             :     point0 and point1 oriented and projected to the facet
     753             :     returns mindist (maximum distance below plane)
     754             : */
     755           0 : void qh_facet2point(qhT *qh, facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
     756             :   vertexT *vertex0, *vertex1;
     757             :   realT dist;
     758             : 
     759           0 :   if (facet->toporient ^ qh_ORIENTclock) {
     760           0 :     vertex0= SETfirstt_(facet->vertices, vertexT);
     761           0 :     vertex1= SETsecondt_(facet->vertices, vertexT);
     762             :   }else {
     763           0 :     vertex1= SETfirstt_(facet->vertices, vertexT);
     764           0 :     vertex0= SETsecondt_(facet->vertices, vertexT);
     765             :   }
     766           0 :   zadd_(Zdistio, 2);
     767           0 :   qh_distplane(qh, vertex0->point, facet, &dist);
     768           0 :   *mindist= dist;
     769           0 :   *point0= qh_projectpoint(qh, vertex0->point, facet, dist);
     770           0 :   qh_distplane(qh, vertex1->point, facet, &dist);
     771           0 :   minimize_(*mindist, dist);
     772           0 :   *point1= qh_projectpoint(qh, vertex1->point, facet, dist);
     773           0 : } /* facet2point */
     774             : 
     775             : 
     776             : /*-<a                             href="qh-io_r.htm#TOC"
     777             :   >-------------------------------</a><a name="facetvertices">-</a>
     778             : 
     779             :   qh_facetvertices(qh, facetlist, facets, allfacets )
     780             :     returns temporary set of vertices in a set and/or list of facets
     781             :     if allfacets, ignores qh_skipfacet()
     782             : 
     783             :   returns:
     784             :     vertices with qh.vertex_visit
     785             : 
     786             :   notes:
     787             :     optimized for allfacets of facet_list
     788             : 
     789             :   design:
     790             :     if allfacets of facet_list
     791             :       create vertex set from vertex_list
     792             :     else
     793             :       for each selected facet in facets or facetlist
     794             :         append unvisited vertices to vertex set
     795             : */
     796           1 : setT *qh_facetvertices(qhT *qh, facetT *facetlist, setT *facets, boolT allfacets) {
     797             :   setT *vertices;
     798             :   facetT *facet, **facetp;
     799             :   vertexT *vertex, **vertexp;
     800             : 
     801           1 :   qh->vertex_visit++;
     802           1 :   if (facetlist == qh->facet_list && allfacets && !facets) {
     803           1 :     vertices= qh_settemp(qh, qh->num_vertices);
     804           5 :     FORALLvertices {
     805           4 :       vertex->visitid= qh->vertex_visit;
     806           4 :       qh_setappend(qh, &vertices, vertex);
     807             :     }
     808             :   }else {
     809           0 :     vertices= qh_settemp(qh, qh->TEMPsize);
     810           0 :     FORALLfacet_(facetlist) {
     811           0 :       if (!allfacets && qh_skipfacet(qh, facet))
     812           0 :         continue;
     813           0 :       FOREACHvertex_(facet->vertices) {
     814           0 :         if (vertex->visitid != qh->vertex_visit) {
     815           0 :           vertex->visitid= qh->vertex_visit;
     816           0 :           qh_setappend(qh, &vertices, vertex);
     817             :         }
     818             :       }
     819             :     }
     820             :   }
     821           1 :   FOREACHfacet_(facets) {
     822           0 :     if (!allfacets && qh_skipfacet(qh, facet))
     823           0 :       continue;
     824           0 :     FOREACHvertex_(facet->vertices) {
     825           0 :       if (vertex->visitid != qh->vertex_visit) {
     826           0 :         vertex->visitid= qh->vertex_visit;
     827           0 :         qh_setappend(qh, &vertices, vertex);
     828             :       }
     829             :     }
     830             :   }
     831           1 :   return vertices;
     832             : } /* facetvertices */
     833             : 
     834             : /*-<a                             href="qh-geom_r.htm#TOC"
     835             :   >-------------------------------</a><a name="geomplanes">-</a>
     836             : 
     837             :   qh_geomplanes(qh, facet, outerplane, innerplane )
     838             :     return outer and inner planes for Geomview
     839             :     qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
     840             : 
     841             :   notes:
     842             :     assume precise calculations in io_r.c with roundoff covered by qh_GEOMepsilon
     843             : */
     844           0 : void qh_geomplanes(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane) {
     845             :   realT radius;
     846             : 
     847           0 :   if (qh->MERGING || qh->JOGGLEmax < REALmax/2) {
     848           0 :     qh_outerinner(qh, facet, outerplane, innerplane);
     849           0 :     radius= qh->PRINTradius;
     850           0 :     if (qh->JOGGLEmax < REALmax/2)
     851           0 :       radius -= qh->JOGGLEmax * sqrt((realT)qh->hull_dim);  /* already accounted for in qh_outerinner() */
     852           0 :     *outerplane += radius;
     853           0 :     *innerplane -= radius;
     854           0 :     if (qh->PRINTcoplanar || qh->PRINTspheres) {
     855           0 :       *outerplane += qh->MAXabs_coord * qh_GEOMepsilon;
     856           0 :       *innerplane -= qh->MAXabs_coord * qh_GEOMepsilon;
     857             :     }
     858             :   }else
     859           0 :     *innerplane= *outerplane= 0;
     860           0 : } /* geomplanes */
     861             : 
     862             : 
     863             : /*-<a                             href="qh-io_r.htm#TOC"
     864             :   >-------------------------------</a><a name="markkeep">-</a>
     865             : 
     866             :   qh_markkeep(qh, facetlist )
     867             :     restrict good facets for qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
     868             :     ignores visible facets (!part of convex hull)
     869             : 
     870             :   returns:
     871             :     may clear facet->good
     872             :     recomputes qh.num_good
     873             : 
     874             :   notes:
     875             :     only called by qh_prepare_output after qh_findgood_all
     876             :     does not throw errors except memory/corruption of qset_r.c
     877             : 
     878             :   design:
     879             :     get set of good facets
     880             :     if qh.KEEParea
     881             :       sort facets by area
     882             :       clear facet->good for all but n largest facets
     883             :     if qh.KEEPmerge
     884             :       sort facets by merge count
     885             :       clear facet->good for all but n most merged facets
     886             :     if qh.KEEPminarea
     887             :       clear facet->good if area too small
     888             :     update qh.num_good
     889             : */
     890           0 : void qh_markkeep(qhT *qh, facetT *facetlist) {
     891             :   facetT *facet, **facetp;
     892           0 :   setT *facets= qh_settemp(qh, qh->num_facets);
     893             :   int size, count;
     894             : 
     895           0 :   trace2((qh, qh->ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
     896             :           qh->KEEParea, qh->KEEPmerge, qh->KEEPminArea));
     897           0 :   FORALLfacet_(facetlist) {
     898           0 :     if (!facet->visible && facet->good)
     899           0 :       qh_setappend(qh, &facets, facet);
     900             :   }
     901           0 :   size= qh_setsize(qh, facets);
     902           0 :   if (qh->KEEParea) {
     903           0 :     qsort(SETaddr_(facets, facetT), (size_t)size,
     904             :              sizeof(facetT *), qh_compare_facetarea);
     905           0 :     if ((count= size - qh->KEEParea) > 0) {
     906           0 :       FOREACHfacet_(facets) {
     907           0 :         facet->good= False;
     908           0 :         if (--count == 0)
     909           0 :           break;
     910             :       }
     911             :     }
     912             :   }
     913           0 :   if (qh->KEEPmerge) {
     914           0 :     qsort(SETaddr_(facets, facetT), (size_t)size,
     915             :              sizeof(facetT *), qh_compare_nummerge);
     916           0 :     if ((count= size - qh->KEEPmerge) > 0) {
     917           0 :       FOREACHfacet_(facets) {
     918           0 :         facet->good= False;
     919           0 :         if (--count == 0)
     920           0 :           break;
     921             :       }
     922             :     }
     923             :   }
     924           0 :   if (qh->KEEPminArea < REALmax/2) {
     925           0 :     FOREACHfacet_(facets) {
     926           0 :       if (!facet->isarea || facet->f.area < qh->KEEPminArea)
     927           0 :         facet->good= False;
     928             :     }
     929             :   }
     930           0 :   qh_settempfree(qh, &facets);
     931           0 :   count= 0;
     932           0 :   FORALLfacet_(facetlist) {
     933           0 :     if (facet->good)
     934           0 :       count++;
     935             :   }
     936           0 :   qh->num_good= count;
     937           0 : } /* markkeep */
     938             : 
     939             : 
     940             : /*-<a                             href="qh-io_r.htm#TOC"
     941             :   >-------------------------------</a><a name="markvoronoi">-</a>
     942             : 
     943             :   qh_markvoronoi(qh, facetlist, facets, printall, isLower, numcenters )
     944             :     mark voronoi vertices for printing by site pairs
     945             : 
     946             :   returns:
     947             :     temporary set of vertices indexed by pointid
     948             :     isLower set if printing lower hull (i.e., at least one facet is lower hull)
     949             :     numcenters= total number of Voronoi vertices
     950             :     bumps qh.printoutnum for vertex-at-infinity
     951             :     clears all facet->seen and sets facet->seen2
     952             : 
     953             :     if selected
     954             :       facet->visitid= Voronoi vertex id
     955             :     else if upper hull (or 'Qu' and lower hull)
     956             :       facet->visitid= 0
     957             :     else
     958             :       facet->visitid >= qh->num_facets
     959             : 
     960             :   notes:
     961             :     ignores qh.ATinfinity, if defined
     962             : */
     963           0 : setT *qh_markvoronoi(qhT *qh, facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
     964           0 :   int numcenters=0;
     965             :   facetT *facet, **facetp;
     966             :   setT *vertices;
     967           0 :   boolT isLower= False;
     968             : 
     969           0 :   qh->printoutnum++;
     970           0 :   qh_clearcenters(qh, qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
     971           0 :   qh_vertexneighbors(qh);
     972           0 :   vertices= qh_pointvertex(qh);
     973           0 :   if (qh->ATinfinity)
     974           0 :     SETelem_(vertices, qh->num_points-1)= NULL;
     975           0 :   qh->visit_id++;
     976           0 :   maximize_(qh->visit_id, (unsigned int)qh->num_facets);
     977           0 :   FORALLfacet_(facetlist) {
     978           0 :     if (printall || !qh_skipfacet(qh, facet)) {
     979           0 :       if (!facet->upperdelaunay) {
     980           0 :         isLower= True;
     981           0 :         break;
     982             :       }
     983             :     }
     984             :   }
     985           0 :   FOREACHfacet_(facets) {
     986           0 :     if (printall || !qh_skipfacet(qh, facet)) {
     987           0 :       if (!facet->upperdelaunay) {
     988           0 :         isLower= True;
     989           0 :         break;
     990             :       }
     991             :     }
     992             :   }
     993           0 :   FORALLfacets {
     994           0 :     if (facet->normal && (facet->upperdelaunay == isLower))
     995           0 :       facet->visitid= 0;  /* facetlist or facets may overwrite */
     996             :     else
     997           0 :       facet->visitid= qh->visit_id;
     998           0 :     facet->seen= False;
     999           0 :     facet->seen2= True;
    1000             :   }
    1001           0 :   numcenters++;  /* qh_INFINITE */
    1002           0 :   FORALLfacet_(facetlist) {
    1003           0 :     if (printall || !qh_skipfacet(qh, facet))
    1004           0 :       facet->visitid= (unsigned int)(numcenters++);
    1005             :   }
    1006           0 :   FOREACHfacet_(facets) {
    1007           0 :     if (printall || !qh_skipfacet(qh, facet))
    1008           0 :       facet->visitid= (unsigned int)(numcenters++);
    1009             :   }
    1010           0 :   *isLowerp= isLower;
    1011           0 :   *numcentersp= numcenters;
    1012           0 :   trace2((qh, qh->ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
    1013           0 :   return vertices;
    1014             : } /* markvoronoi */
    1015             : 
    1016             : /*-<a                             href="qh-io_r.htm#TOC"
    1017             :   >-------------------------------</a><a name="order_vertexneighbors">-</a>
    1018             : 
    1019             :   qh_order_vertexneighbors(qh, vertex )
    1020             :     order facet neighbors of vertex by 2-d (orientation), 3-d (adjacency), or n-d (f.visitid,id)
    1021             : 
    1022             :   notes:
    1023             :     error if qh_vertexneighbors not called beforehand
    1024             :     only 2-d orients the neighbors
    1025             :     for 4-d and higher
    1026             :       set or clear f.visitid for qh_compare_facetvisit
    1027             :       for example, use qh_markvoronoi (e.g., qh_printvornoi) or qh_countfacets (e.g., qh_printvneighbors)
    1028             : 
    1029             :   design (2-d):
    1030             :     see qh_printextremes_2d
    1031             :   design (3-d):
    1032             :     initialize a new neighbor set with the first facet in vertex->neighbors
    1033             :     while vertex->neighbors non-empty
    1034             :       select next neighbor in the previous facet's neighbor set
    1035             :     set vertex->neighbors to the new neighbor set
    1036             :   design (n-d):
    1037             :     qsort by f.visitid, or f.facetid (qh_compare_facetvisit)
    1038             :     facet_id is negated (sorted before visit_id facets)
    1039             : */
    1040           0 : void qh_order_vertexneighbors(qhT *qh, vertexT *vertex) {
    1041             :   setT *newset;
    1042             :   facetT *facet, *facetA, *facetB, *neighbor, **neighborp;
    1043             :   vertexT *vertexA;
    1044             :   int numneighbors;
    1045             : 
    1046           0 :   trace4((qh, qh->ferr, 4018, "qh_order_vertexneighbors: order facet neighbors of v%d by 2-d (orientation), 3-d (adjacency), or n-d (f.visitid,id)\n", vertex->id));
    1047           0 :   if (!qh->VERTEXneighbors) {
    1048           0 :     qh_fprintf(qh, qh->ferr, 6428, "qhull internal error (qh_order_vertexneighbors): call qh_vertexneighbors before calling qh_order_vertexneighbors\n");
    1049           0 :     qh_errexit(qh, qh_ERRqhull, NULL, NULL);
    1050             :   }
    1051           0 :   if (qh->hull_dim == 2) {
    1052           0 :     facetA= SETfirstt_(vertex->neighbors, facetT);
    1053           0 :     if (facetA->toporient ^ qh_ORIENTclock)
    1054           0 :       vertexA= SETfirstt_(facetA->vertices, vertexT);
    1055             :     else
    1056           0 :       vertexA= SETsecondt_(facetA->vertices, vertexT);
    1057           0 :     if (vertexA!=vertex) {
    1058           0 :       facetB= SETsecondt_(vertex->neighbors, facetT);
    1059           0 :       SETfirst_(vertex->neighbors)= facetB;
    1060           0 :       SETsecond_(vertex->neighbors)= facetA;
    1061             :     }
    1062           0 :   }else if (qh->hull_dim == 3) {
    1063           0 :     newset= qh_settemp(qh, qh_setsize(qh, vertex->neighbors));
    1064           0 :     facet= (facetT *)qh_setdellast(vertex->neighbors);
    1065           0 :     qh_setappend(qh, &newset, facet);
    1066           0 :     while (qh_setsize(qh, vertex->neighbors)) {
    1067           0 :       FOREACHneighbor_(vertex) {
    1068           0 :         if (qh_setin(facet->neighbors, neighbor)) {
    1069           0 :           qh_setdel(vertex->neighbors, neighbor);
    1070           0 :           qh_setappend(qh, &newset, neighbor);
    1071           0 :           facet= neighbor;
    1072           0 :           break;
    1073             :         }
    1074             :       }
    1075           0 :       if (!neighbor) {
    1076           0 :         qh_fprintf(qh, qh->ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
    1077             :           vertex->id, facet->id);
    1078           0 :         qh_errexit(qh, qh_ERRqhull, facet, NULL);
    1079             :       }
    1080             :     }
    1081           0 :     qh_setfree(qh, &vertex->neighbors);
    1082           0 :     qh_settemppop(qh);
    1083           0 :     vertex->neighbors= newset;
    1084             :   }else { /* qh.hull_dim >= 4 */
    1085           0 :     numneighbors= qh_setsize(qh, vertex->neighbors);
    1086           0 :     qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
    1087             :         sizeof(facetT *), qh_compare_facetvisit);
    1088             :   }
    1089           0 : } /* order_vertexneighbors */
    1090             : 
    1091             : /*-<a                             href="qh-io_r.htm#TOC"
    1092             :   >-------------------------------</a><a name="prepare_output">-</a>
    1093             : 
    1094             :   qh_prepare_output(qh )
    1095             :     prepare for qh_produce_output2(qh) according to
    1096             :       qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
    1097             :     does not reset facet->good
    1098             : 
    1099             :   notes
    1100             :     called by qh_produce_output, qh_new_qhull, Qhull.outputQhull
    1101             :     except for PRINTstatistics, no-op if previously called with same options
    1102             : */
    1103           3 : void qh_prepare_output(qhT *qh) {
    1104           3 :   if (qh->VORONOI) {
    1105           0 :     qh_clearcenters(qh, qh_ASvoronoi);  /* must be before qh_triangulate */
    1106           0 :     qh_vertexneighbors(qh);
    1107             :   }
    1108           3 :   if (qh->TRIangulate && !qh->hasTriangulation) {
    1109           3 :     qh_triangulate(qh);
    1110           3 :     if (qh->VERIFYoutput && !qh->CHECKfrequently)
    1111           0 :       qh_checkpolygon(qh, qh->facet_list);
    1112             :   }
    1113           3 :   qh_findgood_all(qh, qh->facet_list);
    1114           3 :   if (qh->GETarea)
    1115           0 :     qh_getarea(qh, qh->facet_list);
    1116           3 :   if (qh->KEEParea || qh->KEEPmerge || qh->KEEPminArea < REALmax/2)
    1117           0 :     qh_markkeep(qh, qh->facet_list);
    1118           3 :   if (qh->PRINTstatistics)
    1119           0 :     qh_collectstatistics(qh);
    1120           3 : }
    1121             : 
    1122             : /*-<a                             href="qh-io_r.htm#TOC"
    1123             :   >-------------------------------</a><a name="printafacet">-</a>
    1124             : 
    1125             :   qh_printafacet(qh, fp, format, facet, printall )
    1126             :     print facet to fp in given output format (see qh.PRINTout)
    1127             : 
    1128             :   returns:
    1129             :     nop if !printall and qh_skipfacet()
    1130             :     nop if visible facet and NEWfacets and format != PRINTfacets
    1131             :     must match qh_countfacets
    1132             : 
    1133             :   notes
    1134             :     preserves qh.visit_id
    1135             :     facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
    1136             : 
    1137             :   see
    1138             :     qh_printbegin() and qh_printend()
    1139             : 
    1140             :   design:
    1141             :     test for printing facet
    1142             :     call appropriate routine for format
    1143             :     or output results directly
    1144             : */
    1145           0 : void qh_printafacet(qhT *qh, FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
    1146             :   realT color[4], offset, dist, outerplane, innerplane;
    1147             :   boolT zerodiv;
    1148             :   coordT *point, *normp, *coordp, **pointp, *feasiblep;
    1149             :   int k;
    1150             :   vertexT *vertex, **vertexp;
    1151             :   facetT *neighbor, **neighborp;
    1152             : 
    1153           0 :   if (!printall && qh_skipfacet(qh, facet))
    1154           0 :     return;
    1155           0 :   if (facet->visible && qh->NEWfacets && format != qh_PRINTfacets)
    1156           0 :     return;
    1157           0 :   qh->printoutnum++;
    1158           0 :   switch (format) {
    1159           0 :   case qh_PRINTarea:
    1160           0 :     if (facet->isarea) {
    1161           0 :       qh_fprintf(qh, fp, 9009, qh_REAL_1, facet->f.area);
    1162           0 :       qh_fprintf(qh, fp, 9010, "\n");
    1163             :     }else
    1164           0 :       qh_fprintf(qh, fp, 9011, "0\n");
    1165           0 :     break;
    1166           0 :   case qh_PRINTcoplanars:
    1167           0 :     qh_fprintf(qh, fp, 9012, "%d", qh_setsize(qh, facet->coplanarset));
    1168           0 :     FOREACHpoint_(facet->coplanarset)
    1169           0 :       qh_fprintf(qh, fp, 9013, " %d", qh_pointid(qh, point));
    1170           0 :     qh_fprintf(qh, fp, 9014, "\n");
    1171           0 :     break;
    1172           0 :   case qh_PRINTcentrums:
    1173           0 :     qh_printcenter(qh, fp, format, NULL, facet);
    1174           0 :     break;
    1175           0 :   case qh_PRINTfacets:
    1176           0 :     qh_printfacet(qh, fp, facet);
    1177           0 :     break;
    1178           0 :   case qh_PRINTfacets_xridge:
    1179           0 :     qh_printfacetheader(qh, fp, facet);
    1180           0 :     break;
    1181           0 :   case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
    1182           0 :     if (!facet->normal)
    1183           0 :       break;
    1184           0 :     for (k=qh->hull_dim; k--; ) {
    1185           0 :       color[k]= (facet->normal[k]+1.0)/2.0;
    1186           0 :       maximize_(color[k], -1.0);
    1187           0 :       minimize_(color[k], +1.0);
    1188             :     }
    1189           0 :     qh_projectdim3(qh, color, color);
    1190           0 :     if (qh->PRINTdim != qh->hull_dim)
    1191           0 :       qh_normalize2(qh, color, 3, True, NULL, NULL);
    1192           0 :     if (qh->hull_dim <= 2)
    1193           0 :       qh_printfacet2geom(qh, fp, facet, color);
    1194           0 :     else if (qh->hull_dim == 3) {
    1195           0 :       if (facet->simplicial)
    1196           0 :         qh_printfacet3geom_simplicial(qh, fp, facet, color);
    1197             :       else
    1198           0 :         qh_printfacet3geom_nonsimplicial(qh, fp, facet, color);
    1199             :     }else {
    1200           0 :       if (facet->simplicial)
    1201           0 :         qh_printfacet4geom_simplicial(qh, fp, facet, color);
    1202             :       else
    1203           0 :         qh_printfacet4geom_nonsimplicial(qh, fp, facet, color);
    1204             :     }
    1205           0 :     break;
    1206           0 :   case qh_PRINTids:
    1207           0 :     qh_fprintf(qh, fp, 9015, "%d\n", facet->id);
    1208           0 :     break;
    1209           0 :   case qh_PRINTincidences:
    1210             :   case qh_PRINToff:
    1211             :   case qh_PRINTtriangles:
    1212           0 :     if (qh->hull_dim == 3 && format != qh_PRINTtriangles)
    1213           0 :       qh_printfacet3vertex(qh, fp, facet, format);
    1214           0 :     else if (facet->simplicial || qh->hull_dim == 2 || format == qh_PRINToff)
    1215           0 :       qh_printfacetNvertex_simplicial(qh, fp, facet, format);
    1216             :     else
    1217           0 :       qh_printfacetNvertex_nonsimplicial(qh, fp, facet, qh->printoutvar++, format);
    1218           0 :     break;
    1219           0 :   case qh_PRINTinner:
    1220           0 :     qh_outerinner(qh, facet, NULL, &innerplane);
    1221           0 :     offset= facet->offset - innerplane;
    1222           0 :     goto LABELprintnorm;
    1223             :     break; /* prevent warning */
    1224           0 :   case qh_PRINTmerges:
    1225           0 :     qh_fprintf(qh, fp, 9016, "%d\n", facet->nummerge);
    1226           0 :     break;
    1227           0 :   case qh_PRINTnormals:
    1228           0 :     offset= facet->offset;
    1229           0 :     goto LABELprintnorm;
    1230             :     break; /* prevent warning */
    1231           0 :   case qh_PRINTouter:
    1232           0 :     qh_outerinner(qh, facet, &outerplane, NULL);
    1233           0 :     offset= facet->offset - outerplane;
    1234           0 :   LABELprintnorm:
    1235           0 :     if (!facet->normal) {
    1236           0 :       qh_fprintf(qh, fp, 9017, "no normal for facet f%d\n", facet->id);
    1237           0 :       break;
    1238             :     }
    1239           0 :     if (qh->CDDoutput) {
    1240           0 :       qh_fprintf(qh, fp, 9018, qh_REAL_1, -offset);
    1241           0 :       for (k=0; k < qh->hull_dim; k++)
    1242           0 :         qh_fprintf(qh, fp, 9019, qh_REAL_1, -facet->normal[k]);
    1243             :     }else {
    1244           0 :       for (k=0; k < qh->hull_dim; k++)
    1245           0 :         qh_fprintf(qh, fp, 9020, qh_REAL_1, facet->normal[k]);
    1246           0 :       qh_fprintf(qh, fp, 9021, qh_REAL_1, offset);
    1247             :     }
    1248           0 :     qh_fprintf(qh, fp, 9022, "\n");
    1249           0 :     break;
    1250           0 :   case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
    1251             :   case qh_PRINTmaple:
    1252           0 :     if (qh->hull_dim == 2)
    1253           0 :       qh_printfacet2math(qh, fp, facet, format, qh->printoutvar++);
    1254             :     else
    1255           0 :       qh_printfacet3math(qh, fp, facet, format, qh->printoutvar++);
    1256           0 :     break;
    1257           0 :   case qh_PRINTneighbors:
    1258           0 :     qh_fprintf(qh, fp, 9023, "%d", qh_setsize(qh, facet->neighbors));
    1259           0 :     FOREACHneighbor_(facet)
    1260           0 :       qh_fprintf(qh, fp, 9024, " %d",
    1261           0 :                neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
    1262           0 :     qh_fprintf(qh, fp, 9025, "\n");
    1263           0 :     break;
    1264           0 :   case qh_PRINTpointintersect:
    1265           0 :     if (!qh->feasible_point) {
    1266           0 :       qh_fprintf(qh, qh->ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh->feasible_point\n");
    1267           0 :       qh_errexit(qh, qh_ERRinput, NULL, NULL);
    1268             :     }
    1269           0 :     if (facet->offset > 0)
    1270           0 :       goto LABELprintinfinite;
    1271           0 :     point= coordp= (coordT *)qh_memalloc(qh, qh->normal_size);
    1272           0 :     normp= facet->normal;
    1273           0 :     feasiblep= qh->feasible_point;
    1274           0 :     if (facet->offset < -qh->MINdenom) {
    1275           0 :       for (k=qh->hull_dim; k--; )
    1276           0 :         *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
    1277             :     }else {
    1278           0 :       for (k=qh->hull_dim; k--; ) {
    1279           0 :         *(coordp++)= qh_divzero(*(normp++), facet->offset, qh->MINdenom_1,
    1280           0 :                                  &zerodiv) + *(feasiblep++);
    1281           0 :         if (zerodiv) {
    1282           0 :           qh_memfree(qh, point, qh->normal_size);
    1283           0 :           goto LABELprintinfinite;
    1284             :         }
    1285             :       }
    1286             :     }
    1287           0 :     qh_printpoint(qh, fp, NULL, point);
    1288           0 :     qh_memfree(qh, point, qh->normal_size);
    1289           0 :     break;
    1290           0 :   LABELprintinfinite:
    1291           0 :     for (k=qh->hull_dim; k--; )
    1292           0 :       qh_fprintf(qh, fp, 9026, qh_REAL_1, qh_INFINITE);
    1293           0 :     qh_fprintf(qh, fp, 9027, "\n");
    1294           0 :     break;
    1295           0 :   case qh_PRINTpointnearest:
    1296           0 :     FOREACHpoint_(facet->coplanarset) {
    1297             :       int id, id2;
    1298           0 :       vertex= qh_nearvertex(qh, facet, point, &dist);
    1299           0 :       id= qh_pointid(qh, vertex->point);
    1300           0 :       id2= qh_pointid(qh, point);
    1301           0 :       qh_fprintf(qh, fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
    1302             :     }
    1303           0 :     break;
    1304           0 :   case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
    1305           0 :     if (qh->CDDoutput)
    1306           0 :       qh_fprintf(qh, fp, 9029, "1 ");
    1307           0 :     qh_printcenter(qh, fp, format, NULL, facet);
    1308           0 :     break;
    1309           0 :   case qh_PRINTvertices:
    1310           0 :     qh_fprintf(qh, fp, 9030, "%d", qh_setsize(qh, facet->vertices));
    1311           0 :     FOREACHvertex_(facet->vertices)
    1312           0 :       qh_fprintf(qh, fp, 9031, " %d", qh_pointid(qh, vertex->point));
    1313           0 :     qh_fprintf(qh, fp, 9032, "\n");
    1314           0 :     break;
    1315           0 :   default:
    1316           0 :     break;
    1317             :   }
    1318             : } /* printafacet */
    1319             : 
    1320             : /*-<a                             href="qh-io_r.htm#TOC"
    1321             :   >-------------------------------</a><a name="printbegin">-</a>
    1322             : 
    1323             :   qh_printbegin(qh )
    1324             :     prints header for all output formats
    1325             : 
    1326             :   returns:
    1327             :     checks for valid format
    1328             : 
    1329             :   notes:
    1330             :     uses qh.visit_id for 3/4off
    1331             :     changes qh.interior_point if printing centrums
    1332             :     qh_countfacets clears facet->visitid for non-good facets
    1333             : 
    1334             :   see
    1335             :     qh_printend() and qh_printafacet()
    1336             : 
    1337             :   design:
    1338             :     count facets and related statistics
    1339             :     print header for format
    1340             : */
    1341           0 : void qh_printbegin(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
    1342             :   int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
    1343             :   int i, num;
    1344             :   facetT *facet, **facetp;
    1345             :   vertexT *vertex, **vertexp;
    1346             :   setT *vertices;
    1347             :   pointT *point, **pointp, *pointtemp;
    1348             : 
    1349           0 :   qh->printoutnum= 0;
    1350           0 :   qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
    1351             :       &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
    1352           0 :   switch (format) {
    1353           0 :   case qh_PRINTnone:
    1354           0 :     break;
    1355           0 :   case qh_PRINTarea:
    1356           0 :     qh_fprintf(qh, fp, 9033, "%d\n", numfacets);
    1357           0 :     break;
    1358           0 :   case qh_PRINTcoplanars:
    1359           0 :     qh_fprintf(qh, fp, 9034, "%d\n", numfacets);
    1360           0 :     break;
    1361           0 :   case qh_PRINTcentrums:
    1362           0 :     if (qh->CENTERtype == qh_ASnone)
    1363           0 :       qh_clearcenters(qh, qh_AScentrum);
    1364           0 :     qh_fprintf(qh, fp, 9035, "%d\n%d\n", qh->hull_dim, numfacets);
    1365           0 :     break;
    1366           0 :   case qh_PRINTfacets:
    1367             :   case qh_PRINTfacets_xridge:
    1368           0 :     if (facetlist)
    1369           0 :       qh_printvertexlist(qh, fp, "Vertices and facets:\n", facetlist, facets, printall);
    1370           0 :     break;
    1371           0 :   case qh_PRINTgeom:
    1372           0 :     if (qh->hull_dim > 4)  /* qh_initqhull_globals also checks */
    1373           0 :       goto LABELnoformat;
    1374           0 :     if (qh->VORONOI && qh->hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
    1375           0 :       goto LABELnoformat;
    1376           0 :     if (qh->hull_dim == 2 && (qh->PRINTridges || qh->DOintersections))
    1377           0 :       qh_fprintf(qh, qh->ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
    1378           0 :     if (qh->hull_dim == 4 && (qh->PRINTinner || qh->PRINTouter ||
    1379           0 :                              (qh->PRINTdim == 4 && qh->PRINTcentrums)))
    1380           0 :       qh_fprintf(qh, qh->ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
    1381           0 :     if (qh->PRINTdim == 4 && (qh->PRINTspheres))
    1382           0 :       qh_fprintf(qh, qh->ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
    1383           0 :     if (qh->PRINTdim == 4 && qh->DOintersections && qh->PRINTnoplanes)
    1384           0 :       qh_fprintf(qh, qh->ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
    1385           0 :     if (qh->PRINTdim == 2) {
    1386           0 :       qh_fprintf(qh, fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
    1387           0 :               qh->rbox_command, qh->qhull_command);
    1388           0 :     }else if (qh->PRINTdim == 3) {
    1389           0 :       qh_fprintf(qh, fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
    1390           0 :               qh->rbox_command, qh->qhull_command);
    1391           0 :     }else if (qh->PRINTdim == 4) {
    1392           0 :       qh->visit_id++;
    1393           0 :       num= 0;
    1394           0 :       FORALLfacet_(facetlist)    /* get number of ridges to be printed */
    1395           0 :         qh_printend4geom(qh, NULL, facet, &num, printall);
    1396           0 :       FOREACHfacet_(facets)
    1397           0 :         qh_printend4geom(qh, NULL, facet, &num, printall);
    1398           0 :       qh->ridgeoutnum= num;
    1399           0 :       qh->printoutvar= 0;  /* counts number of ridges in output */
    1400           0 :       qh_fprintf(qh, fp, 9038, "LIST # %s | %s\n", qh->rbox_command, qh->qhull_command);
    1401             :     }
    1402             : 
    1403           0 :     if (qh->PRINTdots) {
    1404           0 :       qh->printoutnum++;
    1405           0 :       num= qh->num_points + qh_setsize(qh, qh->other_points);
    1406           0 :       if (qh->DELAUNAY && qh->ATinfinity)
    1407           0 :         num--;
    1408           0 :       if (qh->PRINTdim == 4)
    1409           0 :         qh_fprintf(qh, fp, 9039, "4VECT %d %d 1\n", num, num);
    1410             :       else
    1411           0 :         qh_fprintf(qh, fp, 9040, "VECT %d %d 1\n", num, num);
    1412             : 
    1413           0 :       for (i=num; i--; ) {
    1414           0 :         if (i % 20 == 0)
    1415           0 :           qh_fprintf(qh, fp, 9041, "\n");
    1416           0 :         qh_fprintf(qh, fp, 9042, "1 ");
    1417             :       }
    1418           0 :       qh_fprintf(qh, fp, 9043, "# 1 point per line\n1 ");
    1419           0 :       for (i=num-1; i--; ) { /* num at least 3 for D2 */
    1420           0 :         if (i % 20 == 0)
    1421           0 :           qh_fprintf(qh, fp, 9044, "\n");
    1422           0 :         qh_fprintf(qh, fp, 9045, "0 ");
    1423             :       }
    1424           0 :       qh_fprintf(qh, fp, 9046, "# 1 color for all\n");
    1425           0 :       FORALLpoints {
    1426           0 :         if (!qh->DELAUNAY || !qh->ATinfinity || qh_pointid(qh, point) != qh->num_points-1) {
    1427           0 :           if (qh->PRINTdim == 4)
    1428           0 :             qh_printpoint(qh, fp, NULL, point);
    1429             :             else
    1430           0 :               qh_printpoint3(qh, fp, point);
    1431             :         }
    1432             :       }
    1433           0 :       FOREACHpoint_(qh->other_points) {
    1434           0 :         if (qh->PRINTdim == 4)
    1435           0 :           qh_printpoint(qh, fp, NULL, point);
    1436             :         else
    1437           0 :           qh_printpoint3(qh, fp, point);
    1438             :       }
    1439           0 :       qh_fprintf(qh, fp, 9047, "0 1 1 1  # color of points\n");
    1440             :     }
    1441             : 
    1442           0 :     if (qh->PRINTdim == 4  && !qh->PRINTnoplanes)
    1443             :       /* 4dview loads up multiple 4OFF objects slowly */
    1444           0 :       qh_fprintf(qh, fp, 9048, "4OFF %d %d 1\n", 3*qh->ridgeoutnum, qh->ridgeoutnum);
    1445           0 :     qh->PRINTcradius= 2 * qh->DISTround;  /* include test DISTround */
    1446           0 :     if (qh->PREmerge) {
    1447           0 :       maximize_(qh->PRINTcradius, qh->premerge_centrum + qh->DISTround);
    1448           0 :     }else if (qh->POSTmerge)
    1449           0 :       maximize_(qh->PRINTcradius, qh->postmerge_centrum + qh->DISTround);
    1450           0 :     qh->PRINTradius= qh->PRINTcradius;
    1451           0 :     if (qh->PRINTspheres + qh->PRINTcoplanar)
    1452           0 :       maximize_(qh->PRINTradius, qh->MAXabs_coord * qh_MINradius);
    1453           0 :     if (qh->premerge_cos < REALmax/2) {
    1454           0 :       maximize_(qh->PRINTradius, (1- qh->premerge_cos) * qh->MAXabs_coord);
    1455           0 :     }else if (!qh->PREmerge && qh->POSTmerge && qh->postmerge_cos < REALmax/2) {
    1456           0 :       maximize_(qh->PRINTradius, (1- qh->postmerge_cos) * qh->MAXabs_coord);
    1457             :     }
    1458           0 :     maximize_(qh->PRINTradius, qh->MINvisible);
    1459           0 :     if (qh->JOGGLEmax < REALmax/2)
    1460           0 :       qh->PRINTradius += qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
    1461           0 :     if (qh->PRINTdim != 4 &&
    1462           0 :         (qh->PRINTcoplanar || qh->PRINTspheres || qh->PRINTcentrums)) {
    1463           0 :       vertices= qh_facetvertices(qh, facetlist, facets, printall);
    1464           0 :       if (qh->PRINTspheres && qh->PRINTdim <= 3)
    1465           0 :         qh_printspheres(qh, fp, vertices, qh->PRINTradius);
    1466           0 :       if (qh->PRINTcoplanar || qh->PRINTcentrums) {
    1467           0 :         qh->firstcentrum= True;
    1468           0 :         if (qh->PRINTcoplanar&& !qh->PRINTspheres) {
    1469           0 :           FOREACHvertex_(vertices)
    1470           0 :             qh_printpointvect2(qh, fp, vertex->point, NULL, qh->interior_point, qh->PRINTradius);
    1471             :         }
    1472           0 :         FORALLfacet_(facetlist) {
    1473           0 :           if (!printall && qh_skipfacet(qh, facet))
    1474           0 :             continue;
    1475           0 :           if (!facet->normal)
    1476           0 :             continue;
    1477           0 :           if (qh->PRINTcentrums && qh->PRINTdim <= 3)
    1478           0 :             qh_printcentrum(qh, fp, facet, qh->PRINTcradius);
    1479           0 :           if (!qh->PRINTcoplanar)
    1480           0 :             continue;
    1481           0 :           FOREACHpoint_(facet->coplanarset)
    1482           0 :             qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
    1483           0 :           FOREACHpoint_(facet->outsideset)
    1484           0 :             qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
    1485             :         }
    1486           0 :         FOREACHfacet_(facets) {
    1487           0 :           if (!printall && qh_skipfacet(qh, facet))
    1488           0 :             continue;
    1489           0 :           if (!facet->normal)
    1490           0 :             continue;
    1491           0 :           if (qh->PRINTcentrums && qh->PRINTdim <= 3)
    1492           0 :             qh_printcentrum(qh, fp, facet, qh->PRINTcradius);
    1493           0 :           if (!qh->PRINTcoplanar)
    1494           0 :             continue;
    1495           0 :           FOREACHpoint_(facet->coplanarset)
    1496           0 :             qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
    1497           0 :           FOREACHpoint_(facet->outsideset)
    1498           0 :             qh_printpointvect2(qh, fp, point, facet->normal, NULL, qh->PRINTradius);
    1499             :         }
    1500             :       }
    1501           0 :       qh_settempfree(qh, &vertices);
    1502             :     }
    1503           0 :     qh->visit_id++; /* for printing hyperplane intersections */
    1504           0 :     break;
    1505           0 :   case qh_PRINTids:
    1506           0 :     qh_fprintf(qh, fp, 9049, "%d\n", numfacets);
    1507           0 :     break;
    1508           0 :   case qh_PRINTincidences:
    1509           0 :     if (qh->VORONOI && qh->PRINTprecision)
    1510           0 :       qh_fprintf(qh, qh->ferr, 7053, "qhull warning: input sites of Delaunay regions (option 'i').  Use option 'p' or 'o' for Voronoi centers.  Disable warning with option 'Pp'\n");
    1511           0 :     qh->printoutvar= (int)qh->vertex_id;  /* centrum id for 4-d+, non-simplicial facets */
    1512           0 :     if (qh->hull_dim <= 3)
    1513           0 :       qh_fprintf(qh, fp, 9050, "%d\n", numfacets);
    1514             :     else
    1515           0 :       qh_fprintf(qh, fp, 9051, "%d\n", numsimplicial+numridges);
    1516           0 :     break;
    1517           0 :   case qh_PRINTinner:
    1518             :   case qh_PRINTnormals:
    1519             :   case qh_PRINTouter:
    1520           0 :     if (qh->CDDoutput)
    1521           0 :       qh_fprintf(qh, fp, 9052, "%s | %s\nbegin\n    %d %d real\n", qh->rbox_command,
    1522           0 :             qh->qhull_command, numfacets, qh->hull_dim+1);
    1523             :     else
    1524           0 :       qh_fprintf(qh, fp, 9053, "%d\n%d\n", qh->hull_dim+1, numfacets);
    1525           0 :     break;
    1526           0 :   case qh_PRINTmathematica:
    1527             :   case qh_PRINTmaple:
    1528           0 :     if (qh->hull_dim > 3)  /* qh_initbuffers also checks */
    1529           0 :       goto LABELnoformat;
    1530           0 :     if (qh->VORONOI)
    1531           0 :       qh_fprintf(qh, qh->ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
    1532           0 :     if (format == qh_PRINTmaple) {
    1533           0 :       if (qh->hull_dim == 2)
    1534           0 :         qh_fprintf(qh, fp, 9054, "PLOT(CURVES(\n");
    1535             :       else
    1536           0 :         qh_fprintf(qh, fp, 9055, "PLOT3D(POLYGONS(\n");
    1537             :     }else
    1538           0 :       qh_fprintf(qh, fp, 9056, "{\n");
    1539           0 :     qh->printoutvar= 0;   /* counts number of facets for notfirst */
    1540           0 :     break;
    1541           0 :   case qh_PRINTmerges:
    1542           0 :     qh_fprintf(qh, fp, 9057, "%d\n", numfacets);
    1543           0 :     break;
    1544           0 :   case qh_PRINTpointintersect:
    1545           0 :     qh_fprintf(qh, fp, 9058, "%d\n%d\n", qh->hull_dim, numfacets);
    1546           0 :     break;
    1547           0 :   case qh_PRINTneighbors:
    1548           0 :     qh_fprintf(qh, fp, 9059, "%d\n", numfacets);
    1549           0 :     break;
    1550           0 :   case qh_PRINToff:
    1551             :   case qh_PRINTtriangles:
    1552           0 :     if (qh->VORONOI)
    1553           0 :       goto LABELnoformat;
    1554           0 :     num= qh->hull_dim;
    1555           0 :     if (format == qh_PRINToff || qh->hull_dim == 2)
    1556           0 :       qh_fprintf(qh, fp, 9060, "%d\n%d %d %d\n", num,
    1557           0 :         qh->num_points+qh_setsize(qh, qh->other_points), numfacets, totneighbors/2);
    1558             :     else { /* qh_PRINTtriangles */
    1559           0 :       qh->printoutvar= qh->num_points+qh_setsize(qh, qh->other_points); /* first centrum */
    1560           0 :       if (qh->DELAUNAY)
    1561           0 :         num--;  /* drop last dimension */
    1562           0 :       qh_fprintf(qh, fp, 9061, "%d\n%d %d %d\n", num, qh->printoutvar
    1563           0 :         + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
    1564             :     }
    1565           0 :     FORALLpoints
    1566           0 :       qh_printpointid(qh, qh->fout, NULL, num, point, qh_IDunknown);
    1567           0 :     FOREACHpoint_(qh->other_points)
    1568           0 :       qh_printpointid(qh, qh->fout, NULL, num, point, qh_IDunknown);
    1569           0 :     if (format == qh_PRINTtriangles && qh->hull_dim > 2) {
    1570           0 :       FORALLfacets {
    1571           0 :         if (!facet->simplicial && facet->visitid)
    1572           0 :           qh_printcenter(qh, qh->fout, format, NULL, facet);
    1573             :       }
    1574             :     }
    1575           0 :     break;
    1576           0 :   case qh_PRINTpointnearest:
    1577           0 :     qh_fprintf(qh, fp, 9062, "%d\n", numcoplanars);
    1578           0 :     break;
    1579           0 :   case qh_PRINTpoints:
    1580           0 :     if (!qh->VORONOI)
    1581           0 :       goto LABELnoformat;
    1582           0 :     if (qh->CDDoutput)
    1583           0 :       qh_fprintf(qh, fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh->rbox_command,
    1584           0 :            qh->qhull_command, numfacets, qh->hull_dim);
    1585             :     else
    1586           0 :       qh_fprintf(qh, fp, 9064, "%d\n%d\n", qh->hull_dim-1, numfacets);
    1587           0 :     break;
    1588           0 :   case qh_PRINTvertices:
    1589           0 :     qh_fprintf(qh, fp, 9065, "%d\n", numfacets);
    1590           0 :     break;
    1591             :   case qh_PRINTsummary:
    1592             :   default:
    1593           0 :   LABELnoformat:
    1594           0 :     qh_fprintf(qh, qh->ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
    1595             :          qh->hull_dim);
    1596           0 :     qh_errexit(qh, qh_ERRqhull, NULL, NULL);
    1597             :   }
    1598           0 : } /* printbegin */
    1599             : 
    1600             : /*-<a                             href="qh-io_r.htm#TOC"
    1601             :   >-------------------------------</a><a name="printcenter">-</a>
    1602             : 
    1603             :   qh_printcenter(qh, fp, string, facet )
    1604             :     print facet->center as centrum or Voronoi center
    1605             :     string may be NULL.  Don't include '%' codes.
    1606             :     nop if qh->CENTERtype neither CENTERvoronoi nor CENTERcentrum
    1607             :     if upper envelope of Delaunay triangulation and point at-infinity
    1608             :       prints qh_INFINITE instead;
    1609             : 
    1610             :   notes:
    1611             :     defines facet->center if needed
    1612             :     if format=PRINTgeom, adds a 0 if would otherwise be 2-d
    1613             :     Same as QhullFacet::printCenter
    1614             : */
    1615           0 : void qh_printcenter(qhT *qh, FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
    1616             :   int k, num;
    1617             : 
    1618           0 :   if (qh->CENTERtype != qh_ASvoronoi && qh->CENTERtype != qh_AScentrum)
    1619           0 :     return;
    1620           0 :   if (string)
    1621           0 :     qh_fprintf(qh, fp, 9066, string);
    1622           0 :   if (qh->CENTERtype == qh_ASvoronoi) {
    1623           0 :     num= qh->hull_dim-1;
    1624           0 :     if (!facet->normal || !facet->upperdelaunay || !qh->ATinfinity) {
    1625           0 :       if (!facet->center)
    1626           0 :         facet->center= qh_facetcenter(qh, facet->vertices);
    1627           0 :       for (k=0; k < num; k++)
    1628           0 :         qh_fprintf(qh, fp, 9067, qh_REAL_1, facet->center[k]);
    1629             :     }else {
    1630           0 :       for (k=0; k < num; k++)
    1631           0 :         qh_fprintf(qh, fp, 9068, qh_REAL_1, qh_INFINITE);
    1632             :     }
    1633             :   }else /* qh.CENTERtype == qh_AScentrum */ {
    1634           0 :     num= qh->hull_dim;
    1635           0 :     if (format == qh_PRINTtriangles && qh->DELAUNAY)
    1636           0 :       num--;
    1637           0 :     if (!facet->center)
    1638           0 :       facet->center= qh_getcentrum(qh, facet);
    1639           0 :     for (k=0; k < num; k++)
    1640           0 :       qh_fprintf(qh, fp, 9069, qh_REAL_1, facet->center[k]);
    1641             :   }
    1642           0 :   if (format == qh_PRINTgeom && num == 2)
    1643           0 :     qh_fprintf(qh, fp, 9070, " 0\n");
    1644             :   else
    1645           0 :     qh_fprintf(qh, fp, 9071, "\n");
    1646             : } /* printcenter */
    1647             : 
    1648             : /*-<a                             href="qh-io_r.htm#TOC"
    1649             :   >-------------------------------</a><a name="printcentrum">-</a>
    1650             : 
    1651             :   qh_printcentrum(qh, fp, facet, radius )
    1652             :     print centrum for a facet in OOGL format
    1653             :     radius defines size of centrum
    1654             :     2-d or 3-d only
    1655             : 
    1656             :   returns:
    1657             :     defines facet->center if needed
    1658             : */
    1659           0 : void qh_printcentrum(qhT *qh, FILE *fp, facetT *facet, realT radius) {
    1660             :   pointT *centrum, *projpt;
    1661           0 :   boolT tempcentrum= False;
    1662           0 :   realT xaxis[4] = {0}, yaxis[4], normal[4] = {0}, dist;
    1663           0 :   realT green[3]={0, 1, 0};
    1664             :   vertexT *apex;
    1665             :   int k;
    1666             : 
    1667           0 :   if (qh->CENTERtype == qh_AScentrum) {
    1668           0 :     if (!facet->center)
    1669           0 :       facet->center= qh_getcentrum(qh, facet);
    1670           0 :     centrum= facet->center;
    1671             :   }else {
    1672           0 :     centrum= qh_getcentrum(qh, facet);
    1673           0 :     tempcentrum= True;
    1674             :   }
    1675           0 :   qh_fprintf(qh, fp, 9072, "{appearance {-normal -edge normscale 0} ");
    1676           0 :   if (qh->firstcentrum) {
    1677           0 :     qh->firstcentrum= False;
    1678           0 :     qh_fprintf(qh, fp, 9073, "{INST geom { define centrum CQUAD  # f%d\n\
    1679             : -0.3 -0.3 0.0001     0 0 1 1\n\
    1680             :  0.3 -0.3 0.0001     0 0 1 1\n\
    1681             :  0.3  0.3 0.0001     0 0 1 1\n\
    1682             : -0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
    1683             :   }else
    1684           0 :     qh_fprintf(qh, fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
    1685           0 :   apex= SETfirstt_(facet->vertices, vertexT);
    1686           0 :   qh_distplane(qh, apex->point, facet, &dist);
    1687           0 :   projpt= qh_projectpoint(qh, apex->point, facet, dist);
    1688           0 :   for (k=qh->hull_dim; k--; ) {
    1689           0 :     xaxis[k]= projpt[k] - centrum[k];
    1690           0 :     normal[k]= facet->normal[k];
    1691             :   }
    1692           0 :   if (qh->hull_dim == 2) {
    1693           0 :     xaxis[2]= 0;
    1694           0 :     normal[2]= 0;
    1695           0 :   }else if (qh->hull_dim == 4) {
    1696           0 :     qh_projectdim3(qh, xaxis, xaxis);
    1697           0 :     qh_projectdim3(qh, normal, normal);
    1698           0 :     qh_normalize2(qh, normal, qh->PRINTdim, True, NULL, NULL);
    1699             :   }
    1700           0 :   qh_crossproduct(3, xaxis, normal, yaxis);
    1701           0 :   qh_fprintf(qh, fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
    1702           0 :   qh_fprintf(qh, fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
    1703           0 :   qh_fprintf(qh, fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
    1704           0 :   qh_printpoint3(qh, fp, centrum);
    1705           0 :   qh_fprintf(qh, fp, 9078, "1 }}}\n");
    1706           0 :   qh_memfree(qh, projpt, qh->normal_size);
    1707           0 :   qh_printpointvect(qh, fp, centrum, facet->normal, NULL, radius, green);
    1708           0 :   if (tempcentrum)
    1709           0 :     qh_memfree(qh, centrum, qh->normal_size);
    1710           0 : } /* printcentrum */
    1711             : 
    1712             : /*-<a                             href="qh-io_r.htm#TOC"
    1713             :   >-------------------------------</a><a name="printend">-</a>
    1714             : 
    1715             :   qh_printend(qh, fp, format )
    1716             :     prints trailer for all output formats
    1717             : 
    1718             :   see:
    1719             :     qh_printbegin() and qh_printafacet()
    1720             : 
    1721             : */
    1722           0 : void qh_printend(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
    1723             :   int num;
    1724             :   facetT *facet, **facetp;
    1725             : 
    1726           0 :   if (!qh->printoutnum)
    1727           0 :     qh_fprintf(qh, qh->ferr, 7055, "qhull warning: no facets printed\n");
    1728           0 :   switch (format) {
    1729           0 :   case qh_PRINTgeom:
    1730           0 :     if (qh->hull_dim == 4 && qh->DROPdim < 0  && !qh->PRINTnoplanes) {
    1731           0 :       qh->visit_id++;
    1732           0 :       num= 0;
    1733           0 :       FORALLfacet_(facetlist)
    1734           0 :         qh_printend4geom(qh, fp, facet,&num, printall);
    1735           0 :       FOREACHfacet_(facets)
    1736           0 :         qh_printend4geom(qh, fp, facet, &num, printall);
    1737           0 :       if (num != qh->ridgeoutnum || qh->printoutvar != qh->ridgeoutnum) {
    1738           0 :         qh_fprintf(qh, qh->ferr, 6069, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh->ridgeoutnum, qh->printoutvar, num);
    1739           0 :         qh_errexit(qh, qh_ERRqhull, NULL, NULL);
    1740             :       }
    1741             :     }else
    1742           0 :       qh_fprintf(qh, fp, 9079, "}\n");
    1743           0 :     break;
    1744           0 :   case qh_PRINTinner:
    1745             :   case qh_PRINTnormals:
    1746             :   case qh_PRINTouter:
    1747           0 :     if (qh->CDDoutput)
    1748           0 :       qh_fprintf(qh, fp, 9080, "end\n");
    1749           0 :     break;
    1750           0 :   case qh_PRINTmaple:
    1751           0 :     qh_fprintf(qh, fp, 9081, "));\n");
    1752           0 :     break;
    1753           0 :   case qh_PRINTmathematica:
    1754           0 :     qh_fprintf(qh, fp, 9082, "}\n");
    1755           0 :     break;
    1756           0 :   case qh_PRINTpoints:
    1757           0 :     if (qh->CDDoutput)
    1758           0 :       qh_fprintf(qh, fp, 9083, "end\n");
    1759           0 :     break;
    1760           0 :   default:
    1761           0 :     break;
    1762             :   }
    1763           0 : } /* printend */
    1764             : 
    1765             : /*-<a                             href="qh-io_r.htm#TOC"
    1766             :   >-------------------------------</a><a name="printend4geom">-</a>
    1767             : 
    1768             :   qh_printend4geom(qh, fp, facet, numridges, printall )
    1769             :     helper function for qh_printbegin/printend
    1770             : 
    1771             :   returns:
    1772             :     number of printed ridges
    1773             : 
    1774             :   notes:
    1775             :     just counts printed ridges if fp=NULL
    1776             :     uses facet->visitid
    1777             :     must agree with qh_printfacet4geom...
    1778             : 
    1779             :   design:
    1780             :     computes color for facet from its normal
    1781             :     prints each ridge of facet
    1782             : */
    1783           0 : void qh_printend4geom(qhT *qh, FILE *fp, facetT *facet, int *nump, boolT printall) {
    1784             :   realT color[3];
    1785           0 :   int i, num= *nump;
    1786             :   facetT *neighbor, **neighborp;
    1787             :   ridgeT *ridge, **ridgep;
    1788             : 
    1789           0 :   if (!printall && qh_skipfacet(qh, facet))
    1790           0 :     return;
    1791           0 :   if (qh->PRINTnoplanes || (facet->visible && qh->NEWfacets))
    1792           0 :     return;
    1793           0 :   if (!facet->normal)
    1794           0 :     return;
    1795           0 :   if (fp) {
    1796           0 :     for (i=0; i < 3; i++) {
    1797           0 :       color[i]= (facet->normal[i]+1.0)/2.0;
    1798           0 :       maximize_(color[i], -1.0);
    1799           0 :       minimize_(color[i], +1.0);
    1800             :     }
    1801             :   }
    1802           0 :   facet->visitid= qh->visit_id;
    1803           0 :   if (facet->simplicial) {
    1804           0 :     FOREACHneighbor_(facet) {
    1805           0 :       if (neighbor->visitid != qh->visit_id) {
    1806           0 :         if (fp)
    1807           0 :           qh_fprintf(qh, fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
    1808           0 :                  3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
    1809             :                  facet->id, neighbor->id);
    1810           0 :         num++;
    1811             :       }
    1812             :     }
    1813             :   }else {
    1814           0 :     FOREACHridge_(facet->ridges) {
    1815           0 :       neighbor= otherfacet_(ridge, facet);
    1816           0 :       if (neighbor->visitid != qh->visit_id) {
    1817           0 :         if (fp)
    1818           0 :           qh_fprintf(qh, fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
    1819           0 :                  3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
    1820             :                  ridge->id, facet->id, neighbor->id);
    1821           0 :         num++;
    1822             :       }
    1823             :     }
    1824             :   }
    1825           0 :   *nump= num;
    1826             : } /* printend4geom */
    1827             : 
    1828             : /*-<a                             href="qh-io_r.htm#TOC"
    1829             :   >-------------------------------</a><a name="printextremes">-</a>
    1830             : 
    1831             :   qh_printextremes(qh, fp, facetlist, facets, printall )
    1832             :     print extreme points for convex hulls or halfspace intersections
    1833             : 
    1834             :   notes:
    1835             :     #points, followed by ids, one per line
    1836             : 
    1837             :     sorted by id
    1838             :     same order as qh_printpoints_out if no coplanar/interior points
    1839             : */
    1840           0 : void qh_printextremes(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
    1841             :   setT *vertices, *points;
    1842             :   pointT *point;
    1843             :   vertexT *vertex, **vertexp;
    1844             :   int id;
    1845           0 :   int numpoints=0, point_i, point_n;
    1846           0 :   int allpoints= qh->num_points + qh_setsize(qh, qh->other_points);
    1847             : 
    1848           0 :   points= qh_settemp(qh, allpoints);
    1849           0 :   qh_setzero(qh, points, 0, allpoints);
    1850           0 :   vertices= qh_facetvertices(qh, facetlist, facets, printall);
    1851           0 :   FOREACHvertex_(vertices) {
    1852           0 :     id= qh_pointid(qh, vertex->point);
    1853           0 :     if (id >= 0) {
    1854           0 :       SETelem_(points, id)= vertex->point;
    1855           0 :       numpoints++;
    1856             :     }
    1857             :   }
    1858           0 :   qh_settempfree(qh, &vertices);
    1859           0 :   qh_fprintf(qh, fp, 9086, "%d\n", numpoints);
    1860           0 :   FOREACHpoint_i_(qh, points) {
    1861           0 :     if (point)
    1862           0 :       qh_fprintf(qh, fp, 9087, "%d\n", point_i);
    1863             :   }
    1864           0 :   qh_settempfree(qh, &points);
    1865           0 : } /* printextremes */
    1866             : 
    1867             : /*-<a                             href="qh-io_r.htm#TOC"
    1868             :   >-------------------------------</a><a name="printextremes_2d">-</a>
    1869             : 
    1870             :   qh_printextremes_2d(qh, fp, facetlist, facets, printall )
    1871             :     prints point ids for facets in qh_ORIENTclock order
    1872             : 
    1873             :   notes:
    1874             :     #points, followed by ids, one per line
    1875             :     if facetlist/facets are disjoint than the output includes skips
    1876             :     errors if facets form a loop
    1877             :     does not print coplanar points
    1878             : */
    1879           0 : void qh_printextremes_2d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
    1880             :   int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
    1881             :   setT *vertices;
    1882             :   facetT *facet, *startfacet, *nextfacet;
    1883             :   vertexT *vertexA, *vertexB;
    1884             : 
    1885           0 :   qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
    1886             :       &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh->visit_id */
    1887           0 :   vertices= qh_facetvertices(qh, facetlist, facets, printall);
    1888           0 :   qh_fprintf(qh, fp, 9088, "%d\n", qh_setsize(qh, vertices));
    1889           0 :   qh_settempfree(qh, &vertices);
    1890           0 :   if (!numfacets)
    1891           0 :     return;
    1892           0 :   facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
    1893           0 :   qh->vertex_visit++;
    1894           0 :   qh->visit_id++;
    1895             :   do {
    1896           0 :     if (facet->toporient ^ qh_ORIENTclock) {
    1897           0 :       vertexA= SETfirstt_(facet->vertices, vertexT);
    1898           0 :       vertexB= SETsecondt_(facet->vertices, vertexT);
    1899           0 :       nextfacet= SETfirstt_(facet->neighbors, facetT);
    1900             :     }else {
    1901           0 :       vertexA= SETsecondt_(facet->vertices, vertexT);
    1902           0 :       vertexB= SETfirstt_(facet->vertices, vertexT);
    1903           0 :       nextfacet= SETsecondt_(facet->neighbors, facetT);
    1904             :     }
    1905           0 :     if (facet->visitid == qh->visit_id) {
    1906           0 :       qh_fprintf(qh, qh->ferr, 6218, "qhull internal error (qh_printextremes_2d): loop in facet list.  facet %d nextfacet %d\n",
    1907             :                  facet->id, nextfacet->id);
    1908           0 :       qh_errexit2(qh, qh_ERRqhull, facet, nextfacet);
    1909             :     }
    1910           0 :     if (facet->visitid) {
    1911           0 :       if (vertexA->visitid != qh->vertex_visit) {
    1912           0 :         vertexA->visitid= qh->vertex_visit;
    1913           0 :         qh_fprintf(qh, fp, 9089, "%d\n", qh_pointid(qh, vertexA->point));
    1914             :       }
    1915           0 :       if (vertexB->visitid != qh->vertex_visit) {
    1916           0 :         vertexB->visitid= qh->vertex_visit;
    1917           0 :         qh_fprintf(qh, fp, 9090, "%d\n", qh_pointid(qh, vertexB->point));
    1918             :       }
    1919             :     }
    1920           0 :     facet->visitid= qh->visit_id;
    1921           0 :     facet= nextfacet;
    1922           0 :   }while (facet && facet != startfacet);
    1923             : } /* printextremes_2d */
    1924             : 
    1925             : /*-<a                             href="qh-io_r.htm#TOC"
    1926             :   >-------------------------------</a><a name="printextremes_d">-</a>
    1927             : 
    1928             :   qh_printextremes_d(qh, fp, facetlist, facets, printall )
    1929             :     print extreme points of input sites for Delaunay triangulations
    1930             : 
    1931             :   notes:
    1932             :     #points, followed by ids, one per line
    1933             : 
    1934             :     unordered
    1935             : */
    1936           0 : void qh_printextremes_d(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
    1937             :   setT *vertices;
    1938             :   vertexT *vertex, **vertexp;
    1939             :   boolT upperseen, lowerseen;
    1940             :   facetT *neighbor, **neighborp;
    1941           0 :   int numpoints=0;
    1942             : 
    1943           0 :   vertices= qh_facetvertices(qh, facetlist, facets, printall);
    1944           0 :   qh_vertexneighbors(qh);
    1945           0 :   FOREACHvertex_(vertices) {
    1946           0 :     upperseen= lowerseen= False;
    1947           0 :     FOREACHneighbor_(vertex) {
    1948           0 :       if (neighbor->upperdelaunay)
    1949           0 :         upperseen= True;
    1950             :       else
    1951           0 :         lowerseen= True;
    1952             :     }
    1953           0 :     if (upperseen && lowerseen) {
    1954           0 :       vertex->seen= True;
    1955           0 :       numpoints++;
    1956             :     }else
    1957           0 :       vertex->seen= False;
    1958             :   }
    1959           0 :   qh_fprintf(qh, fp, 9091, "%d\n", numpoints);
    1960           0 :   FOREACHvertex_(vertices) {
    1961           0 :     if (vertex->seen)
    1962           0 :       qh_fprintf(qh, fp, 9092, "%d\n", qh_pointid(qh, vertex->point));
    1963             :   }
    1964           0 :   qh_settempfree(qh, &vertices);
    1965           0 : } /* printextremes_d */
    1966             : 
    1967             : /*-<a                             href="qh-io_r.htm#TOC"
    1968             :   >-------------------------------</a><a name="printfacet">-</a>
    1969             : 
    1970             :   qh_printfacet(qh, fp, facet )
    1971             :     prints all fields of a facet to fp
    1972             : 
    1973             :   notes:
    1974             :     ridges printed in neighbor order
    1975             : */
    1976           0 : void qh_printfacet(qhT *qh, FILE *fp, facetT *facet) {
    1977             : 
    1978           0 :   qh_printfacetheader(qh, fp, facet);
    1979           0 :   if (facet->ridges)
    1980           0 :     qh_printfacetridges(qh, fp, facet);
    1981           0 : } /* printfacet */
    1982             : 
    1983             : 
    1984             : /*-<a                             href="qh-io_r.htm#TOC"
    1985             :   >-------------------------------</a><a name="printfacet2geom">-</a>
    1986             : 
    1987             :   qh_printfacet2geom(qh, fp, facet, color )
    1988             :     print facet as part of a 2-d VECT for Geomview
    1989             : 
    1990             :     notes:
    1991             :       assume precise calculations in io_r.c with roundoff covered by qh_GEOMepsilon
    1992             :       mindist is calculated within io_r.c.  maxoutside is calculated elsewhere
    1993             :       so a DISTround error may have occurred.
    1994             : */
    1995           0 : void qh_printfacet2geom(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
    1996             :   pointT *point0, *point1;
    1997             :   realT mindist, innerplane, outerplane;
    1998             :   int k;
    1999             : 
    2000           0 :   qh_facet2point(qh, facet, &point0, &point1, &mindist);
    2001           0 :   qh_geomplanes(qh, facet, &outerplane, &innerplane);
    2002           0 :   if (qh->PRINTouter || (!qh->PRINTnoplanes && !qh->PRINTinner))
    2003           0 :     qh_printfacet2geom_points(qh, fp, point0, point1, facet, outerplane, color);
    2004           0 :   if (qh->PRINTinner || (!qh->PRINTnoplanes && !qh->PRINTouter &&
    2005           0 :                 outerplane - innerplane > 2 * qh->MAXabs_coord * qh_GEOMepsilon)) {
    2006           0 :     for (k=3; k--; )
    2007           0 :       color[k]= 1.0 - color[k];
    2008           0 :     qh_printfacet2geom_points(qh, fp, point0, point1, facet, innerplane, color);
    2009             :   }
    2010           0 :   qh_memfree(qh, point1, qh->normal_size);
    2011           0 :   qh_memfree(qh, point0, qh->normal_size);
    2012           0 : } /* printfacet2geom */
    2013             : 
    2014             : /*-<a                             href="qh-io_r.htm#TOC"
    2015             :   >-------------------------------</a><a name="printfacet2geom_points">-</a>
    2016             : 
    2017             :   qh_printfacet2geom_points(qh, fp, point1, point2, facet, offset, color )
    2018             :     prints a 2-d facet as a VECT with 2 points at some offset.
    2019             :     The points are on the facet's plane.
    2020             : */
    2021           0 : void qh_printfacet2geom_points(qhT *qh, FILE *fp, pointT *point1, pointT *point2,
    2022             :                                facetT *facet, realT offset, realT color[3]) {
    2023           0 :   pointT *p1= point1, *p2= point2;
    2024             : 
    2025           0 :   qh_fprintf(qh, fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
    2026           0 :   if (offset != 0.0) {
    2027           0 :     p1= qh_projectpoint(qh, p1, facet, -offset);
    2028           0 :     p2= qh_projectpoint(qh, p2, facet, -offset);
    2029             :   }
    2030           0 :   qh_fprintf(qh, fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
    2031           0 :            p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
    2032           0 :   if (offset != 0.0) {
    2033           0 :     qh_memfree(qh, p1, qh->normal_size);
    2034           0 :     qh_memfree(qh, p2, qh->normal_size);
    2035             :   }
    2036           0 :   qh_fprintf(qh, fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
    2037           0 : } /* printfacet2geom_points */
    2038             : 
    2039             : 
    2040             : /*-<a                             href="qh-io_r.htm#TOC"
    2041             :   >-------------------------------</a><a name="printfacet2math">-</a>
    2042             : 
    2043             :   qh_printfacet2math(qh, fp, facet, format, notfirst )
    2044             :     print 2-d Maple or Mathematica output for a facet
    2045             :     may be non-simplicial
    2046             : 
    2047             :   notes:
    2048             :     use %16.8f since Mathematica 2.2 does not handle exponential format
    2049             :     see qh_printfacet3math
    2050             : */
    2051           0 : void qh_printfacet2math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
    2052             :   pointT *point0, *point1;
    2053             :   realT mindist;
    2054             :   const char *pointfmt;
    2055             : 
    2056           0 :   qh_facet2point(qh, facet, &point0, &point1, &mindist);
    2057           0 :   if (notfirst)
    2058           0 :     qh_fprintf(qh, fp, 9096, ",");
    2059           0 :   if (format == qh_PRINTmaple)
    2060           0 :     pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
    2061             :   else
    2062           0 :     pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
    2063           0 :   qh_fprintf(qh, fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
    2064           0 :   qh_memfree(qh, point1, qh->normal_size);
    2065           0 :   qh_memfree(qh, point0, qh->normal_size);
    2066           0 : } /* printfacet2math */
    2067             : 
    2068             : 
    2069             : /*-<a                             href="qh-io_r.htm#TOC"
    2070             :   >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a>
    2071             : 
    2072             :   qh_printfacet3geom_nonsimplicial(qh, fp, facet, color )
    2073             :     print Geomview OFF for a 3-d nonsimplicial facet.
    2074             :     if DOintersections, prints ridges to unvisited neighbors(qh->visit_id)
    2075             : 
    2076             :   notes
    2077             :     uses facet->visitid for intersections and ridges
    2078             : */
    2079           0 : void qh_printfacet3geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
    2080             :   ridgeT *ridge, **ridgep;
    2081             :   setT *projectedpoints, *vertices;
    2082             :   vertexT *vertex, **vertexp, *vertexA, *vertexB;
    2083             :   pointT *projpt, *point, **pointp;
    2084             :   facetT *neighbor;
    2085             :   realT dist, outerplane, innerplane;
    2086             :   int cntvertices, k;
    2087           0 :   realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
    2088             : 
    2089           0 :   qh_geomplanes(qh, facet, &outerplane, &innerplane);
    2090           0 :   vertices= qh_facet3vertex(qh, facet); /* oriented */
    2091           0 :   cntvertices= qh_setsize(qh, vertices);
    2092           0 :   projectedpoints= qh_settemp(qh, cntvertices);
    2093           0 :   FOREACHvertex_(vertices) {
    2094           0 :     zinc_(Zdistio);
    2095           0 :     qh_distplane(qh, vertex->point, facet, &dist);
    2096           0 :     projpt= qh_projectpoint(qh, vertex->point, facet, dist);
    2097           0 :     qh_setappend(qh, &projectedpoints, projpt);
    2098             :   }
    2099           0 :   if (qh->PRINTouter || (!qh->PRINTnoplanes && !qh->PRINTinner))
    2100           0 :     qh_printfacet3geom_points(qh, fp, projectedpoints, facet, outerplane, color);
    2101           0 :   if (qh->PRINTinner || (!qh->PRINTnoplanes && !qh->PRINTouter &&
    2102           0 :                 outerplane - innerplane > 2 * qh->MAXabs_coord * qh_GEOMepsilon)) {
    2103           0 :     for (k=3; k--; )
    2104           0 :       color[k]= 1.0 - color[k];
    2105           0 :     qh_printfacet3geom_points(qh, fp, projectedpoints, facet, innerplane, color);
    2106             :   }
    2107           0 :   FOREACHpoint_(projectedpoints)
    2108           0 :     qh_memfree(qh, point, qh->normal_size);
    2109           0 :   qh_settempfree(qh, &projectedpoints);
    2110           0 :   qh_settempfree(qh, &vertices);
    2111           0 :   if ((qh->DOintersections || qh->PRINTridges)
    2112           0 :   && (!facet->visible || !qh->NEWfacets)) {
    2113           0 :     facet->visitid= qh->visit_id;
    2114           0 :     FOREACHridge_(facet->ridges) {
    2115           0 :       neighbor= otherfacet_(ridge, facet);
    2116           0 :       if (neighbor->visitid != qh->visit_id) {
    2117           0 :         if (qh->DOintersections)
    2118           0 :           qh_printhyperplaneintersection(qh, fp, facet, neighbor, ridge->vertices, black);
    2119           0 :         if (qh->PRINTridges) {
    2120           0 :           vertexA= SETfirstt_(ridge->vertices, vertexT);
    2121           0 :           vertexB= SETsecondt_(ridge->vertices, vertexT);
    2122           0 :           qh_printline3geom(qh, fp, vertexA->point, vertexB->point, green);
    2123             :         }
    2124             :       }
    2125             :     }
    2126             :   }
    2127           0 : } /* printfacet3geom_nonsimplicial */
    2128             : 
    2129             : /*-<a                             href="qh-io_r.htm#TOC"
    2130             :   >-------------------------------</a><a name="printfacet3geom_points">-</a>
    2131             : 
    2132             :   qh_printfacet3geom_points(qh, fp, points, facet, offset )
    2133             :     prints a 3-d facet as OFF Geomview object.
    2134             :     offset is relative to the facet's hyperplane
    2135             :     Facet is determined as a list of points
    2136             : */
    2137           0 : void qh_printfacet3geom_points(qhT *qh, FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
    2138           0 :   int k, n= qh_setsize(qh, points), i;
    2139             :   pointT *point, **pointp;
    2140             :   setT *printpoints;
    2141             : 
    2142           0 :   qh_fprintf(qh, fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
    2143           0 :   if (offset != 0.0) {
    2144           0 :     printpoints= qh_settemp(qh, n);
    2145           0 :     FOREACHpoint_(points)
    2146           0 :       qh_setappend(qh, &printpoints, qh_projectpoint(qh, point, facet, -offset));
    2147             :   }else
    2148           0 :     printpoints= points;
    2149           0 :   FOREACHpoint_(printpoints) {
    2150           0 :     for (k=0; k < qh->hull_dim; k++) {
    2151           0 :       if (k == qh->DROPdim)
    2152           0 :         qh_fprintf(qh, fp, 9099, "0 ");
    2153             :       else
    2154           0 :         qh_fprintf(qh, fp, 9100, "%8.4g ", point[k]);
    2155             :     }
    2156           0 :     if (printpoints != points)
    2157           0 :       qh_memfree(qh, point, qh->normal_size);
    2158           0 :     qh_fprintf(qh, fp, 9101, "\n");
    2159             :   }
    2160           0 :   if (printpoints != points)
    2161           0 :     qh_settempfree(qh, &printpoints);
    2162           0 :   qh_fprintf(qh, fp, 9102, "%d ", n);
    2163           0 :   for (i=0; i < n; i++)
    2164           0 :     qh_fprintf(qh, fp, 9103, "%d ", i);
    2165           0 :   qh_fprintf(qh, fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
    2166           0 : } /* printfacet3geom_points */
    2167             : 
    2168             : 
    2169             : /*-<a                             href="qh-io_r.htm#TOC"
    2170             :   >-------------------------------</a><a name="printfacet3geom_simplicial">-</a>
    2171             : 
    2172             :   qh_printfacet3geom_simplicial(qh )
    2173             :     print Geomview OFF for a 3-d simplicial facet.
    2174             : 
    2175             :   notes:
    2176             :     may flip color
    2177             :     uses facet->visitid for intersections and ridges
    2178             : 
    2179             :     assume precise calculations in io_r.c with roundoff covered by qh_GEOMepsilon
    2180             :     innerplane may be off by qh->DISTround.  Maxoutside is calculated elsewhere
    2181             :     so a DISTround error may have occurred.
    2182             : */
    2183           0 : void qh_printfacet3geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
    2184             :   setT *points, *vertices;
    2185             :   vertexT *vertex, **vertexp, *vertexA, *vertexB;
    2186             :   facetT *neighbor, **neighborp;
    2187             :   realT outerplane, innerplane;
    2188           0 :   realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
    2189             :   int k;
    2190             : 
    2191           0 :   qh_geomplanes(qh, facet, &outerplane, &innerplane);
    2192           0 :   vertices= qh_facet3vertex(qh, facet);
    2193           0 :   points= qh_settemp(qh, qh->TEMPsize);
    2194           0 :   FOREACHvertex_(vertices)
    2195           0 :     qh_setappend(qh, &points, vertex->point);
    2196           0 :   if (qh->PRINTouter || (!qh->PRINTnoplanes && !qh->PRINTinner))
    2197           0 :     qh_printfacet3geom_points(qh, fp, points, facet, outerplane, color);
    2198           0 :   if (qh->PRINTinner || (!qh->PRINTnoplanes && !qh->PRINTouter &&
    2199           0 :               outerplane - innerplane > 2 * qh->MAXabs_coord * qh_GEOMepsilon)) {
    2200           0 :     for (k=3; k--; )
    2201           0 :       color[k]= 1.0 - color[k];
    2202           0 :     qh_printfacet3geom_points(qh, fp, points, facet, innerplane, color);
    2203             :   }
    2204           0 :   qh_settempfree(qh, &points);
    2205           0 :   qh_settempfree(qh, &vertices);
    2206           0 :   if ((qh->DOintersections || qh->PRINTridges)
    2207           0 :   && (!facet->visible || !qh->NEWfacets)) {
    2208           0 :     facet->visitid= qh->visit_id;
    2209           0 :     FOREACHneighbor_(facet) {
    2210           0 :       if (neighbor->visitid != qh->visit_id) {
    2211           0 :         vertices= qh_setnew_delnthsorted(qh, facet->vertices, qh->hull_dim,
    2212           0 :                           SETindex_(facet->neighbors, neighbor), 0);
    2213           0 :         if (qh->DOintersections)
    2214           0 :            qh_printhyperplaneintersection(qh, fp, facet, neighbor, vertices, black);
    2215           0 :         if (qh->PRINTridges) {
    2216           0 :           vertexA= SETfirstt_(vertices, vertexT);
    2217           0 :           vertexB= SETsecondt_(vertices, vertexT);
    2218           0 :           qh_printline3geom(qh, fp, vertexA->point, vertexB->point, green);
    2219             :         }
    2220           0 :         qh_setfree(qh, &vertices);
    2221             :       }
    2222             :     }
    2223             :   }
    2224           0 : } /* printfacet3geom_simplicial */
    2225             : 
    2226             : /*-<a                             href="qh-io_r.htm#TOC"
    2227             :   >-------------------------------</a><a name="printfacet3math">-</a>
    2228             : 
    2229             :   qh_printfacet3math(qh, fp, facet, notfirst )
    2230             :     print 3-d Maple or Mathematica output for a facet
    2231             : 
    2232             :   notes:
    2233             :     may be non-simplicial
    2234             :     use %16.8f since Mathematica 2.2 does not handle exponential format
    2235             :     see qh_printfacet2math
    2236             : */
    2237           0 : void qh_printfacet3math(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
    2238             :   vertexT *vertex, **vertexp;
    2239             :   setT *points, *vertices;
    2240             :   pointT *point, **pointp;
    2241           0 :   boolT firstpoint= True;
    2242             :   realT dist;
    2243             :   const char *pointfmt, *endfmt;
    2244             : 
    2245           0 :   if (notfirst)
    2246           0 :     qh_fprintf(qh, fp, 9105, ",\n");
    2247           0 :   vertices= qh_facet3vertex(qh, facet);
    2248           0 :   points= qh_settemp(qh, qh_setsize(qh, vertices));
    2249           0 :   FOREACHvertex_(vertices) {
    2250           0 :     zinc_(Zdistio);
    2251           0 :     qh_distplane(qh, vertex->point, facet, &dist);
    2252           0 :     point= qh_projectpoint(qh, vertex->point, facet, dist);
    2253           0 :     qh_setappend(qh, &points, point);
    2254             :   }
    2255           0 :   if (format == qh_PRINTmaple) {
    2256           0 :     qh_fprintf(qh, fp, 9106, "[");
    2257           0 :     pointfmt= "[%16.8f, %16.8f, %16.8f]";
    2258           0 :     endfmt= "]";
    2259             :   }else {
    2260           0 :     qh_fprintf(qh, fp, 9107, "Polygon[{");
    2261           0 :     pointfmt= "{%16.8f, %16.8f, %16.8f}";
    2262           0 :     endfmt= "}]";
    2263             :   }
    2264           0 :   FOREACHpoint_(points) {
    2265           0 :     if (firstpoint)
    2266           0 :       firstpoint= False;
    2267             :     else
    2268           0 :       qh_fprintf(qh, fp, 9108, ",\n");
    2269           0 :     qh_fprintf(qh, fp, 9109, pointfmt, point[0], point[1], point[2]);
    2270             :   }
    2271           0 :   FOREACHpoint_(points)
    2272           0 :     qh_memfree(qh, point, qh->normal_size);
    2273           0 :   qh_settempfree(qh, &points);
    2274           0 :   qh_settempfree(qh, &vertices);
    2275           0 :   qh_fprintf(qh, fp, 9110, "%s", endfmt);
    2276           0 : } /* printfacet3math */
    2277             : 
    2278             : 
    2279             : /*-<a                             href="qh-io_r.htm#TOC"
    2280             :   >-------------------------------</a><a name="printfacet3vertex">-</a>
    2281             : 
    2282             :   qh_printfacet3vertex(qh, fp, facet, format )
    2283             :     print vertices in a 3-d facet as point ids
    2284             : 
    2285             :   notes:
    2286             :     prints number of vertices first if format == qh_PRINToff
    2287             :     the facet may be non-simplicial
    2288             : */
    2289           0 : void qh_printfacet3vertex(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format) {
    2290             :   vertexT *vertex, **vertexp;
    2291             :   setT *vertices;
    2292             : 
    2293           0 :   vertices= qh_facet3vertex(qh, facet);
    2294           0 :   if (format == qh_PRINToff)
    2295           0 :     qh_fprintf(qh, fp, 9111, "%d ", qh_setsize(qh, vertices));
    2296           0 :   FOREACHvertex_(vertices)
    2297           0 :     qh_fprintf(qh, fp, 9112, "%d ", qh_pointid(qh, vertex->point));
    2298           0 :   qh_fprintf(qh, fp, 9113, "\n");
    2299           0 :   qh_settempfree(qh, &vertices);
    2300           0 : } /* printfacet3vertex */
    2301             : 
    2302             : 
    2303             : /*-<a                             href="qh-io_r.htm#TOC"
    2304             :   >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a>
    2305             : 
    2306             :   qh_printfacet4geom_nonsimplicial(qh )
    2307             :     print Geomview 4OFF file for a 4d nonsimplicial facet
    2308             :     prints all ridges to unvisited neighbors (qh.visit_id)
    2309             :     if qh.DROPdim
    2310             :       prints in OFF format
    2311             : 
    2312             :   notes:
    2313             :     must agree with printend4geom()
    2314             : */
    2315           0 : void qh_printfacet4geom_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
    2316             :   facetT *neighbor;
    2317             :   ridgeT *ridge, **ridgep;
    2318             :   vertexT *vertex, **vertexp;
    2319             :   pointT *point;
    2320             :   int k;
    2321             :   realT dist;
    2322             : 
    2323           0 :   facet->visitid= qh->visit_id;
    2324           0 :   if (qh->PRINTnoplanes || (facet->visible && qh->NEWfacets))
    2325           0 :     return;
    2326           0 :   FOREACHridge_(facet->ridges) {
    2327           0 :     neighbor= otherfacet_(ridge, facet);
    2328           0 :     if (neighbor->visitid == qh->visit_id)
    2329           0 :       continue;
    2330           0 :     if (qh->PRINTtransparent && !neighbor->good)
    2331           0 :       continue;
    2332           0 :     if (qh->DOintersections)
    2333           0 :       qh_printhyperplaneintersection(qh, fp, facet, neighbor, ridge->vertices, color);
    2334             :     else {
    2335           0 :       if (qh->DROPdim >= 0)
    2336           0 :         qh_fprintf(qh, fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
    2337             :       else {
    2338           0 :         qh->printoutvar++;
    2339           0 :         qh_fprintf(qh, fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
    2340             :       }
    2341           0 :       FOREACHvertex_(ridge->vertices) {
    2342           0 :         zinc_(Zdistio);
    2343           0 :         qh_distplane(qh, vertex->point,facet, &dist);
    2344           0 :         point=qh_projectpoint(qh, vertex->point,facet, dist);
    2345           0 :         for (k=0; k < qh->hull_dim; k++) {
    2346           0 :           if (k != qh->DROPdim)
    2347           0 :             qh_fprintf(qh, fp, 9116, "%8.4g ", point[k]);
    2348             :         }
    2349           0 :         qh_fprintf(qh, fp, 9117, "\n");
    2350           0 :         qh_memfree(qh, point, qh->normal_size);
    2351             :       }
    2352           0 :       if (qh->DROPdim >= 0)
    2353           0 :         qh_fprintf(qh, fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
    2354             :     }
    2355             :   }
    2356             : } /* printfacet4geom_nonsimplicial */
    2357             : 
    2358             : 
    2359             : /*-<a                             href="qh-io_r.htm#TOC"
    2360             :   >-------------------------------</a><a name="printfacet4geom_simplicial">-</a>
    2361             : 
    2362             :   qh_printfacet4geom_simplicial(qh, fp, facet, color )
    2363             :     print Geomview 4OFF file for a 4d simplicial facet
    2364             :     prints triangles for unvisited neighbors (qh.visit_id)
    2365             : 
    2366             :   notes:
    2367             :     must agree with printend4geom()
    2368             : */
    2369           0 : void qh_printfacet4geom_simplicial(qhT *qh, FILE *fp, facetT *facet, realT color[3]) {
    2370             :   setT *vertices;
    2371             :   facetT *neighbor, **neighborp;
    2372             :   vertexT *vertex, **vertexp;
    2373             :   int k;
    2374             : 
    2375           0 :   facet->visitid= qh->visit_id;
    2376           0 :   if (qh->PRINTnoplanes || (facet->visible && qh->NEWfacets))
    2377           0 :     return;
    2378           0 :   FOREACHneighbor_(facet) {
    2379           0 :     if (neighbor->visitid == qh->visit_id)
    2380           0 :       continue;
    2381           0 :     if (qh->PRINTtransparent && !neighbor->good)
    2382           0 :       continue;
    2383           0 :     vertices= qh_setnew_delnthsorted(qh, facet->vertices, qh->hull_dim,
    2384           0 :                           SETindex_(facet->neighbors, neighbor), 0);
    2385           0 :     if (qh->DOintersections)
    2386           0 :       qh_printhyperplaneintersection(qh, fp, facet, neighbor, vertices, color);
    2387             :     else {
    2388           0 :       if (qh->DROPdim >= 0)
    2389           0 :         qh_fprintf(qh, fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
    2390             :                 facet->id, neighbor->id);
    2391             :       else {
    2392           0 :         qh->printoutvar++;
    2393           0 :         qh_fprintf(qh, fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
    2394             :       }
    2395           0 :       FOREACHvertex_(vertices) {
    2396           0 :         for (k=0; k < qh->hull_dim; k++) {
    2397           0 :           if (k != qh->DROPdim)
    2398           0 :             qh_fprintf(qh, fp, 9121, "%8.4g ", vertex->point[k]);
    2399             :         }
    2400           0 :         qh_fprintf(qh, fp, 9122, "\n");
    2401             :       }
    2402           0 :       if (qh->DROPdim >= 0)
    2403           0 :         qh_fprintf(qh, fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
    2404             :     }
    2405           0 :     qh_setfree(qh, &vertices);
    2406             :   }
    2407             : } /* printfacet4geom_simplicial */
    2408             : 
    2409             : 
    2410             : /*-<a                             href="qh-io_r.htm#TOC"
    2411             :   >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a>
    2412             : 
    2413             :   qh_printfacetNvertex_nonsimplicial(qh, fp, facet, id, format )
    2414             :     print vertices for an N-d non-simplicial facet
    2415             :     triangulates each ridge to the id
    2416             : */
    2417           0 : void qh_printfacetNvertex_nonsimplicial(qhT *qh, FILE *fp, facetT *facet, int id, qh_PRINT format) {
    2418             :   vertexT *vertex, **vertexp;
    2419             :   ridgeT *ridge, **ridgep;
    2420             : 
    2421           0 :   if (facet->visible && qh->NEWfacets)
    2422           0 :     return;
    2423           0 :   FOREACHridge_(facet->ridges) {
    2424           0 :     if (format == qh_PRINTtriangles)
    2425           0 :       qh_fprintf(qh, fp, 9124, "%d ", qh->hull_dim);
    2426           0 :     qh_fprintf(qh, fp, 9125, "%d ", id);
    2427           0 :     if ((ridge->top == facet) ^ qh_ORIENTclock) {
    2428           0 :       FOREACHvertex_(ridge->vertices)
    2429           0 :         qh_fprintf(qh, fp, 9126, "%d ", qh_pointid(qh, vertex->point));
    2430             :     }else {
    2431           0 :       FOREACHvertexreverse12_(ridge->vertices)
    2432           0 :         qh_fprintf(qh, fp, 9127, "%d ", qh_pointid(qh, vertex->point));
    2433             :     }
    2434           0 :     qh_fprintf(qh, fp, 9128, "\n");
    2435             :   }
    2436             : } /* printfacetNvertex_nonsimplicial */
    2437             : 
    2438             : 
    2439             : /*-<a                             href="qh-io_r.htm#TOC"
    2440             :   >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a>
    2441             : 
    2442             :   qh_printfacetNvertex_simplicial(qh, fp, facet, format )
    2443             :     print vertices for an N-d simplicial facet
    2444             :     prints vertices for non-simplicial facets
    2445             :       2-d facets (orientation preserved by qh_mergefacet2d)
    2446             :       PRINToff ('o') for 4-d and higher
    2447             : */
    2448           0 : void qh_printfacetNvertex_simplicial(qhT *qh, FILE *fp, facetT *facet, qh_PRINT format) {
    2449             :   vertexT *vertex, **vertexp;
    2450             : 
    2451           0 :   if (format == qh_PRINToff || format == qh_PRINTtriangles)
    2452           0 :     qh_fprintf(qh, fp, 9129, "%d ", qh_setsize(qh, facet->vertices));
    2453           0 :   if ((facet->toporient ^ qh_ORIENTclock)
    2454           0 :   || (qh->hull_dim > 2 && !facet->simplicial)) {
    2455           0 :     FOREACHvertex_(facet->vertices)
    2456           0 :       qh_fprintf(qh, fp, 9130, "%d ", qh_pointid(qh, vertex->point));
    2457             :   }else {
    2458           0 :     FOREACHvertexreverse12_(facet->vertices)
    2459           0 :       qh_fprintf(qh, fp, 9131, "%d ", qh_pointid(qh, vertex->point));
    2460             :   }
    2461           0 :   qh_fprintf(qh, fp, 9132, "\n");
    2462           0 : } /* printfacetNvertex_simplicial */
    2463             : 
    2464             : 
    2465             : /*-<a                             href="qh-io_r.htm#TOC"
    2466             :   >-------------------------------</a><a name="printfacetheader">-</a>
    2467             : 
    2468             :   qh_printfacetheader(qh, fp, facet )
    2469             :     prints header fields of a facet to fp
    2470             : 
    2471             :   notes:
    2472             :     for 'f' output and debugging
    2473             :     Same as QhullFacet::printHeader()
    2474             : */
    2475           0 : void qh_printfacetheader(qhT *qh, FILE *fp, facetT *facet) {
    2476             :   pointT *point, **pointp, *furthest;
    2477             :   facetT *neighbor, **neighborp;
    2478             :   realT dist;
    2479             : 
    2480           0 :   if (facet == qh_MERGEridge) {
    2481           0 :     qh_fprintf(qh, fp, 9133, " MERGEridge\n");
    2482           0 :     return;
    2483           0 :   }else if (facet == qh_DUPLICATEridge) {
    2484           0 :     qh_fprintf(qh, fp, 9134, " DUPLICATEridge\n");
    2485           0 :     return;
    2486           0 :   }else if (!facet) {
    2487           0 :     qh_fprintf(qh, fp, 9135, " NULLfacet\n");
    2488           0 :     return;
    2489             :   }
    2490           0 :   qh->old_randomdist= qh->RANDOMdist;
    2491           0 :   qh->RANDOMdist= False;
    2492           0 :   qh_fprintf(qh, fp, 9136, "- f%d\n", facet->id);
    2493           0 :   qh_fprintf(qh, fp, 9137, "    - flags:");
    2494           0 :   if (facet->toporient)
    2495           0 :     qh_fprintf(qh, fp, 9138, " top");
    2496             :   else
    2497           0 :     qh_fprintf(qh, fp, 9139, " bottom");
    2498           0 :   if (facet->simplicial)
    2499           0 :     qh_fprintf(qh, fp, 9140, " simplicial");
    2500           0 :   if (facet->tricoplanar)
    2501           0 :     qh_fprintf(qh, fp, 9141, " tricoplanar");
    2502           0 :   if (facet->upperdelaunay)
    2503           0 :     qh_fprintf(qh, fp, 9142, " upperDelaunay");
    2504           0 :   if (facet->visible)
    2505           0 :     qh_fprintf(qh, fp, 9143, " visible");
    2506           0 :   if (facet->newfacet)
    2507           0 :     qh_fprintf(qh, fp, 9144, " newfacet");
    2508           0 :   if (facet->tested)
    2509           0 :     qh_fprintf(qh, fp, 9145, " tested");
    2510           0 :   if (!facet->good)
    2511           0 :     qh_fprintf(qh, fp, 9146, " notG");
    2512           0 :   if (facet->seen && qh->IStracing)
    2513           0 :     qh_fprintf(qh, fp, 9147, " seen");
    2514           0 :   if (facet->seen2 && qh->IStracing)
    2515           0 :     qh_fprintf(qh, fp, 9418, " seen2");
    2516           0 :   if (facet->isarea)
    2517           0 :     qh_fprintf(qh, fp, 9419, " isarea");
    2518           0 :   if (facet->coplanarhorizon)
    2519           0 :     qh_fprintf(qh, fp, 9148, " coplanarhorizon");
    2520           0 :   if (facet->mergehorizon)
    2521           0 :     qh_fprintf(qh, fp, 9149, " mergehorizon");
    2522           0 :   if (facet->cycledone)
    2523           0 :     qh_fprintf(qh, fp, 9420, " cycledone");
    2524           0 :   if (facet->keepcentrum)
    2525           0 :     qh_fprintf(qh, fp, 9150, " keepcentrum");
    2526           0 :   if (facet->dupridge)
    2527           0 :     qh_fprintf(qh, fp, 9151, " dupridge");
    2528           0 :   if (facet->mergeridge && !facet->mergeridge2)
    2529           0 :     qh_fprintf(qh, fp, 9152, " mergeridge1");
    2530           0 :   if (facet->mergeridge2)
    2531           0 :     qh_fprintf(qh, fp, 9153, " mergeridge2");
    2532           0 :   if (facet->newmerge)
    2533           0 :     qh_fprintf(qh, fp, 9154, " newmerge");
    2534           0 :   if (facet->flipped)
    2535           0 :     qh_fprintf(qh, fp, 9155, " flipped");
    2536           0 :   if (facet->notfurthest)
    2537           0 :     qh_fprintf(qh, fp, 9156, " notfurthest");
    2538           0 :   if (facet->degenerate)
    2539           0 :     qh_fprintf(qh, fp, 9157, " degenerate");
    2540           0 :   if (facet->redundant)
    2541           0 :     qh_fprintf(qh, fp, 9158, " redundant");
    2542           0 :   qh_fprintf(qh, fp, 9159, "\n");
    2543           0 :   if (facet->isarea)
    2544           0 :     qh_fprintf(qh, fp, 9160, "    - area: %2.2g\n", facet->f.area);
    2545           0 :   else if (qh->NEWfacets && facet->visible && facet->f.replace)
    2546           0 :     qh_fprintf(qh, fp, 9161, "    - replacement: f%d\n", facet->f.replace->id);
    2547           0 :   else if (facet->newfacet) {
    2548           0 :     if (facet->f.samecycle && facet->f.samecycle != facet)
    2549           0 :       qh_fprintf(qh, fp, 9162, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
    2550           0 :   }else if (facet->tricoplanar /* !isarea */) {
    2551           0 :     if (facet->f.triowner)
    2552           0 :       qh_fprintf(qh, fp, 9163, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
    2553           0 :   }else if (facet->f.newcycle)
    2554           0 :     qh_fprintf(qh, fp, 9164, "    - was horizon to f%d\n", facet->f.newcycle->id);
    2555           0 :   if (facet->nummerge == qh_MAXnummerge)
    2556           0 :     qh_fprintf(qh, fp, 9427, "    - merges: %dmax\n", qh_MAXnummerge);
    2557           0 :   else if (facet->nummerge)
    2558           0 :     qh_fprintf(qh, fp, 9165, "    - merges: %d\n", facet->nummerge);
    2559           0 :   qh_printpointid(qh, fp, "    - normal: ", qh->hull_dim, facet->normal, qh_IDunknown);
    2560           0 :   qh_fprintf(qh, fp, 9166, "    - offset: %10.7g\n", facet->offset);
    2561           0 :   if (qh->CENTERtype == qh_ASvoronoi || facet->center)
    2562           0 :     qh_printcenter(qh, fp, qh_PRINTfacets, "    - center: ", facet);
    2563             : #if qh_MAXoutside
    2564           0 :   if (facet->maxoutside > qh->DISTround) /* initial value */
    2565           0 :     qh_fprintf(qh, fp, 9167, "    - maxoutside: %10.7g\n", facet->maxoutside);
    2566             : #endif
    2567           0 :   if (!SETempty_(facet->outsideset)) {
    2568           0 :     furthest= (pointT *)qh_setlast(facet->outsideset);
    2569           0 :     if (qh_setsize(qh, facet->outsideset) < 6) {
    2570           0 :       qh_fprintf(qh, fp, 9168, "    - outside set(furthest p%d):\n", qh_pointid(qh, furthest));
    2571           0 :       FOREACHpoint_(facet->outsideset)
    2572           0 :         qh_printpoint(qh, fp, "     ", point);
    2573           0 :     }else if (qh_setsize(qh, facet->outsideset) < 21) {
    2574           0 :       qh_printpoints(qh, fp, "    - outside set:", facet->outsideset);
    2575             :     }else {
    2576           0 :       qh_fprintf(qh, fp, 9169, "    - outside set:  %d points.", qh_setsize(qh, facet->outsideset));
    2577           0 :       qh_printpoint(qh, fp, "  Furthest", furthest);
    2578             :     }
    2579             : #if !qh_COMPUTEfurthest
    2580           0 :     qh_fprintf(qh, fp, 9170, "    - furthest distance= %2.2g\n", facet->furthestdist);
    2581             : #endif
    2582             :   }
    2583           0 :   if (!SETempty_(facet->coplanarset)) {
    2584           0 :     furthest= (pointT *)qh_setlast(facet->coplanarset);
    2585           0 :     if (qh_setsize(qh, facet->coplanarset) < 6) {
    2586           0 :       qh_fprintf(qh, fp, 9171, "    - coplanar set(furthest p%d):\n", qh_pointid(qh, furthest));
    2587           0 :       FOREACHpoint_(facet->coplanarset)
    2588           0 :         qh_printpoint(qh, fp, "     ", point);
    2589           0 :     }else if (qh_setsize(qh, facet->coplanarset) < 21) {
    2590           0 :       qh_printpoints(qh, fp, "    - coplanar set:", facet->coplanarset);
    2591             :     }else {
    2592           0 :       qh_fprintf(qh, fp, 9172, "    - coplanar set:  %d points.", qh_setsize(qh, facet->coplanarset));
    2593           0 :       qh_printpoint(qh, fp, "  Furthest", furthest);
    2594             :     }
    2595           0 :     zinc_(Zdistio);
    2596           0 :     qh_distplane(qh, furthest, facet, &dist);
    2597           0 :     qh_fprintf(qh, fp, 9173, "      furthest distance= %2.2g\n", dist);
    2598             :   }
    2599           0 :   qh_printvertices(qh, fp, "    - vertices:", facet->vertices);
    2600           0 :   qh_fprintf(qh, fp, 9174, "    - neighboring facets:");
    2601           0 :   FOREACHneighbor_(facet) {
    2602           0 :     if (neighbor == qh_MERGEridge)
    2603           0 :       qh_fprintf(qh, fp, 9175, " MERGEridge");
    2604           0 :     else if (neighbor == qh_DUPLICATEridge)
    2605           0 :       qh_fprintf(qh, fp, 9176, " DUPLICATEridge");
    2606             :     else
    2607           0 :       qh_fprintf(qh, fp, 9177, " f%d", neighbor->id);
    2608             :   }
    2609           0 :   qh_fprintf(qh, fp, 9178, "\n");
    2610           0 :   qh->RANDOMdist= qh->old_randomdist;
    2611             : } /* printfacetheader */
    2612             : 
    2613             : 
    2614             : /*-<a                             href="qh-io_r.htm#TOC"
    2615             :   >-------------------------------</a><a name="printfacetridges">-</a>
    2616             : 
    2617             :   qh_printfacetridges(qh, fp, facet )
    2618             :     prints ridges of a facet to fp
    2619             : 
    2620             :   notes:
    2621             :     ridges printed in neighbor order
    2622             :     assumes the ridges exist
    2623             :     for 'f' output
    2624             :     same as QhullFacet::printRidges
    2625             : */
    2626           0 : void qh_printfacetridges(qhT *qh, FILE *fp, facetT *facet) {
    2627             :   facetT *neighbor, **neighborp;
    2628             :   ridgeT *ridge, **ridgep;
    2629           0 :   int numridges= 0;
    2630             :   int n;
    2631             : 
    2632           0 :   if (facet->visible && qh->NEWfacets) {
    2633           0 :     qh_fprintf(qh, fp, 9179, "    - ridges (tentative ids):");
    2634           0 :     FOREACHridge_(facet->ridges)
    2635           0 :       qh_fprintf(qh, fp, 9180, " r%d", ridge->id);
    2636           0 :     qh_fprintf(qh, fp, 9181, "\n");
    2637             :   }else {
    2638           0 :     qh_fprintf(qh, fp, 9182, "    - ridges:\n");
    2639           0 :     FOREACHridge_(facet->ridges)
    2640           0 :       ridge->seen= False;
    2641           0 :     if (qh->hull_dim == 3) {
    2642           0 :       ridge= SETfirstt_(facet->ridges, ridgeT);
    2643           0 :       while (ridge && !ridge->seen) {
    2644           0 :         ridge->seen= True;
    2645           0 :         qh_printridge(qh, fp, ridge);
    2646           0 :         numridges++;
    2647           0 :         ridge= qh_nextridge3d(ridge, facet, NULL);
    2648             :         }
    2649             :     }else {
    2650           0 :       FOREACHneighbor_(facet) {
    2651           0 :         FOREACHridge_(facet->ridges) {
    2652           0 :           if (otherfacet_(ridge, facet) == neighbor && !ridge->seen) {
    2653           0 :             ridge->seen= True;
    2654           0 :             qh_printridge(qh, fp, ridge);
    2655           0 :             numridges++;
    2656             :           }
    2657             :         }
    2658             :       }
    2659             :     }
    2660           0 :     n= qh_setsize(qh, facet->ridges);
    2661           0 :     if (n == 1 && facet->newfacet && qh->NEWtentative) {
    2662           0 :       qh_fprintf(qh, fp, 9411, "     - horizon ridge to visible facet\n");
    2663             :     }
    2664           0 :     if (numridges != n) {
    2665           0 :       qh_fprintf(qh, fp, 9183, "     - all ridges:");
    2666           0 :       FOREACHridge_(facet->ridges)
    2667           0 :         qh_fprintf(qh, fp, 9184, " r%d", ridge->id);
    2668           0 :       qh_fprintf(qh, fp, 9185, "\n");
    2669             :     }
    2670             :     /* non-3d ridges w/o non-simplicial neighbors */
    2671           0 :     FOREACHridge_(facet->ridges) {
    2672           0 :       if (!ridge->seen)
    2673           0 :         qh_printridge(qh, fp, ridge);
    2674             :     }
    2675             :   }
    2676           0 : } /* printfacetridges */
    2677             : 
    2678             : /*-<a                             href="qh-io_r.htm#TOC"
    2679             :   >-------------------------------</a><a name="printfacets">-</a>
    2680             : 
    2681             :   qh_printfacets(qh, fp, format, facetlist, facets, printall )
    2682             :     prints facetlist and/or facet set in output format
    2683             : 
    2684             :   notes:
    2685             :     also used for specialized formats ('FO' and summary)
    2686             :     turns off 'Rn' option since want actual numbers
    2687             : */
    2688           0 : void qh_printfacets(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
    2689             :   int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
    2690             :   facetT *facet, **facetp;
    2691             :   setT *vertices;
    2692             :   coordT *center;
    2693             :   realT outerplane, innerplane;
    2694             : 
    2695           0 :   qh->old_randomdist= qh->RANDOMdist;
    2696           0 :   qh->RANDOMdist= False;
    2697           0 :   if (qh->CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
    2698           0 :     qh_fprintf(qh, qh->ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
    2699           0 :   if (format == qh_PRINTnone)
    2700             :     ; /* print nothing */
    2701           0 :   else if (format == qh_PRINTaverage) {
    2702           0 :     vertices= qh_facetvertices(qh, facetlist, facets, printall);
    2703           0 :     center= qh_getcenter(qh, vertices);
    2704           0 :     qh_fprintf(qh, fp, 9186, "%d 1\n", qh->hull_dim);
    2705           0 :     qh_printpointid(qh, fp, NULL, qh->hull_dim, center, qh_IDunknown);
    2706           0 :     qh_memfree(qh, center, qh->normal_size);
    2707           0 :     qh_settempfree(qh, &vertices);
    2708           0 :   }else if (format == qh_PRINTextremes) {
    2709           0 :     if (qh->DELAUNAY)
    2710           0 :       qh_printextremes_d(qh, fp, facetlist, facets, printall);
    2711           0 :     else if (qh->hull_dim == 2)
    2712           0 :       qh_printextremes_2d(qh, fp, facetlist, facets, printall);
    2713             :     else
    2714           0 :       qh_printextremes(qh, fp, facetlist, facets, printall);
    2715           0 :   }else if (format == qh_PRINToptions)
    2716           0 :     qh_fprintf(qh, fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh->qhull_options);
    2717           0 :   else if (format == qh_PRINTpoints && !qh->VORONOI)
    2718           0 :     qh_printpoints_out(qh, fp, facetlist, facets, printall);
    2719           0 :   else if (format == qh_PRINTqhull)
    2720           0 :     qh_fprintf(qh, fp, 9188, "%s | %s\n", qh->rbox_command, qh->qhull_command);
    2721           0 :   else if (format == qh_PRINTsize) {
    2722           0 :     qh_fprintf(qh, fp, 9189, "0\n2 ");
    2723           0 :     qh_fprintf(qh, fp, 9190, qh_REAL_1, qh->totarea);
    2724           0 :     qh_fprintf(qh, fp, 9191, qh_REAL_1, qh->totvol);
    2725           0 :     qh_fprintf(qh, fp, 9192, "\n");
    2726           0 :   }else if (format == qh_PRINTsummary) {
    2727           0 :     qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
    2728             :       &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
    2729           0 :     vertices= qh_facetvertices(qh, facetlist, facets, printall);
    2730           0 :     qh_fprintf(qh, fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh->hull_dim,
    2731           0 :                 qh->num_points + qh_setsize(qh, qh->other_points),
    2732           0 :                 qh->num_vertices, qh->num_facets - qh->num_visible,
    2733             :                 qh_setsize(qh, vertices), numfacets, numcoplanars,
    2734             :                 numfacets - numsimplicial, zzval_(Zdelvertextot),
    2735             :                 numtricoplanars);
    2736           0 :     qh_settempfree(qh, &vertices);
    2737           0 :     qh_outerinner(qh, NULL, &outerplane, &innerplane);
    2738           0 :     qh_fprintf(qh, fp, 9194, qh_REAL_2n, outerplane, innerplane);
    2739           0 :   }else if (format == qh_PRINTvneighbors)
    2740           0 :     qh_printvneighbors(qh, fp, facetlist, facets, printall);
    2741           0 :   else if (qh->VORONOI && format == qh_PRINToff)
    2742           0 :     qh_printvoronoi(qh, fp, format, facetlist, facets, printall);
    2743           0 :   else if (qh->VORONOI && format == qh_PRINTgeom) {
    2744           0 :     qh_printbegin(qh, fp, format, facetlist, facets, printall);
    2745           0 :     qh_printvoronoi(qh, fp, format, facetlist, facets, printall);
    2746           0 :     qh_printend(qh, fp, format, facetlist, facets, printall);
    2747           0 :   }else if (qh->VORONOI
    2748           0 :   && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
    2749           0 :     qh_printvdiagram(qh, fp, format, facetlist, facets, printall);
    2750             :   else {
    2751           0 :     qh_printbegin(qh, fp, format, facetlist, facets, printall);
    2752           0 :     FORALLfacet_(facetlist)
    2753           0 :       qh_printafacet(qh, fp, format, facet, printall);
    2754           0 :     FOREACHfacet_(facets)
    2755           0 :       qh_printafacet(qh, fp, format, facet, printall);
    2756           0 :     qh_printend(qh, fp, format, facetlist, facets, printall);
    2757             :   }
    2758           0 :   qh->RANDOMdist= qh->old_randomdist;
    2759           0 : } /* printfacets */
    2760             : 
    2761             : 
    2762             : /*-<a                             href="qh-io_r.htm#TOC"
    2763             :   >-------------------------------</a><a name="printhyperplaneintersection">-</a>
    2764             : 
    2765             :   qh_printhyperplaneintersection(qh, fp, facet1, facet2, vertices, color )
    2766             :     print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
    2767             : */
    2768           0 : void qh_printhyperplaneintersection(qhT *qh, FILE *fp, facetT *facet1, facetT *facet2,
    2769             :                    setT *vertices, realT color[3]) {
    2770             :   realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
    2771             :   vertexT *vertex, **vertexp;
    2772             :   int i, k;
    2773             :   boolT nearzero1, nearzero2;
    2774             : 
    2775           0 :   costheta= qh_getangle(qh, facet1->normal, facet2->normal);
    2776           0 :   denominator= 1 - costheta * costheta;
    2777           0 :   i= qh_setsize(qh, vertices);
    2778           0 :   if (qh->hull_dim == 3)
    2779           0 :     qh_fprintf(qh, fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
    2780           0 :   else if (qh->hull_dim == 4 && qh->DROPdim >= 0)
    2781           0 :     qh_fprintf(qh, fp, 9196, "OFF 3 1 1 ");
    2782             :   else
    2783           0 :     qh->printoutvar++;
    2784           0 :   qh_fprintf(qh, fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
    2785           0 :   mindenom= 1 / (10.0 * qh->MAXabs_coord);
    2786           0 :   FOREACHvertex_(vertices) {
    2787           0 :     zadd_(Zdistio, 2);
    2788           0 :     qh_distplane(qh, vertex->point, facet1, &dist1);
    2789           0 :     qh_distplane(qh, vertex->point, facet2, &dist2);
    2790           0 :     s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
    2791           0 :     t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
    2792           0 :     if (nearzero1 || nearzero2)
    2793           0 :       s= t= 0.0;
    2794           0 :     for (k=qh->hull_dim; k--; )
    2795           0 :       p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
    2796           0 :     if (qh->PRINTdim <= 3) {
    2797           0 :       qh_projectdim3(qh, p, p);
    2798           0 :       qh_fprintf(qh, fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
    2799             :     }else
    2800           0 :       qh_fprintf(qh, fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
    2801           0 :     if (nearzero1+nearzero2)
    2802           0 :       qh_fprintf(qh, fp, 9200, "p%d(coplanar facets)\n", qh_pointid(qh, vertex->point));
    2803             :     else
    2804           0 :       qh_fprintf(qh, fp, 9201, "projected p%d\n", qh_pointid(qh, vertex->point));
    2805             :   }
    2806           0 :   if (qh->hull_dim == 3)
    2807           0 :     qh_fprintf(qh, fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
    2808           0 :   else if (qh->hull_dim == 4 && qh->DROPdim >= 0)
    2809           0 :     qh_fprintf(qh, fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
    2810           0 : } /* printhyperplaneintersection */
    2811             : 
    2812             : /*-<a                             href="qh-io_r.htm#TOC"
    2813             :   >-------------------------------</a><a name="printline3geom">-</a>
    2814             : 
    2815             :   qh_printline3geom(qh, fp, pointA, pointB, color )
    2816             :     prints a line as a VECT
    2817             :     prints 0's for qh.DROPdim
    2818             : 
    2819             :   notes:
    2820             :     if pointA == pointB,
    2821             :       it's a 1 point VECT
    2822             : */
    2823           0 : void qh_printline3geom(qhT *qh, FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
    2824             :   int k;
    2825             :   realT pA[4], pB[4];
    2826             : 
    2827           0 :   qh_projectdim3(qh, pointA, pA);
    2828           0 :   qh_projectdim3(qh, pointB, pB);
    2829           0 :   if ((fabs(pA[0] - pB[0]) > 1e-3) ||
    2830           0 :       (fabs(pA[1] - pB[1]) > 1e-3) ||
    2831           0 :       (fabs(pA[2] - pB[2]) > 1e-3)) {
    2832           0 :     qh_fprintf(qh, fp, 9204, "VECT 1 2 1 2 1\n");
    2833           0 :     for (k=0; k < 3; k++)
    2834           0 :        qh_fprintf(qh, fp, 9205, "%8.4g ", pB[k]);
    2835           0 :     qh_fprintf(qh, fp, 9206, " # p%d\n", qh_pointid(qh, pointB));
    2836             :   }else
    2837           0 :     qh_fprintf(qh, fp, 9207, "VECT 1 1 1 1 1\n");
    2838           0 :   for (k=0; k < 3; k++)
    2839           0 :     qh_fprintf(qh, fp, 9208, "%8.4g ", pA[k]);
    2840           0 :   qh_fprintf(qh, fp, 9209, " # p%d\n", qh_pointid(qh, pointA));
    2841           0 :   qh_fprintf(qh, fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
    2842           0 : }
    2843             : 
    2844             : /*-<a                             href="qh-io_r.htm#TOC"
    2845             :   >-------------------------------</a><a name="printneighborhood">-</a>
    2846             : 
    2847             :   qh_printneighborhood(qh, fp, format, facetA, facetB, printall )
    2848             :     print neighborhood of one or two facets
    2849             : 
    2850             :   notes:
    2851             :     calls qh_findgood_all()
    2852             :     bumps qh.visit_id
    2853             : */
    2854           0 : void qh_printneighborhood(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
    2855             :   facetT *neighbor, **neighborp, *facet;
    2856             :   setT *facets;
    2857             : 
    2858           0 :   if (format == qh_PRINTnone)
    2859           0 :     return;
    2860           0 :   qh_findgood_all(qh, qh->facet_list);
    2861           0 :   if (facetA == facetB)
    2862           0 :     facetB= NULL;
    2863           0 :   facets= qh_settemp(qh, 2*(qh_setsize(qh, facetA->neighbors)+1));
    2864           0 :   qh->visit_id++;
    2865           0 :   for (facet=facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
    2866           0 :     if (facet->visitid != qh->visit_id) {
    2867           0 :       facet->visitid= qh->visit_id;
    2868           0 :       qh_setappend(qh, &facets, facet);
    2869             :     }
    2870           0 :     FOREACHneighbor_(facet) {
    2871           0 :       if (neighbor->visitid == qh->visit_id)
    2872           0 :         continue;
    2873           0 :       neighbor->visitid= qh->visit_id;
    2874           0 :       if (printall || !qh_skipfacet(qh, neighbor))
    2875           0 :         qh_setappend(qh, &facets, neighbor);
    2876             :     }
    2877             :   }
    2878           0 :   qh_printfacets(qh, fp, format, NULL, facets, printall);
    2879           0 :   qh_settempfree(qh, &facets);
    2880             : } /* printneighborhood */
    2881             : 
    2882             : /*-<a                             href="qh-io_r.htm#TOC"
    2883             :   >-------------------------------</a><a name="printpoint">-</a>
    2884             : 
    2885             :   qh_printpoint(qh, fp, string, point )
    2886             :   qh_printpointid(qh, fp, string, dim, point, id )
    2887             :     prints the coordinates of a point
    2888             : 
    2889             :   returns:
    2890             :     if string is defined
    2891             :       prints 'string p%d'.  Skips p%d if id=qh_IDunknown(-1) or qh_IDnone(-3)
    2892             : 
    2893             :   notes:
    2894             :     nop if point is NULL
    2895             :     Same as QhullPoint's printPoint
    2896             : */
    2897           0 : void qh_printpoint(qhT *qh, FILE *fp, const char *string, pointT *point) {
    2898           0 :   int id= qh_pointid(qh, point);
    2899             : 
    2900           0 :   qh_printpointid(qh, fp, string, qh->hull_dim, point, id);
    2901           0 : } /* printpoint */
    2902             : 
    2903           1 : void qh_printpointid(qhT *qh, FILE *fp, const char *string, int dim, pointT *point, int id) {
    2904             :   int k;
    2905             :   realT r; /*bug fix*/
    2906             : 
    2907           1 :   if (!point)
    2908           0 :     return;
    2909           1 :   if (string) {
    2910           1 :     qh_fprintf(qh, fp, 9211, "%s", string);
    2911           1 :     if (id != qh_IDunknown && id != qh_IDnone)
    2912           0 :       qh_fprintf(qh, fp, 9212, " p%d: ", id);
    2913             :   }
    2914           4 :   for (k=dim; k--; ) {
    2915           3 :     r= *point++;
    2916           3 :     if (string)
    2917           3 :       qh_fprintf(qh, fp, 9213, " %8.4g", r);
    2918             :     else
    2919           0 :       qh_fprintf(qh, fp, 9214, qh_REAL_1, r);
    2920             :   }
    2921           1 :   qh_fprintf(qh, fp, 9215, "\n");
    2922             : } /* printpointid */
    2923             : 
    2924             : /*-<a                             href="qh-io_r.htm#TOC"
    2925             :   >-------------------------------</a><a name="printpoint3">-</a>
    2926             : 
    2927             :   qh_printpoint3(qh, fp, point )
    2928             :     prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
    2929             : */
    2930           0 : void qh_printpoint3(qhT *qh, FILE *fp, pointT *point) {
    2931             :   int k;
    2932             :   realT p[4];
    2933             : 
    2934           0 :   qh_projectdim3(qh, point, p);
    2935           0 :   for (k=0; k < 3; k++)
    2936           0 :     qh_fprintf(qh, fp, 9216, "%8.4g ", p[k]);
    2937           0 :   qh_fprintf(qh, fp, 9217, " # p%d\n", qh_pointid(qh, point));
    2938           0 : } /* printpoint3 */
    2939             : 
    2940             : /*----------------------------------------
    2941             : -printpoints- print pointids for a set of points starting at index
    2942             :    see geom_r.c
    2943             : */
    2944             : 
    2945             : /*-<a                             href="qh-io_r.htm#TOC"
    2946             :   >-------------------------------</a><a name="printpoints_out">-</a>
    2947             : 
    2948             :   qh_printpoints_out(qh, fp, facetlist, facets, printall )
    2949             :     prints vertices, coplanar/inside points, for facets by their point coordinates
    2950             :     allows qh.CDDoutput
    2951             : 
    2952             :   notes:
    2953             :     same format as qhull input
    2954             :     if no coplanar/interior points,
    2955             :       same order as qh_printextremes
    2956             : */
    2957           0 : void qh_printpoints_out(qhT *qh, FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
    2958           0 :   int allpoints= qh->num_points + qh_setsize(qh, qh->other_points);
    2959           0 :   int numpoints=0, point_i, point_n;
    2960             :   setT *vertices, *points;
    2961             :   facetT *facet, **facetp;
    2962             :   pointT *point, **pointp;
    2963             :   vertexT *vertex, **vertexp;
    2964             :   int id;
    2965             : 
    2966           0 :   points= qh_settemp(qh, allpoints);
    2967           0 :   qh_setzero(qh, points, 0, allpoints);
    2968           0 :   vertices= qh_facetvertices(qh, facetlist, facets, printall);
    2969           0 :   FOREACHvertex_(vertices) {
    2970           0 :     id= qh_pointid(qh, vertex->point);
    2971           0 :     if (id >= 0)
    2972           0 :       SETelem_(points, id)= vertex->point;
    2973             :   }
    2974           0 :   if (qh->KEEPinside || qh->KEEPcoplanar || qh->KEEPnearinside) {
    2975           0 :     FORALLfacet_(facetlist) {
    2976           0 :       if (!printall && qh_skipfacet(qh, facet))
    2977           0 :         continue;
    2978           0 :       FOREACHpoint_(facet->coplanarset) {
    2979           0 :         id= qh_pointid(qh, point);
    2980           0 :         if (id >= 0)
    2981           0 :           SETelem_(points, id)= point;
    2982             :       }
    2983             :     }
    2984           0 :     FOREACHfacet_(facets) {
    2985           0 :       if (!printall && qh_skipfacet(qh, facet))
    2986           0 :         continue;
    2987           0 :       FOREACHpoint_(facet->coplanarset) {
    2988           0 :         id= qh_pointid(qh, point);
    2989           0 :         if (id >= 0)
    2990           0 :           SETelem_(points, id)= point;
    2991             :       }
    2992             :     }
    2993             :   }
    2994           0 :   qh_settempfree(qh, &vertices);
    2995           0 :   FOREACHpoint_i_(qh, points) {
    2996           0 :     if (point)
    2997           0 :       numpoints++;
    2998             :   }
    2999           0 :   if (qh->CDDoutput)
    3000           0 :     qh_fprintf(qh, fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh->rbox_command,
    3001           0 :              qh->qhull_command, numpoints, qh->hull_dim + 1);
    3002             :   else
    3003           0 :     qh_fprintf(qh, fp, 9219, "%d\n%d\n", qh->hull_dim, numpoints);
    3004           0 :   FOREACHpoint_i_(qh, points) {
    3005           0 :     if (point) {
    3006           0 :       if (qh->CDDoutput)
    3007           0 :         qh_fprintf(qh, fp, 9220, "1 ");
    3008           0 :       qh_printpoint(qh, fp, NULL, point);
    3009             :     }
    3010             :   }
    3011           0 :   if (qh->CDDoutput)
    3012           0 :     qh_fprintf(qh, fp, 9221, "end\n");
    3013           0 :   qh_settempfree(qh, &points);
    3014           0 : } /* printpoints_out */
    3015             : 
    3016             : 
    3017             : /*-<a                             href="qh-io_r.htm#TOC"
    3018             :   >-------------------------------</a><a name="printpointvect">-</a>
    3019             : 
    3020             :   qh_printpointvect(qh, fp, point, normal, center, radius, color )
    3021             :     prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
    3022             : */
    3023           0 : void qh_printpointvect(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
    3024             :   realT diff[4], pointA[4];
    3025             :   int k;
    3026             : 
    3027           0 :   for (k=qh->hull_dim; k--; ) {
    3028           0 :     if (center)
    3029           0 :       diff[k]= point[k]-center[k];
    3030           0 :     else if (normal)
    3031           0 :       diff[k]= normal[k];
    3032             :     else
    3033           0 :       diff[k]= 0;
    3034             :   }
    3035           0 :   if (center)
    3036           0 :     qh_normalize2(qh, diff, qh->hull_dim, True, NULL, NULL);
    3037           0 :   for (k=qh->hull_dim; k--; )
    3038           0 :     pointA[k]= point[k]+diff[k] * radius;
    3039           0 :   qh_printline3geom(qh, fp, point, pointA, color);
    3040           0 : } /* printpointvect */
    3041             : 
    3042             : /*-<a                             href="qh-io_r.htm#TOC"
    3043             :   >-------------------------------</a><a name="printpointvect2">-</a>
    3044             : 
    3045             :   qh_printpointvect2(qh, fp, point, normal, center, radius )
    3046             :     prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
    3047             : */
    3048           0 : void qh_printpointvect2(qhT *qh, FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
    3049           0 :   realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
    3050             : 
    3051           0 :   qh_printpointvect(qh, fp, point, normal, center, radius, red);
    3052           0 :   qh_printpointvect(qh, fp, point, normal, center, -radius, yellow);
    3053           0 : } /* printpointvect2 */
    3054             : 
    3055             : /*-<a                             href="qh-io_r.htm#TOC"
    3056             :   >-------------------------------</a><a name="printridge">-</a>
    3057             : 
    3058             :   qh_printridge(qh, fp, ridge )
    3059             :     prints the information in a ridge
    3060             : 
    3061             :   notes:
    3062             :     for qh_printfacetridges()
    3063             :     same as operator<< [QhullRidge.cpp]
    3064             : */
    3065           0 : void qh_printridge(qhT *qh, FILE *fp, ridgeT *ridge) {
    3066             : 
    3067           0 :   qh_fprintf(qh, fp, 9222, "     - r%d", ridge->id);
    3068           0 :   if (ridge->tested)
    3069           0 :     qh_fprintf(qh, fp, 9223, " tested");
    3070           0 :   if (ridge->nonconvex)
    3071           0 :     qh_fprintf(qh, fp, 9224, " nonconvex");
    3072           0 :   if (ridge->mergevertex)
    3073           0 :     qh_fprintf(qh, fp, 9421, " mergevertex");
    3074           0 :   if (ridge->mergevertex2)
    3075           0 :     qh_fprintf(qh, fp, 9422, " mergevertex2");
    3076           0 :   if (ridge->simplicialtop)
    3077           0 :     qh_fprintf(qh, fp, 9425, " simplicialtop");
    3078           0 :   if (ridge->simplicialbot)
    3079           0 :     qh_fprintf(qh, fp, 9423, " simplicialbot");
    3080           0 :   qh_fprintf(qh, fp, 9225, "\n");
    3081           0 :   qh_printvertices(qh, fp, "           vertices:", ridge->vertices);
    3082           0 :   if (ridge->top && ridge->bottom)
    3083           0 :     qh_fprintf(qh, fp, 9226, "           between f%d and f%d\n",
    3084           0 :             ridge->top->id, ridge->bottom->id);
    3085           0 : } /* printridge */
    3086             : 
    3087             : /*-<a                             href="qh-io_r.htm#TOC"
    3088             :   >-------------------------------</a><a name="printspheres">-</a>
    3089             : 
    3090             :   qh_printspheres(qh, fp, vertices, radius )
    3091             :     prints 3-d vertices as OFF spheres
    3092             : 
    3093             :   notes:
    3094             :     inflated octahedron from Stuart Levy earth/mksphere2
    3095             : */
    3096           0 : void qh_printspheres(qhT *qh, FILE *fp, setT *vertices, realT radius) {
    3097             :   vertexT *vertex, **vertexp;
    3098             : 
    3099           0 :   qh->printoutnum++;
    3100           0 :   qh_fprintf(qh, fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
    3101             : INST geom {define vsphere OFF\n\
    3102             : 18 32 48\n\
    3103             : \n\
    3104             : 0 0 1\n\
    3105             : 1 0 0\n\
    3106             : 0 1 0\n\
    3107             : -1 0 0\n\
    3108             : 0 -1 0\n\
    3109             : 0 0 -1\n\
    3110             : 0.707107 0 0.707107\n\
    3111             : 0 -0.707107 0.707107\n\
    3112             : 0.707107 -0.707107 0\n\
    3113             : -0.707107 0 0.707107\n\
    3114             : -0.707107 -0.707107 0\n\
    3115             : 0 0.707107 0.707107\n\
    3116             : -0.707107 0.707107 0\n\
    3117             : 0.707107 0.707107 0\n\
    3118             : 0.707107 0 -0.707107\n\
    3119             : 0 0.707107 -0.707107\n\
    3120             : -0.707107 0 -0.707107\n\
    3121             : 0 -0.707107 -0.707107\n\
    3122             : \n\
    3123             : 3 0 6 11\n\
    3124             : 3 0 7 6 \n\
    3125             : 3 0 9 7 \n\
    3126             : 3 0 11 9\n\
    3127             : 3 1 6 8 \n\
    3128             : 3 1 8 14\n\
    3129             : 3 1 13 6\n\
    3130             : 3 1 14 13\n\
    3131             : 3 2 11 13\n\
    3132             : 3 2 12 11\n\
    3133             : 3 2 13 15\n\
    3134             : 3 2 15 12\n\
    3135             : 3 3 9 12\n\
    3136             : 3 3 10 9\n\
    3137             : 3 3 12 16\n\
    3138             : 3 3 16 10\n\
    3139             : 3 4 7 10\n\
    3140             : 3 4 8 7\n\
    3141             : 3 4 10 17\n\
    3142             : 3 4 17 8\n\
    3143             : 3 5 14 17\n\
    3144             : 3 5 15 14\n\
    3145             : 3 5 16 15\n\
    3146             : 3 5 17 16\n\
    3147             : 3 6 13 11\n\
    3148             : 3 7 8 6\n\
    3149             : 3 9 10 7\n\
    3150             : 3 11 12 9\n\
    3151             : 3 14 8 17\n\
    3152             : 3 15 13 14\n\
    3153             : 3 16 12 15\n\
    3154             : 3 17 10 16\n} transforms { TLIST\n");
    3155           0 :   FOREACHvertex_(vertices) {
    3156           0 :     qh_fprintf(qh, fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
    3157             :       radius, vertex->id, radius, radius);
    3158           0 :     qh_printpoint3(qh, fp, vertex->point);
    3159           0 :     qh_fprintf(qh, fp, 9229, "1\n");
    3160             :   }
    3161           0 :   qh_fprintf(qh, fp, 9230, "}}}\n");
    3162           0 : } /* printspheres */
    3163             : 
    3164             : 
    3165             : /*----------------------------------------------
    3166             : -printsummary-
    3167             :                 see libqhull_r.c
    3168             : */
    3169             : 
    3170             : /*-<a                             href="qh-io_r.htm#TOC"
    3171             :   >-------------------------------</a><a name="printvdiagram">-</a>
    3172             : 
    3173             :   qh_printvdiagram(qh, fp, format, facetlist, facets, printall )
    3174             :     print voronoi diagram
    3175             :       # of pairs of input sites
    3176             :       #indices site1 site2 vertex1 ...
    3177             : 
    3178             :     sites indexed by input point id
    3179             :       point 0 is the first input point
    3180             :     vertices indexed by 'o' and 'p' order
    3181             :       vertex 0 is the 'vertex-at-infinity'
    3182             :       vertex 1 is the first Voronoi vertex
    3183             : 
    3184             :   see:
    3185             :     qh_printvoronoi()
    3186             :     qh_eachvoronoi_all()
    3187             : 
    3188             :   notes:
    3189             :     if all facets are upperdelaunay,
    3190             :       prints upper hull (furthest-site Voronoi diagram)
    3191             : */
    3192           0 : void qh_printvdiagram(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
    3193             :   setT *vertices;
    3194             :   int totcount, numcenters;
    3195             :   boolT isLower;
    3196           0 :   qh_RIDGE innerouter= qh_RIDGEall;
    3197           0 :   printvridgeT printvridge= NULL;
    3198             : 
    3199           0 :   if (format == qh_PRINTvertices) {
    3200           0 :     innerouter= qh_RIDGEall;
    3201           0 :     printvridge= qh_printvridge;
    3202           0 :   }else if (format == qh_PRINTinner) {
    3203           0 :     innerouter= qh_RIDGEinner;
    3204           0 :     printvridge= qh_printvnorm;
    3205           0 :   }else if (format == qh_PRINTouter) {
    3206           0 :     innerouter= qh_RIDGEouter;
    3207           0 :     printvridge= qh_printvnorm;
    3208             :   }else {
    3209           0 :     qh_fprintf(qh, qh->ferr, 6219, "qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
    3210           0 :     qh_errexit(qh, qh_ERRqhull, NULL, NULL);
    3211             :   }
    3212           0 :   vertices= qh_markvoronoi(qh, facetlist, facets, printall, &isLower, &numcenters);
    3213           0 :   totcount= qh_printvdiagram2(qh, NULL, NULL, vertices, innerouter, False);
    3214           0 :   qh_fprintf(qh, fp, 9231, "%d\n", totcount);
    3215           0 :   totcount= qh_printvdiagram2(qh, fp, printvridge, vertices, innerouter, True /* inorder*/);
    3216           0 :   qh_settempfree(qh, &vertices);
    3217             : #if 0  /* for testing qh_eachvoronoi_all */
    3218             :   qh_fprintf(qh, fp, 9232, "\n");
    3219             :   totcount= qh_eachvoronoi_all(qh, fp, printvridge, qh->UPPERdelaunay, innerouter, True /* inorder*/);
    3220             :   qh_fprintf(qh, fp, 9233, "%d\n", totcount);
    3221             : #endif
    3222           0 : } /* printvdiagram */
    3223             : 
    3224             : /*-<a                             href="qh-io_r.htm#TOC"
    3225             :   >-------------------------------</a><a name="printvdiagram2">-</a>
    3226             : 
    3227             :   qh_printvdiagram2(qh, fp, printvridge, vertices, innerouter, inorder )
    3228             :     visit all pairs of input sites (vertices) for selected Voronoi vertices
    3229             :     vertices may include NULLs
    3230             : 
    3231             :   innerouter:
    3232             :     qh_RIDGEall   print inner ridges(bounded) and outer ridges(unbounded)
    3233             :     qh_RIDGEinner print only inner ridges
    3234             :     qh_RIDGEouter print only outer ridges
    3235             : 
    3236             :   inorder:
    3237             :     print 3-d Voronoi vertices in order
    3238             : 
    3239             :   assumes:
    3240             :     qh_markvoronoi marked facet->visitid for Voronoi vertices
    3241             :     all facet->seen= False
    3242             :     all facet->seen2= True
    3243             : 
    3244             :   returns:
    3245             :     total number of Voronoi ridges
    3246             :     if printvridge,
    3247             :       calls printvridge( fp, vertex, vertexA, centers) for each ridge
    3248             :       [see qh_eachvoronoi()]
    3249             : 
    3250             :   see:
    3251             :     qh_eachvoronoi_all()
    3252             : */
    3253           0 : int qh_printvdiagram2(qhT *qh, FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
    3254           0 :   int totcount= 0;
    3255             :   int vertex_i, vertex_n;
    3256             :   vertexT *vertex;
    3257             : 
    3258           0 :   FORALLvertices
    3259           0 :     vertex->seen= False;
    3260           0 :   FOREACHvertex_i_(qh, vertices) {
    3261           0 :     if (vertex) {
    3262           0 :       if (qh->GOODvertex > 0 && qh_pointid(qh, vertex->point)+1 != qh->GOODvertex)
    3263           0 :         continue;
    3264           0 :       totcount += qh_eachvoronoi(qh, fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
    3265             :     }
    3266             :   }
    3267           0 :   return totcount;
    3268             : } /* printvdiagram2 */
    3269             : 
    3270             : /*-<a                             href="qh-io_r.htm#TOC"
    3271             :   >-------------------------------</a><a name="printvertex">-</a>
    3272             : 
    3273             :   qh_printvertex(qh, fp, vertex )
    3274             :     prints the information in a vertex
    3275             :     Duplicated as operator<< [QhullVertex.cpp]
    3276             : */
    3277           4 : void qh_printvertex(qhT *qh, FILE *fp, vertexT *vertex) {
    3278             :   pointT *point;
    3279           4 :   int k, count= 0;
    3280             :   facetT *neighbor, **neighborp;
    3281             :   realT r; /*bug fix*/
    3282             : 
    3283           4 :   if (!vertex) {
    3284           0 :     qh_fprintf(qh, fp, 9234, "  NULLvertex\n");
    3285           0 :     return;
    3286             :   }
    3287           4 :   qh_fprintf(qh, fp, 9235, "- p%d(v%d):", qh_pointid(qh, vertex->point), vertex->id);
    3288           4 :   point= vertex->point;
    3289           4 :   if (point) {
    3290          16 :     for (k=qh->hull_dim; k--; ) {
    3291          12 :       r= *point++;
    3292          12 :       qh_fprintf(qh, fp, 9236, " %5.2g", r);
    3293             :     }
    3294             :   }
    3295           4 :   if (vertex->deleted)
    3296           0 :     qh_fprintf(qh, fp, 9237, " deleted");
    3297           4 :   if (vertex->delridge)
    3298           0 :     qh_fprintf(qh, fp, 9238, " delridge");
    3299           4 :   if (vertex->newfacet)
    3300           0 :     qh_fprintf(qh, fp, 9415, " newfacet");
    3301           4 :   if (vertex->seen && qh->IStracing)
    3302           0 :     qh_fprintf(qh, fp, 9416, " seen");
    3303           4 :   if (vertex->seen2 && qh->IStracing)
    3304           0 :     qh_fprintf(qh, fp, 9417, " seen2");
    3305           4 :   qh_fprintf(qh, fp, 9239, "\n");
    3306           4 :   if (vertex->neighbors) {
    3307           0 :     qh_fprintf(qh, fp, 9240, "  neighbors:");
    3308           0 :     FOREACHneighbor_(vertex) {
    3309           0 :       if (++count % 100 == 0)
    3310           0 :         qh_fprintf(qh, fp, 9241, "\n     ");
    3311           0 :       qh_fprintf(qh, fp, 9242, " f%d", neighbor->id);
    3312             :     }
    3313           0 :     qh_fprintf(qh, fp, 9243, "\n");
    3314             :   }
    3315             : } /* printvertex */
    3316             : 
    3317             : 
    3318             : /*-<a                             href="qh-io_r.htm#TOC"
    3319             :   >-------------------------------</a><a name="printvertexlist">-</a>
    3320             : 
    3321             :   qh_printvertexlist(qh, fp, string, facetlist, facets, printall )
    3322             :     prints vertices used by a facetlist or facet set
    3323             :     tests qh_skipfacet() if !printall
    3324             : */
    3325           1 : void qh_printvertexlist(qhT *qh, FILE *fp, const char* string, facetT *facetlist,
    3326             :                          setT *facets, boolT printall) {
    3327             :   vertexT *vertex, **vertexp;
    3328             :   setT *vertices;
    3329             : 
    3330           1 :   vertices= qh_facetvertices(qh, facetlist, facets, printall);
    3331           1 :   qh_fprintf(qh, fp, 9244, "%s", string);
    3332           5 :   FOREACHvertex_(vertices)
    3333           4 :     qh_printvertex(qh, fp, vertex);
    3334           1 :   qh_settempfree(qh, &vertices);
    3335           1 : } /* printvertexlist */
    3336             : 
    3337             : 
    3338             : /*-<a                             href="qh-io_r.htm#TOC"
    3339             :   >-------------------------------</a><a name="printvertices">-</a>
    3340             : 
    3341             :   qh_printvertices(qh, fp, string, vertices )
    3342             :     prints vertices in a set
    3343             :     duplicated as printVertexSet [QhullVertex.cpp]
    3344             : */
    3345           0 : void qh_printvertices(qhT *qh, FILE *fp, const char* string, setT *vertices) {
    3346             :   vertexT *vertex, **vertexp;
    3347             : 
    3348           0 :   qh_fprintf(qh, fp, 9245, "%s", string);
    3349           0 :   FOREACHvertex_(vertices)
    3350           0 :     qh_fprintf(qh, fp, 9246, " p%d(v%d)", qh_pointid(qh, vertex->point), vertex->id);
    3351           0 :   qh_fprintf(qh, fp, 9247, "\n");
    3352           0 : } /* printvertices */
    3353             : 
    3354             : /*-<a                             href="qh-io_r.htm#TOC"
    3355             :   >-------------------------------</a><a name="printvneighbors">-</a>
    3356             : 
    3357             :   qh_printvneighbors(qh, fp, facetlist, facets, printall )
    3358             :     print vertex neighbors of vertices in facetlist and facets ('FN')
    3359             : 
    3360             :   notes:
    3361             :     qh_countfacets clears facet->visitid for non-printed facets
    3362             : 
    3363             :   design:
    3364             :     collect facet count and related statistics
    3365             :     if necessary, build neighbor sets for each vertex
    3366             :     collect vertices in facetlist and facets
    3367             :     build a point array for point->vertex and point->coplanar facet
    3368             :     for each point
    3369             :       list vertex neighbors or coplanar facet
    3370             : */
    3371           0 : void qh_printvneighbors(qhT *qh, FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
    3372             :   int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
    3373             :   setT *vertices, *vertex_points, *coplanar_points;
    3374           0 :   int numpoints= qh->num_points + qh_setsize(qh, qh->other_points);
    3375             :   vertexT *vertex, **vertexp;
    3376             :   int vertex_i, vertex_n;
    3377             :   facetT *facet, **facetp, *neighbor, **neighborp;
    3378             :   pointT *point, **pointp;
    3379             : 
    3380           0 :   qh_countfacets(qh, facetlist, facets, printall, &numfacets, &numsimplicial,
    3381             :       &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
    3382           0 :   qh_fprintf(qh, fp, 9248, "%d\n", numpoints);
    3383           0 :   qh_vertexneighbors(qh);
    3384           0 :   vertices= qh_facetvertices(qh, facetlist, facets, printall);
    3385           0 :   vertex_points= qh_settemp(qh, numpoints);
    3386           0 :   coplanar_points= qh_settemp(qh, numpoints);
    3387           0 :   qh_setzero(qh, vertex_points, 0, numpoints);
    3388           0 :   qh_setzero(qh, coplanar_points, 0, numpoints);
    3389           0 :   FOREACHvertex_(vertices)
    3390           0 :     qh_point_add(qh, vertex_points, vertex->point, vertex);
    3391           0 :   FORALLfacet_(facetlist) {
    3392           0 :     FOREACHpoint_(facet->coplanarset)
    3393           0 :       qh_point_add(qh, coplanar_points, point, facet);
    3394             :   }
    3395           0 :   FOREACHfacet_(facets) {
    3396           0 :     FOREACHpoint_(facet->coplanarset)
    3397           0 :       qh_point_add(qh, coplanar_points, point, facet);
    3398             :   }
    3399           0 :   FOREACHvertex_i_(qh, vertex_points) {
    3400           0 :     if (vertex) {
    3401           0 :       numneighbors= qh_setsize(qh, vertex->neighbors);
    3402           0 :       qh_fprintf(qh, fp, 9249, "%d", numneighbors);
    3403           0 :       qh_order_vertexneighbors(qh, vertex);
    3404           0 :       FOREACHneighbor_(vertex)
    3405           0 :         qh_fprintf(qh, fp, 9250, " %d",
    3406           0 :                  neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
    3407           0 :       qh_fprintf(qh, fp, 9251, "\n");
    3408           0 :     }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
    3409           0 :       qh_fprintf(qh, fp, 9252, "1 %d\n",
    3410           0 :                   facet->visitid ? facet->visitid - 1 : 0 - facet->id);
    3411             :     else
    3412           0 :       qh_fprintf(qh, fp, 9253, "0\n");
    3413             :   }
    3414           0 :   qh_settempfree(qh, &coplanar_points);
    3415           0 :   qh_settempfree(qh, &vertex_points);
    3416           0 :   qh_settempfree(qh, &vertices);
    3417           0 : } /* printvneighbors */
    3418             : 
    3419             : /*-<a                             href="qh-io_r.htm#TOC"
    3420             :   >-------------------------------</a><a name="printvoronoi">-</a>
    3421             : 
    3422             :   qh_printvoronoi(qh, fp, format, facetlist, facets, printall )
    3423             :     print voronoi diagram in 'o' or 'G' format
    3424             :     for 'o' format
    3425             :       prints voronoi centers for each facet and for infinity
    3426             :       for each vertex, lists ids of printed facets or infinity
    3427             :       assumes facetlist and facets are disjoint
    3428             :     for 'G' format
    3429             :       prints an OFF object
    3430             :       adds a 0 coordinate to center
    3431             :       prints infinity but does not list in vertices
    3432             : 
    3433             :   see:
    3434             :     qh_printvdiagram()
    3435             : 
    3436             :   notes:
    3437             :     if 'o',
    3438             :       prints a line for each point except "at-infinity"
    3439             :     if all facets are upperdelaunay,
    3440             :       reverses lower and upper hull
    3441             : */
    3442           0 : void qh_printvoronoi(qhT *qh, FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
    3443           0 :   int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
    3444             :   facetT *facet, **facetp, *neighbor, **neighborp;
    3445             :   setT *vertices;
    3446             :   vertexT *vertex;
    3447             :   boolT isLower;
    3448           0 :   unsigned int numfacets= (unsigned int)qh->num_facets;
    3449             : 
    3450           0 :   vertices= qh_markvoronoi(qh, facetlist, facets, printall, &isLower, &numcenters);
    3451           0 :   FOREACHvertex_i_(qh, vertices) {
    3452           0 :     if (vertex) {
    3453           0 :       numvertices++;
    3454           0 :       numneighbors= numinf= 0;
    3455           0 :       FOREACHneighbor_(vertex) {
    3456           0 :         if (neighbor->visitid == 0)
    3457           0 :           numinf= 1;
    3458           0 :         else if (neighbor->visitid < numfacets)
    3459           0 :           numneighbors++;
    3460             :       }
    3461           0 :       if (numinf && !numneighbors) {
    3462           0 :         SETelem_(vertices, vertex_i)= NULL;
    3463           0 :         numvertices--;
    3464             :       }
    3465             :     }
    3466             :   }
    3467           0 :   if (format == qh_PRINTgeom)
    3468           0 :     qh_fprintf(qh, fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
    3469             :                 numcenters, numvertices);
    3470             :   else
    3471           0 :     qh_fprintf(qh, fp, 9255, "%d\n%d %d 1\n", qh->hull_dim-1, numcenters, qh_setsize(qh, vertices));
    3472           0 :   if (format == qh_PRINTgeom) {
    3473           0 :     for (k=qh->hull_dim-1; k--; )
    3474           0 :       qh_fprintf(qh, fp, 9256, qh_REAL_1, 0.0);
    3475           0 :     qh_fprintf(qh, fp, 9257, " 0 # infinity not used\n");
    3476             :   }else {
    3477           0 :     for (k=qh->hull_dim-1; k--; )
    3478           0 :       qh_fprintf(qh, fp, 9258, qh_REAL_1, qh_INFINITE);
    3479           0 :     qh_fprintf(qh, fp, 9259, "\n");
    3480             :   }
    3481           0 :   FORALLfacet_(facetlist) {
    3482           0 :     if (facet->visitid && facet->visitid < numfacets) {
    3483           0 :       if (format == qh_PRINTgeom)
    3484           0 :         qh_fprintf(qh, fp, 9260, "# %d f%d\n", vid++, facet->id);
    3485           0 :       qh_printcenter(qh, fp, format, NULL, facet);
    3486             :     }
    3487             :   }
    3488           0 :   FOREACHfacet_(facets) {
    3489           0 :     if (facet->visitid && facet->visitid < numfacets) {
    3490           0 :       if (format == qh_PRINTgeom)
    3491           0 :         qh_fprintf(qh, fp, 9261, "# %d f%d\n", vid++, facet->id);
    3492           0 :       qh_printcenter(qh, fp, format, NULL, facet);
    3493             :     }
    3494             :   }
    3495           0 :   FOREACHvertex_i_(qh, vertices) {
    3496           0 :     numneighbors= 0;
    3497           0 :     numinf=0;
    3498           0 :     if (vertex) {
    3499           0 :       qh_order_vertexneighbors(qh, vertex);
    3500           0 :       FOREACHneighbor_(vertex) {
    3501           0 :         if (neighbor->visitid == 0)
    3502           0 :           numinf= 1;
    3503           0 :         else if (neighbor->visitid < numfacets)
    3504           0 :           numneighbors++;
    3505             :       }
    3506             :     }
    3507           0 :     if (format == qh_PRINTgeom) {
    3508           0 :       if (vertex) {
    3509           0 :         qh_fprintf(qh, fp, 9262, "%d", numneighbors);
    3510           0 :         FOREACHneighbor_(vertex) {
    3511           0 :           if (neighbor->visitid && neighbor->visitid < numfacets)
    3512           0 :             qh_fprintf(qh, fp, 9263, " %d", neighbor->visitid);
    3513             :         }
    3514           0 :         qh_fprintf(qh, fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
    3515             :       }else
    3516           0 :         qh_fprintf(qh, fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
    3517             :     }else {
    3518           0 :       if (numinf)
    3519           0 :         numneighbors++;
    3520           0 :       qh_fprintf(qh, fp, 9266, "%d", numneighbors);
    3521           0 :       if (vertex) {
    3522           0 :         FOREACHneighbor_(vertex) {
    3523           0 :           if (neighbor->visitid == 0) {
    3524           0 :             if (numinf) {
    3525           0 :               numinf= 0;
    3526           0 :               qh_fprintf(qh, fp, 9267, " %d", neighbor->visitid);
    3527             :             }
    3528           0 :           }else if (neighbor->visitid < numfacets)
    3529           0 :             qh_fprintf(qh, fp, 9268, " %d", neighbor->visitid);
    3530             :         }
    3531             :       }
    3532           0 :       qh_fprintf(qh, fp, 9269, "\n");
    3533             :     }
    3534             :   }
    3535           0 :   if (format == qh_PRINTgeom)
    3536           0 :     qh_fprintf(qh, fp, 9270, "}\n");
    3537           0 :   qh_settempfree(qh, &vertices);
    3538           0 : } /* printvoronoi */
    3539             : 
    3540             : /*-<a                             href="qh-io_r.htm#TOC"
    3541             :   >-------------------------------</a><a name="printvnorm">-</a>
    3542             : 
    3543             :   qh_printvnorm(qh, fp, vertex, vertexA, centers, unbounded )
    3544             :     print one separating plane of the Voronoi diagram for a pair of input sites
    3545             :     unbounded==True if centers includes vertex-at-infinity
    3546             : 
    3547             :   assumes:
    3548             :     qh_ASvoronoi and qh_vertexneighbors() already set
    3549             : 
    3550             :   note:
    3551             :     parameter unbounded is UNUSED by this callback
    3552             : 
    3553             :   see:
    3554             :     qh_printvdiagram()
    3555             :     qh_eachvoronoi()
    3556             : */
    3557           0 : void qh_printvnorm(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
    3558             :   pointT *normal;
    3559             :   realT offset;
    3560             :   int k;
    3561             :   QHULL_UNUSED(unbounded);
    3562             : 
    3563           0 :   normal= qh_detvnorm(qh, vertex, vertexA, centers, &offset);
    3564           0 :   qh_fprintf(qh, fp, 9271, "%d %d %d ",
    3565           0 :       2+qh->hull_dim, qh_pointid(qh, vertex->point), qh_pointid(qh, vertexA->point));
    3566           0 :   for (k=0; k< qh->hull_dim-1; k++)
    3567           0 :     qh_fprintf(qh, fp, 9272, qh_REAL_1, normal[k]);
    3568           0 :   qh_fprintf(qh, fp, 9273, qh_REAL_1, offset);
    3569           0 :   qh_fprintf(qh, fp, 9274, "\n");
    3570           0 : } /* printvnorm */
    3571             : 
    3572             : /*-<a                             href="qh-io_r.htm#TOC"
    3573             :   >-------------------------------</a><a name="printvridge">-</a>
    3574             : 
    3575             :   qh_printvridge(qh, fp, vertex, vertexA, centers, unbounded )
    3576             :     print one ridge of the Voronoi diagram for a pair of input sites
    3577             :     unbounded==True if centers includes vertex-at-infinity
    3578             : 
    3579             :   see:
    3580             :     qh_printvdiagram()
    3581             : 
    3582             :   notes:
    3583             :     the user may use a different function
    3584             :     parameter unbounded is UNUSED
    3585             : */
    3586           0 : void qh_printvridge(qhT *qh, FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
    3587             :   facetT *facet, **facetp;
    3588             :   QHULL_UNUSED(unbounded);
    3589             : 
    3590           0 :   qh_fprintf(qh, fp, 9275, "%d %d %d", qh_setsize(qh, centers)+2,
    3591             :        qh_pointid(qh, vertex->point), qh_pointid(qh, vertexA->point));
    3592           0 :   FOREACHfacet_(centers)
    3593           0 :     qh_fprintf(qh, fp, 9276, " %d", facet->visitid);
    3594           0 :   qh_fprintf(qh, fp, 9277, "\n");
    3595           0 : } /* printvridge */
    3596             : 
    3597             : /*-<a                             href="qh-io_r.htm#TOC"
    3598             :   >-------------------------------</a><a name="projectdim3">-</a>
    3599             : 
    3600             :   qh_projectdim3(qh, source, destination )
    3601             :     project 2-d 3-d or 4-d point to a 3-d point
    3602             :     uses qh.DROPdim and qh.hull_dim
    3603             :     source and destination may be the same
    3604             : 
    3605             :   notes:
    3606             :     allocate 4 elements to destination just in case
    3607             : */
    3608           0 : void qh_projectdim3(qhT *qh, pointT *source, pointT *destination) {
    3609             :   int i,k;
    3610             : 
    3611           0 :   for (k=0, i=0; k < qh->hull_dim; k++) {
    3612           0 :     if (qh->hull_dim == 4) {
    3613           0 :       if (k != qh->DROPdim)
    3614           0 :         destination[i++]= source[k];
    3615           0 :     }else if (k == qh->DROPdim)
    3616           0 :       destination[i++]= 0;
    3617             :     else
    3618           0 :       destination[i++]= source[k];
    3619             :   }
    3620           0 :   while (i < 3)
    3621           0 :     destination[i++]= 0.0;
    3622           0 : } /* projectdim3 */
    3623             : 
    3624             : /*-<a                             href="qh-io_r.htm#TOC"
    3625             :   >-------------------------------</a><a name="readfeasible">-</a>
    3626             : 
    3627             :   qh_readfeasible(qh, dim, curline )
    3628             :     read feasible point from current line and qh.fin
    3629             : 
    3630             :   returns:
    3631             :     number of lines read from qh.fin
    3632             :     sets qh.feasible_point with malloc'd coordinates
    3633             : 
    3634             :   notes:
    3635             :     checks for qh.HALFspace
    3636             :     assumes dim > 1
    3637             : 
    3638             :   see:
    3639             :     qh_setfeasible
    3640             : */
    3641           0 : int qh_readfeasible(qhT *qh, int dim, const char *curline) {
    3642           0 :   boolT isfirst= True;
    3643           0 :   int linecount= 0, tokcount= 0;
    3644             :   const char *s;
    3645             :   char *t, firstline[qh_MAXfirst+1];
    3646             :   coordT *coords, value;
    3647             : 
    3648           0 :   if (!qh->HALFspace) {
    3649           0 :     qh_fprintf(qh, qh->ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
    3650           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3651             :   }
    3652           0 :   if (qh->feasible_string)
    3653           0 :     qh_fprintf(qh, qh->ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
    3654           0 :   if (!(qh->feasible_point= (coordT *)qh_malloc((size_t)dim * sizeof(coordT)))) {
    3655           0 :     qh_fprintf(qh, qh->ferr, 6071, "qhull error: insufficient memory for feasible point\n");
    3656           0 :     qh_errexit(qh, qh_ERRmem, NULL, NULL);
    3657             :   }
    3658           0 :   coords= qh->feasible_point;
    3659           0 :   while ((s= (isfirst ?  curline : fgets(firstline, qh_MAXfirst, qh->fin)))) {
    3660           0 :     if (isfirst)
    3661           0 :       isfirst= False;
    3662             :     else
    3663           0 :       linecount++;
    3664           0 :     while (*s) {
    3665           0 :       while (isspace(*s))
    3666           0 :         s++;
    3667           0 :       value= qh_strtod(s, &t);
    3668           0 :       if (s == t)
    3669           0 :         break;
    3670           0 :       s= t;
    3671           0 :       *(coords++)= value;
    3672           0 :       if (++tokcount == dim) {
    3673           0 :         while (isspace(*s))
    3674           0 :           s++;
    3675           0 :         qh_strtod(s, &t);
    3676           0 :         if (s != t) {
    3677           0 :           qh_fprintf(qh, qh->ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
    3678             :                s);
    3679           0 :           qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3680             :         }
    3681           0 :         return linecount;
    3682             :       }
    3683             :     }
    3684             :   }
    3685           0 :   qh_fprintf(qh, qh->ferr, 6073, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
    3686             :            tokcount, dim);
    3687           0 :   qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3688           0 :   return 0;
    3689             : } /* readfeasible */
    3690             : 
    3691             : /*-<a                             href="qh-io_r.htm#TOC"
    3692             :   >-------------------------------</a><a name="readpoints">-</a>
    3693             : 
    3694             :   qh_readpoints(qh, numpoints, dimension, ismalloc )
    3695             :     read points from qh.fin into qh.first_point, qh.num_points
    3696             :     qh.fin is lines of coordinates, one per vertex, first line number of points
    3697             :     if 'rbox D4',
    3698             :       gives message
    3699             :     if qh.ATinfinity,
    3700             :       adds point-at-infinity for Delaunay triangulations
    3701             : 
    3702             :   returns:
    3703             :     number of points, array of point coordinates, dimension, ismalloc True
    3704             :     if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
    3705             :         and clears qh.PROJECTdelaunay
    3706             :     if qh.HALFspace, reads optional feasible point, reads halfspaces,
    3707             :         converts to dual.
    3708             : 
    3709             :   for feasible point in "cdd format" in 3-d:
    3710             :     3 1
    3711             :     coordinates
    3712             :     comments
    3713             :     begin
    3714             :     n 4 real/integer
    3715             :     ...
    3716             :     end
    3717             : 
    3718             :   notes:
    3719             :     dimension will change in qh_initqhull_globals if qh.PROJECTinput
    3720             :     uses malloc() since qh_mem not initialized
    3721             :     QH11012 FIX: qh_readpoints needs rewriting, too long
    3722             : */
    3723           0 : coordT *qh_readpoints(qhT *qh, int *numpoints, int *dimension, boolT *ismalloc) {
    3724           0 :   coordT *points, *coords, *infinity= NULL;
    3725           0 :   realT paraboloid, maxboloid= -REALmax, value;
    3726           0 :   realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
    3727           0 :   char *s= 0, *t, firstline[qh_MAXfirst+1];
    3728           0 :   int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
    3729           0 :   int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
    3730           0 :   int tokcount= 0, linecount=0, maxcount, coordcount=0;
    3731           0 :   boolT islong, isfirst= True, wasbegin= False;
    3732           0 :   boolT isdelaunay= qh->DELAUNAY && !qh->PROJECTinput;
    3733             : 
    3734           0 :   if (qh->CDDinput) {
    3735           0 :     while ((s= fgets(firstline, qh_MAXfirst, qh->fin))) {
    3736           0 :       linecount++;
    3737           0 :       if (qh->HALFspace && linecount == 1 && isdigit(*s)) {
    3738           0 :         dimfeasible= qh_strtol(s, &s);
    3739           0 :         while (isspace(*s))
    3740           0 :           s++;
    3741           0 :         if (qh_strtol(s, &s) == 1)
    3742           0 :           linecount += qh_readfeasible(qh, dimfeasible, s);
    3743             :         else
    3744           0 :           dimfeasible= 0;
    3745           0 :       }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
    3746             :         break;
    3747           0 :       else if (!*qh->rbox_command)
    3748           0 :         strncat(qh->rbox_command, s, sizeof(qh->rbox_command)-1);
    3749             :     }
    3750           0 :     if (!s) {
    3751           0 :       qh_fprintf(qh, qh->ferr, 6074, "qhull input error: missing \"begin\" for cdd-formated input\n");
    3752           0 :       qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3753             :     }
    3754             :   }
    3755           0 :   while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh->fin))) {
    3756           0 :     linecount++;
    3757           0 :     if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
    3758           0 :       wasbegin= True;
    3759           0 :     while (*s) {
    3760           0 :       while (isspace(*s))
    3761           0 :         s++;
    3762           0 :       if (!*s)
    3763           0 :         break;
    3764           0 :       if (!isdigit(*s)) {
    3765           0 :         if (!*qh->rbox_command) {
    3766           0 :           strncat(qh->rbox_command, s, sizeof(qh->rbox_command)-1);
    3767           0 :           firsttext= linecount;
    3768             :         }
    3769           0 :         break;
    3770             :       }
    3771           0 :       if (!diminput)
    3772           0 :         diminput= qh_strtol(s, &s);
    3773             :       else {
    3774           0 :         numinput= qh_strtol(s, &s);
    3775           0 :         if (numinput == 1 && diminput >= 2 && qh->HALFspace && !qh->CDDinput) {
    3776           0 :           linecount += qh_readfeasible(qh, diminput, s); /* checks if ok */
    3777           0 :           dimfeasible= diminput;
    3778           0 :           diminput= numinput= 0;
    3779             :         }else
    3780             :           break;
    3781             :       }
    3782             :     }
    3783             :   }
    3784           0 :   if (!s) {
    3785           0 :     qh_fprintf(qh, qh->ferr, 6075, "qhull input error: short input file.  Did not find dimension and number of points\n");
    3786           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3787             :   }
    3788           0 :   if (diminput > numinput) {
    3789           0 :     tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */
    3790           0 :     diminput= numinput;
    3791           0 :     numinput= tempi;
    3792             :   }
    3793           0 :   if (diminput < 2) {
    3794           0 :     qh_fprintf(qh, qh->ferr, 6220, "qhull input error: dimension %d (first or smaller number) should be at least 2\n",
    3795             :             diminput);
    3796           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3797             :   }
    3798           0 :   if (numinput < 1 || numinput > qh_POINTSmax) {
    3799           0 :     qh_fprintf(qh, qh->ferr, 6411, "qhull input error: expecting between 1 and %d points.  Got %d %d-d points\n",
    3800             :       qh_POINTSmax, numinput, diminput);
    3801           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3802             :     /* same error message in qh_initqhull_globals */
    3803             :   }
    3804             : 
    3805           0 :   if (isdelaunay && qh->HALFspace) {
    3806           0 :     qh_fprintf(qh, qh->ferr, 6037, "qhull option error (qh_readpoints): can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
    3807           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3808             :     /* otherwise corrupted memory allocations, same error message as in qh_initqhull_globals */
    3809           0 :   }else if (isdelaunay) {
    3810           0 :     qh->PROJECTdelaunay= False;
    3811           0 :     if (qh->CDDinput)
    3812           0 :       *dimension= diminput;
    3813             :     else
    3814           0 :       *dimension= diminput+1;
    3815           0 :     *numpoints= numinput;
    3816           0 :     if (qh->ATinfinity)
    3817           0 :       (*numpoints)++;
    3818           0 :   }else if (qh->HALFspace) {
    3819           0 :     *dimension= diminput - 1;
    3820           0 :     *numpoints= numinput;
    3821           0 :     if (diminput < 3) {
    3822           0 :       qh_fprintf(qh, qh->ferr, 6221, "qhull input error: dimension %d (first number, includes offset) should be at least 3 for halfspaces\n",
    3823             :             diminput);
    3824           0 :       qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3825             :     }
    3826           0 :     if (dimfeasible) {
    3827           0 :       if (dimfeasible != *dimension) {
    3828           0 :         qh_fprintf(qh, qh->ferr, 6222, "qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
    3829             :           dimfeasible, diminput);
    3830           0 :         qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3831             :       }
    3832             :     }else
    3833           0 :       qh_setfeasible(qh, *dimension);
    3834             :   }else {
    3835           0 :     if (qh->CDDinput)
    3836           0 :       *dimension= diminput-1;
    3837             :     else
    3838           0 :       *dimension= diminput;
    3839           0 :     *numpoints= numinput;
    3840             :   }
    3841           0 :   qh->normal_size= *dimension * (int)sizeof(coordT); /* for tracing with qh_printpoint */
    3842           0 :   if (qh->HALFspace) {
    3843           0 :     qh->half_space= coordp= (coordT *)qh_malloc((size_t)qh->normal_size + sizeof(coordT));
    3844           0 :     if (qh->CDDinput) {
    3845           0 :       offsetp= qh->half_space;
    3846           0 :       normalp= offsetp + 1;
    3847             :     }else {
    3848           0 :       normalp= qh->half_space;
    3849           0 :       offsetp= normalp + *dimension;
    3850             :     }
    3851             :   }
    3852           0 :   qh->maxline= diminput * (qh_REALdigits + 5);
    3853           0 :   maximize_(qh->maxline, 500);
    3854           0 :   qh->line= (char *)qh_malloc((size_t)(qh->maxline+1) * sizeof(char));
    3855           0 :   *ismalloc= True;  /* use malloc since memory not setup */
    3856           0 :   coords= points= qh->temp_malloc=  /* numinput and diminput >=2 by QH6220 */
    3857           0 :         (coordT *)qh_malloc((size_t)((*numpoints)*(*dimension))*sizeof(coordT));
    3858           0 :   if (!coords || !qh->line || (qh->HALFspace && !qh->half_space)) {
    3859           0 :     qh_fprintf(qh, qh->ferr, 6076, "qhull error: insufficient memory to read %d points\n",
    3860             :             numinput);
    3861           0 :     qh_errexit(qh, qh_ERRmem, NULL, NULL);
    3862             :   }
    3863           0 :   if (isdelaunay && qh->ATinfinity) {
    3864           0 :     infinity= points + numinput * (*dimension);
    3865           0 :     for (k= (*dimension) - 1; k--; )
    3866           0 :       infinity[k]= 0.0;
    3867             :   }
    3868           0 :   maxcount= numinput * diminput;
    3869           0 :   paraboloid= 0.0;
    3870           0 :   while ((s= (isfirst ?  s : fgets(qh->line, qh->maxline, qh->fin)))) {
    3871           0 :     if (!isfirst) {
    3872           0 :       linecount++;
    3873           0 :       if (*s == 'e' || *s == 'E') {
    3874           0 :         if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
    3875           0 :           if (qh->CDDinput )
    3876           0 :             break;
    3877           0 :           else if (wasbegin)
    3878           0 :             qh_fprintf(qh, qh->ferr, 7058, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
    3879             :         }
    3880             :       }
    3881             :     }
    3882           0 :     islong= False;
    3883           0 :     while (*s) {
    3884           0 :       while (isspace(*s))
    3885           0 :         s++;
    3886           0 :       value= qh_strtod(s, &t);
    3887           0 :       if (s == t) {
    3888           0 :         if (!*qh->rbox_command)
    3889           0 :          strncat(qh->rbox_command, s, sizeof(qh->rbox_command)-1);
    3890           0 :         if (*s && !firsttext)
    3891           0 :           firsttext= linecount;
    3892           0 :         if (!islong && !firstshort && coordcount)
    3893           0 :           firstshort= linecount;
    3894           0 :         break;
    3895             :       }
    3896           0 :       if (!firstpoint)
    3897           0 :         firstpoint= linecount;
    3898           0 :       s= t;
    3899           0 :       if (++tokcount > maxcount)
    3900           0 :         continue;
    3901           0 :       if (qh->HALFspace) {
    3902           0 :         if (qh->CDDinput)
    3903           0 :           *(coordp++)= -value; /* both coefficients and offset */
    3904             :         else
    3905           0 :           *(coordp++)= value;
    3906             :       }else {
    3907           0 :         *(coords++)= value;
    3908           0 :         if (qh->CDDinput && !coordcount) {
    3909           0 :           if (value != 1.0) {
    3910           0 :             qh_fprintf(qh, qh->ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
    3911             :                    linecount);
    3912           0 :             qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3913             :           }
    3914           0 :           coords--;
    3915           0 :         }else if (isdelaunay) {
    3916           0 :           paraboloid += value * value;
    3917           0 :           if (qh->ATinfinity) {
    3918           0 :             if (qh->CDDinput)
    3919           0 :               infinity[coordcount-1] += value;
    3920             :             else
    3921           0 :               infinity[coordcount] += value;
    3922             :           }
    3923             :         }
    3924             :       }
    3925           0 :       if (++coordcount == diminput) {
    3926           0 :         coordcount= 0;
    3927           0 :         if (isdelaunay) {
    3928           0 :           *(coords++)= paraboloid;
    3929           0 :           maximize_(maxboloid, paraboloid);
    3930           0 :           paraboloid= 0.0;
    3931           0 :         }else if (qh->HALFspace) {
    3932           0 :           if (!qh_sethalfspace(qh, *dimension, coords, &coords, normalp, offsetp, qh->feasible_point)) {
    3933           0 :             qh_fprintf(qh, qh->ferr, 8048, "The halfspace was on line %d\n", linecount);
    3934           0 :             if (wasbegin)
    3935           0 :               qh_fprintf(qh, qh->ferr, 8049, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
    3936           0 :             qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3937             :           }
    3938           0 :           coordp= qh->half_space;
    3939             :         }
    3940           0 :         while (isspace(*s))
    3941           0 :           s++;
    3942           0 :         if (*s) {
    3943           0 :           islong= True;
    3944           0 :           if (!firstlong)
    3945           0 :             firstlong= linecount;
    3946             :         }
    3947             :       }
    3948             :     }
    3949           0 :     if (!islong && !firstshort && coordcount)
    3950           0 :       firstshort= linecount;
    3951           0 :     if (!isfirst && s - qh->line >= qh->maxline) {
    3952           0 :       qh_fprintf(qh, qh->ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
    3953           0 :               linecount, (int) (s - qh->line));   /* WARN64 */
    3954           0 :       qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3955             :     }
    3956           0 :     isfirst= False;
    3957             :   }
    3958           0 :   if (qh->rbox_command[0])
    3959           0 :     qh->rbox_command[strlen(qh->rbox_command)-1]= '\0'; /* remove \n, previous qh_errexit's display command as two lines */
    3960           0 :   if (tokcount != maxcount) {
    3961           0 :     newnum= fmin_(numinput, tokcount/diminput);
    3962           0 :     if (qh->ALLOWshort)
    3963           0 :       qh_fprintf(qh, qh->ferr, 7073, "qhull warning: instead of %d points in %d-d, input contains %d points and %d extra coordinates.\n",
    3964             :           numinput, diminput, tokcount/diminput, tokcount % diminput);
    3965             :     else
    3966           0 :       qh_fprintf(qh, qh->ferr, 6410, "qhull error: instead of %d points in %d-d, input contains %d points and %d extra coordinates.\n",
    3967             :           numinput, diminput, tokcount/diminput, tokcount % diminput);
    3968           0 :     if (firsttext)
    3969           0 :       qh_fprintf(qh, qh->ferr, 8051, "    Line %d is the first comment.\n", firsttext);
    3970           0 :     qh_fprintf(qh, qh->ferr, 8033,   "    Line %d is the first point.\n", firstpoint);
    3971           0 :     if (firstshort)
    3972           0 :       qh_fprintf(qh, qh->ferr, 8052, "    Line %d is the first short line.\n", firstshort);
    3973           0 :     if (firstlong)
    3974           0 :       qh_fprintf(qh, qh->ferr, 8053, "    Line %d is the first long line.\n", firstlong);
    3975           0 :     if (qh->ALLOWshort)
    3976           0 :       qh_fprintf(qh, qh->ferr, 8054, "    Continuing with %d points.\n", newnum);
    3977             :     else {
    3978           0 :       qh_fprintf(qh, qh->ferr, 8077, "    Override with option 'Qa' (allow-short)\n");
    3979           0 :       qh_errexit(qh, qh_ERRinput, NULL, NULL);
    3980             :     }
    3981           0 :     numinput= newnum;
    3982           0 :     if (isdelaunay && qh->ATinfinity) {
    3983           0 :       for (k= tokcount % diminput; k--; )
    3984           0 :         infinity[k] -= *(--coords);
    3985           0 :       *numpoints= newnum+1;
    3986             :     }else {
    3987           0 :       coords -= tokcount % diminput;
    3988           0 :       *numpoints= newnum;
    3989             :     }
    3990             :   }
    3991           0 :   if (isdelaunay && qh->ATinfinity) {
    3992           0 :     for (k= (*dimension) - 1; k--; )
    3993           0 :       infinity[k] /= numinput;
    3994           0 :     if (coords == infinity)
    3995           0 :       coords += (*dimension) -1;
    3996             :     else {
    3997           0 :       for (k=0; k < (*dimension) - 1; k++)
    3998           0 :         *(coords++)= infinity[k];
    3999             :     }
    4000           0 :     *(coords++)= maxboloid * 1.1;
    4001             :   }
    4002           0 :   if (!strcmp(qh->rbox_command, "./rbox D4"))
    4003           0 :     qh_fprintf(qh, qh->ferr, 8055, "\n\
    4004             : This is the qhull test case.  If any errors or core dumps occur,\n\
    4005             : recompile qhull with 'make new'.  If errors still occur, there is\n\
    4006             : an incompatibility.  You should try a different compiler.  You can also\n\
    4007             : change the choices in user_r.h.  If you discover the source of the problem,\n\
    4008             : please send mail to qhull_bug@qhull.org.\n\
    4009             : \n\
    4010             : Type 'qhull' for a short list of options.\n");
    4011           0 :   qh_free(qh->line);
    4012           0 :   qh->line= NULL;
    4013           0 :   if (qh->half_space) {
    4014           0 :     qh_free(qh->half_space);
    4015           0 :     qh->half_space= NULL;
    4016             :   }
    4017           0 :   qh->temp_malloc= NULL;
    4018           0 :   trace1((qh, qh->ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
    4019             :           numinput, diminput));
    4020           0 :   return(points);
    4021             : } /* readpoints */
    4022             : 
    4023             : 
    4024             : /*-<a                             href="qh-io_r.htm#TOC"
    4025             :   >-------------------------------</a><a name="setfeasible">-</a>
    4026             : 
    4027             :   qh_setfeasible(qh, dim )
    4028             :     set qh.feasible_point from qh.feasible_string in "n,n,n" or "n n n" format
    4029             : 
    4030             :   notes:
    4031             :     "n,n,n" already checked by qh_initflags()
    4032             :     see qh_readfeasible()
    4033             :     called only once from qh_new_qhull, otherwise leaks memory
    4034             : */
    4035           0 : void qh_setfeasible(qhT *qh, int dim) {
    4036           0 :   int tokcount= 0;
    4037             :   char *s;
    4038             :   coordT *coords, value;
    4039             : 
    4040           0 :   if (!(s= qh->feasible_string)) {
    4041           0 :     qh_fprintf(qh, qh->ferr, 6223, "qhull input error: halfspace intersection needs a feasible point.  Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
    4042           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    4043             :   }
    4044           0 :   if (!(qh->feasible_point= (pointT *)qh_malloc((size_t)dim * sizeof(coordT)))) {
    4045           0 :     qh_fprintf(qh, qh->ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
    4046           0 :     qh_errexit(qh, qh_ERRmem, NULL, NULL);
    4047             :   }
    4048           0 :   coords= qh->feasible_point;
    4049           0 :   while (*s) {
    4050           0 :     value= qh_strtod(s, &s);
    4051           0 :     if (++tokcount > dim) {
    4052           0 :       qh_fprintf(qh, qh->ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
    4053             :           qh->feasible_string, dim);
    4054           0 :       break;
    4055             :     }
    4056           0 :     *(coords++)= value;
    4057           0 :     if (*s)
    4058           0 :       s++;
    4059             :   }
    4060           0 :   while (++tokcount <= dim)
    4061           0 :     *(coords++)= 0.0;
    4062           0 : } /* setfeasible */
    4063             : 
    4064             : /*-<a                             href="qh-io_r.htm#TOC"
    4065             :   >-------------------------------</a><a name="skipfacet">-</a>
    4066             : 
    4067             :   qh_skipfacet(qh, facet )
    4068             :     returns 'True' if this facet is not to be printed
    4069             : 
    4070             :   notes:
    4071             :     based on the user provided slice thresholds and 'good' specifications
    4072             : */
    4073           0 : boolT qh_skipfacet(qhT *qh, facetT *facet) {
    4074             :   facetT *neighbor, **neighborp;
    4075             : 
    4076           0 :   if (qh->PRINTneighbors) {
    4077           0 :     if (facet->good)
    4078           0 :       return !qh->PRINTgood;
    4079           0 :     FOREACHneighbor_(facet) {
    4080           0 :       if (neighbor->good)
    4081           0 :         return False;
    4082             :     }
    4083           0 :     return True;
    4084           0 :   }else if (qh->PRINTgood)
    4085           0 :     return !facet->good;
    4086           0 :   else if (!facet->normal)
    4087           0 :     return True;
    4088           0 :   return(!qh_inthresholds(qh, facet->normal, NULL));
    4089             : } /* skipfacet */
    4090             : 
    4091             : /*-<a                             href="qh-io_r.htm#TOC"
    4092             :   >-------------------------------</a><a name="skipfilename">-</a>
    4093             : 
    4094             :   qh_skipfilename(qh, string )
    4095             :     returns pointer to character after filename
    4096             : 
    4097             :   notes:
    4098             :     skips leading spaces
    4099             :     ends with spacing or eol
    4100             :     if starts with ' or " ends with the same, skipping \' or \"
    4101             :     For qhull, qh_argv_to_command() only uses double quotes
    4102             : */
    4103           0 : char *qh_skipfilename(qhT *qh, char *filename) {
    4104           0 :   char *s= filename;  /* non-const due to return */
    4105             :   char c;
    4106             : 
    4107           0 :   while (*s && isspace(*s))
    4108           0 :     s++;
    4109           0 :   c= *s++;
    4110           0 :   if (c == '\0') {
    4111           0 :     qh_fprintf(qh, qh->ferr, 6204, "qhull input error: filename expected, none found.\n");
    4112           0 :     qh_errexit(qh, qh_ERRinput, NULL, NULL);
    4113             :   }
    4114           0 :   if (c == '\'' || c == '"') {
    4115           0 :     while (*s !=c || s[-1] == '\\') {
    4116           0 :       if (!*s) {
    4117           0 :         qh_fprintf(qh, qh->ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
    4118           0 :         qh_errexit(qh, qh_ERRinput, NULL, NULL);
    4119             :       }
    4120           0 :       s++;
    4121             :     }
    4122           0 :     s++;
    4123             :   }
    4124           0 :   else while (*s && !isspace(*s))
    4125           0 :       s++;
    4126           0 :   return s;
    4127             : } /* skipfilename */
    4128             : 

Generated by: LCOV version 1.14